Error codes
Every JSON error response has the same shape:
json
{
"error": "Job not found",
"code": "NOT_FOUND",
"requestId": "req-42"
}| Field | Always present | Meaning |
|---|---|---|
error | Yes | A human-readable message. Safe to show to users. Do not parse it. |
code | Yes | A stable, machine-readable code. Branch on this. |
requestId | Yes | The server's ID for this request. Quote it when you report a problem; it matches the server log. |
details | Sometimes | More context for some 4xx errors, such as the validation message. |
Messages can change between releases. Codes do not, so write client logic against code.
Codes from the HTTP status
When a route does not set its own code, the server derives one from the status:
| HTTP status | code |
|---|---|
| 400 | BAD_REQUEST |
| 401 | AUTH_REQUIRED |
| 403 | FORBIDDEN |
| 404 | NOT_FOUND |
| 409 | CONFLICT |
| 413 | PAYLOAD_TOO_LARGE |
| 415 | UNSUPPORTED_MEDIA_TYPE |
| 422 | UNPROCESSABLE_ENTITY |
| 429 | RATE_LIMITED |
| 500 | INTERNAL_ERROR |
| 501 | NOT_IMPLEMENTED |
| 503 | SERVICE_UNAVAILABLE |
| 507 | INSUFFICIENT_STORAGE |
Any other 4xx falls back to BAD_REQUEST, and any other 5xx to INTERNAL_ERROR.
A route can set a more specific code, and then the response carries that code instead. For example, a tool that cannot run because its AI bundle is missing returns a feature-specific code. Those codes are described with the feature that raises them.
Authentication and access
code | Status | What to do |
|---|---|---|
AUTH_REQUIRED | 401 | Send Authorization: Bearer <token> with a session token or an API key (si_...). |
FORBIDDEN | 403 | The credential is valid but lacks the permission. Ask an admin for the permission. |
MUST_CHANGE_PASSWORD | 403 | The account must change its password before it can call other endpoints. Call POST /api/auth/change-password with the session token, then retry. |
USER_DISABLED | 403 | The account is disabled. An admin has to re-enable it. |
LOGIN_THROTTLED | 429 | Too many failed sign-in attempts. Wait before trying again. |
VALIDATION_ERROR | 400 | The request body or parameters failed validation. details names the problem. |
The first-run admin account is admin with the password admin unless DEFAULT_USERNAME or DEFAULT_PASSWORD changed it. Unless SKIP_MUST_CHANGE_PASSWORD is set, that account gets MUST_CHANGE_PASSWORD on every call until the password changes.
Jobs
A job that fails reports its reason on the job itself, not in the HTTP error. Read error.code and error.message from GET /api/v1/jobs/{jobId}. See Progress Tracking.
Not yet cataloged
The codes raised by individual features (for example encryption, OIDC, SCIM, and teams) are not described on this page yet. Each one is a stable code; treat an unlisted code as opaque and handle it by its status.
