Error codes
Every error response uses the envelope { "error": { "code", "message", "details"? } }. code is a stable, machine-checked identifier — branch on it, not on message (which is a human sentence and may change). Every response also carries an X-Request-ID header; include it when reporting an issue. The most common cross-cutting codes:
| Code | HTTP | When it occurs |
|---|---|---|
VALIDATION_ERROR | 422 | Request body or query params failed Zod validation; details lists the offending paths. |
UNAUTHORIZED | 401 | No valid credential (missing/expired JWT or API key). |
INVALID_CREDENTIALS | 401 | Login failed — email/password did not match. |
INVALID_TOKEN | 401 | A one-time or scoped token (invite, verify, onboarding, refresh) is malformed, expired, or already used. |
FORBIDDEN | 403 | Authenticated, but the principal’s role lacks permission for this action (RBAC). |
NOT_FOUND | 404 | The resource does not exist, or is not visible to the caller under row-level security. |
CONFLICT | 409 | The request conflicts with current state (e.g. a duplicate unique value). |
INVALID_STATE | 422 | The target is not in a state that permits this transition. |
RATE_LIMITED | 429 | The per-plan sliding-window rate limit was exceeded; see the Retry-After header. |
GONE | 410 | The resource once existed but has been withdrawn or offboarded. |
ORG_SUSPENDED | 403 | The organisation is suspended — reads and DSAR export stay open, mutations are frozen. |
INTERNAL_ERROR | 500 | An unexpected server error; internals are never leaked to the client. |
SANDBOX_READONLY | 403 | A sandbox API key attempted a mutating request; sandbox keys are read-only. |
INSUFFICIENT_SCOPE | 403 | The API key lacks the *:read/*:write scope this verb requires. |
SELECTION_TOO_LARGE | 422 | A bulk selection (e.g. enrichment ids) exceeds the per-job cap. |
CONDITION_NOT_MET | 422 | A workflow transition’s data condition evaluated false (fail-closed). |
TRANSFORM_FAILED | 422 | An onboarding mapping transform failed; approve is all-or-nothing with row-addressed details. |
GLN_INVALID | 422 | A supplied GLN failed check-digit or ownership validation. |
UNKNOWN_FRAMEWORK | 400 | A compliance framework code is not registered. |
GDSN_NO_CONNECTION | 400 | A GDSN publish was attempted with no active data-pool connection. |
SSO_FAILED | 401 | The SAML/OIDC assertion could not be validated or mapped to an org connection. |