Idempotency
Networks fail: a request can succeed on our side while your client times out. To retry a POST safely, send an Idempotency-Key header. A retry with the same key does not act twice.
POST /api/v2/parties
Idempotency-Key: 4f1c2e8a-7d3b-4c55-9a0e-1b2c3d4e5f60
Rules
- Where: any v2
POST.GET,PATCHandDELETEignore the header. - The key: an opaque string of 1 to 255 characters that you generate, one per logical operation (a UUID is a good choice). It is compared byte for byte: case and internal spaces count; avoid leading or trailing spaces. Keys are per API key: two of your keys never share them.
- How long: a key is remembered for 24 hours after its request completes.
- What is remembered: only successful (
2xx) requests. A refused request (4xx, 5xx) is not remembered, so a retry is simply evaluated again. - Same request: the parameters you sent, plus the SHA-256 of each uploaded file. The raw body is not compared, so a retried multipart upload (with a new boundary) still matches.
What a retry gets
| Situation | Response |
|---|---|
| Same key, same request, first one finished | The resource the first request created or acted on, rendered as it is now (not a copy of the first response), with the header Idempotency-Replayed: true. An action that is not naturally repeatable, such as resend, is not performed again |
| Same key, different request | 422 idempotency_key_reused |
| Same key while the first request is still running | 409 idempotency_in_progress. Wait and retry: this protects you when your client gave up before we finished |
| Same key, but what the first request created no longer exists | 409 idempotency_not_replayable ("the resource this key created no longer exists"), for example a record a dashboard user deleted since, or a certificate that was since converted into a tax form |
| Same key on an endpoint whose first response held a one-time value | 409 idempotency_not_replayable ("the original response contained a one-time value; create a new one"). These are POST /webhook_subscriptions, POST /webhook_subscriptions/:id/rotate_secret and POST /direct_uploads |
Because a replay re-renders the resource under the current rules, it never repeats a one-time secret, and a field that needs a grant appears only if your key and account may see it at the time of the replay. A replay returns the earlier result even if a feature it needed has since been switched off; it never performs the action again.
A signing request your earlier call superseded or invalidated still exists, so its replay renders it as no_longer_needed.
Good to know
- Replays count against your rate limit like any request (Rate limits).
- In the rare event our idempotency store is unavailable, the request is processed without replay protection rather than refused. A retry during such an incident may be told the first request is still running (409
idempotency_in_progress), and may run again later. - See Errors for the error shape.