Payouts
Idempotency
Networks fail. Idempotency keys make it safe to retry any payout request without ever paying a recipient twice.
How it works#
Every request that creates a payout or a batch must carry an idempotency key — a unique string you choose, such as your order or commission ID. Send it as the Idempotency-Key header or the idempotency_key body field.
curl https://api.muny.io/v1/payouts \
-H "Authorization: Bearer $MUNY_API_KEY" \
-H "Idempotency-Key: order_8392" \
-H "Content-Type: application/json" \
-d '{ "recipient": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "amount": "500" }'Outcomes#
| Situation | Result |
|---|---|
| First request with a key | The payout is created normally. |
| Same key, same body | The original payout is returned. Nothing new is created or sent. |
| Same key, different body | 409 idempotency_error with code idempotency_key_reused. |
| Same key while the first request is still running | 409 idempotency_error with code idempotency_key_in_progress. Retry after a short delay. |
Retention#
- The stored response for a key is kept for 24 hours, so retries within that window get the exact original response.
- The guarantee itself is permanent: an organization can only ever have one payout per idempotency key, enforced by a unique constraint in the database. A retry days later still can't create a second payout.
- Keys are scoped to your organization and are up to 255 printable ASCII characters.
Choosing keys#
Derive the key from the thing you are paying for — commission_7731, invoice_2026_0142 — rather than a random value generated per attempt. Then even a crashed worker that restarts from scratch cannot double-pay.
// Safe to run as many times as you like
await muny.payouts.create(
{ recipient: affiliate.wallet, amount: commission.amount, reference: commission.id },
{ idempotencyKey: `commission_${commission.id}` },
);The SDK has your back
If you don't pass a key,@muny/sdk generates one per call and reuses it across its own automatic retries. For full protection across process restarts, pass your own.Beyond the request#
Idempotency continues after the API accepts a payout. Payout processing uses compare-and-set state transitions, so two workers can never send the same payout, and a payout is only re-sent after its previous transaction has provably expired without landing.