Skip to content

Idempotency

Every call that moves money carries a key you choose:

X-Idempotency-Key: order-2026-09-03-00417

Required on POST /payments and POST /payouts. 8 to 128 characters.

You sendMoria does
Same key, same bodyReplays the stored result. No second payment, no second transfer.
Same key, different bodyRefuses with 409. The key is already spoken for.
New keyA new operation, every time.

So: one fresh key per distinct thing you want to happen. When retrying, keep the same financial intent and send the same request body. The signature must cover the exact bytes sent on each attempt.

Derive it from something in your own system that is already unique — an order id, an invoice number — rather than a random value you would have to store to reuse.

What to do instead:

  1. Retry with the same key. A completed request returns its prior result. If the outcome is still uncertain, you may receive PROVIDER_INDETERMINATE again; do not switch keys.
  2. If you have the transaction ID, poll GET /payments/{id} or GET /payouts/{id}. If a payment response was lost before you received its ID, search GET /payments?external_ref=... using the unique external_ref you supplied. An uncertain payment may have no payment_code yet; do not present it as payable.
  3. Wait for a terminal state to treat money as final. A payment also needs a non-null payment_code before you can give the customer payment instructions. Contact Moria support with your key, reference and request_id if you cannot identify or use the pending order. Never create a second operation to resolve uncertainty.

Moria records the key before dispatch and writes the response against it when the work completes. If the payment was committed but the response never reached you, a retry can rebuild the answer from the order once its payment instrument is known. An uncertain provider outcome remains unresolved until Moria can establish what happened.

It also means a 409 is informative rather than annoying. It says the key you sent is already attached to a different request — usually a bug where a key is being reused across orders, which is exactly the bug you want reported loudly rather than silently honoured.

Two things that look related and are not:

  • A retried webhook. That is at-least-once delivery, deduplicated on the event id, and it is a different mechanism — see Webhooks.
  • A duplicate customer payment. If a customer genuinely pays a virtual account twice, that is two payments and you will hear about both. Idempotency governs your instructions to us, not your customer’s behaviour.