POST /v1/payouts is idempotent. Retry the same logical request as many
times as you need — the API will return the original payout instead of
creating a new one.
How keys are picked
Two sources, in order:Idempotency-Keyheader, if you send one. Any opaque string is fine — a ULID, a UUID, or a deterministic key derived from your payroll run (e.g.payroll-co-2026-05-emp-001).external_idfrom the body, if no header is provided. Every payout already requires a uniqueexternal_id, so this gives you idempotency “for free” without managing a separate key.
external_id without colliding — and rotating your
own key does not turn a retry into a second payout. Your client identity is
stable across key rotation; see Authentication.
Replay semantics
Note the status code: idempotent replays return
200, not 201. This
lets your client tell “I just created this” from “I called this same request
again”.Recommended pattern
Derive an idempotency key from the payroll run that produced thenet_salary you’re paying out. A good key is deterministic (so retries
match) and unique per logical payout (so unrelated requests don’t
collide).
What counts as “identical body”?
The whole JSON request body. If you change any field — amount, beneficiary details, metadata — and reuse the sameIdempotency-Key, you get
409 IDEMPOTENCY_KEY_REUSED. That is intentional: it surfaces caller bugs
(e.g. you re-derived the amount but kept the key) instead of silently paying
out something different from the original intent.
Idempotency-Key vs. external_id
If you only ever set
external_id (and skip the header), you still get full
idempotency. The header exists for cases where you want to retry the same
logical create with a fresh external_id — uncommon, but supported.