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.
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.
listing_id*stringThe listing's id.
^lst_[0-9A-Za-z]{22}$application/json- body
Where to move the test listing. An empty body moves it 1 step along the usual path.
to?stringThe status to move to. It must be a move the listing could make in live mode.
"in_progress""action_required""submitted""live""not_accepted""cancelled"The listing in its new status.
application/json- response
One project at one directory. Its times are rounded down to the hour.
object*stringAlways listing.
id*stringThe listing's id. A project has 1 listing per directory, and it keeps its id after a correction.
^lst_[0-9A-Za-z]{22}$livemode*booleantrue for a live listing, false for a test listing.
project*stringThe project's id.
^prj_[0-9A-Za-z]{22}$directory*The directory.
status*stringWhere 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;actionsays what.submitted: the directory has it and is reviewing it.live: published;live_urlpoints to it.not_accepted: the directory declined it, could not take it, or took it down;reasonsays 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.
"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.
uriproof_url*|A screenshot of the live listing, served from the badge feed host. null when there is none.
uricreated_at*stringWhen the listing was created, rounded down to the hour.
date-timesubmitted_at*|When the directory received the listing, rounded down to the hour. null before that.
date-timelive_at*|When the listing went live, rounded down to the hour. null unless it is or was live.
date-timeTypical errors
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"}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.
application/json- body
Your test launch balance.
available*integerTest launches to make available, 0 to 1,000.
0 <= value <= 1000Your test account with the new balance.
application/json- response
Your launches, the listings in progress and your request budget, in the key's mode.
object*stringAlways account.
livemode*booleantrue in live mode, false in test mode.
name*stringYour agency's name.
state*stringsetup before your first purchase, active after it, suspended when the account can read but not write.
"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.
Typical errors
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" }}