Partner API, v1
Send us products by API
Send us a product's website and its founder's email. We read the website ourselves, and a product that meets our bar launches on LaunchScaler within your agreed lead time, on a public page and on that day's launch board. Follow each submission by reading it or through signed webhooks.
Keys
Once we approve your application you get two keys. The test key answers with scripted results: nothing is read, listed or emailed, and it works before your account is switched on. The live key submits real products.
Send the key on every call as Authorization: Bearer <your key>. Use HTTPS only. If we agreed fixed server addresses with you, calls from any other address are refused.
Create a submission
POST https://www.launchscaler.com/api/partners/v1/submissions
Authorization: Bearer <your key>
Idempotency-Key: <optional, up to 128 characters>
Content-Type: application/json
{
"url": "https://www.example.com",
"contact_email": "founder@example.com",
"partner_ref": "prj_4QzX1m9L"
}urlis the product's public website. We read its name, copy, logo and pricing ourselves.contact_emailis the founder's address. We use it for one email, on launch day, inviting them to claim the listing, and to recognise them when they sign in to claim it. We never show it publicly or return it to you.partner_refis your own id for the project: letters, digits and_ . : -, up to 128 characters.
{ "id": "sub_8fK2qLx9Vb3Nm7Tz4wQa", "status": "in_progress", "badge_html": "<a href=…>…</a>" }badge_html is our badge for this product, ready to place in the founder's footer. It lets the founder claim the listing in one click. Where your agreement with us requires our badge, a free listing goes live only once it's on the site.
Sending the same Idempotency-Key, or the same partner_ref while its submission is still active, returns the first answer with 200 and creates nothing new. After a refusal, the same partner_ref can be sent again and gets a fresh read of the website.
Read a submission
GET https://www.launchscaler.com/api/partners/v1/submissions/{id}
Authorization: Bearer <your key>{ "id": "sub_…", "status": "in_progress" }
{ "id": "sub_…", "status": "submitted", "launch_date": "2026-12-01" }
{ "id": "sub_…", "status": "live", "launch_date": "2026-12-01", "live_url": "https://www.launchscaler.com/products/example.com" }
{ "id": "sub_…", "status": "not_accepted", "reason": "below_bar" }| Status | What it means |
|---|---|
| in_progress | We have it and are reading the website. |
| submitted | It passed, and launch_date is its launch day. |
| live | It's public at live_url. |
| not_accepted | It won't be listed from this submission. reason says why. |
| Reason | What it means |
|---|---|
| below_bar | The website didn't meet our bar. The founder can improve it and you can submit again. |
| unreachable | We couldn't read the website. |
| not_allowed | We don't list this website. |
| withdrawn | The launch was taken down before its day. |
| badge_missing | Only for partners whose products must carry our badge: it wasn't found in time. |
Most products move from in_progress to submitted within an hour. A launch day can move if the founder claims the listing and picks another day; the next read, or the next webhook, shows the new date.
Webhooks
If you give us an HTTPS address, we POST the same body a read returns whenever it changes, with three headers:
| Header | What it carries |
|---|---|
| LS-Event-Id | The same on every retry of one delivery, so you can drop duplicates. |
| LS-Timestamp | Seconds since the epoch. |
| LS-Signature | v1= followed by the hex HMAC-SHA256 of "<LS-Timestamp>.<body>", keyed with the signing secret we give you. |
Check the signature against the raw body, and reject a timestamp more than five minutes old. Answer with any 2xx. We don't follow redirects. A failed delivery is retried for three days with growing gaps, and you can always read the current state with a GET.
Errors
{ "error": { "code": "…", "message": "…" } }| Code | HTTP | What to do |
|---|---|---|
| invalid_request | 400 | Send JSON with url, contact_email and partner_ref. |
| invalid_key | 401 | Check the key. |
| forbidden | 403 | Call from one of your agreed server addresses. |
| paused | 403 | Submissions are paused for this key. |
| https_required | 403 | Use HTTPS. |
| not_found | 404 | No submission of yours has this id. |
| payload_too_large | 413 | Keep the body under 8 KB. |
| unsupported_media_type | 415 | Send Content-Type: application/json. |
| invalid_url | 422 | Send a public HTTPS website. |
| not_allowed | 422 | We don't list this website. |
| rate_limited | 429 | Wait a minute (Retry-After). The limit is 120 calls a minute per key. |
| daily_cap_reached | 429 | Your daily limit is used. It resets at 00:00 UTC (Retry-After). |
| unavailable | 503 | Retry later. |
Testing with the test key
Test submissions move on their own: to submitted, with a launch day three days out, on our first run at least a minute after you send one, then to live on a run at least two minutes after that. We run every five minutes, so expect each step within about five minutes.
A test URL is never fetched, so it doesn't need to exist. To get a refusal, start the website's first label with fail. (below_bar), unreachable. or not-allowed., for example https://fail.example.com. Webhooks are sent for test submissions too, signed the same way. The live_url of a test submission is not a real page, and its badge does not draw.
Ready to send products?
Apply, and we'll set you up with a test key first.