Skip to main content

Errors

All errors come back as JSON with a consistent envelope. Status codes follow normal HTTP conventions; the body always carries a human-readable message.

Envelope

{
"error": {
"message": "Owner role required"
}
}

Validation errors include an issues field with the flattened output from Zod, so you can map each issue back to the field that caused it:

{
"error": {
"message": "Validation failed",
"issues": {
"fieldErrors": {
"name": ["String must contain at least 1 character(s)"]
}
}
}
}

Status codes

  • 400 — invalid body, invalid path parameter, or assume-role failure.
  • 401 — missing or invalid Authorization header.
  • 403 — authenticated, but the caller doesn't have the required role.
  • 404 — resource not found, or the caller is not a member of the org they're targeting.
  • 409 — the request conflicts with current state. This includes hitting the concurrently active boxes per seat ceiling: starting or launching another box is refused until you stop one, or until the org moves to the API plan, where that ceiling is raised or removed. See Rate limits & fair use.
  • 410 — invite has expired.
  • 429 — you've hit a rate limit; check the Retry-After header and wait that many seconds before retrying. The body uses the same envelope shown above ({ "error": { "message": ... } }).
  • 500 — unexpected server error. We log these; report persistent occurrences.

CORS preflight

Browser clients see CORS responses for cross-origin requests. The allow-list lives in the API stack; if your origin isn't in it the preflight will fail before your request body is ever inspected.