Skip to main content

Response envelope

Every endpoint — success or failure — returns the same JSON shape:

{
"status": "SUCCESS",
"statusCode": 0,
"statusMessage": "Human-readable message",
"traceId": "uuid-hex-string",
"data": { },
"errors": null
}
FieldTypeMeaning
statusTransactionStatusOutcome of this request/operation — not always the outcome of an order
statusCodeint (0–14)Internal request-handling code: replay, accepted, validation error. Not an HTTP status, not an order status
statusMessagestringHuman-readable message
traceIdstringCorrelation id, mirrors the X-Trace-Id header
dataobject | nullPayload, null on error
errorsarray | nullField-level validation errors

TransactionStatus

ValueMeaning
SUCCESSTerminal success
IN_PROGRESSWorking — poll for the result
PARTIALLY_COMPLETEDTerminal partial success (some items delivered, the rest refunded). A single order or a cart aggregate can have this value
CANCELLEDFailure or refusal. All errors return CANCELLED

Three status surfaces

There are three places a status can appear in one response, and they answer different questions. Most integration bugs are a confusion between them.

WhereFieldAnswersTrust it for
EnvelopestatusHow did this request endDepends on the endpoint (below)
EnvelopestatusCodeHow to handle the request: retry, replay, validation errorRetry / idempotency logic — not the order outcome
Payloaddata.status, data.orders[].status, data.page.items[].statusThe order lifecycle: delivered / working / cancelledThe only source of truth about an order

What the envelope status means depends on which endpoint you called:

EndpointEnvelope status
POST /ordersMirrors data.status. IN_PROGRESS → HTTP 202 + Retry-After
POST /cartsAggregate over the cart. Individual order statuses are in data.orders[].status
GET /orders, catalog, balances, any successful list/readSUCCESS = "request served". It says nothing about the orders inside — for GET /orders, read data.page.items[].status

The integration rule, in one line

Branch business logic (delivered / wait / failed) only on data[...].status. The envelope status and statusCode describe the request, not the fate of the order.

Two non-obvious traps (both by design)

  • HTTP 200 ≠ the order succeeded. A cancelled order comes back with HTTP 200 and statusCode 0 or 2; the failure is visible only as data.status = CANCELLED. The request was served fine — the order failed. Never mark an order delivered based on the HTTP code or the envelope status.
  • status: SUCCESS on a list means nothing about the orders in it. On GET /orders and every other list/read endpoint the envelope status is always SUCCESS. The real statuses live in each element of data.

Field-level errors

Validation failures fill errors with one entry per offending field:

{
"status": "CANCELLED",
"statusCode": 3,
"statusMessage": "Validation error",
"traceId": "...",
"data": null,
"errors": [
{"field": "orders.0.denominationId", "code": "INVALID_VALUE", "message": "Item not found"}
]
}
codeMeaning
MISSINGRequired field absent
OUT_OF_RANGEValue outside the allowed range
INVALID_FORMATMalformed value
INVALID_VALUEWell-formed but not acceptable
NOT_ALLOWEDValue not permitted here
TOO_LONGToo long
TOO_SHORTToo short

Tracing

Send X-Trace-Id and we echo it back in the envelope and in every log line for that request; omit it and we generate one. The response header X-Trace-Id is CORS-exposed, so a browser-side debug tool can read it. Quote this id in support tickets — it is how we find your request.