Skip to content

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.

CodeMeaning
AUTH_INVALID_API_KEYThe key is unknown, revoked, or malformed
AUTH_SIGNATURE_REQUIREDx-partner-signature was missing, or your account has no signing secret yet — see Authentication
AUTH_INVALID_SIGNATUREThe signature did not match the body — see Authentication
AUTH_PARTNER_INACTIVEYour account is not active
AUTH_PERMISSION_DENIEDThe key is valid but lacks the permission for this endpoint

None of these are worth retrying. Fix the request.

CodeMeaning
REQUEST_INVALID_PAYLOADA field is missing, the wrong type, or unknown; a payment-instrument gross is fractional
REQUEST_IDEMPOTENCY_KEY_REQUIREDThis endpoint moves money and needs X-Idempotency-Key
REQUEST_IDEMPOTENCY_KEY_REUSEDThe 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.

CodeMeaning
RESOURCE_NOT_FOUNDNo such id — or it is not yours. We do not distinguish
RESOURCE_NOT_LINKEDThe organization_id you named is not linked to your account, or its link was revoked
STATE_CONFLICTThe transaction is not in a state where this makes sense
CodeMeaning
FUNDS_INSUFFICIENT_BALANCEYour available balance does not cover it
FUNDS_LIMIT_EXCEEDEDA payout limit would be breached — see Payouts
FUNDS_PAYOUT_SUSPENDEDPayouts are off for your account, or no limits are configured yet
CodeMeaningRetry?
PROVIDER_UNAVAILABLEThe payment provider could not be reachedYes, same key
PROVIDER_INDETERMINATEWe asked, and cannot tell whether it workedPoll — do not re-send
RATE_LIMIT_EXCEEDEDToo many requestsYes, after backing off
INTERNAL_ERROROur faultYes, same key

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.

A rule of thumb that holds for all of them:

  • 4xx that names your requestREQUEST_*, AUTH_* — is a bug in the call. Do not retry until it is fixed.
  • 4xx about state or fundsSTATE_*, 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.

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.