Idempotency
Updated
Use an Idempotency-Key to replay the same decision while its stored answer is available.
Keep the key and body
Generate a fresh key for a new decision. Keep that key and the same JSON body for retries, using the same workspace and API key.
The API compares the canonical JSON body with the method and route. Changing the body while keeping the key returns 400 idempotency_key_reuse.
A request policy is part of that comparison, so a changed policy under the same key returns the same refusal.
The header is optional. Without it, repeating a call cannot retrieve an answer lost in transit.
Read a replay
Successful keys have a 24-hour answer window and retain an identity tombstone without request or answer content for 30 days after that window; after answer expiry, the same body returns 409 idempotency_replay_unavailable and a changed body returns 400 idempotency_key_reuse.
The same key and body can return the completed answer with X-: true. The replay has a new request trace and current rate-limit headers.
Replay availability is not guaranteed. If the settled answer cannot be read, the response uses X-: unavailable and 409 idempotency_.
If a stored answer cannot be read temporarily, the same key and body may replay it after the store recovers and before the answer expires or is evicted. Recovery is not guaranteed. This refusal has error.retryable: false; stop automatic retries. A new key starts new work and may produce a different answer.
Handle a replay refusal
| Code | What to do |
|---|---|
idempotency_conflict | The same work is still running. Wait for Retry-After, then retry with the same Idempotency-Key and body. |
idempotency_key_reuse | Use the original body with this Idempotency-Key, or a new key for changed work. |
idempotency_ | Inspect error.details.original_status. A new key starts new work rather than recovering the old answer. |
invalid_idempotency_key | Correct the blank or malformed key. |
idempotency_unavailable | Wait for Retry-After, then retry with the same Idempotency-Key. |
Changed parameters fail; running work waits. Stored replies replay; missing replies stop automatic retries.
Use error.retryable and x-should-retry to decide whether to retry. Follow the wait in the response; see Errors.