Skip to content
P
Back to Guides

Errors

The consistent error envelope and its validation details.

The error envelope

Every error — validation, auth, rate-limit, or server — comes back in one consistent shape. Branch on the machine-readable code, and surface message for humans:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request body is invalid",
    "details": [ /* optional, structured — see below */ ]
  }
}

The HTTP status still carries meaning (401 unauthenticated, 403 forbidden, 404 not found, 422 unprocessable, 429 rate-limited, 5xx server), but code is the stable value to switch on — messages may be reworded. See the error codes reference for the full list.

Validation details

A 422 validation failure includes a details array. Each entry is normalised to a path, a code, and a message, so you can map failures back to the offending field regardless of the validator version:

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request body is invalid",
    "details": [
      { "path": "name", "code": "too_small", "message": "String must contain at least 1 character(s)" },
      { "path": "attributes.netWeight", "code": "invalid_type", "message": "Expected number, received string" }
    ]
  }
}

Request IDs

Every response carries an X-Request-ID header. Log it and include it when contacting support — it lets us trace a single request end-to-end through the platform.

Always branch on error.code, never on error.message. Codes are part of the API contract; messages are for display and may change.