Limits and errors
📏 Limits
| Limit | Default |
|---|---|
| Minimum payout | $2.00 |
| Maximum payout | $500.00 |
| Exposure per account | $5,000.00 — see below |
| Payouts created per account | 30 per rolling hour |
Open payouts per customer_id | 3 (redirect delivery only) |
| Fee | $0.50 per payout, paid by you |
Read the live values from Get balance; yours may be set differently. Do not hardcode them.
Exposure is the principal of every payout still holding funds, plus the principal paid out in the last 24 hours. Paid payouts keep counting for a full day, so exposure does not drop back the moment a payout completes.
Open payouts per customer counts payouts for the same customer_id that are
awaiting_choice, processing or review_required. link payouts carry no
customer_id and are not counted.
The fee is reserved with the payout and charged only when it completes. A cancelled or expired payout returns both principal and fee.
⚠️ Errors
Every error has the same shape:
{
"error": "insufficient_funds",
"message": "This payout needs $25.50. Your available balance is $12.40.",
"detail": { "available": "12.40", "required": "25.50", "currency": "USD" }
}
detail is present only on some errors. Branch on error, not on the HTTP
status or the message — the message is for people and may change.
Request and authentication
| Code | HTTP | What to do |
|---|---|---|
invalid_body | 400 | Send a JSON object |
missing_idempotency_key | 400 | Send the Idempotency-Key header (≤191 chars) |
invalid_amount | 400 | Decimal string, max 2 dp |
invalid_merchant_reference | 400 | Supply one, ≤191 chars |
invalid_delivery | 400 | link or redirect |
unsupported_currency | 400 | USD only |
customer_email_required / invalid_customer_email | 400 | link delivery needs a valid customer_email |
customer_id_required / return_url_required | 400 | redirect delivery needs both |
invalid_return_url | 400 | An absolute https URL without credentials |
return_origin_not_configured | 400 | No return origin registered for your account yet — contact us |
return_origin_not_allowed | 400 | The return_url origin is not registered — scheme, host and port must match exactly |
destination_not_accepted | 400 | Remove it; the recipient chooses |
unauthorized | 401 | Credential missing, wrong or revoked |
insufficient_scope | 403 | Needs payouts:write |
wrong_credential_kind | 403 | This credential is not for this endpoint |
wrong_environment | 403 | A sandbox credential on production, or the reverse |
not_approved_by_platform | 403 | Your account is not approved for payouts — contact us |
payouts_not_enabled | 403 | Your administrator has not switched payouts on |
not_found | 404 | No such payout for this account |
Creating a payout
| Code | HTTP | What to do |
|---|---|---|
below_minimum / above_payout_limit | 400 | See Limits |
above_exposure_limit | 400 | Too much open or recently paid; see Limits |
attempt_unresolved | 409 | Outcome unknown — retry with the same key |
merchant_reference_conflict | 409 | That reference already has a payout with different details. detail.payout_id names it |
idempotency_key_conflict | 409 | Same key, different body |
insufficient_funds | 409 | Not enough available balance; detail shows how much |
balance_unavailable | 409 | Your balance cannot be calculated right now — contact us |
too_many_pending | 409 | This customer already has the maximum open payouts |
rate_limited | 429 | Too many payouts created in the last hour; slow down |
payouts_disabled | 503 | Temporarily unavailable; retry later |
Managing a payout
| Code | HTTP | Endpoint | What to do |
|---|---|---|---|
not_cancellable | 409 | Cancel | The recipient has already confirmed |
attempt_unresolved | 409 | Cancel | Our side was busy — retry |
wrong_delivery | 409 | Link, Session | Claim links are for link payouts, sessions for redirect payouts |
customer_mismatch | 403 | Session | customer_id differs from the one the payout was created with |
not_resumable | 409 | Session | The payout is no longer open |
link_unavailable | 409 | Link | The link cannot be shown again — rotate it to issue a new one |
attempt_unresolved— retry with the same key and the same body until you get a definite answer.payouts_disabled(503) — retry later; the same key is fine.- Any other error — the request cannot succeed as written. A rejected
create stays rejected for that
Idempotency-Key: retrying the same key returns the sameerror, even after the cause is gone (your balance topped up, the hourly limit reset). Fix the cause, then create the payout with a new key.