Test mode

With a sbm_test_ key every call works as in live mode, on separate data, and nothing is submitted or spent. Share links are the one exception: a client page needs a live project, so creating one answers 422 validation_failed and reading or turning one off answers 404. Listings move on their own: in_progress after 1 to 5 minutes, submitted after 3 to 8 minutes and an outcome after 6 to 15 minutes, where 80% go live, 12% end not_accepted and 8% stay submitted. The outcome depends only on the listing's id, so a listing always ends the same way.

Apart from webhook deliveries, nothing leaves our servers in test mode. Image URLs are not downloaded and files are checked but not stored, feed URLs have the right shape but return 404, and autofill and Domain Ratings are simulated. Hosts on .test and .example are accepted here and rejected in live mode.

Logins are placeholders: about 45% of test listings get one, on the project's contact email or on an address at login.test, with a password made from the project's id and sample emails whose links point to login.test. Nothing signs up anywhere.

Two inputs fail on purpose: a host that starts with nobadge. never passes badge verification, and an image URL ending in /fail.png returns image_unreachable. Test data is deleted after 30 days without activity.

POST
/test_helpers/listings/{listing_id}/advance

Moves a test listing to its next status now, or to the status you name in to. Events and webhooks fire as they would in live mode. Live keys get 403 test_mode_only.

Path Parameters

listing_id*string

The listing's id.

Match^lst_[0-9A-Za-z]{22}$

Request Body

application/json
  1. body

Where to move the test listing. An empty body moves it 1 step along the usual path.

to?string

The status to move to. It must be a move the listing could make in live mode.

Value in"in_progress""action_required""submitted""live""not_accepted""cancelled"

Response Body

The listing in its new status.

application/json
  1. response

One project at one directory. Its times are rounded down to the hour.

object*string

Always listing.

id*string

The listing's id. A project has 1 listing per directory, and it keeps its id after a correction.

Match^lst_[0-9A-Za-z]{22}$
livemode*boolean

true for a live listing, false for a test listing.

project*string

The project's id.

Match^prj_[0-9A-Za-z]{22}$
directory*

The directory.

status*string

Where the listing stands:

  • pending: waiting to start. Listings start as capacity frees: up to 100 of yours are in progress at once.
  • in_progress: being prepared and sent to the directory.
  • action_required: waiting on you or your client; action says what.
  • submitted: the directory has it and is reviewing it.
  • live: published; live_url points to it.
  • not_accepted: the directory declined it, could not take it, or took it down; reason says which.
  • cancelled: withdrawn before it reached the directory.

The usual path is pending → in_progress ⇄ action_required → submitted → live, and some listings go live without submitted. Rare corrections each send their own event: live → not_accepted (removed), live → submitted, and not_accepted or cancelled → pending, in_progress, submitted or live. The console and reports show the statuses as Pending, In progress, Needs you, Submitted, Live, Not accepted and Cancelled.

Value in"pending""in_progress""action_required""submitted""live""not_accepted""cancelled"
reason*|

Why the listing ended, for not_accepted and cancelled; null otherwise. New values can appear.

  • declined: the directory reviewed the listing and said no.
  • unavailable: the directory could not take the listing, for example because it stopped taking new products.
  • removed: the directory took down a listing that was live.
  • withdrawn: we withdrew the listing before it reached the directory.
action*|

What to do, when status is action_required. null otherwise.

live_url*|

The published listing, when status is live. null before that, and when it went live without a link.

Formaturi
proof_url*|

A screenshot of the live listing, served from the badge feed host. null when there is none.

Formaturi
created_at*string

When the listing was created, rounded down to the hour.

Formatdate-time
submitted_at*|

When the directory received the listing, rounded down to the hour. null before that.

Formatdate-time
live_at*|

When the listing went live, rounded down to the hour. null unless it is or was live.

Formatdate-time
curl -X POST "https://api.submitator.com/v1/test_helpers/listings/lst_7Hk2Qn4Rt9Vx1Bm6Cz3LdK/advance" \  -H "Authorization: Bearer $SUBMITATOR_API_KEY" \  -H "Content-Type: application/json" \  -d '{"to":"live"}'
{  "object": "listing",  "id": "lst_5Wq9Lm2Xr7Kt3Vb8Nz1HcD",  "livemode": false,  "project": "prj_4QzX1m9Lr2Vb7Nc8Tk3HwP",  "directory": {    "id": "dir_6Pw3Kx9Ty2Rq7Lm1Zb5VcN",    "name": "SaaSHub",    "domain_rating": 61,    "logo_url": "https://feed.example.net/a/h4Sw8Lp.q2Xn"  },  "status": "live",  "reason": null,  "action": null,  "live_url": "https://www.saashub.com/ledgerly",  "proof_url": "https://feed.example.net/a/Ps6Wn2Kx.h8Lq4",  "created_at": "2026-10-03T14:00:00Z",  "submitted_at": "2026-10-05T11:00:00Z",  "live_at": "2026-10-08T15:00:00Z"}

Set your test launches

POST
/test_helpers/account/launches

Sets how many test launches are available, from 0 to 1,000. Set 0 to try the no_launches_left path. Live keys get 403 test_mode_only.

Request Body

application/json
  1. body

Your test launch balance.

available*integer

Test launches to make available, 0 to 1,000.

Range0 <= value <= 1000

Response Body

Your test account with the new balance.

application/json
  1. response

Your launches, the listings in progress and your request budget, in the key's mode.

object*string

Always account.

livemode*boolean

true in live mode, false in test mode.

name*string

Your agency's name.

state*string

setup before your first purchase, active after it, suspended when the account can read but not write.

Value in"setup""active""suspended"
launches*

Launches you have, 1 per project. In test mode these are test launches: 100 to start, and POST /test_helpers/account/launches sets them.

capacity*

Listings in progress across all your projects. Above the limit, new listings wait in pending and start as others finish; launches are accepted either way.

rate_limit*

Your request budget for the current UTC hour, the same numbers as the RateLimit-* headers.

curl -X POST "https://api.submitator.com/v1/test_helpers/account/launches" \  -H "Authorization: Bearer $SUBMITATOR_API_KEY" \  -H "Content-Type: application/json" \  -d '{"available":0}'
{  "object": "account",  "livemode": false,  "name": "Northlight Studio",  "state": "active",  "launches": {    "available": 0,    "used": 3,    "total": 3  },  "capacity": {    "in_flight": 25,    "limit": 100  },  "rate_limit": {    "limit": 3600,    "remaining": 3488,    "resets_at": "2026-10-08T16:00:00Z"  }}