Skip to main content
Every BlooBank error response uses the same JSON envelope, regardless of which endpoint produced it. This page is the reference contract — the developer-facing guide on how to react to errors lives in Errors → Handling.
Branch on error.status and error.details[].reason. Never string-match error.message — its wording changes between releases.

The envelope

Every error response is a JSON object with exactly one top-level key: error.
The envelope shape is invariant:
  • error is always present.
  • error.code, error.status, error.message, and error.details are always present.
  • error.details is always an array. It may be empty ([]), but it is never null and never missing.
  • The response Content-Type is always application/json; charset=utf-8.

Field reference

error.status vs error.details[].reason

Both carry stable UPPER_SNAKE_CASE identifiers. The practical rule:
  • For simple failures with a single cause (most cases), error.status and error.details[0].reason carry the same value (e.g., both WALLET_NOT_FOUND).
  • For validation failures with multiple field issues, error.status is the cross-cutting class (INVALID_ARGUMENT) and error.details[] carries one entry per invalid field.
Always inspect both. error.status is the coarse classifier; details[].reason is the specific cause.

Status to HTTP mapping

The mapping is fixed. The full catalog of reason codes returned by this API lives in the Error catalog.

Validation errors (INVALID_ARGUMENT)

The most common error during integration is request validation. The platform formats these consistently across every endpoint.
  • error.status is "INVALID_ARGUMENT".
  • error.code is 400.
  • error.message is a generic summary, e.g. "One or more fields have invalid values.".
  • error.details[] contains one entry per failed constraint.

field vs param

The platform distinguishes body fields from query/path parameters. Each detail carries exactly one of these. Use it to locate the offending input in your request.

Example — multiple invalid fields

Example — invalid query parameter

Query-parameter errors may use a more specific reason than INVALID_FIELD (e.g., INVALID_PAGE_SIZE, INVALID_FILTER, INVALID_ORDER_BY, INVALID_PAGE_TOKEN).

Sanitized 500s

Responses with error.status: "INTERNAL" receive special treatment.

What sanitization means

When a service produces an internal error, the platform mutates the response before sending it:
  • The original error.message is replaced with a generic phrase such as "An internal error has occurred.".
  • Any original details[] entries are dropped.
  • A single details[] entry with reason: "ERROR_RECORDED" is appended (when the audit record was persisted successfully).
This is intentional and non-negotiable — internal errors may carry implementation details that must not cross the network boundary.

Anatomy of a recorded internal error

The metadata.id (format exc_…) is the single most valuable piece of information you can forward to support. With it, a BlooBank engineer can locate the full audit trail in seconds.

What to do on INTERNAL

  1. Locate the detail with reason === "ERROR_RECORDED".
  2. Extract metadata.id.
  3. Log it with the URL, method, approximate UTC time, and your X-Access-Request-Id.
  4. Forward it when escalating.
If ERROR_RECORDED is missing (rare — the audit-record persistence itself failed), send the approximate UTC time and your request id; engineers can still trace via access logs.
Do not retry INTERNAL blindly. It indicates a known backend failure that the service understands but cannot resolve for you. Retry only if you have explicit reason to believe it was transient.

What is not in the envelope

Do not depend on these — they may appear or disappear between releases:
  • Top-level fields outside error (timestamp, path, traceId at the root). Treat as informational.
  • Nested fields inside error other than the four documented above.
  • Stack traces. Never returned, regardless of failure mode.

Next

Error catalog

Every reason code returned by the API, with remediation.

Handling errors

Branching patterns and retry strategy in code.