Every BlooBank error response uses the same JSON envelope, regardless of which endpoint produced it. Learn this shape once and you have a single uniform error-handling code path for the entire API. For the full normative contract, see the Errors reference. For implementation patterns, see Handling errors.Documentation Index
Fetch the complete documentation index at: https://developers.bloobank.com/llms.txt
Use this file to discover all available pages before exploring further.
Core principles
- Uniform envelope. Every error response uses the structure described below. No endpoint deviates.
- HTTP status is informational. Use
error.codefor coarse routing (< 500vs>= 500). It is not granular enough for business logic. error.statusis the contract. This is the stable, machine-readable identifier you branch on. It does not change between releases.error.messageis human-facing. Wording may change. Never string-matcherror.messagein code.error.details[]carries machine context. When you need to react programmatically to a specific condition, readdetails[].reasonanddetails[].metadata— never parsemessage.
The envelope
erroris always present.error.code,error.status,error.message, anderror.detailsare always present.error.detailsis always an array. It may be empty ([]), nevernull, never missing.- The
Content-Typeis alwaysapplication/json; charset=utf-8.
| Field | Stability | What to do with it |
|---|---|---|
error.code | Stable per status | Use for coarse routing only. |
error.status | Stable | Branch on this. |
error.message | Unstable | Log it; do not branch on it. |
error.details[] | Stable per reason | Inspect for specific causes. |
error.details[].reason | Stable | Branch on this for specific conditions. |
error.details[].description | Unstable | Log it; suitable for direct UI display. |
error.details[].metadata | Stable per reason | Read for context (e.g., field, param, decisionId, excRecordId). |
How to branch
The decision tree:Coarse routing on error.code
2xx → success. 4xx → caller error (do not retry without changing the request). 5xx → server error (may be retryable with backoff).Branch on error.status
The canonical reason — e.g.,
SIGNATURE_INVALID, WALLET_NOT_FOUND, IDEMPOTENCY_KEY_IN_USE_WITH_DIFFERENT_PARAMS, RESOURCE_EXHAUSTED. The full catalog is in Error catalog.Inspect error.details[].reason for specifics
For validation failures (
INVALID_ARGUMENT), details[] carries one entry per failed field. For sanitized 5xx (INTERNAL), details[] carries the ERROR_RECORDED reference id.A worked example
APOST /wallets/production-main/paymentOrders with a missing field:
- Branch on
error.status === 'INVALID_ARGUMENT'. - Iterate
details[]— there is one entry per invalid field. - For each, read
metadata.fieldto locate the form input; readdescriptionfor the user-facing message. - Do not retry — fix the request and let the user resubmit.
Two patterns to remember
Pattern 1 — simple failure (single cause)
error.status and error.details[0].reason carry the same value.
Pattern 2 — multi-cause validation
error.status is the cross-cutting class (INVALID_ARGUMENT); details[] carries one entry per cause.
details.length before indexing — both patterns are valid; some failures legitimately return empty details.
INTERNAL errors are sanitized
When the API returnsHTTP 500 with error.status: "INTERNAL", the response is deliberately stripped of detail to avoid leaking implementation specifics. What you get:
error.messageis a generic phrase like"An internal error has occurred."details[]carries a singleERROR_RECORDEDentry withmetadata.id(formatexc_…).
metadata.id is gold — it lets BlooBank engineers locate the exact failure server-side. Always log it on INTERNAL and include it when contacting support.
See Errors reference §Sanitized 500s for details.
What to log
For every non-2xx response, log:- HTTP method and URL.
error.statusanderror.code.- Every
details[].reason. metadata.decisionId(DENY decisions) andmetadata.id(ERROR_RECORDED).- Approximate UTC time.
- Your
X-Access-Request-Id.
Next
Error catalog
Every reason code returned by the API, with HTTP status and remediation.
Handling errors
Branching patterns in code, language by language.
Retry strategy
Exponential backoff with jitter — when to retry, when to give up.