Errors
Every failure answers the same shape:
{ "error": { "code": "FUNDS_LIMIT_EXCEEDED", "message": "Payout would exceed the daily limit of 20000000.0000 (already 19800000.0000).", "details": { "field": "amount" } }, "request_id": "req_…"}Branch on code, never on message. The code is contractual; the message is written for a human reading a log and may be reworded or translated. details is present only when there is something specific to point at.
Quote request_id when you contact us. It is the fastest way for us to find the exact call.
The codes
Section titled “The codes”Authentication
Section titled “Authentication”| Code | Meaning |
|---|---|
AUTH_INVALID_API_KEY | The key is unknown, revoked, or malformed |
AUTH_SIGNATURE_REQUIRED | x-partner-signature was missing, or your account has no signing secret yet — see Authentication |
AUTH_INVALID_SIGNATURE | The signature did not match the body — see Authentication |
AUTH_PARTNER_INACTIVE | Your account is not active |
AUTH_PERMISSION_DENIED | The key is valid but lacks the permission for this endpoint |
None of these are worth retrying. Fix the request.
Request
Section titled “Request”| Code | Meaning |
|---|---|
REQUEST_INVALID_PAYLOAD | A field is missing, the wrong type, or unknown; a payment-instrument gross is fractional |
REQUEST_IDEMPOTENCY_KEY_REQUIRED | This endpoint moves money and needs X-Idempotency-Key |
REQUEST_IDEMPOTENCY_KEY_REUSED | The key is already attached to a different request |
REQUEST_IDEMPOTENCY_KEY_REUSED almost always means a bug where one key is being used across several orders. It is refused rather than honoured because honouring it would silently merge two payments.
For supported money-in instruments, the provider-facing gross must be a whole IDR amount. A fractional gross is rejected before the provider call with this code. The human-readable message is Payment amount must be a whole IDR amount for this payment method.
Resource and state
Section titled “Resource and state”| Code | Meaning |
|---|---|
RESOURCE_NOT_FOUND | No such id — or it is not yours. We do not distinguish |
RESOURCE_NOT_LINKED | The organization_id you named is not linked to your account, or its link was revoked |
STATE_CONFLICT | The transaction is not in a state where this makes sense |
| Code | Meaning |
|---|---|
FUNDS_INSUFFICIENT_BALANCE | Your available balance does not cover it |
FUNDS_LIMIT_EXCEEDED | A payout limit would be breached — see Payouts |
FUNDS_PAYOUT_SUSPENDED | Payouts are off for your account, or no limits are configured yet |
Provider and platform
Section titled “Provider and platform”| Code | Meaning | Retry? |
|---|---|---|
PROVIDER_UNAVAILABLE | The payment provider could not be reached | Yes, same key |
PROVIDER_INDETERMINATE | We asked, and cannot tell whether it worked | Poll — do not re-send |
RATE_LIMIT_EXCEEDED | Too many requests | Yes, after backing off |
INTERNAL_ERROR | Our fault | Yes, same key |
Rate limits
Section titled “Rate limits”1,000 requests per 15 minutes, counted per partner rather than per IP — a partner behind a pool of egress addresses is not throttled unevenly because of it.
Over the ceiling you get 429 with RATE_LIMIT_EXCEEDED, and a Retry-After header in seconds. Back off by that, not by a guess: it is the real time left in your window, and every HTTP client already knows the header, so you do not need to parse our error body to obey it.
Retrying a money-moving call after a 429 is safe, as long as you reuse the same X-Idempotency-Key — the request never reached the operation, but the rule is the rule.
What to do with each
Section titled “What to do with each”A rule of thumb that holds for all of them:
- 4xx that names your request —
REQUEST_*,AUTH_*— is a bug in the call. Do not retry until it is fixed. - 4xx about state or funds —
STATE_*,FUNDS_*— is a true answer about right now. Retrying unchanged gives the same answer. - 5xx and provider codes — retry with the same key, with a widening gap.
HTTP status
Section titled “HTTP status”The HTTP status is a coarse hint; code is the contract. In particular, a 409 is always about idempotency or state, never a network problem, and a 404 on someone else’s id is deliberate — telling you an id exists but is not yours would be telling you something about another partner.