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 sendYou get
A new keyThe request runs normally.
The same key and the same body, after the first succeededThe first response again, with Idempotency-Replay: true. Nothing runs twice.
The same key and a different body400 invalid_request. A changed request needs a new key.
The same key while the first request is still running409 conflict. Retry once it has finished.
The same key after the first request failedThe 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

OperationEndpoint
Launch ads pausedPOST /api/v1/launches
Save a report viewPOST /api/v1/report-views
Create a lead formPOST /api/v1/lead-forms
Create a launch presetPOST /api/v1/launch-presets
Create a ValuePOST /api/v1/taxonomy/values
Save a brief to the boardPOST /api/v1/briefs/board
Commit a TestPOST /api/v1/tests
Append an ObservationPOST /api/v1/tests/{testId}/observations
Save a learningPOST /api/v1/learnings
Save a swipePOST /api/v1/swipes
Add a research sourcePOST /api/v1/research/sources
Add a copy linePOST /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.

On this page