Skip to main content
On this page

Use an idempotency key when a network failure or client timeout leaves the result of a state-changing request uncertain. DEUNA associates the key with the operation and request body, then replays the stored response instead of processing the same operation again.

Retry flow#

01 · merchant
Persist one key
Generate a UUID v4 and store it with the business operation before sending the request.
02 · DEUNA
Process or replay
DEUNA processes the first request, or replays its stored result when the same key and body arrive again.
03 · merchant
Reconcile the result
Use the response and current order state to decide whether the operation finished or can be retried safely.

The merchant owns key generation, persistence, and retry timing. DEUNA owns the association between the key, operation, request body, and stored response within the documented retention window.

Supported operations#

Send X-Idempotency-Key with these public operations:

OperationMethod and pathReference
Create an order · Optional flowPOST /merchants/ordersCreate an order
Create a payment · Purchase V2POST /v2/merchants/orders/purchaseCreate a payment
Capture an authorized paymentPOST /v2/merchants/orders/{order_token}/captureCapture a payment
Void an authorizationPOST /merchants/orders/{order_token}/voidVoid an authorization
Refund a paymentPOST /v2/merchants/orders/{order_token}/refundRefund a payment

Do not assume that every POST endpoint supports idempotency. Use the operation list above or check whether the endpoint reference includes the X-Idempotency-Key header.

Generate and persist the key#

Generate one UUID v4 in your merchant backend for each distinct business operation. Store it with your own operation record before calling DEUNA.

Generate a key in Node.jsJavaScript
const idempotencyKey = crypto.randomUUID();

Follow these rules:

  • Reuse the same key only when retrying the same operation.
  • Send the exact same request body on every retry. DEUNA compares the body hash, so even a semantically equivalent body serialized differently can be rejected.
  • Generate a new key for a new payment, capture, void, refund, or order-creation attempt.
  • Generate a new key when you correct request data after a validation or business error.
  • Do not derive keys from a short sequence that can collide across systems or environments.

The key is scoped to the merchant and operation, but your integration should still treat it as globally unique and never deliberately reuse it for another action.

Send the request#

Add the key to the original request and every retry of that request. This Purchase V2 example uses an order token that the integration already created:

curl --request POST \
  --url https://api.sandbox.deuna.io/v2/merchants/orders/purchase \
  --header "X-Api-Key: YOUR_PRIVATE_API_KEY" \
  --header "X-Idempotency-Key: 9f510c4a-0f7d-4c31-94c5-590b85e4d231" \
  --header "Content-Type: application/json" \
  --data '{
    "order_token": "ORDER_TOKEN",
    "payer_info": {
      "email": "buyer@example.com",
      "external_user_id": "customer_1042"
    },
    "payment_source": {
      "method_type": "credit_card",
      "payment_method": "PAYMENT_METHOD_TOKEN"
    }
  }'

If the response has X-Idempotency-Replay: true, DEUNA returned the stored result for an earlier request with the same key and body. Handle its status code and payload exactly as you would the original response.

Understand the retention window#

The key-to-body association begins when DEUNA first receives the key. The response replay window begins when DEUNA stores the completed result, and its behavior depends on that result:

Original resultReplay behavior
Successful responseDEUNA stores the response for 24 hours by default after the operation completes. A retry with the same key and body during that window returns the stored status code, headers, and payload.
4xx or 5xx responseDEUNA stores the error response for approximately 2 seconds to absorb immediate duplicates. The association between the key and the original request body remains for the full 24-hour window.
Request still in progressA concurrent request waits briefly for the first result. If the first request is still running, DEUNA can return HTTP 409 with IS-4409.

After the successful-response retention window expires, the same key can be treated as a new operation. Never depend on that behavior: create a new key for every new business attempt, even when an older key has expired.

For an error response, do not reuse the key with corrected request data. Because the original body association remains active, the changed body returns IS-4401 until the retention window ends. Correct the request and send it as a new operation with a new key.

Handle retries and conflicts#

SituationWhat DEUNA returnsWhat your integration should do
Same key and same body after a completed successful requestThe stored response with X-Idempotency-Replay: trueAccept the response, then reconcile the current order state when it is not final.
Same key with a different bodyHTTP 400, code IS-4401Do not retry that combination. Use a new key only when the changed body represents a corrected or new operation.
Duplicate arrives while the first request is still runningHTTP 409, code IS-4409, when the in-flight wait endsBack off, then retry the exact request with the same key. Reconcile the original order before starting a new attempt.
Rate limit is exceededHTTP 429, which can include code IS-4429Honor Retry-After when present, then retry the same body and key.
Client timeout or connection lossThe client may receive no response although processing continuesPreserve the key and body, reconcile the order, and retry only according to the documented timeout procedure.
Non-retryable validation or business errorA 4xx responseFix the request and use a new key. Do not retry a changed body under the old key.

Use bounded exponential backoff with jitter. Do not send several concurrent retries for the same business operation.

See API errors for the response-code model and client timeouts for the reconciliation procedure.

Verify the behavior in sandbox#

  1. Send a valid supported request to https://api.sandbox.deuna.io with a new UUID v4 key.
  2. Save its status code, response headers, and payload.
  3. Send the exact request again with the same key and body.
  4. Verify that the second response has the same result and includes X-Idempotency-Replay: true.
  5. During a separate negative test, change the body but keep the key and verify that DEUNA returns HTTP 400 with IS-4401.

Do not reuse either test key for another sandbox operation.

Continue the integration#