Idempotency and retries
The idempotency key
Section titled “The idempotency key”POST /v2/payins and POST /v2/payouts require the Idempotency-Key header
(8 to 128 characters). Sending the same request again with the same key
returns the same operation, in whatever state it is at that moment, and
asks nothing new of the bank or of your user. The same key with a different
body is 409 idempotency_key_reused.
Derive the key from your order identifier (order-4821), not from the
time or a random value: that way a retry from a brand-new process sends the
same key. If you use an SDK and don’t pass a key, the SDK generates one,
reuses it on every retry and returns it to you with the created
operation: store it next to your order.
What retries on its own, and what doesn’t
Section titled “What retries on its own, and what doesn’t”| Situation | What to do |
|---|---|
Network error before any response, 429, 5xx on a GET |
Retry with growing backoff. Nothing moved. |
The same on a POST with Idempotency-Key |
Retry with the same key. It is safe by definition. |
POST .../confirm, .../resend-code, .../cancel, /v2/webhook-endpoints |
Do not retry blindly. Look the operation up with GET and decide. |
503 temporarily_unavailable on .../cancel |
The payout is still pending. Look it up; the system resolves it on its own. |
4xx (validation, scope, not found) |
Fix the request. Retrying the same thing gives the same result. |
The SDKs apply exactly this table: three attempts by default, exponential backoff with jitter, and never a retry that could move money twice.
A pending result resolves itself
Section titled “A pending result resolves itself”If an operation stays pending with pending_reason: processing, the API
keeps asking the provider until the final answer and notifies you by webhook.
You don’t need to poll in a loop; if you do, GET /v2/transactions/{id} costs
you nothing and asks nothing of the bank.
