Developers
API error codes
Use the stable code for exact handling and the class for a safe fallback when a newer code is unknown. Messages are for people and can change.
Every page below documents the HTTP status, class, typed meta keys, meaning, and a concrete client response. The runtime catalog is also published by GET /v1/meta.
| Code | Class | Status | Meaning |
|---|---|---|---|
invalid_argument | invalid_request | 400 | umbrella; see details[]. |
invalid_json | invalid_request | 400 | body is not a JSON object. |
unknown_field | invalid_request | 400 | a body field the route does not define. |
unknown_parameter | invalid_request | 400 | a query parameter the route does not define. |
missing_field | invalid_request | 400 | a required field was absent. |
invalid_id | invalid_request | 400 | wrong id type or malformed id. |
invalid_cursor | invalid_request | 400 | tampered, malformed, or filters changed mid-page. |
invalid_filter | invalid_request | 400 | unknown value for an enum filter. |
invalid_sort | invalid_request | 400 | field is not sortable on this collection. |
content_conflict | invalid_request | 400 | both data and url on content. |
content_auth_not_allowed | invalid_request | 400 | content.auth sent with anything but url. |
invalid_base64 | invalid_request | 400 | content.data did not decode. |
invalid_option | invalid_request | 400 | unknown print-option key. |
invalid_option_value | invalid_request | 400 | option value outside its grammar. |
invalid_event_type | invalid_request | 400 | unknown or malformed event-type selector. |
invalid_webhook_url | invalid_request | 400 | not an absolute http(s) URL. |
confirm_required | invalid_request | 400 | filter or all without confirm_count. |
idempotency_not_supported | invalid_request | 400 | Idempotency-Key on a route that does not honor it. |
token_invalid | invalid_request | 400 | expired or already-used email link. |
password_policy | invalid_request | 400 | The password does not satisfy the published password rules. |
content_too_large | invalid_request | 413 | content over the cap. |
unsupported_media_type | invalid_request | 415 | not application/json. |
method_not_allowed | invalid_request | 405 | known path, wrong method. |
upgrade_required | invalid_request | 426 | frozen; plain GET on the agent WebSocket path. |
invalid_credentials | authentication | 401 | absent, malformed, unknown, expired or revoked credential; also the uniform sign-in answer and the dead-session answer. |
role_forbidden | permission | 403 | the console role is insufficient. |
session_required | permission | 403 | an API key on a session-only route. |
marker_required | permission | 403 | pre-session /v1/auth/* without a PrintHook marker. |
cross_site_refused | permission | 403 | the Sec-Fetch-Site gate. |
account_suspended | permission | 403 | the acting account is not active. |
account_not_permitted | permission | 403 | acting-account selector unknown or not yours (one answer for both), or the header is not allowed on this route. |
computer_key_not_permitted | permission | 403 | a computer key outside its four surfaces. |
permission_required | permission | 403 | the acting account lacks an account-level permission; the one instance is Admin on PATCH /v1/agent-releases/{id}. |
trial_expired | permission | 403 | new print admission at or after the native trial deadline without a valid paid entitlement; existing jobs, retries, login and account access remain available. |
quota_exceeded | permission | 403 | POST /v1/jobs would exceed the month's print allowance for quantity multiplied by copies; the whole request is refused without overage. |
child_accounts_not_permitted | permission | 403 | POST /v1/accounts while the account may not create child accounts. |
password_incorrect | permission | 403 | wrong current password (never a 401; the console signs out on a 401). |
mfa_required | permission | 403 | valid password needs an authenticator or recovery code. |
mfa_invalid | permission | 403 | incorrect, expired or reused factor. |
mfa_already_enabled | conflict | 409 | setup cannot replace an active factor. |
mfa_not_enabled | conflict | 409 | factor change without an active factor. |
team_change_not_permitted | permission | 403 | protected owner/self or a role above the manager's authority. |
registration_disabled | permission | 403 | sign-up switched off. |
email_not_verified | permission | 403 | defined, not raised (see below). |
not_found | not_found | 404 | no such resource on this account. |
idempotency_key_reused | conflict | 409 | same key, different request fingerprint. |
idempotency_in_progress | conflict | 409 | same key, the original request is still running; retry_after_sec: 1. |
confirm_count_mismatch | conflict | 409 | the selection moved between the caller's read and the write. |
printer_online | conflict | 409 | retire refused while the printer is online. |
station_name_in_use | conflict | 409 | the station name is already used on this account (case-insensitive). |
station_busy | conflict | 409 | delete refused while jobs addressed to the station are pending. |
role_unbound | conflict | 409 | a job addressed to a station role that has no live binding (unbound, or stale after the device moved). |
role_not_bindable | conflict | 409 | the device cannot hold that role (a scale is not a printer, and so on). |
device_not_on_station_computer | conflict | 409 | the device lives on another computer than the station. |
station_pairing_invalid | permission | 403 | a wrong, expired, used or other-tenant pairing code or barcode at enrollment. |
computer_disconnected | conflict | 409 | retire refused because the printer's computer is disconnected. |
not_cancelable | conflict | 409 | the job already left queued (also a bulk unchanged code). |
email_in_use | conflict | 409 | the address already belongs to an account or user. |
creator_ref_in_use | conflict | 409 | the creator reference is already used on this parent. |
key_label_in_use | conflict | 409 | the label is not unique among the account's live keys. |
webhook_limit_reached | conflict | 409 | the per-account webhook cap. |
delivery_in_progress | conflict | 409 | an active delivery/retry prevents manual replay. |
rate_limited | rate_limit | 429 | the per-account bucket; retry_after_sec set. |
too_many_attempts | rate_limit | 429 | a sign-in throttle bucket; retry_after_sec set. |
internal_error | server | 500 | An unexpected server failure occurred; the public message intentionally does not expose its cause. |