Errors and limits
Error format, error codes, rate limits and pagination.
Error format
Every error response is JSON. message is English text you can show to users; code is stable. Branch on code, never on message.
{ "message": "Insufficient balance.", "code": "insufficient_balance" }Validation errors add errors, keyed by field:
{
"message": "The order no field is required.",
"code": "validation_failed",
"errors": { "order_no": ["The order no field is required."] }
}Error codes
| HTTP | code | Meaning |
|---|---|---|
| 401 | unauthenticated | API key or signature authentication failed, including invalid timestamps and replayed requests |
| 403 | forbidden | Feature disabled or not allowed |
| 404 | not_found | Resource does not exist or belongs to another merchant |
| 422 | validation_failed | Parameters failed validation; see errors |
| 422 | insufficient_balance | Merchant balance too low (card balance for card withdrawals) |
| 422 | duplicate_order_no | order_no already used |
| 422 | card_status_conflict | Card status does not allow the operation |
| 422 | operation_not_supported | Card product or provider does not support the operation |
| 422 | limit_reached | Usage limit reached (cards, virtual accounts); see Settings → Limits |
| 422 | card_rejected, compliance_rejected, exchange_rejected, file_rejected, funding_rejected, ledger_rejected, merchant_rejected, provider_rejected, reference_rejected | Other business rules |
| 429 | too_many_requests | Rate limited; retry after Retry-After seconds |
| 500 | server_error | Internal error, already alerted; retry later |
| 503 | provider_unavailable | Upstream provider temporarily unavailable; retry later |
| 503 | service_unavailable | Maintenance |
New codes may be added. Treat an unknown code by its HTTP status.
Rate limits
- 300 requests per minute per merchant, across all of its API keys.
X-RateLimit-LimitandX-RateLimit-Remainingreport the limit and what is left this minute.- Over the limit, requests return
429 too_many_requestswithRetry-After. - More than 10 requests with failed authentication from one IP within a minute block that IP with
429untilRetry-Afterpasses.
Idempotency
Endpoints that move money take an order_no that is unique per merchant. Retrying with the same order_no returns 422 duplicate_order_no instead of creating a second order, so it is safe to retry after a timeout and then look the order up.
Pagination
List endpoints use cursor pagination.
| Parameter | Description |
|---|---|
limit | 1–100, default 20 |
cursor | next_cursor from the previous page |
{ "data": [], "next_cursor": "eyJpZCI6MTIzfQ" }next_cursor is null on the last page.