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

EndpointIdempotency-Key
POST /v1/payoutsRequired. A request without one is rejected with 400 VALIDATION_FAILED.
POST /v1/sessionsRecommended. Without it, a retry opens a second checkout for the same intent.
POST /v1/quotesIgnored — quotes have no side effects.
Webhook endpoint writesIgnored — 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:

  1. A 502 GATEWAY_ERROR is a result. The transaction was created and declined; the response carries its reference. Retrying with the same key replays that decline. To try again, send a new request with a new key.
  2. 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.


Did this page help you?