Idempotency
Every call that moves money carries a key you choose:
X-Idempotency-Key: order-2026-09-03-00417Required on POST /payments and POST /payouts. 8 to 128 characters.
The rule
Section titled “The rule”| You send | Moria does |
|---|---|
| Same key, same body | Replays the stored result. No second payment, no second transfer. |
| Same key, different body | Refuses with 409. The key is already spoken for. |
| New key | A new operation, every time. |
So: one fresh key per distinct thing you want to happen, reused only when repeating a request that is identical in every byte.
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.
The retry that charges twice
Section titled “The retry that charges twice”What to do instead:
- Retry with the same key. If the first attempt landed, you get the stored result. If it never landed, it runs now.
- If you would rather ask than retry, poll
GET /payments/{id}orGET /payouts/{id}. - Either way, wait for a terminal state.
pendingmeans unfinished, not lost.
Why this exists on our side too
Section titled “Why this exists on our side too”Moria records the key before doing anything, and writes the response against it when the work completes. That covers the awkward case in the middle: the payment committed but the response never reached you. On your retry we rebuild the answer from the row rather than creating a second payment.
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.
Not idempotency
Section titled “Not idempotency”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.