Skip to main content
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