Errors

Every error response is JSON in this shape:

json
{
  "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "insufficient balance: requested 5000000, available 3000000",
    "request_id": "8c3a..."
  }
}

Status codes

HTTPCodeMeaning
400INVALID_INPUTField validation failed; check the message.
400IDEMPOTENCY_REQUIREDMissing Idempotency-Key on a write.
400INSUFFICIENT_BALANCEPayout / refund exceeds available.
400INVALID_DESTINATIONAddress format invalid for the chain.
400REFUND_EXCEEDS_NETRefund larger than what's left to refund.
400MEMO_NOT_ALLOWEDMemo on a network that doesn't use one.
400PAY_IN_ASSET_NOT_ALLOWEDAsset/network combo not enabled for you.
401MISSING_API_KEYNo Authorization header.
401INVALID_API_KEYKey not recognised or mismatched.
401API_KEY_REVOKEDKey revoked.
403MISSING_SCOPEKey doesn't have the required scope.
403IP_NOT_ALLOWEDRequest IP outside the key's allowlist.
403MERCHANT_SUSPENDEDMerchant account is suspended.
403MERCHANT_BANNEDMerchant account is banned.
403DAILY_CAP_EXCEEDEDPayout cap for the asset reached.
404INVOICE_NOT_FOUND / PAYOUT_NOT_FOUND / REFUND_NOT_FOUNDResource doesn't exist (or isn't yours).
409INVOICE_NOT_CANCELLABLEOnly awaiting_deposit invoices can be cancelled.
409INVOICE_NOT_REFUNDABLEInvoice must be paid first.
409DUPLICATEIdempotency-Key replay with a different body, or duplicate order_id.
429RATE_LIMITToo many requests on this key.
429API_KEY_LOCKEDBrute-force lockout in effect.
503POOL_EXHAUSTEDNo deposit address available; retry shortly.
503PAYOUTS_DISABLED / REFUNDS_DISABLED / MERCHANT_DISABLEDOperator paused that surface; try later.

Retry strategy

Treat 429 and 503 as transient. Use the Retry-After header when present. 5xx responses can be retried with the same Idempotency-Key — we return the cached response if the original write completed. 4xx other than 409 should be treated as final and not retried.