Documentation Index
Fetch the complete documentation index at: https://docs.arcuserp.com/llms.txt
Use this file to discover all available pages before exploring further.
Error envelope
All errors return a JSON body in this shape:
{
"error": "not_found",
"code": "not_found",
"type": "not_found",
"hint": "The requested order does not exist or does not belong to this entity.",
"param": null,
"request_id": "req_01H..."
}
| 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
import Arcus, { ArcusAPIError } from '@arcuserp/sdk-node';
try {
const order = await arcus.orders.retrieve('ord_invalid');
} catch (err) {
if (err instanceof ArcusAPIError) {
console.error(err.code); // e.g. "not_found"
console.error(err.hint); // human-readable
console.error(err.requestId); // for support
console.error(err.status); // HTTP status code
if (err.status === 429) {
// Respect Retry-After
const retryAfter = err.headers['retry-after'];
await sleep(parseInt(retryAfter, 10) * 1000);
}
}
}
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-After response header before retrying
- 4xx errors (except 429): do not retry; fix the request first
- Always use
Idempotency-Key on retried POST/PATCH/DELETE requests to prevent duplicates
Support
Include request_id when contacting support. It allows the Arcus team to retrieve the full trace for the failing request.