Errors
Every error code the API can return, with HTTP status, common triggers, and recovery guidance.
Errors share one envelope:
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Project not found"
}
}
The code is stable; the message is descriptive and may change. Treat code as the contract.
Payment and auth examples:
{ "success": false, "error": { "code": "PAYMENT_REQUIRED", "message": "Insufficient balance" } }
Production POST bodies without Content-Length return 411 Length Required. Step-up-required mutations return 403 with browser-session copy.
Code reference
BAD_REQUEST — HTTP 400
The request body or query string is malformed. Common triggers:
- Missing required field (e.g.
nameon agent create). - Wrong type (
label must be a string,amountCents must be an integer). - Field exceeds its length cap.
- Unknown enum value (model ID, status, visibility).
- Empty JSON body where one is required.
- Rate limit exceeded on routes that surface limits as
BAD_REQUEST(e.g. API key minting).
Recovery: fix the payload and retry.
UNAUTHORIZED — HTTP 401
No Authorization header, malformed Bearer, or the API key has been revoked. Recovery: confirm the header format Bearer alm_<env>_<...> and that the key is not revoked.
PAYMENT_REQUIRED — HTTP 402
The org cannot run a managed paid operation because credits, package limits, or budgets block it. Surfaced by chat/copilot routes during Billing preflight. Recovery: buy a credit top-up, wait for the next monthly grant, adjust budgets, or switch model-token calls to BYOK where allowed.
LENGTH_REQUIRED — HTTP 411
Production POST requests without a Content-Length header are rejected before the body is buffered. Recovery: send Content-Length with the encoded body size.
PAYLOAD_TOO_LARGE — HTTP 413
The request body exceeds the route cap (typically 128 KB JSON, 256 KB inbound webhooks). Recovery: shrink the payload or split the operation.
FORBIDDEN — HTTP 403
Authenticated, but the action is not allowed. Common triggers:
- Caller has no workspace access.
- Step-up authentication required — response may include
{ error: "step_up_required", methods: ["totp", "passkey"] }(API key minting, account-security changes, workspace mutations, project sharing, privileged agent config, org settings, memory deletes, session sharing). - Browser session required — API keys cannot perform workspace changes, project share links, org membership management, webhook/MCP/domain administration, skill/guardrail edits, org settings updates, memory deletes, account-security changes, or some session mutations even when scopes match.
- Attempt to deactivate, re-model, or delete the default
Alaagent. - Attempt to rename, move, or delete a protected folder.
- Caller lacks billing-manage role on billing mutations.
Recovery: re-authenticate in the dashboard (passkey or TOTP step-up), grant the user the needed role, or use an API route that allows key auth.
NOT_FOUND — HTTP 404
The resource does not exist, is soft-deleted, or is invisible to the caller because of workspace scope or visibility rules. The API never reveals that a resource exists in a different org or workspace; both cases collapse to 404. Recovery: verify the ID and the caller's workspace.
CONFLICT — HTTP 409
State conflict. Examples: a concurrent update has invalidated the row, or a uniqueness constraint failed. Recovery: refetch and retry.
VALIDATION_ERROR — HTTP 422
Input shape is valid, but a value is semantically out of range. Used for nuanced field-level rejections that do not map cleanly to BAD_REQUEST. Recovery: adjust the value and retry.
TOO_MANY_REQUESTS — HTTP 429
Rate limit exceeded for a non-bypassed route. Recovery: back off, then retry. (Some endpoints surface limits as BAD_REQUEST with a Too many requests message — these are functionally equivalent.)
SERVICE_UNAVAILABLE — HTTP 503
A dependency is temporarily down (LLM provider, storage, background worker). Recovery: retry with exponential backoff.
INTERNAL_ERROR — HTTP 500
Unhandled exception. In production the message is Internal server error; in development it surfaces the original error message to aid debugging. Recovery: report the request ID and retry; if it persists, the issue is server-side.
How errors are classified
Route handlers throw subclasses of ApiError (UnauthorizedError, NotFoundError, …) which the shared errorResponse helper translates into the envelope above. Anything that is not an ApiError is logged and returned as INTERNAL_ERROR with HTTP 500. Code paths that intentionally degrade — e.g. deletion of an S3 object after the DB row was soft-deleted — are caught and ignored without surfacing an error to the client.