Idempotency
Creating a resource is the one kind of request you never want to run twice by
accident. A dropped connection or a timed-out retry could otherwise leave you
with two identical audiences, or a second activation delivering to a partner.
The optional Idempotency-Key header makes a create safe to retry: the
platform recognises the repeat and replays the original outcome instead of
doing the work again.
Which endpoints honor it
Eight endpoints - the resource creates and Estimate Audience Size - read the
Idempotency-Key header:
| Endpoint | Route |
|---|---|
| Create Audience | POST /api/v2/analyses/audiences/create |
| Estimate Audience Size | POST /api/v2/analyses/audiences/estimate |
| Create Lookalike Audience | POST /api/v2/analyses/audiences/create-lookalike |
| Create Cohort | POST /api/v2/analyses/cohorts/create |
| Create Activation | POST /api/v2/analyses/activations/create |
| Create Project | POST /api/v2/analyses/projects/create |
| Create Schedule | POST /api/v2/analyses/schedules/create |
| Create Submission by Upload | POST /api/v2/my-data/pois/submissions/create-by-upload |
The header is ignored everywhere else. Cancel Lookalike, the schedule activate/deactivate writes, and the delete endpoints do not participate - sending the header does not make a cancel, a status toggle or a delete idempotent.
How a key behaves
The key is optional and caller-generated: you supply any unique string
(a UUID v4 is typical) in the Idempotency-Key header. Omit it and the create
runs normally, with no replay protection.
When you do send a key:
- First request - runs normally. If it succeeds (a
2xxresponse), that response is stored against the key. - Same key, same body, within the TTL - the stored response is replayed
verbatim, carrying an extra
Idempotency-Replayed: trueheader. No second resource is created. - Same key, different body - rejected with
409 Conflict. A key is a promise that the request is the same one; changing the body breaks that promise. - Same key while the first request is still in flight - a concurrent
duplicate also returns
409 Conflictrather than starting a second run.
The stored response lives for 24 hours. After that TTL expires, the same key is free to start a fresh create.
Only successful responses are cached
Only 2xx responses are stored. If the first attempt fails with a 429 (rate
limited) or a 5xx, nothing is cached, so a retry with the same key genuinely
re-executes the create - which is exactly what you want, because the
resource was never made. Retry those safely.
Replay is scoped to you
A stored response is scoped to the token, the company, and the exact route that produced it. Keys never collide across different tokens, different companies, or different endpoints: the same string used by two callers, or on two different create routes, is two independent keys. You will only ever replay a response your own token created on that same route.
Using it well
- Generate a fresh key per logical operation - one UUID for “create this audience”, a different one for the next audience.
- Reuse that same key on every retry of that one operation - on a timeout, a
dropped connection, or a
429/5xx, resend with the key you already generated. You either get the original result back (if the first attempt actually succeeded) or a clean re-execution (if it did not). - Do not reuse a key for a genuinely new create - a new operation carrying an
old key either replays the old result or, if the body differs, returns
409.
idempotency_key argument that maps to this exact header, with identical
semantics - pass a fresh value per logical create and reuse it on retries. See
Automate with an AI Agent.Related
- The Async Model - create returns fast, then you poll.
- Errors - the error envelope, including
409and429. - Polling and Rate Limits - retrying on a
429withRetry-After, and idempotent retries in practice.