Idempotency and safe retries
Networks fail. A request may reach us while its answer never reaches you. Idempotency makes the retry safe: the same request again answers the result of the first, and does nothing twice.
The key
Section titled “The key”Send Idempotency-Key — 1 to 200 characters, a UUID is fine — on every command that creates or changes
money:
| Command | Key | Second key |
|---|---|---|
POST /v1/payments |
required | merchant_order_id |
POST /v1/payments/{id}/cancel |
required | — |
POST /v1/payments/{id}/amount-correction |
required | — |
POST /v1/payments/{id}/refunds |
required | — |
POST /v1/payouts |
required | merchant_payout_id |
POST /v1/payouts/{id}/cancel |
required | — |
Reads and the webhook settings take none.
- Same key, same body → the first answer again: the same object,
Idempotent-Replayed: trueon payments and payouts. - Same key, another body →
409 idempotency_conflict. Use a new key for a new request. - Same
merchant_order_idormerchant_payout_idunder a new key, same body → the object made first, as a repeat. With another body →409 idempotency_conflict. A double click that sends two keys still makes one payment.
Retrying
Section titled “Retrying”| You got | Do |
|---|---|
| A timeout or a dropped connection | Retry with the same key and body. |
503 payment_unavailable, payout_unavailable |
The outcome is unknown. Retry with the same key, or read the object. |
409 payment_busy |
Wait Retry-After (1 s) and retry with the same key. |
429 rate_limited |
Wait Retry-After (1 s) and retry with the same key. |
400, 404, 409 idempotency_conflict, 422 |
Do not retry: fix the request. |
Every retry is a new signature: a new nonce and timestamp, the same Idempotency-Key. Back off — 1, 2, 4,
8 seconds — and stop after a few attempts; then reconcile by reading.
Generate the key when you decide to make the request — when the order is placed — and store it with the order, so a retry after your own process restarts reuses it.