Skip to content

Idempotency ​

Send an Idempotency-Key with a POST, PATCH or DELETE, and a quick retry of the same request returns the original response instead of doing the work twice.

How to use it when retrying: Handle errors and retries.

The header ​

http
Idempotency-Key: "d7c59ab2-3f12-4ad8-9b03-2a7b4f9c7e10"
  • Use a fresh UUID per logical operation, and keep it for that operation's retries.
  • Per RFC 9651 the value is quoted. An empty value returns 400.
  • GET requests ignore the header — they are safe to repeat anyway.

Behavior ​

SituationWhat happens
Same key, same request, original finished less than 30 seconds agoThe original response is replayed; nothing is executed again
Same key, same request, original still in progress429 with retry-after: 2 — retry after two seconds
Same key, same request, more than 30 seconds laterExecuted again, as a new request
Same key, different body, path or methodTreated as a different request and executed

"Same request" means the same method, URL and body, from the same merchant. The signing headers are not part of it, so a retry can be re-signed with a fresh zay-timestamp.

Successful responses and 4xx errors are replayed. 429 and 5xx responses are not, so a retry after a server error runs the request again.

The replay window is 30 seconds. It protects you from a retry right after a timeout — not from reporting the same payout again minutes later. Before retrying a payout after a longer gap, check whether it was created; see Report a payout.

Responses ​

The two idempotency errors use their own body, not the problem-details shape:

json
{
  "ok": false,
  "error": {
    "message": "Another request with this idempotency key is still in progress, please try again later"
  }
}
json
{
  "ok": false,
  "error": {
    "message": "The Idempotency-Key header provided was empty or malformed"
  }
}

Submit events also deduplicates each event by its own event_id, for 24 hours.