Skip to content

Errors

Every response — success or failure — is wrapped the same way:

// success
{ "state": "SUCCESS", "payload": { "...": "..." } }
// created (201 responses)
{ "state": "CREATED", "payload": { "...": "..." } }
// error
{ "state": "SOME_ERROR_CODE", "payload": null, "details": { "...": "optional context" } }

state is always present. On an error, it carries a stable, machine-readable code — parse and branch on state, not on the HTTP status code alone, and never on the human-readable text some errors surface in details.

HTTP status Meaning
200 / 201 Success (state: "SUCCESS" / "CREATED").
400 Request validation failed (a malformed/missing field).
401 Missing, invalid, or expired credentials/token.
403 Authenticated, but not allowed to do this specific thing (e.g. an invalid delegation target).
404 The resource doesn’t exist — or belongs to another partner. Cross-tenant access always reports 404, never 403, so a not-yours resource is indistinguishable from a genuinely nonexistent one.
409 A conflict — usually a duplicate/in-progress/racing request.
422 The request was well-formed but violates a business rule (e.g. a margin floor).
429 Rate-limited — see Rate limits.
5xx Something went wrong on our side. Retries with backoff are safe for these (and, for order creation, always safe regardless of status — see Idempotency).

This isn’t every code the API can ever return, but it covers what you’re likely to build error handling around:

Code HTTP When
UNAUTHORIZED_INVALID_CREDENTIALS 401 Wrong clientId/clientSecret at the token endpoint.
UNAUTHORIZED_PARTNER_INACTIVE 401 Your partner account is inactive.
FORBIDDEN_NOT_YOUR_DESCENDANT / FORBIDDEN_DELEGATION_TARGET_INVALID 403 An onBehalfOf delegation target you don’t actually have authority over.
NOT_FOUND_ORDER / NOT_FOUND_TOPUP_ORDER / NOT_FOUND_ESIM_ORDER / NOT_FOUND_SCENT_ORDER 404 Unknown order id/reference, or one belonging to another partner.
NOT_FOUND_WALLET / NOT_FOUND_STATEMENT 404 No wallet provisioned yet / unknown or not-yours statement.
NOT_FOUND_WEBHOOK_SUBSCRIPTION 404 Unknown subscription id.
NOT_FOUND_SCENT / NOT_FOUND_BRAND / NOT_FOUND_VARIANT 404 Unknown catalog entity.
NOT_FOUND_CART_ITEM 404 No such line in your cart.
NOT_FOUND_FULFILLMENT_GROUP / NOT_FOUND_ORDER_LINE 404 Unknown target for a return request.
VALIDATION_MISSING_REPORT_RANGE 400 mode=report on /api/v1/statements without both from and to.
VALIDATION_PRICE_LOCK_INVALID / VALIDATION_PRICE_LOCK_EXPIRED 400 A lockId that’s unusable — see Cart preview & price locks.
VALIDATION_CUSTOMER_REF_TOO_LONG 400 customerRef over 128 characters.
VALIDATION_WEBHOOK_EVENT_TYPE_NOT_SUBSCRIBED 400 Test-firing an event type your subscription isn’t subscribed to.
VALIDATION_INVALID_REASON_CODE 400 An unrecognized reasonCode on a return request line.
BUSINESS_MARGIN_BELOW_FLOOR / BUSINESS_PRICE_BELOW_COST 422 Live prices/costs moved enough since pricing that the order can’t be accepted at a viable margin.
BUSINESS_WEBHOOK_SUBSCRIPTION_LIMIT 422 You already have 5 active subscriptions.
BUSINESS_RETURN_REQUEST_GROUP_NOT_DELIVERED / _WINDOW_EXPIRED / _EXCEEDS_REMAINING / _DUPLICATE_LINE 422 A return request eligibility rule failed — see the API Reference for each.
CONFLICT_CART_HAS_PENDING_ORDER 409 The cart already has an order in flight.
CONFLICT_CART_CHECKOUT_RACE / CONFLICT_PRICE_LOCK_CREATE_RACE 409 A concurrent request on the same cart lost a race — safe to retry.
RATE_LIMITED 429 See Rate limits.
  • Never distinguish “wrong client ID” from “wrong secret” at the token endpoint — both are the same generic UNAUTHORIZED_INVALID_CREDENTIALS, to avoid letting a caller enumerate valid client IDs.
  • Never leak a stack trace, an internal exception message, or implementation detail in details.
  • Never return a 200 with an error state embedded in the payload — if state isn’t SUCCESS/ CREATED, the HTTP status code is always a matching 4xx/5xx too.