Error Responses
BLOX APIs use standard HTTP status codes. Error responses have a JSON body.
Error Format
All errors on /v1 and /checkout have the same three fields:
{
"code": "UNAUTHORIZED",
"message": "API key is required",
"requestId": "9f21ab04-6c3e-4d90-b1a7-8e5f2c0d4416"
}| Field | Type | Description |
|---|---|---|
code | string | A stable SCREAMING_SNAKE_CASE identifier. This field is the contract. Use it to select how your code handles the error. |
message | string | Text for persons to read. BLOX can change the text at any time. Do not parse it. |
requestId | string (uuid) | The identifier of the request. If you report a 5xx error, give this value to BLOX. |
BLOX can add new codes. A new code is not a breaking change. A change to a code or the removal of a code is a breaking change.
Codes
| Status | Codes |
|---|---|
400 | INVALID_REQUEST, VALIDATION_FAILED, CONFLICT, INSUFFICIENT_BALANCE, LIMIT_EXCEEDED, UNKNOWN_BENEFICIARY, BENEFICIARY_NAME_MISMATCH, NAME_CHECK_UNAVAILABLE |
401 | UNAUTHORIZED |
403 | FORBIDDEN, FEATURE_DISABLED, LIMIT_EXCEEDED, ACCOUNT_TERMINATED, ACCOUNT_FROZEN, ACCOUNT_SUSPENDED, ACCOUNT_PENDING_VERIFICATION, ACCOUNT_NOT_ACTIVE |
404 | NOT_FOUND |
422 | CONFLICT |
429 | RATE_LIMITED |
503 | SERVICE_UNAVAILABLE |
5xx | INTERNAL_ERROR |
BLOX returns LIMIT_EXCEEDED with 400 if an amount is more than a daily or monthly limit. BLOX returns it with 403 if a count is at its maximum. For example, the number of beneficiaries on the account, or the number of allowed senders on a trigger address.
A 5xx response does not give the cause of the error. The body contains INTERNAL_ERROR and a fixed message. To get help, report the requestId to BLOX. The exception is 503 SERVICE_UNAVAILABLE. It means that BLOX did not process the request and that you can retry later. It has its own message.
Authentication errors
401 Unauthorized
All causes in this table return code: "UNAUTHORIZED". The message gives more information to help you debug. It is text only. Do not use it to select how your code handles the error.
| Cause | Fix |
|---|---|
| The API key is missing, unknown, or inactive | Send blox-api-key (or Authorization: Bearer) with an active key |
A write request does not have Signature, Signature-Input, or Content-Digest | Sign each POST / PUT / PATCH / DELETE request. Refer to Request Signing. |
| The signature or the digest does not match | Sign the exact bytes that you send. The usual cause is that you serialize the body two times. |
| The signature algorithm is different from the algorithm of your registered key | Sign with the key that you registered |
| Clock drift | Make sure that created is in the window below. Synchronize your server clock. |
| The signature was used before | Make a new signature for each request. BLOX accepts a signature one time only. |
{
"code": "UNAUTHORIZED",
"message": "…",
"requestId": "…"
}Freshness windows:
| Surface | created must be within | Reuse |
|---|---|---|
/v1 (Wallet, Onramp, Checkout) | 30s in the past, 5s in the future | BLOX rejects it. Make a new signature for each request. |
Payout routes (/v1/payouts*, /v1/payout/prefund/balance) | ±300s | BLOX rejects it. Make a new signature for each request. |
403 Forbidden
code | When |
|---|---|
ACCOUNT_TERMINATED | The account is terminated |
ACCOUNT_FROZEN | The account is frozen |
ACCOUNT_PENDING_VERIFICATION | The account waits for verification |
ACCOUNT_SUSPENDED | The account is suspended |
ACCOUNT_NOT_ACTIVE | The account is inactive or closed |
FEATURE_DISABLED | The product feature that the request needs is not enabled for the account |
ACCOUNT_TERMINATED blocks all routes, also the read routes. The other codes block only the routes that move money. The read routes continue to work. ACCOUNT_SUSPENDED blocks only the routes that move money into the account. The routes that move money out of the account continue to work.
To enable an API product for your account (for example, Payout), contact the BLOX team.
Other common status codes
| Status | Meaning |
|---|---|
202 | This status is not an error. BLOX did not complete the first request with your Idempotency-Key. Retry with the same key (Idempotency). |
400 | The request failed validation or a business rule |
404 | BLOX did not find the resource |
422 | You used an Idempotency-Key again with a different body |
429 | You sent more requests than the rate limit permits (refer to Rate Limits) |
500 | An unexpected error occurred at BLOX |
If the request does not agree with the schema, BLOX returns VALIDATION_FAILED. The message field lists the fields that are not valid.
Handling errors
If you get a 429 response, wait and then retry with exponential backoff. Rate-limit headers are not always in the response. Do not use them.
Testing
# Missing / invalid API key
curl https://api.sandbox.blox.my/v1/health \
-H "blox-api-key: invalid_key"
# POST without signature headers (expect 401)
curl -X POST https://api.sandbox.blox.my/v1/payouts/beneficiaries \
-H "blox-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"TEST","bankCode":"MBBEMYKL","accountNumber":"1234567890"}'Support
- Email: support@blox.my
- GitHub: github.com/Blox-My