Every money-moving operation requires an idempotency key. The
complete table:
How to send it
Two equivalent ways (if you send both, the body wins):
Omitting it returns 400 idempotency_key_required.
What happens on retry
The key is unique per source account. If you repeat a call with the same
key:
- No new operation is created and no money moves again.
- You receive
200 OK (instead of 201/202) with the original object
plus idempotency_hit: true.
Which key do I retry with?
The full decision rule, so you never have to guess:
Recommendations
- Use an identifier from your system (order ID, payroll ID, etc.), not a
timestamp or a UUID regenerated on every retry.
- Persist the key before calling the API; that way you can retry after a
timeout with a no-duplication guarantee.
- On network errors or
5xx, retry with the same key. On validation
4xx, fix the request and use a new key.
The key comes back to you
The operation’s webhooks carry your key back as idempotency_key
(payout_status_changed, payin_credited, payin_settlement_scheduled,
payin_expired, payin_refunded, crypto_withdrawal_status_changed,
wallet_send_status_changed), and the payin resource returns it on
GET /v1/payins/{id} — reconcile notifications against your own reference
without an extra lookup. The field is omitted when the operation was
created without a key (or by the platform itself — internal keys are never
exposed). transfer_received does not carry it. See
Webhooks. Last modified on September 6, 2026