Idempotency and retries
Send a Kustom-Idempotency-Key on every Order Management write so a retried capture or refund runs once, and retry a 5xx on a schedule or escalate it.
When a backend call to Kustom fails, the dangerous case is not the one that clearly failed — it is the one whose outcome you cannot know. The connection may have broken after Kustom committed a capture but before the response reached you. An idempotency key removes the ambiguity by making a repeat of the same request a no-op, which is what turns “retry” from a gamble into a policy. This page covers the Order Management API, where the money moves.
Why an uncertain outcome is the real problem
Section titled “Why an uncertain outcome is the real problem”A call can fail three ways, and only one of them is safe to blindly repeat:
| Failure | State of the order in Kustom |
|---|---|
| The connection never opened | Unchanged. Safe to retry. |
| The call failed midway through the operation | Unknown. |
| The call succeeded, then the connection broke before the reply | Already changed. A blind retry duplicates it. |
Two captures of €10 sent without idempotency keys, or with different ones, are two captures: €20 captured. The same two requests sharing one key are one capture of €10, and both requests get the same response.
Sending a Kustom-Idempotency-Key
Section titled “Sending a Kustom-Idempotency-Key”Send an idempotency key as an HTTP header on every Order Management POST and PATCH. Kustom honors it for 24 hours from the first attempt. After that the same key is treated as a new request.
The key exists on the Order Management API only. Checkout calls, including
POST /checkout/v3/orders, take none, so an ambiguous 5xx on one of them is not safe to
retry blindly: read the order back first.
POST /ordermanagement/v1/orders/{order_id}/capturesKustom-Idempotency-Key: c6010e41-5eb0-46a9-8cc0-decb265419b1Content-Type: application/jsonThe API reference lists Klarna-Idempotency-Key. The Order Management API reference still names this header
Klarna-Idempotency-Key, from the platform’s Klarna origins. Both names work on every Order
Management call and mean the same thing: a key sent under one name matches the same key sent
under the other, so an integration already sending Klarna-Idempotency-Key keeps working.
Send one of them, not both. If a request carries both with different values,
Klarna-Idempotency-Key is the one Kustom uses.
Generate one UUID per logical operation, not per attempt: the retry has to carry the key the original attempt used, or it is not a retry as far as Kustom is concerned. Derive it from something stable in your own system — the capture row’s primary key, say — so that a process restart mid-retry still produces the same key.
Retrying a 5xx
Section titled “Retrying a 5xx”When a 5xx comes back, retry on this schedule, keeping the same idempotency key each time:
| Attempt | Wait before it |
|---|---|
| 1st retry | 5 seconds |
| 2nd retry | 5 minutes |
| 3rd retry | 5 hours |
After the third retry fails, stop and escalate. The widening intervals are deliberate: a 5 second retry catches a blip, a 5 hour retry catches an incident and nothing in between is worth burning quota on.
GET calls change nothing and can always be retried on this schedule. POST and PATCH
calls can use it only if the original request carried an idempotency key. If it did not,
the retry is not safe — a second capture or refund may be created — so escalate immediately
instead.
Escalating a 3xx or 4xx
Section titled “Escalating a 3xx or 4xx”A 3xx or 4xx will not fix itself, so it does not get retried. Route it to a technical
support team inside your own organization, which can inspect the request, correct it and
then re-send it if appropriate. Some cases will need Kustom Merchant Support to resolve.
Escalation is also where customer communication lives. Kustom sends no message to the customer when one of your API calls fails. If a failed capture or refund means the customer needs to be told something, you tell them.
Before escalating, read the order back. After an uncertain outcome the order body is the only authority on what actually happened — see Update or cancel an order.
Related
Section titled “Related”- Deciding whether a failure is retryable — the error object and its status classes
- Backing off after a 429 — the rate limit headers that pace a retry loop
- Capture an order — the call this policy most often protects
- Reading an order back after an unknown outcome — confirming what a retry actually did
This page is also available as Markdown — append .md to its URL — and is indexed in llms.txt.