Idempotency
Retry a create without doing the work twice by sending an Idempotency-Key.
Networks fail after the server has done the work. Without a way to say "this is the same
request again", a retry after a timeout uploads a second set of ads or saves a second
Test. The creates a retry could duplicate take an Idempotency-Key header:
curl https://winandscale.com/api/v1/launches \
-H "Authorization: Bearer rsk_your_key" \
-H "Idempotency-Key: launch/2026-spring-0042" \
-H "Content-Type: application/json" \
-d '{ "preset_id": "…", "creatives": [ … ] }'The rules
| You send | You get |
|---|---|
| A new key | The request runs normally. |
| The same key and the same body, after the first succeeded | The first response again, with Idempotency-Replay: true. Nothing runs twice. |
| The same key and a different body | 400 invalid_request. A changed request needs a new key. |
| The same key while the first request is still running | 409 conflict. Retry once it has finished. |
| The same key after the first request failed | The request runs again. Only successes are kept. |
- A key is up to 256 characters. A longer one is rejected, not truncated.
- Keys are scoped to the workspace and the operation, so the same key on two different endpoints is two different requests.
- A claim left behind by a request that never finished is ignored after ten minutes.
- Build keys from the thing you are creating, such as
launch/2026-spring-0042, not a random value per attempt. A random value per attempt protects nothing. - A key is optional. Without one the request runs unprotected.
Which operations take it
| Operation | Endpoint |
|---|---|
| Launch ads paused | POST /api/v1/launches |
| Save a report view | POST /api/v1/report-views |
| Create a lead form | POST /api/v1/lead-forms |
| Create a launch preset | POST /api/v1/launch-presets |
| Create a Value | POST /api/v1/taxonomy/values |
| Save a brief to the board | POST /api/v1/briefs/board |
| Commit a Test | POST /api/v1/tests |
| Append an Observation | POST /api/v1/tests/{testId}/observations |
| Save a learning | POST /api/v1/learnings |
| Save a swipe | POST /api/v1/swipes |
| Add a research source | POST /api/v1/research/sources |
| Add a copy line | POST /api/v1/research/messaging |
Other operations take no key.
Launches
A retry of a launch without a key reuses an ad set that the failed attempt already made, but it can still upload the creatives twice. Send the key. A failed or refused launch releases its key, so you can fix the cause and retry with the same one.
After a 500, a 502 or a timeout, retry with the same key. Retrying without one
risks doing the work twice.