Error envelope
All errors return a JSON body in this shape:| Field | Always present | Description |
|---|---|---|
error | Yes | Machine-readable error key |
code | Yes | Same as error (included for forward compatibility) |
type | No | Error category (see below) |
hint | No | Human-readable one-sentence explanation |
param | No | The request parameter that caused the error |
required | No | The scope required (only on insufficient_scope errors) |
request_id | No | Unique request ID for support tracing |
HTTP status codes
| Status | Meaning |
|---|---|
200 OK | Success |
201 Created | Resource created |
204 No Content | Success with no body (DELETE) |
304 Not Modified | ETag matched; use your cached copy |
400 Bad Request | Invalid request body or parameters |
401 Unauthorized | Missing or invalid API key |
403 Forbidden | Valid key but insufficient scope or IP not allowlisted |
404 Not Found | Resource does not exist or belongs to a different entity |
409 Conflict | State conflict (idempotency key mismatch, duplicate record, RI violation) |
422 Unprocessable Entity | Validation error on request body |
429 Too Many Requests | Rate limit exceeded |
500 Internal Server Error | Arcus-side error; safe to retry with exponential backoff |
Error types
| Type | HTTP status | Description |
|---|---|---|
validation_error | 400 / 422 | Request body or parameter failed validation |
permission_error | 401 / 403 | Auth or scope issue |
not_found | 404 | Resource not found |
conflict | 409 | State conflict |
rate_limit | 429 | Too many requests |
expand_error | 400 | Expand parameter syntax or limit violated |
not_implemented | 501 | Endpoint exists but the operation is not yet available |
internal | 500 | Arcus-side error |
Common error codes
Authentication and authorization
| Code | Status | Description |
|---|---|---|
missing_api_key | 401 | Authorization header not provided |
invalid_api_key | 401 | Key not found or revoked |
missing_entity_id | 401 | Entity ID not present in the URL path |
entity_id_mismatch | 403 | Entity ID in the URL does not match the key’s entity |
insufficient_scope | 403 | Key lacks the required scope |
ip_not_allowlisted | 403 | Request IP is not in the key’s allowlist |
key_expired | 401 | Key has passed its expiry date |
Validation
| Code | Status | Description |
|---|---|---|
invalid_id_format | 400 | Path parameter is not a valid UUID |
missing_required_field | 422 | Required field missing from request body |
invalid_field_value | 422 | Field value fails type or range validation |
idempotency_key_mismatch | 409 | Same key reused with a different request body |
Resource state
| Code | Status | Description |
|---|---|---|
not_found | 404 | Resource not found or belongs to a different entity |
conflict | 409 | Operation conflicts with current resource state |
resource_in_use | 409 | Cannot delete; resource is referenced by other records |
Expand
| Code | Status | Description |
|---|---|---|
invalid_expand_unknown_field | 400 | Expand path does not exist on this resource |
invalid_expand_too_many_paths | 400 | More than 10 expand paths in one request |
invalid_expand_depth_exceeded | 400 | Expand path nesting deeper than 4 levels |
invalid_expand_list_requires_data_prefix | 400 | List endpoint expand missing data. prefix |
Rate limits
| Code | Status | Description |
|---|---|---|
rate_limit_exceeded | 429 | Per-key rate limit hit; check Retry-After header |
Handling errors in code
Retry strategy
- 5xx errors: safe to retry with exponential backoff (1s, 2s, 4s, 8s, max 5 retries)
- 429 errors: wait the number of seconds in the
Retry-Afterresponse header before retrying - 4xx errors (except 429): do not retry; fix the request first
- Always use
Idempotency-Keyon retried POST/PATCH/DELETE requests to prevent duplicates
Support
Includerequest_id when contacting support. It allows the Arcus team to retrieve the full trace for the failing request.
