OuiPay
Transactions

Idempotency

Safe retries for money-moving requests : keys, replay, and what "safe" means.

Every financial mutation requires an Idempotency-Key header. It is what makes retries safe: losing a response, a timeout, or a client retry can never create a duplicate transaction.

The contract

curl https://api.ouipay.com/v1/payments \
  -H "Authorization: Bearer sk_test_..." \
  -H "Idempotency-Key: pay-2026-0001" \
  -H "Content-Type: application/json" \
  -d '{ "customer_id": "01M2S17...", "amount_minor": 50000, "currency": "NGN", "method": "card" }'
  • Required on all money-moving POSTs: payments, transfers, exchanges, refunds, funding
  • Replay-safe: re-sending the same key returns the original response (same transaction id), not a new operation
  • Scoped: per endpoint; the same key on /payments and /transfers are independent operations

How replay works

Request arrives → key checked → if seen, return the stored response
                             → if new, process and store the result under the key

The dedupe is a database uniqueness constraint, not an in-memory check: it survives restarts and races. Two concurrent requests with the same key: one wins, the other gets the winner's response.

Generating keys

Use a unique, deterministic value per logical operation:

  • order-42-attempt-1: your system's id for the operation
  • A UUID generated at submit time and stored with the user's intent

Do not reuse keys across different operations, and do not use a per-request random value on a retry: a retry must reuse the original key.

What replay returns

The stored response: including its original status. If the first attempt failed, the replay returns that same failure (it does not re-run the operation). To retry a failed business operation, submit a new request with a new key.

The unknown case

A transaction in unknown must not be blindly retried: the provider may have processed it. The idempotency key alone cannot rescue a retry if the first attempt reached the provider. Wait for the webhook or query status; only re-submit (new key) once the original is failed or completed.

Key reuse is not retry safety

Reusing a key returns the first result: it does not retry the operation. Retrying means: same key for transport safety, new key only after the original is definitively done.

Retention window

Keys are honored for 24 hours. After that a key is treated as new: do not rely on replay beyond the window for recovery.

On this page