Idempotency
Retry any write safely with the Idempotency-Key header.
Networks fail between your request and OmiCloud's response. Without protection, a retried POST /v1/payouts could pay an end user twice. The Idempotency-Key header makes retries safe.
How it works
Send any string up to 255 characters, unique per request, on POST /v1/sessions and POST /v1/payouts:
POST /v1/payouts
Idempotency-Key: 0d5b6c1e-3a9f-4a7e-9c0b-2e8f1d7a6b54- First request with a key: processed normally.
- Retry with the same key and the same body: OmiCloud returns the original response — same status code, same JSON — and adds
Idempotent-Replayed: true. No second transaction is created and the gateway is not called again. - Same key, different body:
409 IDEMPOTENCY_KEY_REUSED. Nothing is created.
Keys are scoped to your operator (another operator's keys cannot collide with yours) and remembered for 24 hours.
Which endpoints
| Endpoint | Idempotency-Key |
|---|---|
POST /v1/payouts | Required. A request without one is rejected with 400 VALIDATION_FAILED. |
POST /v1/sessions | Recommended. Without it, a retry opens a second checkout for the same intent. |
POST /v1/quotes | Ignored — quotes have no side effects. |
| Webhook endpoint writes | Ignored — these are naturally idempotent by url. |
Choosing a key
Use something that identifies the intent, not the attempt:
- Good: your own withdrawal id (
wd-20260902-4413), a UUID generated once when the end user pressed the button and stored with the request. - Bad: a fresh UUID per HTTP attempt (defeats the purpose), a timestamp, the end user id on its own.
operatorReference and Idempotency-Key can be the same value — many integrations do exactly that.
Retrying correctly
attempt = 0
loop:
response = POST /v1/payouts with Idempotency-Key = wd_id
if response is 2xx or 4xx: stop # 4xx will not change on retry
if response is 502 GATEWAY_ERROR: stop # transaction exists and is declined; create a NEW request
if network error or 5xx INTERNAL or 429: backoff, attempt += 1, retry (max 5)
Two details matter:
- A
502 GATEWAY_ERRORis a result. The transaction was created and declined; the response carries itsreference. Retrying with the same key replays that decline. To try again, send a new request with a new key. - If you got no response at all, you cannot know whether the transaction was created. Retry with the same key — that is the whole point. You will get either the original success or the original failure.
What a replay looks like
HTTP/1.1 201 Created
Idempotent-Replayed: true
Content-Type: application/json
{"transaction":"txn_2b7d9e4f11a0","state":"processing","gateway":"dce","gatewayReference":"wd_7f1c2a"}Note state is whatever it was at the time of the original response. The transaction may have moved on since — fetch it if you need the current state.
Updated about 2 months ago