error.code are the two identifiers to branch on — error.message is human-readable and may change without notice.
Error envelope
request_id appears in both error and meta — the duplication is intentional for convenience when parsing either field.
Error codes by HTTP status
400 — invalid_request
| Code | Description |
|---|---|
VALIDATION_FAILED | Request body failed validation. error.param names the offending field. |
PHI_IN_TOOL_SCHEMA | A tool definition contains PHI. Tool schemas are stored in plaintext at the provider — this is always rejected regardless of phi_mode. |
UNSUPPORTED_PARAMETER | A parameter not in Anthropic’s wire format was sent to /v1/messages. |
401 — unauthorized
| Code | Description |
|---|---|
INVALID_API_KEY | Bearer token is missing, malformed, or revoked. |
402 — payment_required
| Code | Description |
|---|---|
BAA_REQUIRED | No active Business Associate Agreement on the org. Sign at Settings → Compliance. |
AI_CREDITS_EXHAUSTED | Org has used its full credit allotment this cycle. error.details.cycle_reset_at shows when credits reset. |
403 — forbidden
| Code | Description |
|---|---|
MISSING_SCOPE | API key exists but lacks the required scope. error.details.required_scope names the missing scope. |
PHI_BLOCKED | Message contains PHI and phi_mode=block is configured. error.details.entity_types lists what was detected. |
FEATURE_NOT_HIPAA_ELIGIBLE | The requested AI feature is not HIPAA-eligible and is disabled in the allowlist. |
OPUS_NOT_ENABLED | Opus model access is disabled for this org. Enable at Settings → Billing → Model Access. |
404 — not_found
| Code | Description |
|---|---|
RESOURCE_NOT_FOUND | The requested resource does not exist or belongs to another org. |
410 — gone
| Code | Description |
|---|---|
MODEL_RETIRED | The specified model has been retired. error.details includes retired_at, recommended_replacement, and docs_url. HASP provides at least 90 days notice before retiring a model. |
422 — unprocessable_entity
| Code | Description |
|---|---|
UNSUPPORTED_DOCUMENT_TYPE | The uploaded document format is not supported. |
429 — rate_limited / budget_exceeded
| Code | Description |
|---|---|
RATE_LIMITED | RPM or daily request limit exceeded. Check the Retry-After header and error.details.retry_after_seconds. error.retryable: true. |
BUDGET_EXCEEDED | Org-configured spend cap reached. error.details includes cycle_reset_at, current_spend_usd, cap_usd. Retryable after the cap is raised or the cycle resets. |
502 — provider_error
| Code | Description |
|---|---|
INFERENCE_UPSTREAM_FAILURE | The upstream model provider returned an error. error.retryable: true. |
503 — service_unavailable
| Code | Description |
|---|---|
INFERENCE_UNAVAILABLE | The AI inference gateway is temporarily unavailable. Retry with backoff. |
DOCUMENT_STILL_PROCESSING | Document ingestion is in progress — use webhooks instead of polling. |
500 — internal_error
| Code | Description |
|---|---|
INTERNAL_ERROR | Unexpected server error. If this persists, contact support with the request_id. |
Streaming errors
On SSE streams, errors after the stream has opened are delivered as events rather than HTTP status codes:run.failed (includes both data.object and data.error). The standalone error event fires for errors that occur before a run could be created.