Orivanta PayDocs

Idempotency

Retry a charge safely without double-charging a customer.

A network timeout doesn't tell you whether the request landed — only that you didn't hear back. If you retry blindly, you risk charging (or paying out) twice. idempotencyKey exists to make retrying safe.

One endpoint, not the whole API

idempotencyKey exists only on POST /api/v1/pay-in/charge. It is not a field on checkout, and transfers have no idempotency protection at all — see that page before you wire up payout retries.

How it works

Pass the same idempotencyKey on every retry of one logical charge attempt. The key is scoped to your application — the same key string used by a different application is a different key.

{
  "amount": 5000,
  "currency": "XAF",
  "paymentMethod": "MTN_MOMO_CM",
  "payerAccount": "670000000",
  "idempotencyKey": "order-4471-attempt-1"
}

If a charge with that key already exists for your application, the API returns the original response — same 201, same body, same reference — without contacting the payment provider again or creating a second transaction. A genuinely new attempt needs a new key; don't reuse one across unrelated charges.

What it doesn't protect against

The check is "does a charge with this key already exist?", evaluated once, before the new row is written. Two requests carrying the same key that arrive close enough together can both pass that check before either one commits — a real race, not a hypothetical one, if your own retry logic ever fires two attempts concurrently instead of sequentially.

When that happens, the database's own uniqueness constraint blocks the second write, but the API does not currently turn that into a clean 409 Conflict. It surfaces as:

{
  "success": false,
  "code": "INTERNAL_SERVER_ERROR",
  "message": "Une erreur inattendue est survenue",
  "data": null,
  "timestamp": "2026-09-05T10:00:00.000"
}

with HTTP 500. Treat a 500 immediately following a charge with a key you've used before as "probably already succeeded, go check its status" rather than "safe to retry again." Query GET /api/v1/pay-in/check_status/{reference} — you likely don't have the reference yet in this specific failure mode, so in practice this means: never fire two attempts with the same key concurrently in the first place. Retry sequentially, and wait for a response (or a clear timeout) before retrying at all.

On this page