Error Code Reference
Every Orbit API error response carries a machine-readablecode,
human-readable message, HTTP status, and contextual details.
This page is generated from the canonical ERROR_CODES registry in
packages/shared/src/errors.ts and lists every code in that
registry — 698 in total — grouped by domain. Every code
listed here is one the SDK and meta.docs_url link against. Some
route handlers also return operational codes that are not yet in the
registry and so are absent from the table below, so treat the code
on any server response as authoritative even when it is not listed
here.
HTTP status codes shown reflect the canonical status documented in the
source. Some codes are reused at multiple call sites with different
statuses (e.g.
VALIDATION_ERROR may surface as 400 or 422); the
table picks the dominant value. Treat the status field on the
response envelope as authoritative for any given response.Error Response Format
{
"error": {
"code": "INVALID_PHONE_NUMBER",
"message": "The 'to' field must be a valid E.164 phone number",
"status": 422,
"details": {
"field": "to",
"value": "+1234",
"expected": "E.164 format e.g. +14155552671"
}
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-03-08T00:00:00Z",
"docs_url": "https://docs.orbit.devotel.io/errors/INVALID_PHONE_NUMBER"
}
}
meta.docs_url resolves to a stable per-code anchor on this
page (/reference/error-codes#CODE_NAME — case-insensitive).
Authentication
| Code | HTTP | Description |
|---|---|---|
UNAUTHORIZED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_API_KEY | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
EXPIRED_TOKEN | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INSUFFICIENT_PERMISSIONS | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
IP_NOT_ALLOWED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
NOT_OWNING_AGENT | 404 | 404 — POST /voice/queues/:queueId/calls/:callId/disposition refused to record a disposition because the authenticated agent is not the assigned_agent_user_id on the queue entry. |
WRONG_KEY_MODE | 403 | Audit #SANDBOX-1 — returned when an API key’s mode (sandbox vs. live, derived from the dv_test_sk_* / dv_live_sk_* prefix and the api_keys.mode column) does not match the resolved organization’s is_sandbox flag. |
SAML_USER_NOT_IN_ORG | varies | Returned by the SAML ACS when an IdP assertion succeeds cryptographically but the asserted email either belongs to a different Devotel organisation OR has no invitation / enforcement on the callback org. |
SCIM_ROLE_CEILING_EXCEEDED | varies | Returned by the SCIM PATCH /Groups endpoint when the requested target role exceeds the org’s configured max_assignable_role ceiling (default ‘admin’). |
WEBHOOK_BODY_MISSING | varies | Returned when a Clerk webhook arrives but the content-type parser that captures the raw request bytes for svix signature verification didn’t run (e.g. non-JSON content-type). |
INVALID_SIGNATURE | 401 | HTTP 401 — an inbound webhook receiver rejected a request because the provider signature (HMAC / svix / X-Hub-Signature-256 / Twilio X-Twilio-Signature, etc.) failed verification, or the timing-safe comparison against the configured sh… |
STALE_WEBHOOK | 401 | HTTP 401 — an inbound webhook/DLR receiver rejected a request because the event timestamp is missing or falls outside the allowed replay window (a clock-skew / replay-attack guard). |
CANNOT_REVOKE_CURRENT_SESSION | 400 | HTTP 400 — the session-revoke endpoint (DELETE /settings/security/sessions/:sessionId) refused to revoke the caller’s own currently-signed-in session; end the current session through the sign-out flow instead. |
Validation
| Code | HTTP | Description |
|---|---|---|
VALIDATION_ERROR | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
DB_ERROR | 500 | 500 — generic database operation failure surfaced to clients by the inbox conversation-tags + SLA controllers (e.g. “Failed to create conversation tag definition”). |
NO_VARIANT_FOR_CHANNEL | 422 | 422 — a content template (multi-channel message template) has no variant for the requested target channel and no fallback in fallback_chain resolved to a channel that does. |
WEAK_IDENTITY_MATCH_REQUIRES_CONFIRMATION | 422 | 422 — POST /conversations/:id/merge refused a merge whose only cross-row identity overlap is phone OR email while the rows ALSO carry contradicting contact_id values (different ids, or one side has an id and the other doesn’t). |
INVALID_PHONE_NUMBER | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_FROM_NUMBER | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_EMAIL | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_TEMPLATE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
MISSING_REQUIRED_FIELD | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
MMS_NANP_ONLY | varies | MMS submitted to a non-NANP destination. |
ATTACHMENT_TOO_LARGE | 422 | 422 — POST /inbox/tickets/:id/attachments refused to register a ticket attachment because the declared size_bytes exceeds the per-attachment ceiling (TICKET_ATTACHMENT_MAX_BYTES, 25 MiB). |
INVALID_CURSOR | 400 | HTTP 400 — a cursor-paginated list endpoint rejected the cursor query parameter because it is malformed, truncated, tampered, or no longer resolves to a row in the current result window. |
TURNSTILE_REQUIRED | 422 | 422 — a public, unauthenticated anti-bot endpoint rejected a submission because the Cloudflare Turnstile token was missing, malformed, or failed siteverify (fail-closed when the Turnstile secret is configured). |
Resources
| Code | HTTP | Description |
|---|---|---|
NOT_FOUND | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
ALREADY_EXISTS | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CONFLICT | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
DUPLICATE_SENDER_ID | 409 | 409 — POST /settings/sender-ids refused to register a sender ID because an entry with the same value already exists on this workspace for the same channel. |
CONTACT_PHONE_ALREADY_EXISTS | 409 | 409 — POST /contacts or PATCH /contacts/:id collided with the tenant’s partial UNIQUE index contacts_phone_live_uq (predicate: deleted_at IS NULL AND phone IS NOT NULL). |
CONTACT_EMAIL_ALREADY_EXISTS | 409 | 409 — same shape as CONTACT_PHONE_ALREADY_EXISTS but for the partial UNIQUE index contacts_email_live_uq. |
CONTACT_WHATSAPP_BSUID_ALREADY_EXISTS | 409 | 409 — partial UNIQUE index idx_contacts_whatsapp_bsuid collision. |
CONTACT_ARCHIVED_REQUIRES_UNARCHIVE | 409 | 409 — PUT /contacts/:id attempted to move an archived contact to a non-archived lifecycle_stage without the explicit unarchive: true companion flag. |
TEMPLATE_NAME_ALREADY_EXISTS | 409 | 409 — POST /messages/templates collided with the tenant’s uq_templates_channel_name unique index (channel, name). |
CONTACT_NOT_FOUND_FOR_IDENTIFIER | 404 | 404 — POST /contacts/lists/:id/members identifier resolver could not map the operator-supplied phone / email / contact id / name to any existing contact in the tenant. |
GONE | 410 | HTTP 410 Gone — resource existed but is permanently unavailable (revoked / expired / single-use exhausted). |
Rate Limiting
| Code | HTTP | Description |
|---|---|---|
RATE_LIMIT_EXCEEDED | 429 | Per-recipient, per-tenant, and per-resource frequency-cap HTTP 429, raised by the messaging, verify, DSAR, and number-pool limiters with a retry_after value in seconds. |
QUOTA_EXCEEDED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
DAILY_CAP_EXCEEDED | 429 | Audit #WARMING-1 — per-DID 10DLC daily-cap reached on the pre-send gate (apps/api/src/lib/sms-warming-cap.ts). |
WARMING_QUOTA_EXCEEDED | varies | NaaS number-warming progression (2026-05-28) — newly-acquired 10DLC numbers ramp gradually for carrier reputation. |
NUMBER_MPS_EXCEEDED | 429 | NaaS per-DID messaging throughput cap (2026-06-09) — operator-set hard per-second send ceiling on a single number, enforced by apps/api/src/lib/per-number-mps-cap.ts. |
Messaging
| Code | HTTP | Description |
|---|---|---|
MESSAGE_SEND_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
EMAIL_SEND_FAILED | 500 | 500 — POST /messages email send: a single recipient’s send failed with a non-DevotelError rejection (e.g. a Resend 5xx, fetch ECONNRESET, or a Drizzle/postgres fault inside the send pipeline). |
EMAIL_SEND_FAILED_ALL | varies | POST /messages email fan-out: EVERY recipient failed. |
MESSAGE_NOT_EDITABLE | 409 | 409 — PATCH /messages/:id (Twilio Message.update parity) refused to edit a scheduled message that is no longer in scheduled state. |
MESSAGE_NOT_CANCELLABLE | 409 | 409 — DELETE /messages/:id refused to cancel a scheduled message that is no longer in scheduled state. |
CONVERSATION_NOT_FOUND | 404 | 404 — POST /messages was given an optional conversation_id to thread a reply, but the id does not reference a conversation on your account. |
CONVERSATION_MISMATCH | 422 | 422 — POST /messages conversation_id resolved to a real conversation, but it does not belong to this recipient and channel. |
CHANNEL_UNAVAILABLE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CHANNEL_NOT_CONFIGURED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CHANNEL_COMING_SOON | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CHANNEL_NOT_REPLYABLE | 422 | SCAN-INBOX-018 (2026-05-23) — caller selected a reply channel that is an inbox-only triage label (agent, video) rather than an outbound provider. |
MISSING_IDENTITY | varies | SCAN-INBOX-018 (2026-05-23) — caller asked to reply on a real channel but the conversation row carries no usable identity for that channel (e.g. web_chat thread with no metadata.visitor_id; SMS thread with no contact_phone). |
SENDER_ID_NOT_REGISTERED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
SENDER_ID_NOT_APPROVED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
NO_SENDER_CONFIGURED | 422 | #R3-ONB-T1-FIRSTSEND (2026-05-24) — first-send opaque error fix. |
SENDER_REQUIRED | 422 | 422 — a direct API / SDK send omitted every sender selector (from, sender_pool_id, messaging_service_id, from_extension). |
SENDER_INVALID_FOR_DESTINATION | varies | Wave-W5-C — Sender ID violates the destination country’s per-country format / prefix / length rules (see packages/messaging/src/sender-id-rules.ts). |
SENDER_ID_CHECK_UNAVAILABLE | 503 | Wave-W1 CPA-001 — Alpha sender approval gate could not reach Redis or the DB to verify whether the supplied alphanumeric sender ID is approved for this tenant. |
SENDER_NOT_OWNED | 422 | Wave-W1 SCAN-TI-005 — numeric E.164 sender that is NOT in the calling tenant’s phone_numbers table BUT does exist in public.platform_numbers assigned to a different organization. |
SENDER_OWNERSHIP_CHECK_UNAVAILABLE | 503 | TI-2026-002 — companion to SENDER_NOT_OWNED. |
SENDER_POOL_RESOLUTION_FAILED | varies | Sender-pool resolution failed at send time. |
SENDER_POOL_NOT_FOUND | varies | The sender_pool_id on a send refers to a row that doesn’t exist in this tenant. |
SENDER_POOL_EMPTY | varies | The pool resolved fine but its sender_dids array is empty — the dashboard should prompt for at least one DID. |
FALLBACK_CARRIER_NOT_FOUND | varies | retry_policy.fallback_carriers referenced a carrier id (or slug) that doesn’t exist in this tenant’s smpp_carriers table. |
TEMPLATE_NOT_APPROVED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
TEMPLATE_SEND_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
TEMPLATE_FETCH_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
TEMPLATE_CREATE_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
TEMPLATE_PARAMS_MISMATCH | varies | Legacy — superseded by WHATSAPP_TEMPLATE_VAR_COUNT_MISMATCH. |
TEMPLATE_NOT_LOCALIZABLE | 422 | 422 — POST /messages/templates/:id/localize refused to auto-localize a template that has no translatable body text, because there is nothing for the model to translate into the target locales. |
WHATSAPP_TEMPLATE_VAR_COUNT_MISMATCH | 400 | Pre-flight check for WhatsApp template sends — caller supplied a template_params count that doesn’t match the distinct {{N}} positional placeholders declared across the template’s header + body components, OR supplied empty/whitespac… |
SANDBOX_MAGIC_NUMBER_BLOCKED | 422 | Pre-send guard — recipient is a vendor-reserved sandbox magic number (Twilio +1 (500) 555-000X range). |
SMS_BLOCKED_DESTINATION | varies | SMS fraud guard: destination prefix on the platform blocklist (premium / pumped routes). |
SMS_RATE_LIMITED | varies | SMS fraud guard: tenant exceeded per-minute send cap. |
SMS_DAILY_SPEND_CAP | varies | SMS fraud guard: tenant exceeded daily spend cap (estimate-based). |
CHANNEL_BLOCKED_DESTINATION | varies | Cross-channel fraud guard codes (audit #MSG-003, 2026-05-11). |
CHANNEL_RATE_LIMITED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CHANNEL_DAILY_SPEND_CAP | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
WHATSAPP_TIER_LIMIT_EXCEEDED | 429 | WhatsApp tier-aware backpressure (CPaaS gap closure, 2026-05-30). |
NOT_SMS_CAPABLE | varies | Reserved messaging-capability error code. |
MEDIA_UPLOAD_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_RECIPIENT | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
FRAUD_BLOCKED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
FRAUD_SHIELD_BLOCKED | 403 | 403 — the SMS send was rejected by the tenant’s Fraud Shield policy running in enforcement mode block (configured at /settings/compliance/fraud-shield). |
WHATSAPP_SESSION_EXPIRED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
MESSAGING_WINDOW_CLOSED | varies | Meta’s 24-hour messaging window has elapsed for this Messenger or Instagram conversation and the caller did not supply a messaging tag. |
RCS_NOT_SUPPORTED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
PENDING_ACCEPTANCE | 425 | Returned by /rcs/test-account/verify-otp while waiting for the user to tap “Make me tester” on the Dotgo RBM tester invite they received in Google Messages. |
INVITE_DECLINED | varies | The user tapped “Decline” on the Dotgo RBM tester invite. |
WHATSAPP_NOT_CONNECTED | varies | Caller tried to use a WhatsApp feature (template create, send, etc.) but the org has no connected WABA. |
WHATSAPP_CONNECTION_INVALID | varies | The org has a WABA row but the encrypted access_token failed to decrypt (key rotation, manual DB edit, encryption-version drift). |
WHATSAPP_BYO_INCOMPLETE | varies | TEST-USER K-004 (2026-05-26) — BYO WhatsApp half-config billing-leak guard. |
WHATSAPP_PAY_NOT_ENABLED | varies | WhatsApp Pay is not enabled on the tenant’s WABA. |
TEMPLATE_REJECTED | varies | Meta rejected a template submission for content reasons. |
WHATSAPP_CALL_PERMISSION_FAILED | varies | Meta rejected a WhatsApp Business Calling permission request — the recipient hasn’t granted call permission inside WhatsApp, or the conversation window is closed. |
WHATSAPP_OUTSIDE_24H_WINDOW | 422 | Meta’s 24-hour customer-service-window gate. |
WHATSAPP_CALLING_BLOCKED_COUNTRY | 422 | The (E.164 country code of the) phone number is on the WA-Calling-blocked country list (US/CA/EG/VN/NG as of May 2026 per Meta’s WhatsApp Business Calling rollout). |
WHATSAPP_CALLING_PROVISION_FAILED | varies | Generic provisioning failure when toggling calling on/off via Meta. |
WHATSAPP_CALLING_PERMISSION_MISSING | varies | The recipient contact has not granted business-calling permission (or it has expired / been revoked). |
WHATSAPP_CALLING_NO_PERMISSION | varies | Phase-2 alias of WHATSAPP_CALLING_PERMISSION_MISSING surfaced specifically by the outbound POST /whatsapp/calling/calls route (initiateCall). |
WHATSAPP_CALLING_INSUFFICIENT_BALANCE | 402 | 402 (or 503) — WA Calling wallet pre-flight on POST /whatsapp/calling/calls: 402 when the wallet can’t cover the worst-case (max-call-minutes × per-minute rate) cost, 503 when the balance read itself fails (fail-closed, retryable). |
WHATSAPP_CALLING_DAILY_CAP_EXCEEDED | 429 | Outbound or inbound WA Calling event was admitted past the country gate but the per-tenant daily cost cap (configured in organizations.settings.whatsapp_calling_daily_cap_cents) is already exhausted. |
WHATSAPP_NO_CALLING_PHONE | 422 | Shared-WABA calling resolver fell through with no callable phone (audit #WABA-SHARED-CALLING-1, 2026-05-11). |
WHATSAPP_CALLING_MEDIA_NOT_PROVISIONED | 503 | Outbound WA Calling refused because the platform’s WhatsApp media gateway is not provisioned yet. |
WHATSAPP_SHARED_CALLING_QUALITY_PAUSED | 503 | Devotel’s shared calling phone has a quality_rating=RED per Meta Graph (audit #WABA-SHARED-CALLING-1). |
VERIFIED_PHONE_OVERWRITE_REQUIRES_CONFIRMATION | 409 | Audit #WABA-TEST-EDITABLE-1 — caller attempted to send a test-account OTP to a phone different from the org’s currently-verified number WITHOUT passing allow_overwrite=true. |
WHATSAPP_CALL_ACTION_FAILED | varies | Meta rejected a call-control action (pre_accept / accept / reject / terminate). |
WHATSAPP_CALL_INITIATE_FAILED | varies | Outbound WhatsApp call initiate failed (POST //calls). |
WHATSAPP_BLOCK_OPERATION_FAILED | varies | Block-list management failed (POST/DELETE/GET //block_users). |
WHATSAPP_BLOCK_LIST_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
WHATSAPP_PROFILE_GET_FAILED | varies | Business profile read / update via /whatsapp_business_profile. |
WHATSAPP_PROFILE_UPDATE_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
WHATSAPP_CONVERSATIONAL_AUTOMATION_GET_FAILED | varies | Conversational automation (ice breakers / commands / welcome message) read + update via /conversational_automation. |
WHATSAPP_CONVERSATIONAL_AUTOMATION_UPDATE_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
WHATSAPP_TEMPLATE_EDIT_FAILED | varies | Template edit (POST /) and delete (DELETE //message_templates). |
WHATSAPP_TEMPLATE_DELETE_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
WHATSAPP_REQUEST_CODE_FAILED | varies | Display-name change verification (request_code / verify_code). |
WHATSAPP_VERIFY_CODE_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VERIFY_RECIPIENT_RATE_LIMITED | 429 | Per-recipient verify OTP rate limit hit (anti-SMS-pumping / anti-harassment gate in verify.service.sendVerification). |
VERIFY_RESEND_COOLDOWN | 429 | Per-recipient verify OTP resend cooldown hit. |
WHATSAPP_CATALOG_API_FAILED | varies | Catalog / product CRUD against //owned_product_catalogs. |
CATALOG_ERROR | 500 | 500 — the WhatsApp commerce catalog-list surface (GET /whatsapp/catalogs and GET /whatsapp/catalog) hit an unexpected server-side failure while fetching the tenant’s Meta product catalog. |
CATALOG_SEND_ERROR | 500 | 500 — a WhatsApp commerce product-message send hit an unexpected server-side failure while dispatching a catalog or single/multi product interactive to Meta. |
WHATSAPP_FLOW_SEND_FAILED | varies | Send-flow as interactive message — POST //messages type=flow. |
WHATSAPP_INTERACTIVE_SEND_FAILED | varies | Generic interactive (reply-button / list) send — POST //messages type=interactive. |
WHATSAPP_ANALYTICS_API_FAILED | varies | //pricing_analytics or /template_analytics fetch. |
WHATSAPP_UPLOAD_API_FAILED | varies | Resumable upload session create / append chunk / finalize. |
WHATSAPP_TEMPLATE_PARAM_MISSING | varies | Meta 131008 — required template parameter missing (commonly AUTH OTP button). |
WHATSAPP_RE_ENGAGEMENT_WINDOW_CLOSED | varies | Meta 131026 — 24h customer-care window expired; only templates allowed. |
WHATSAPP_RE_ENGAGEMENT_REQUIRED | varies | Meta 131047 — re-engagement requires a template since contact’s last message >24h ago. |
WHATSAPP_UNSUPPORTED_MESSAGE_TYPE | varies | Meta 131051 — message type unsupported on recipient device/region. |
WHATSAPP_TEMPLATE_NOT_FOUND | varies | Meta 132001 — template name does not exist in any of the requested languages. |
WHATSAPP_TEMPLATE_PARAM_FORMAT | varies | Meta 132012 — parameter format mismatch (named vs positional, type, length). |
WHATSAPP_TEMPLATE_PAUSED | varies | Meta 132016 — template paused due to low quality / high block rate. |
WHATSAPP_TEMPLATE_DISABLED | varies | Meta 132068/132069 — template disabled by Meta after policy violation. |
WHATSAPP_ACCOUNT_NOT_REGISTERED | varies | Meta 133010 — account hasn’t completed registration; sends blocked. |
WHATSAPP_BILLING_ISSUE | varies | Meta 131042 — WABA payment method failing on Meta’s side; sends blocked until the operator updates billing in Meta Business Manager. |
WHATSAPP_INVALID_PARAMETER | varies | Meta 100 — invalid parameter or deprecated field. |
WHATSAPP_TOKEN_EXPIRED | varies | Meta 190 — access token expired / revoked / scopes removed. |
WHATSAPP_POLICY_BLOCK | varies | Meta 368/470 — temporary policy block on account or recipient. |
WHATSAPP_RECIPIENT_INVALID | varies | Meta 1304/2388042 — recipient phone number invalid for this region. |
WHATSAPP_SERVICE_UNAVAILABLE | varies | Meta 131016 — Cloud API service unavailable. |
WHATSAPP_ACCOUNT_LOCKED | varies | Meta 131031 — WABA locked by Meta after sustained policy issue. |
WHATSAPP_SENDER_NOT_APPROVED | varies | Meta 131045 — sender not approved for marketing templates yet. |
TEMPLATE_SYNC_FAILED | 400 | Devotel — POST /whatsapp/templates/sync failed against Meta Graph (OAuth/token/IP-allowlist/WABA-state). |
WHATSAPP_US_MARKETING_PAUSED | 422 | Devotel preflight — marketing templates to US (+1, non-Canada NANP) recipients are paused by Meta since April 2025. |
WHATSAPP_MARKETING_FREQUENCY_CAPPED | varies | Meta 131049 — a MARKETING template was not delivered to this recipient “to maintain healthy ecosystem engagement” (Meta’s per-recipient marketing-message frequency cap). |
WHATSAPP_USER_OPTED_OUT | varies | Meta 131050 — recipient opted out of marketing on WhatsApp. |
WHATSAPP_MEDIA_DOWNLOAD_FAILED | varies | Meta 131052 — media at the supplied URL couldn’t be downloaded. |
WHATSAPP_MEDIA_UPLOAD_FAILED | varies | Meta 131053 — media upload to WhatsApp failed (size / MIME). |
WHATSAPP_ACCOUNT_QUALITY_LOW | varies | Meta 133000 — overall account quality dropped; sends still allowed but Meta will reduce the messaging tier if it persists. |
WHATSAPP_RATE_LIMITED | varies | Meta 133004/133015 — short rate-limit / cooldown asked by Meta. |
WHATSAPP_2FA_PIN_REQUIRED | varies | Meta 133005-133009 — 2-step verification PIN required / mismatch / cooldown / wrong-attempt lock / wrong length. |
WHATSAPP_TOKEN_EXCHANGE_FAILED | varies | Auth code expired / single-use / wrong redirect — re-run signup. |
WHATSAPP_ACCESS_TOKEN_EXPIRED | varies | Stored long-lived token expired (60d max) — reconnect to refresh. |
WHATSAPP_NO_WABA | varies | No WABA on the user’s Meta login. |
WHATSAPP_NO_PHONE_NUMBER | varies | WABA exists but no phone number is registered on it. |
WHATSAPP_INVALID_SELECTION | varies | Selected (waba_id, phone_number_id) pair isn’t on the user’s token. |
WHATSAPP_PHONE_NOT_OWNED | varies | Selected phone number isn’t part of any WABA the user owns. |
WHATSAPP_BUSINESS_STATUS_PENDING | varies | Business is still under Meta verification review. |
WHATSAPP_BUSINESS_VERIFICATION_REQUIRED | varies | Business hasn’t completed verification at all. |
WHATSAPP_PHONE_VERIFY_REQUIRED | varies | Phone-number SMS/voice OTP not yet completed in WhatsApp Manager. |
WHATSAPP_WABA_ALREADY_LINKED | varies | WABA already linked to another Orbit organization. |
WHATSAPP_META_APP_DISABLED | varies | Devotel’s Meta app is temporarily disabled. |
WHATSAPP_REGION_UNSUPPORTED | varies | Region not in Meta’s supported country list for WhatsApp Business API. |
WHATSAPP_CONNECTION_NOT_FOUND | varies | Existing connection not found on the org (reconnect / rename / default). |
Telegram
| Code | HTTP | Description |
|---|---|---|
TELEGRAM_PROVIDER_ERROR | varies | Telegram Bot API returned a non-2xx ({ok:false, description}) or a network failure on getMe/setWebhook/sendMessage. |
TELEGRAM_BOT_ALREADY_CONNECTED | varies | Org already has a BYO Telegram bot connected; reconnect by disconnecting first. |
TELEGRAM_INVALID_BOT_TOKEN | varies | BotFather token failed regex / getMe validation. |
TELEGRAM_CHANNEL_NOT_CONNECTED | varies | Caller attempted a Telegram send (e.g. State 5 test send) but the org has no active row in public.telegram_bot_credentials. |
Email (test-mode gate)
| Code | HTTP | Description |
|---|---|---|
EMAIL_TEST_RECIPIENT_NOT_VERIFIED | varies | Shared-account test-mode recipient gate (mirrors WhatsApp test): only addresses the tenant has explicitly OTP-verified can receive shared-Resend mail. |
Crypto envelope
| Code | HTTP | Description |
|---|---|---|
ENCRYPTION_FAILED | varies | AES-256-GCM enc:v1: envelope failed during write (random IV / authTag generation failure, libsodium / WebCrypto unavailable). |
DECRYPTION_FAILED | 502 | AES-256-GCM enc:v1: envelope failed during read (key rotation left a stale ciphertext, authTag mismatch, or the master key is missing). |
Voice
| Code | HTTP | Description |
|---|---|---|
CALL_FAILED | 502 | 502 — generic voice call-control failure raised when the Jambonz REST control surface (jambonz-rest.ts) or the outbound call-create path cannot complete a call create / update / hangup. |
SIP_ERROR | varies | Reserved SIP-layer call-control error code. |
VOICE_GATEWAY_ERROR | 502 | 502 — the voice gateway (Jambonz / SBC) returned a transient error or was unreachable during a call-control or media operation (outbound dispatch, voicemail-greeting TTS synthesis + GCS upload, mid-call actions). |
TTS_SYNTHESIS_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
STT_TRANSCRIPTION_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VOICE_BLOCKED_DESTINATION | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VOICE_DNO_BLOCKED | 422 | Gap CSPAAS — Do-Not-Originate (DNO) origination-time block. |
EMERGENCY_CALLING_NOT_SUPPORTED | varies | Audit #E911-BLOCK-1 / invariant #49 — outbound voice rejected because the dialed number resolved to an emergency short code (911 / 112 / 999 / 000 — see EMERGENCY_NUMBERS_BLOCKED in @devotel/shared/constants). |
VOICE_RATE_LIMITED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VOICE_COUNTRY_RATE_LIMITED | 429 | HTTP 429 — outbound voice rejected by the per-destination-country sliding-window rate cap in voice-fraud-guard.ts. |
SOFTSWITCH_UNHEALTHY | 503 | CCaaS dialer — wholesale softswitch / Jambonz transport-health circuit breaker tripped (failed-attempt rate above threshold in the recent window). |
VOICE_DAILY_SPEND_CAP | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VOICE_TRANSFER_FAILED | 502 | 502 — the voice gateway rejected a mid-call transfer. |
VOICE_CALLER_ID_REJECTED | varies | Customer-trunk INVITE rejected — caller-id not in allowedCallerIds nor an org-owned DID. |
VOICE_CHALLENGE_FAILED | varies | Caller-ID ownership-challenge (OTP verify/resend) failed; infra detail redacted before re-throw (r3 S14). |
UNVERIFIED_CALLER_ID | varies | R16FIX3_UNVERIFIED_CALLER_ID_GATE (2026-05-30) — outbound voice/SMS preflight refused the supplied from because it is neither a platform-owned/assigned DID for the org NOR a status='verified' row in the tenant’s verified_caller_ids… |
VOICE_TRUNK_HOURLY_CAP | varies | Customer-trunk hourly call cap exceeded for the trunk. |
VOICE_CLONE_CONSENT_REQUIRED | varies | Voice-clone creation refused for missing or invalid consent (SCAN-V-010). |
DTMF_UNSUPPORTED | varies | Mid-call DTMF inject not supported on this leg (B-237). |
RECORDING_TOGGLE_UNSUPPORTED | varies | Mid-call recording toggle not supported on this leg (B-242). |
EXPORT_TOO_LARGE | varies | CDR / call-log export filter would exceed the 100k row hard cap (B-240). |
TCPA_QUIET_HOURS | varies | Outbound voice call blocked by TCPA quiet-hours policy (08:00-21:00). |
TCPA_DIALING_WINDOW_BLOCKED | varies | Outbound voice call blocked by the TCPA dialing-window gate (8 AM–9 PM recipient-local). |
TCPA_FEDERAL_DIALING_WINDOW_BLOCKED | varies | Outbound voice call to a +1 NANP recipient blocked by the US TCPA FEDERAL dialing-window hard guard (47 U.S.C. |
TCPA_STATE_DIALING_WINDOW_BLOCKED | 422 | Outbound voice call blocked by a STATE mini-TCPA dialing-window or day-of-week restriction (e.g. FL Fla. |
FCC_AI_VOICE_WRITTEN_CONSENT_REQUIRED | varies | Outbound voice call blocked because the recipient has not granted “prior express WRITTEN consent” for AI-generated / synthesized / cloned voice content. |
QUIET_HOURS_BLOCKED | varies | Outbound non-voice send (SMS / MMS / WhatsApp / RCS / Email / Telegram / Viber / Instagram / Messenger / LINE / Apple Messages) blocked by the universal quiet-hours gate. |
TCPA_TIMEZONE_UNKNOWN | varies | Outbound voice call blocked because the recipient’s timezone could not be resolved (neither NANP area-code nor E.164 country prefix matched). |
QUIET_HOURS_TIMEZONE_UNKNOWN | varies | Non-voice channel equivalent of TCPA_TIMEZONE_UNKNOWN. |
DNC_CONTACT | varies | Recipient contact row has dnc=true. |
DNC_NUMBER | varies | Recipient number found in dnc_list table. |
COMPLIANCE_CHECK_UNAVAILABLE | varies | Compliance-layer DB check could not run. |
CAMPAIGN_VOICE_SPEND_CAP_REACHED | varies | Per-campaign voice-spend cap reached; campaign auto-paused. |
NOT_IMPLEMENTED | varies | Returned when a request targets a provider integration or capability that is defined but not yet generally available — e.g. a compliance submission for a carrier without a live provider, or an upstream SMPP carrier type reserved for a fu… |
FLIP_ALREADY_PULLED | 410 | 410 — POST /voice/call-flip/pull refused: the one-time call-flip handoff token was already pulled by the targeted device. |
FLIP_EXPIRED | 410 | 410 — call-flip pull refused: the handoff token expired before it was pulled. |
FLIP_TARGET_MISMATCH | 403 | 403 — call-flip pull refused: the handoff is pinned to a different target device than the caller’s. |
FLIP_NOT_FOUND | 404 | 404 — no live call-flip handoff matches the supplied pull token. |
FLIP_ALREADY_CONSUMED | 410 | 410 — call-flip cancel/pull refused: the handoff was already pulled or cancelled. |
PARK_SLOTS_FULL | 409 | 409 — auto-park refused: every park slot in the tenant’s park orbit is already occupied. |
PARK_SLOT_OCCUPIED | 409 | 409 — park-to-slot refused: the explicitly requested park slot is already occupied. |
PARK_ALREADY_RETRIEVED | 410 | 410 — park retrieve refused: the call previously parked in that slot was already retrieved. |
PARK_SLOT_EMPTY | 404 | 404 — park retrieve refused: no call is currently parked in the requested slot. |
PARK_ALREADY_RELEASED | 410 | 410 — park release refused: the parked call was already released. |
PARK_NOT_FOUND | 404 | 404 — parked call not found for the supplied identifier. |
HOT_DESK_RACE | 409 | 409 — hot-desk sign-in lost a concurrent race for the device and should be retried. |
HOT_DESK_ALREADY_SIGNED_OUT | 410 | 410 — hot-desk sign-out refused: the user is already signed out. |
HOT_DESK_NO_ACTIVE_SESSION | 404 | 404 — hot-desk sign-out refused: the user has no active hot-desk session. |
HOT_DESK_ALREADY_RELEASED | 410 | 410 — hot-desk session release refused: the session was already released. |
HOT_DESK_NOT_FOUND | 404 | 404 — hot-desk session not found for the supplied id. |
SECURE_PAYMENT_UNSUPPORTED | 422 | 422 — agent-assisted secure payment requires a Jambonz-bridged call leg and this call has none. |
SECURE_PAYMENT_ALREADY_ACTIVE | 409 | 409 — a secure-payment capture session is already active on this call. |
SECURE_PAYMENT_SESSION_NOT_FOUND | 404 | 404 — no secure-payment session with the supplied id exists on this call. |
SECURE_PAYMENT_NOT_ACTIVE | 409 | 409 — the secure-payment session is not in the capturing state (already completed or cancelled). |
SECURE_PAYMENT_INVALID_MASK | 422 | 422 — card_last4 must be exactly the last four digits of the PAN, never the full card number. |
PICKUP_NO_RINGING_CALL | 404 | 404 — POST /voice/pickup/directed (or /voice/pickup/group) found no ringing call to answer: nothing is ringing on the target extension, or no call is ringing in the caller’s pickup group. |
PICKUP_ALREADY_TAKEN | 409 | 409 — a call-pickup request lost the atomic claim race: another device answered the ringing call first. |
Video rooms
| Code | HTTP | Description |
|---|---|---|
VIDEO_ROOM_CREATE_FAILED | varies | Returned when an Orbit Media call fails during video-room creation (immediate path). |
VIDEO_ROOM_OPEN_FAILED | varies | Returned when an Orbit Media call fails during the lazy-open of a scheduled room (first host/participant join). |
VIDEO_PARTICIPANT_KICK_FAILED | varies | Returned when the Orbit Media removeParticipant call fails while removing a participant from a room. |
VIDEO_PARTICIPANT_MUTE_FAILED | varies | Returned when the Orbit Media mutePublishedTrack call fails while muting a participant’s track. |
VIDEO_RECORDING_STOP_BACKEND_FAILED | varies | Returned when the Orbit Media stopEgress call rejects while stopping a room recording. |
VIDEO_WEBHOOK_VERIFICATION_FAILED | varies | Returned when the Orbit Media webhook JWT signature cannot be verified. |
RECORDING_SIGN_FAILED | 503 | P2-shard-F (2026-06-02) — Returned when RecordingService.generateSignedUrl fails to mint a V4 signed GCS playback URL (GCS auth failure, IAM denial, transient GCS outage, ADC misconfiguration). |
VIDEO_BACKGROUND_INVALID | 400 | 400 — POST /video/backgrounds refused to register a branded virtual-background asset because the submitted asset failed library-side validation (e.g. duplicate name, malformed/blocked URL, or the per-tenant background limit was reached). |
VIDEO_BACKGROUND_NOT_FOUND | 404 | 404 — DELETE /video/backgrounds/:assetId could not find a registered virtual-background asset with that id in the tenant’s background library. |
AGENT_NOT_DEPLOYABLE | 409 | 409 — POST /video/rooms/:id/dispatch-agent refused to dispatch an AI agent into a room because the referenced agent is not in the active state. |
Call recordings (QC / legal-hold / integrity / share)
| Code | HTTP | Description |
|---|---|---|
RECORDING_QC_FETCH_FAILED | 500 | 500 — GET /recordings/:id/qc could not load the stored QC verdict for a call recording. |
RECORDING_QC_RUN_FAILED | 500 | 500 — POST /recordings/:id/qc/run failed while synchronously re-running the recording QC scorer (the scorer threw, or a DB write failed). |
RECORDING_QC_INVALID_ID | 400 | 400 — the :id path param on a GET /recordings/:id/qc or POST /recordings/:id/qc/run operation failed param validation (empty / over the length cap). |
RECORDING_QC_NOT_FOUND | 404 | 404 — GET /recordings/:id/qc or POST /recordings/:id/qc/run received a syntactically valid recording id that matched no recording row in the tenant schema (missing / tombstoned). |
RECORDING_LEGAL_HOLD_FETCH_FAILED | 500 | 500 — GET /recordings/:id/legal-hold could not load the legal-hold state for a recording (DB / tenant-schema fault). |
RECORDING_LEGAL_HOLD_SET_FAILED | 500 | 500 — PUT /recordings/:id/legal-hold failed to place or release a legal hold (the compliance-governance write threw after passing validation / auth). |
RECORDING_INTEGRITY_FETCH_FAILED | 500 | 500 — GET /recordings/:id/integrity could not load the recording integrity seal (DB / tenant-schema fault). |
RECORDING_INTEGRITY_VERIFY_FAILED | 500 | 500 — the recording integrity-seal verification path failed unexpectedly (the recompute-and-compare digest check threw before returning a pass/fail verdict). |
RECORDING_INTEGRITY_EXPORT_DIGEST_FAILED | 500 | 500 — building the signed export digest for a recording’s integrity evidence failed unexpectedly (digest assembly / signing threw). |
RECORDING_INTEGRITY_SEAL_FAILED | 500 | 500 — sealing a recording (minting and persisting its tamper-evidence integrity seal) failed unexpectedly. |
RECORDING_SHARE_CREATE_FAILED | 500 | 500 — POST /recordings/:id/shares could not create a share link for a recording (DB write / token-mint fault after validation + auth). |
RECORDING_SHARE_REVOKE_FAILED | 500 | 500 — revoking a recording’s share link(s) failed unexpectedly (the revoke write threw). |
Agent
| Code | HTTP | Description |
|---|---|---|
AGENT_ERROR | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
AGENT_NOT_CONFIGURED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
AGENT_RESPONSE_INVALID | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_MODEL | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
LLM_PROVIDER_ERROR | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
LLM_TIMEOUT | 504 | 504 — An AI-generation endpoint’s LLM round-trip exceeded its abort deadline (AbortSignal.timeout). |
LLM_UPSTREAM_ERROR | 502 | 502 — An AI-generation endpoint’s upstream LLM call failed with a non-timeout provider/transport error. |
AI_PARSE_FAILED | 422 | 422 — An AI-generation endpoint received model output that could not be parsed into the required structured shape (non-JSON / schema mismatch). |
GUARDRAIL_VIOLATION | varies | Reserved AI-guardrail error code. |
GRAPH_VALIDATION_FAILED | 422 | 422 — Agent Studio graph publish validation failed; the submitted graph did not pass structural validation and details carries the per-node validation errors. |
GRAPH_TOOL_NODES_NOT_SUPPORTED_IN_TEST_RUN | 422 | 422 — Agent Studio test-run was asked to execute a graph containing tool nodes, which the sandboxed test-run does not execute; publish the graph and invoke the agent’s /run endpoint instead. |
RESERVED_TOOL_NAME | 422 | 422 — Custom-tool registration rejected because the requested tool name is reserved for a built-in platform tool; pick a tenant-specific slug. |
INVALID_EXECUTOR_URL | 422 | 422 — Custom-tool executor_url rejected by the SSRF write-time guard (non-https, private/loopback, cloud-metadata host, or a DNS record that resolves internally). |
TOOL_NAME_TAKEN | 409 | 409 — Custom-tool create collided with an existing custom tool of the same name in the tenant. |
TOOL_DISABLED | 409 | 409 — Custom-tool invocation refused because the referenced custom tool is disabled. |
INVALID_MCP_SERVER_URL | 422 | 422 — MCP-server registration rejected by the SSRF write-time guard on the server URL (non-https, private/loopback, cloud-metadata host, or a DNS record that resolves internally). |
INVALID_MCP_OAUTH_TOKEN_URL | 422 | 422 — MCP-server registration rejected by the SSRF write-time guard on the OAuth2 grant token_url (non-https, private/loopback, cloud-metadata host, or a DNS record that resolves internally). |
MCP_SERVER_NAME_CONFLICT | 409 | 409 — MCP-server registration collided with a server of the same name already registered for the agent (uq_mcp_servers_agent_name). |
LABELING_NO_INPUT | 422 | 422 — the agent fine-tuning labeling endpoint had nothing to label: the referenced conversation carries no user message and the caller did not supply an explicit input. |
LABELING_DATASET_FULL | 409 | 409 — the agent’s labeling dataset has reached its row ceiling, so no further labeled rows can be added. |
Agent Eval
| Code | HTTP | Description |
|---|---|---|
EVAL_COMPARE_DATASET_MISMATCH | varies | compareEvalRuns: run_a_id and run_b_id reference different datasets. |
EVAL_COMPARE_SAME_RUN | varies | compareEvalRuns: run_a_id === run_b_id. |
EVAL_RUNS_AGENT_MISMATCH | varies | compareEvalRuns: one or both runs belong to a different agent (SCAN-AGT-R2-010). |
EVAL_GATE_FAILED | 422 | 422 — Agent Studio publish blocked by the eval gate because the agent has no completed eval run meeting the configured minimum pass rate; run an eval against the agent before publishing. |
EVAL_REGRESSION_GATE_FAILED | 422 | 422 — Agent Studio publish blocked by the eval regression gate because the latest eval run regressed beyond the configured tolerance versus the baseline run; investigate and re-run evals before publishing. |
Billing
| Code | HTTP | Description |
|---|---|---|
PAYMENT_REQUIRED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
BUDGET_EXCEEDED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
BILLING_PROVIDER_ERROR | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
EMAIL_INTAKE_PARSE_ERROR | 422 | 422 — the admin rate-card email-intake preview could not parse the supplied raw MIME message into rate-card uploads (unreadable MIME, unsupported attachment, or an unparseable rate table). |
VOICE_BILLING_HOLD_FAILED | 503 | Security fix 2026-05-20 (exploit-voice-billing-hold-fail-open): Returned (503) when placeVoiceBillingHold cannot enforce spending controls due to an infrastructure error (Redis down, Lua error, etc.). |
VOICE_BILLING_CURRENCY_DEFERRED | varies | BIL-DEEP-012 (escalated P1, 2026-06-02): tenant wallet-currency could not be resolved at voice settle time (DB lookup threw / org row missing), AND the hold did not stamp a voice_billing.tenant_currency. |
SENDING_PAUSED | varies | A customer-configured billing_alerts rule with action=‘pause_outbound’ tripped; outbound sending is temporarily paused until manually reset. |
SENDING_BLOCKED | varies | A customer-configured billing_alerts rule with action=‘block_outbound’ tripped; outbound sending is hard-blocked until manually reset or the next billing cycle. |
FREQUENCY_CAP_EXCEEDED | 429 | Per-org frequency-cap rule hit — too many sends to this recipient on this channel inside the configured window. |
MESSAGING_SERVICE_MPS_EXCEEDED | 429 | PARITY-R1-016 — per-MessagingService throughput cap (Twilio MessagingService MPS parity) hit on the API-direct send path. |
NO_REACHABLE_CHANNEL | 422 | 422 — POST /billing/pay-by-link (and its /preview companion) could not select a delivery channel for the hosted-checkout link: none of the caller’s preferred_channels appears in reachable_channels, so there is no path to reach th… |
TRIAL_CREDIT_CAP_EXCEEDED | 422 | 422 — POST /billing/trial-credits refused a promotional trial-credit grant because the requested amount exceeds the effective per-tenant trial-credit cap (the platform default, optionally lowered — never raised — by a tenant override). |
TRIAL_CREDITS_FAILED | 500 | 500 — POST /billing/trial-credits failed to grant a promotional trial-credit grant because of an upstream infrastructure fault while applying the grant. |
Tenant / Multi-tenancy
| Code | HTTP | Description |
|---|---|---|
MISSING_TENANT | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
System
| Code | HTTP | Description |
|---|---|---|
INTERNAL_ERROR | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
SERVICE_UNAVAILABLE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
SESSION_REPLAY_OFFLOAD_FAILED | 503 | 503 — the widget session-replay ingest endpoint could not offload the batch’s overflow events to durable storage (the spill-to-GCS path that keeps replay capture lossless). |
ADMIN_ORG_MISSING_TENANT | 422 | Admin attempted an operation on an org whose tenant_id is NULL and whose slug also fails to derive a usable tenant — fail-fast 422 so the admin operator surfaces this to platform engineering instead of silently writing to a wrong tenant… |
BALANCE_SERVICE_UNAVAILABLE | 503 | Balance / credit-resolver service is temporarily unavailable because the Redis idempotency dedup layer is unreachable. |
SMPP_BACKEND_UNAVAILABLE | 503 | SMPP credential issuance / rotation failed because a backing dependency (tenant DB schema, encryption key, Jasmin reconciler queue) is temporarily unavailable. |
A2A_PEER_ERROR | 502 | Returned (502) when an outbound A2A (Agent-to-Agent) federation call to a peer agent failed — peer offline, peer card unreachable, peer JSON-RPC returned a non-2xx, or peer task envelope was malformed. |
A2A_DISCOVERY_DISABLED | 422 | Issue #259 (TU-230 deep-tail) — the dashboard A2A tab requested a card for an agent whose a2a_discovery_mode === 'disabled' (the default). |
WEBHOOK_DELIVERY_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
WEBHOOK_SIGNATURE_INVALID | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
WEBHOOK_SECRET_DECRYPT_FAILED | 503 | Wave-W1 CPA-011 — Webhook signing secret could not be decrypted because the stored value carried the platform enc:v1: envelope but the active DEVOTEL_ENCRYPTION_KEY no longer matches (rotation pending re-encrypt) OR the ciphertext is… |
WEBHOOK_AUTH_FAILED | varies | Wave-W1 CPA-005 (P0) — uniform shape for webhook authentication failures on unauthenticated provider webhooks (Meta WhatsApp Flows /endpoint, etc.). |
WEBHOOK_PROCESSING_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_WEBHOOK_URL | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
WEBHOOK_DNS_INVALID | 422 | Audit #PRV-001 (2026-05-12) — webhook-endpoint URL DNS-resolves to NXDOMAIN / NODATA / SERVFAIL. |
WEBHOOK_ENDPOINT_CAP_REACHED | varies | Tenant tried to create more than MAX_WEBHOOK_ENDPOINTS_PER_TENANT webhook endpoints (default 10). |
BULK_REPLAY_IN_PROGRESS | 409 | 409 — POST /webhooks/:id/replay-range (webhook bulk-replay) refused to start a new bulk-replay because one is already running or queued for the same endpoint. |
ENDPOINT_GONE | 404 | API-CONTRACT (admin DLQ webhook replay) — POST /admin/dlq/webhooks/:id/replay refused to re-enqueue because the target webhook endpoint the DLQ job was destined for has since been deleted or disabled (endpointPresence returned `“gone… |
ENDPOINT_LOOKUP_FAILED | 503 | API-CONTRACT (admin DLQ webhook replay) — companion to ENDPOINT_GONE. |
STRIPE_CUSTOMER_ORG_MISMATCH | varies | Audit #B-004 (2026-05-11) — payment_intent.succeeded webhook with forged metadata.orgId pointing at a victim tenant, paid by an attacker’s Stripe customer on the shared platform account. |
BUDGET_REDIS_UNAVAILABLE | 503 | Audit #B-040 (2026-05-11) — reserveBudget failed CLOSED because Redis was unavailable or the Lua eval threw. |
LLM_PLATFORM_CEILING_EXCEEDED | 503 | Security fix 2026-05-20 (exploit-llm-budget-no-platform-ceiling): Returned (503) when a new reservation would push the platform-wide aggregate monthly LLM spend above the configured ceiling. |
TENANT_NOT_FOUND | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
TENANT_PROVISIONING | 503 | Returned (503) by the auth middleware when an org row exists but its tenant_schema_ready flag is still FALSE — meaning the baseline schema creation or the per-tenant migration run has not finished (or failed). |
TENANT_SCHEMA_INCOMPLETE | 503 | Returned (503) when a tenant-schema-scoped query hits SQLSTATE 42P01 (undefined_table) on a table introduced by a recent feature migration. |
RECIPIENT_OPTED_OUT | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CONTACT_BLOCKED | varies | Contact is blocked at the org level — every outbound send rejected. |
CONTACT_ERASURE_PENDING | varies | Contact has a pending GDPR Article-17 erasure request in its 7-day cooling-off window. |
INVALID_FILE_TYPE | varies | File upload rejected at the FE pre-flight — MIME / extension mismatch. |
FILE_TOO_LARGE | varies | File upload rejected — size exceeds the configured cap. |
MAGIC_BYTE_MISMATCH | varies | File upload rejected — magic-byte signature didn’t match the declared MIME. |
INSUFFICIENT_BALANCE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INSUFFICIENT_CREDITS | varies | @deprecated Use INSUFFICIENT_BALANCE instead |
DEDUCT_IN_FLIGHT | varies | Returned by deductBalance / addBalance when another caller already holds the same idempotency key in Redis but has not yet posted its final result within the poll window (2 s today). |
RESELLER_MARGIN_RESERVE_FAILED | 503 | 503 — the pre-deduct reseller-margin pending-row reservation (reserveResellerMarginPending) failed, so the send is aborted BEFORE the child wallet is debited. |
FORBIDDEN | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_STATE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CONVERSATION_TERMINAL | 422 | SCAN-CINB-010 + SCAN-CINB-011 — ConversationsService.resumeAi and ConversationsService.handoff reject calls against conversations in a terminal/non-actionable status (closed, archived, snoozed). |
TAKEOVER_NOT_ALLOWED | 422 | Supervisor take-over (422) refused on a terminal/closed digital conversation — there is no live conversation to intercept; details carries the current { status }. |
TAKEOVER_ALREADY_ACTIVE | 409 | Supervisor take-over (409) rejected because a take-over is already active on the conversation; details carries { takeover_id, supervisor_id } so the UI can show who is already in control. |
NO_ACTIVE_TAKEOVER | 409 | Supervisor take-over (409) error returned when a send-reply or release is attempted but no take-over is currently active on the conversation. |
TAKEOVER_FORBIDDEN | 403 | Supervisor take-over (403) denied: the caller neither owns the active take-over nor is an elevated owner/admin recovering it. |
REAUTH_REQUIRED | varies | audit #511 backend top-10 #2/#7 — fresh re-authentication required for irreversible operations (GDPR delete, 2FA disable, HIPAA toggle). |
ROLLBACK_WINDOW_EXPIRED | varies | audit #511 backend top-10 #3 — import rollback past the 24h window. |
INVITE_EXPIRED | varies | audit #511 backend top-10 #8 — invitation token has expired. |
AUTO_TOPUP_MONTHLY_CAP_REACHED | varies | Auto-top-up cron tried to recharge but the org’s max_monthly_minor cap has already been reached this calendar month. |
AUTO_TOPUP_PAYMENT_FAILED | varies | Off-session Stripe PaymentIntent for an auto-top-up failed (card declined, no default payment method, etc.). |
SUPERVISOR_ACTION_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
SUPERVISOR_TAKEOVER_FAILED | 500 | 500 — POST /voice/supervisor/takeovers (initiate a voice supervisor takeover / whisper-coach session) failed unexpectedly. |
SUPERVISOR_TAKEOVER_LIST_FAILED | 500 | 500 — GET /voice/supervisor/takeovers (list voice supervisor takeovers) failed unexpectedly. |
SUPERVISOR_TAKEOVER_GET_FAILED | 500 | 500 — GET /voice/supervisor/takeovers/:id (fetch a single voice supervisor takeover) failed unexpectedly. |
SUPERVISOR_TAKEOVER_UPDATE_FAILED | 500 | 500 — PATCH /voice/supervisor/takeovers/:id (advance state or cancel a voice supervisor takeover) failed unexpectedly. |
SUPERVISOR_WHISPER_TEXT_FAILED | 500 | 500 — POST /voice/supervisor/calls/:id/whisper-text (whisper a text coaching line to the live agent) failed unexpectedly. |
SUPERVISOR_ASSIST_STREAM_ERROR | 500 | 500 — GET /voice/supervisor/calls/:callId/assist/stream (supervisor AI-assist SSE card stream) failed unexpectedly. |
DIGITAL_TAKEOVER_START_FAILED | 500 | 500 — POST /conversations/:id/takeover/start (supervisor seizes reply control on a digital conversation) failed unexpectedly. |
DIGITAL_TAKEOVER_REPLY_FAILED | 500 | 500 — POST /conversations/:id/takeover/send-reply (reply under an active digital takeover) failed unexpectedly. |
DIGITAL_TAKEOVER_END_FAILED | 500 | 500 — POST /conversations/:id/takeover/end (release a digital takeover back to the agent) failed unexpectedly. |
DIGITAL_TAKEOVER_GET_FAILED | 500 | 500 — GET /conversations/:id/takeover (read current digital takeover state) failed unexpectedly. |
ONLY_ADMIN | 422 | Audit #SET-003 / #SET-004 — refuses an offboarding operation (SCIM deleteUser, settings removeTeamMember, danger-zone org-deletion) when the target is the only remaining admin/owner of the organisation. |
INSUFFICIENT_SCOPE | 403 | API key was rejected because the declared scope set does not include the scope required by the requested route. |
CALLING_REQUIRES_ELIGIBLE_PHONE | 422 | WhatsApp Business Calling needs a phone whose country is NOT in Meta’s calling-blocked list (US/CA/EG/VN/NG today). |
FEATURE_DISABLED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
ACCOUNT_LOCKED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
AGENT_EXECUTION_TIMEOUT | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
PAYLOAD_TOO_LARGE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
LOOKUP_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
REQUEST_ABORTED | varies | Request cancelled by caller (e.g. campaign pause aborted in-flight provider send). |
POLICY_VIOLATION | varies | Pre-send policy scan blocked the message (TCPA / SHAFT / GDPR). |
POLICY_SCAN_MODE_LOOKUP_FAILED | 503 | SCAN-MSG-DEEP-002 (2026-05-26) — resolvePolicyScanMode could not read organizations.policy_scan_mode from Postgres AND the per-org 5-minute Redis cache is cold. |
BALANCE_OPERATION_FAILED | varies | Admin balance adjust operation (deduct/add) failed at the credits layer. |
BALANCE_CAP_EXCEEDED | 422 | SCAN-BILL-R3-013 (2026-05-23) — addBalance rejected because the resulting wallet balance would exceed MAX_BALANCE_CENTS. |
BILLING_TENANT_UNRESOLVED | 500 | Returned (500) when resolveBillingTenantId produced an empty or still-schema-shaped value on a money-touching path (number purchase, deduct, top-up). |
PRICING_NOT_CONFIGURED | varies | Wave P1-A (2026-05-18) — resolvePrice() could not find a rate row OR an org override for the (channel, sub_type, country, mcc, mnc, prefix) tuple being charged. |
PRICING_FX_NOT_CONFIGURED | varies | Wave P1-A (2026-05-18) — Open Exchange Rates app_id env var is unset but a currency conversion is required. |
PRICING_FX_STALE | varies | Wave P1-A (2026-05-18) — most-recent FX snapshot for the required currency pair is older than the 7-day hard ceiling. |
PRICING_FX_UPSTREAM_FAILED | varies | Wave P1-A (2026-05-18) — Open Exchange Rates returned a non-2xx response while warming a missing rate snapshot. |
PRICING_FX_UNEXPECTED_BASE | varies | Wave P1-A (2026-05-18) — OXR returned a base other than USD when the free-tier API contract guarantees USD-base. |
PRICING_FX_UNSUPPORTED_CURRENCY | varies | Wave P1-A (2026-05-18) — caller requested a currency the supported set doesn’t cover. |
CUSTOM_FIELD_IN_USE | varies | Returned when deleting a custom-field definition would break segments that reference it. |
CONCURRENCY_LIMIT_EXCEEDED | varies | Returned when a voice outbound-call request would exceed the per-org concurrency cap (organizations.voice_max_concurrent). |
CONFERENCE_DIAL_ALL_FAILED | 502 | Audit #CONF-CALLER-ID — every seed participant on POST /voice/conferences failed to dial via Jambonz. |
CONFERENCE_DIAL_PARTIAL | varies | Audit #CONF-CALLER-ID — partial-success companion to CONFERENCE_DIAL_ALL_FAILED. |
CONF_INVALID_PARTICIPANT | varies | wave_conf_core_2026_05_18 — TR-27 — conference create failed because one of the supplied participant numbers did not parse as a valid E.164 phone number. |
CONF_CALLER_ID_NOT_OWNED | varies | wave_conf_core_2026_05_18 — TR-27 — conference create’s from caller-id is not owned by the calling tenant. |
CONF_TRUNK_UNREGISTERED | 503 | wave_conf_core_2026_05_18 — TR-27 — conference create failed because the upstream voice trunk (Devotel softswitch / Jambonz REST) was unregistered or unreachable at dial time. |
CONF_NOT_FOUND_OR_NOT_ACTIVE | 404 | Conference row not found OR found but status != 'active'. |
CONFERENCE_PIN_REQUIRED | 401 | DECISION — UCAAS_003_018_CONFERENCE_PIN_2026_05_28. |
CONFERENCE_PIN_MISMATCH | 401 | DECISION — UCAAS_003_018_CONFERENCE_PIN_2026_05_28. |
CONFERENCE_STATE_UNRESOLVED | 409 | The conference lock was refused because the room has not settled into a live state: no participant is connected while one or more legs are still dialing (pending, dialing, or ringing). |
CONF_AI_AGENT_ALREADY_ACTIVE | 409 | Conference already has an active AI-agent attached. |
CONF_AI_AGENT_NOT_FOUND | 404 | Conference AI-agent attachment row not found. |
INVALID_DESTINATION | 422 | SIP softphone outbound destination failed validation. |
SIP_TRUNK_UNREGISTERED | 503 | SIP trunk dial-time pre-check found status='unregistered'. |
OUTSIDE_SESSION_WINDOW | 422 | Outbound message rejected because the 24h customer-service-window is closed (WhatsApp/Messenger). |
VOICE_TRUNK_CPS_CEILING | 429 | Customer SIP trunk hit its CPS (calls-per-second) ceiling. |
VOICE_TRUNK_CONCURRENT_CAP | 503 | Customer SIP trunk hit its concurrent-call cap. |
INTERNAL_COMPLIANCE_ERROR | 503 | Compliance scanner threw — fail-closed surface. |
NUMBER_ALREADY_TAKEN | 409 | Phone-number purchase race — another tenant already claimed it. |
INVALID_REQUEST | 422 | Generic onboarding-wizard validation failure (typed as a Zod error already, this is the API code). |
DELIVERY_FAILED | 503 | Verify channel send returned a provider failure (upstream/softswitch rejected the submit). |
ALL_CHANNELS_FAILED | 503 | Verify fan-out exhausted all configured channels without one succeeding. |
VERIFY_FRAUD_BLOCKED | 403 | 403 — Verification refused by Fraud Guard: the recipient destination is blocked by the tenant’s anti-fraud policy (geo / high-risk operator / composite risk score). |
VERIFY_RND_REASSIGNED | 422 | 422 — Verification refused by the FCC Reassigned Numbers Database (RND) pre-send guard: the destination phone number (sms / mms / voice / flashcall, US +1) has a permanent-disconnect record in the RND feed and may have been reassigned to… |
VERIFY_SEND_FAILED | varies | Per-recipient failure code in a bulk-verify response row (not an HTTP status). |
CONF_PROVIDER_ERROR | 502 | wave_conf_core_2026_05_18 — TR-27 — conference create’s Jambonz REST call returned a non-2xx that wasn’t structurally a VALIDATION/AUTH error. |
CONF_INSUFFICIENT_CREDIT | 402 | wave_conf_core_2026_05_18 — TR-27 — conference create denied at the billing-hold step (caller has no remaining credit / hit a spend cap). |
NUMBER_NO_LONGER_AVAILABLE | 409 | Returned (409) when a phone number a tenant tried to purchase has been claimed by someone else between the inventory list-fetch and the purchase request. |
NUMBER_PROVISIONING_FAILED | 502 | Returned (502) when a number was successfully purchased upstream and billed but a downstream platform-side step (e.g. mirroring into public.platform_numbers so inbound traffic can resolve the owning tenant) failed. |
INVALID_RING_GROUP_CYCLE | 422 | Returned (422) when a ring-group create/update would introduce a cycle reachable from the group itself (A → B → A or A → B → C → A). |
COMPLIANCE_PROFILE_NOT_APPROVED | 422 | Returned (422) when a feature surface (number purchase, sender-ID registration, brand registration, etc.) tries to attach a compliance profile whose status is not ‘approved’. |
COMPLIANCE_PROFILE_REQUIRED | 422 | Returned (422) when a number-purchase request targets a regulated country (UK / DE / FR / etc.) AND the tenant has no approved compliance profile that covers it. |
PLACEHOLDER_REQUIRES_PROFILE | 422 | Returned (422) when a tenant tries to buy a DIDWW DID-group PLACEHOLDER row (did_group:<uuid>) WITHOUT an approved compliance profile for the row’s country. |
COMPLIANCE_PROFILE_INCOMPLETE | 422 | Returned (422) when a tenant tries to submit a compliance profile that is missing required documents or data fields per the compliance-requirements registry’s RequirementSet for that use_case + country. |
COMPLIANCE_PROFILE_IN_USE | 409 | Returned (409) when a tenant tries to delete a compliance profile, or detach an underlying document, that’s still referenced by an active downstream entity (purchased phone number, registered sender ID, brand, campaign, etc.). |
COMPLIANCE_PROFILE_LOCKED | 409 | Returned (409) when the tenant tries to mutate a compliance profile (data, documents, fields) that has already moved past draft — once submitted to providers we lock the payload to keep our state in sync with what each carrier holds. |
COMPLIANCE_USE_CASE_NOT_SUPPORTED | 422 | Returned (422) when a tenant tries to submit a compliance profile whose use-case fans out only to NOT_IMPLEMENTED provider shells (TCR / Meta WA / Google RCS at the time of writing). |
BRAND_NOT_APPROVED | varies | Tenant tried to submit an RCS bot under a brand that hasn’t been approved yet. |
SIM_SWAP_DETECTED | 403 | Returned (403) by /verify/start when a SIM-swap event is detected inside the block window (24h default) on the recipient MSISDN. |
MESSAGING_TR_URL_STRIP_VIOLATION | 422 | Türkiye BTK Decision 2025/DK-YED/412 (effective 1 Apr 2026) blocks A2P SMS containing URLs from senders not registered in Türkiye — the carrier strips the entire payload at delivery so the recipient sees nothing and the operator burns sp… |
RECORDING_CONSENT_REQUIRED | varies | Two-party recording-consent gate (UAE Penal Code Art. |
RECORDING_CONSENT_INVALID | 422 | Recording-consent receipt failed DB-backed validation (SCAN-RVV-008). |
MESSAGING_IN_DLT_TEMPLATE_REQUIRED | varies | India TRAI DLT (Distributed Ledger Technology) registration requires an approved dlt_template_id for every A2P SMS routed to IN destinations. |
MESSAGING_IN_DLT_CONTENT_MISMATCH | 422 | 422 — India TRAI DLT content-template enforcement: an A2P SMS carries an approved dlt_template_id but its body or sender header does not match the registered template, so Orbit fails the send closed at the platform edge. |
MESSAGING_BR_SENDER_NOT_REGISTERED | varies | Brazil Anatel sender-ID registration is required for any operator sending A2P SMS to BR destinations. |
MESSAGING_SA_SENDER_NOT_REGISTERED | varies | Saudi Arabia CITC sender-name registration is required for any operator sending A2P SMS to KSA (SA) destinations. |
MESSAGING_AE_SENDER_NOT_REGISTERED | varies | United Arab Emirates TDRA sender-name registration is required for any operator sending A2P SMS to UAE (AE) destinations. |
MESSAGING_MX_NOM184_CONSENT_MISSING | varies | Mexico NOM-184-SCFI requires explicit, time-stamped consent for every promotional A2P SMS to a MX subscriber. |
CONSENT_RECEIPT_INVALID | varies | India DPDP Phase II Consent-Manager receipt verification failed: either the receipt id is unknown to the platform, the signature does not match the registered manager’s public key, or the receipt has been tampered with. |
MESSAGING_TCPA_KNOWN_LITIGATOR | 403 | Recipient phone is on the platform’s known-litigator list (TCPA professional plaintiff). |
MESSAGING_CONSENT_REQUIRED | varies | General pre-send affirmative-opt-in (consent) gate. |
TFV_REQUIRED | varies | US toll-free numbers must complete carrier-side Toll-Free Verification (TFV) before they can send A2P SMS to US carriers without aggressive throttling / outright blocking. |
TEN_DLC_NOT_REGISTERED | varies | Audit #COMP-002 — US 10DLC (10-digit long code) send rejected because the org has no approved TCR (The Campaign Registry) brand+campaign registration for the sender. |
IDEMPOTENCY_KEY_REQUIRED | varies | Audit #CB-010 — Idempotency-Key header is REQUIRED on money-moving mutations (top-up checkout, future similar endpoints) but the caller omitted it entirely. |
INVALID_IDEMPOTENCY_KEY | varies | API idempotency-key shape validation failures (length / charset). |
IDEMPOTENCY_KEY_REUSED | varies | Same Idempotency-Key replayed with a DIFFERENT request body. |
PAYMENT_IN_FLIGHT | 409 | TF-BILL-02 (2026-05-18) — tenant tried to cancel a crypto top-up intent that has progressed past waiting/confirming. |
EMPTY_AUDIENCE_NOT_ALLOWED | 422 | TF-SEG-04 (2026-05-18) — operator tried to create a campaign whose explicit audience selection (segment_id / list_id / explicit empty csv array) resolves to 0 recipients. |
BATCH_PRE_INSERT_FAILED | varies | Audit #BATCH-SMS-PERSIST-FAILED-1 — MessagesBatchService failed to bulk-pre-insert the recipients’ pending rows (Postgres unavailable / connection refused / unique-id collision). |
INTEGRATION_DISCONNECTED | 412 | Audit #INTEGRATION-WIRING-4 — campaign audience source references a CRM (HubSpot / Salesforce / Pipedrive) the tenant hasn’t connected via Nango. |
AUDIENCE_RESOLVE_FAILED | 502 | Audit #INTEGRATION-WIRING-4 — the resolver failed mid-iterate on a CRM-backed audience (Nango timeout, rate-limit, auth expired). |
NANGO_DESTINATION_FAILED | 502 | DECISION — CDP_NANGO_DESTINATIONS_2026_05_28 — outbound CDP activation through Nango Cloud’s triggerAction failed (HubSpot, Salesforce, Braze, Iterable, Customer.io, Klaviyo). |
Audit #WAVE-O-FOUNDATION — Orby
| Code | HTTP | Description |
|---|---|---|
ORBY_TOOL_FORBIDDEN | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
ORBY_TOOL_NOT_AUTHORIZED | 403 | Audit #SCAN-AI-V3-010 (AGT-026 follow-up) — execute-time gate. |
ORBY_TOOL_CLAIM_MISSING | 401 | Audit #SCAN-AI-V3-010 — the session token decoded successfully but carries no tools claim (or a non-array claim). |
ORBY_SESSION_MALFORMED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
ORBY_SESSION_SIG_INVALID | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
ORBY_SESSION_EXPIRED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
ORBY_SESSION_REVOKED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
ORBY_SESSION_REQUIRED | 403 | Orby is operator-facing only; a request authenticated with an API key rather than a signed-in dashboard session is rejected. |
ORBY_RATE_LIMITED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
ORBY_THREAD_NOT_OWNED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
ORBY_ITERATION_LIMIT | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
ORBY_COST_CAP_EXCEEDED | varies | Reserved Orby cost-cap error code. |
ORBY_LLM_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
ORBY_TURN_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
ORBY_KB_NOT_INDEXED_YET | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
ORBY_KB_REINDEX_FAILED | varies | Reserved Orby knowledge-base error code. |
KB_VECTOR_DELETE_FAILED | 502 | AIAAS-KB-VECDB-CONSISTENCY (2026-06-02) — a KB document delete could not remove the document’s vectors from the Qdrant search index, so the kb_documents row was deliberately RETAINED (it is the only handle on the orphaned vectors that… |
Audit #AGT-001 — confirmation-gate redemption
| Code | HTTP | Description |
|---|---|---|
PENDING_ACTION_NOT_APPROVABLE | 409 | Pending agent action is not in pending state (already approved / cancelled). |
PENDING_ACTION_RACE | 409 | Pending agent action lost the approve/reject race against a concurrent operator. |
PENDING_ACTION_EXPIRED | 409 | Pending agent action was past its 5-min approval window (#UX-006). |
PENDING_ACTION_PERSIST_FAILED | 500 | The runtime could not persist a pending_agent_actions row, so the tool was refused (fail-closed). |
TOOL_EXECUTION_FAILED | 500 | Approved tool’s executor threw a non-DevotelError exception. |
Audit #AGT-007 — custom-tool dispatch body cap
| Code | HTTP | Description |
|---|---|---|
CUSTOM_TOOL_RESPONSE_TOO_LARGE | 502 | Custom-tool executor response body exceeded the 1 MB ceiling. |
Audit #AGT-002 — accurate cost cap
| Code | HTTP | Description |
|---|---|---|
COST_CAP_EXCEEDED | 402 | Per-conversation LLM cost cap exceeded (accurate computation via Anthropic rate table). |
Audit #WAVE-O-NEW-ENDPOINTS
| Code | HTTP | Description |
|---|---|---|
IVR_FLOW_GRAPH_INVALID | 422 | IVR flow graph failed structural validation (no entry, orphan edges, etc). |
CALL_TRANSCRIPT_UNAVAILABLE | 422 | POST /voice/calls/:id/summary — no usable transcript on the call. |
LLM_PROVIDER_UNCONFIGURED | 503 | No LLM provider key configured on the platform. |
CALL_SUMMARY_LLM_MALFORMED | 502 | LLM reply was malformed / unparseable after retries. |
VIDEO_TRANSCRIPT_UNAVAILABLE | 422 | UCaaS P1 (2026-05-30) — POST /video/sessions/:id/summary — no usable transcript on the meeting (no captions captured, transcript too short, etc.). |
VIDEO_SUMMARY_LLM_MALFORMED | 502 | UCaaS P1 (2026-05-30) — POST /video/sessions/:id/summary — LLM reply was malformed / unparseable after retries. |
VIDEO_SESSION_SUMMARY_FAILED | varies | UCaaS P1 (2026-05-30) — POST /video/sessions/:id/summary — unexpected route-level failure (DB / tenant client / sanitised envelope). |
PUSH_CATEGORY_IDENTIFIER_CONFLICT | 409 | Push category identifier collision with an existing tenant row. |
BROADCAST_TOO_LARGE | 422 | POST /push broadcast (user_ids: ["*"]) whose deliverable audience — enabled device tokens minus push/all suppression-list opt-outs — exceeds the MAX_BROADCAST_RECIPIENTS cap. |
SCHEDULED_PUSH_NOT_CANCELLABLE | 409 | 409 — DELETE /push/scheduled/:id refused to cancel a scheduled push that is no longer in scheduled state. |
SQUAD_DAILY_CAP_REACHED | 429 | Agent squad’s today-so-far LLM cost meets/exceeds its configured daily cap. |
CONVERSATION_COST_CAP_REACHED | 429 | Per-conversation LLM cost meets/exceeds the agent’s configured cap. |
AGENT_DAILY_SPEND_CAP_REACHED | 429 | SCAN-BILL-FRESH-001 / invariant #64 — tenant’s today-so-far agent LLM spend meets/exceeds the configured daily cap, thrown from the gateway-level callClaude / streamClaude / callClaudeStructured chokepoint. |
SAFETY_CLASSIFIER_REFUSAL | 403 | Audit #VOICE-FRAUD-9 — Anthropic’s server-side Constitutional Classifiers refused the completion (stop_reason:"refusal") AND DEVOTEL_ANTHROPIC_CONSTITUTIONAL_CLASSIFIERS_ENABLED is on, so the LLM gateway BLOCKS the refused content ra… |
VOICE_BIOMETRICS_TIMEOUT | 503 | Voice biometrics sidecar did not respond within the 10-second timeout. |
VOICE_BIOMETRICS_UNAVAILABLE | 503 | Voice biometrics sidecar is unreachable (network error). |
VOICE_BIOMETRICS_AUTH_FAILED | 500 | HMAC authentication with voice biometrics sidecar failed. |
VOICE_BIOMETRICS_ERROR | 503 | Voice biometrics sidecar returned an unexpected error. |
CONFIGURATION_ERROR | 500 | DEVOTEL_VOICE_BIOMETRICS_INTERNAL_SECRET env var missing. |
INVALID_AUDIO | 400 | Audio payload is invalid (not WAV, empty, or corrupt). |
AUDIO_TOO_LARGE | 400 | Audio clip exceeds the 30-second / 2MB maximum. |
SPOOF_DETECTED | 422 | Voice enrollment rejected — anti-spoof score is below threshold. |
DEEPFAKE_DETECTED | 422 | Voice enrollment rejected — Resemble Detect flagged the audio as a synthetic / cloned voice (deepfake score at or above threshold). |
DUPLICATE_VOICEPRINT | 409 | Identical voiceprint already enrolled for this contact. |
IVR_INTENT_CREATE_ERROR | 500 | IVR intent create failed (non-constraint DB error). |
IVR_CLASSIFY_LLM_ERROR | 503 | Conversational IVR NLU classifier — LLM call failed. |
IVR_SLOT_EXTRACT_LLM_ERROR | 503 | Conversational IVR slot-filling / entity extraction — LLM call failed. |
HIPAA_BAA_REQUIRED | varies | HIPAA BAA enforcement gate (SCAN-CSPAAS-004) — tenant is opted into HIPAA mode (settings.hipaa_required = true) but does not have an executed, in-term Business Associate Agreement on file. |
HIPAA_BAA_GATE_DB_FAIL | 500 | HIPAA BAA enforcement gate (SCAN-CSPAAS-004) — DB read failed while verifying BAA status. |
ESCALATION_EMAIL_RECIPIENTS_FORBIDDEN | 403 | Returned by PUT /settings/general when the operator attempts to persist settings.escalation.email_recipients containing one or more entries whose domain is not present in the org-member domain allowlist. |
ESCALATION_EMAIL_RECIPIENTS_INVALID | varies | Returned by PUT /settings/general when the operator submits settings.escalation.email_recipients as a non-array or with non-string entries. |
ESCALATION_EMAIL_RECIPIENTS_TOO_MANY | varies | Returned by PUT /settings/general when the operator submits a settings.escalation.email_recipients array of length > 20. |
ESCALATION_CHANNEL_FORBIDDEN | 403 | Returned by POST /agents and PUT /agents/:id when the operator sets an AI-agent escalation forward with delivery medium email (config.escalation_channel_type === "email") whose escalation_channel address is on a domain that does NO… |
ORG_COMPLIANCE_EMERGENCY_STOP | varies | CCaaS gap #51 — Org-wide compliance emergency stop (panic button). |
CDP_SOURCE_QUERY_MULTI_STATEMENT_FORBIDDEN | 400 | DECISION — CDPAAS_REVERSE_ETL_SQL_INJECTION_AND_MIGRATION_FIX_2026_05_28. |
AGENT_CHANNEL_CAP_EXCEEDED | 422 | CCaaS-PARITY (2026-05-30) — raised by the per-agent per-channel concurrency-cap routing gate (apps/api/src/lib/agent-channel-cap.ts) when an attempt to assign a conversation onto an agent would exceed the configured `agent_channel_caps… |
AGENT_INVOCATION_RATE_LIMIT_EXCEEDED | 429 | AIaaS per-agent invocation throttle (2026-06-29) — a single AI agent exceeded its operator-configured per-minute invocation rate (config.invocation_rate_limit_per_min). |
AGENT_INVOCATION_QUOTA_EXCEEDED | 429 | AIaaS per-agent invocation throttle (2026-06-29) — a single AI agent exhausted its operator-configured daily invocation quota (config.invocation_quota_per_day). |
AGENT_RATE_LIMIT_EXCEEDED | 429 | AIaaS per-agent configured rate-limit gate (2026-06-30) — a single AI agent exceeded one of its operator-configured invocation ceilings on the chat / stream entrypoint. |
INTERNAL | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
BAD_GATEWAY | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
UPSTREAM_ERROR | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
RATE_LIMITED | 429 | Global HTTP 429 rate limit from the platform-wide request limiter, carrying a retry_after value in seconds and a matching Retry-After header. |
UNAUTHENTICATED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
UNPROCESSABLE_ENTITY | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVARIANT_VIOLATION | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
SESSION_REVOKED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
LIGHT_SEAT_RESTRICTED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_TOKEN | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_CODE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CHALLENGE_INVALID | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
ALREADY_VERIFIED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VERIFICATION_REJECTED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_FILTER | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_STATUS | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_PRIORITY | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_STATE_TRANSITION | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_TRANSITION | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_LAUNCH_STATE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_PHONE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_CALLER_ID | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_DESTINATION_URL | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INSUFFICIENT_FUNDS | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
MAX_PRICE_EXCEEDED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
COUNTRY_NOT_ALLOWED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CHANNEL_COUNTRY_BLOCKED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CHANNEL_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
BINDING_REQUIRED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
BINDING_MISMATCH | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
AGENT_NOT_FOUND | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
AGENT_ARCHIVED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
AGENT_REQUIRED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
AGENT_REFERENCED_BY_CHILD_ROWS | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
AGENT_REFERENCED_BY_SQUAD | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
NO_AGENT_AVAILABLE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
UNKNOWN_SKILL | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
SKILL_CATALOG_ORG_MISSING | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
SKILL_SLUG_ALREADY_EXISTS | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
TOOL_IMPL_NOT_REGISTERED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_HANDOFF_TARGETS | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
INVALID_KNOWLEDGE_BASE_IDS | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
LEGACY_KB_DOC_NOT_RECHUNKABLE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
POLICY_SCANNER_UNAVAILABLE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CUSTOM_CODE_FORBIDDEN | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
QUEUE_NOT_FOUND | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
QUEUE_DEPTH_CAP_REACHED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
QUEUE_ENTRY_NOT_QUEUED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
OVERFLOW_QUEUE_NOT_FOUND | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
OVERFLOW_QUEUE_CHAIN_CYCLE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
OVERFLOW_QUEUE_SELF_CHAIN | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
SKIP_INELIGIBLE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
NOT_IN_WRAPUP | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
DISPOSITION_REQUIRED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
DISPOSITION_CODE_NOT_FOUND | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
DISPOSITION_TAG_REQUIRED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
DISPOSITION_TAG_NOT_FOUND | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
AUX_CODE_ALREADY_EXISTS | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
AUX_CODE_UPDATE_EMPTY | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
TEMPLATE_NOT_FOUND | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
TEMPLATE_NAME_CONFLICT | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
TEMPLATE_LIMIT_EXCEEDED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
SPEECH_CATEGORY_NOT_FOUND | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
SPEECH_CATEGORY_SLUG_CONFLICT | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
RECORDING_CONSENT_ACKNOWLEDGEMENT_REQUIRED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
EMERGENCY_DESTINATION_REQUIRED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VOICE_OVERLOAD_CHAT_VETOED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CAMPAIGN_NOT_DRAFT | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CAMPAIGN_NOT_PENDING_APPROVAL | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CONVERSATION_LINK_EXISTS | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
BLOCKED_NUMBER_ALREADY_EXISTS | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
OPT_OUT_LIST_LABEL_CONFLICT | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
SEND_WINDOW_LOOKUP_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
MESSAGING_SERVICE_NOT_FOUND | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
MESSAGING_SERVICE_EXTERNAL_ID_CONFLICT | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
MESSAGING_SERVICE_RESOLUTION_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
MESSENGER_TAG_REQUIRED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
MESSENGER_OUTSIDE_24H_WINDOW | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
CARRIER_PORT_OUT_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
PORT_OUT_NOT_SUPPORTED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
PORT_OUT_PIN_MISMATCH | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
MEF_INTEGRATION_PENDING | varies | DEPRECATED — no longer emitted; country-rule sync now fails open, returning HTTP 200 with any sync issues reported in the response’s errors[] array instead of throwing this former HTTP 501 code. |
VERIFY_LINE_TYPE_BLOCKED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VERIFY_EMAIL_UNDELIVERABLE | 422 | 422 — an email OTP (channel: email | magic_link) was requested for an address whose domain PROVABLY cannot receive mail: the domain publishes no MX record (NXDOMAIN / ENODATA). |
QR_RENDER_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VIDEO_ROOM_LOCKED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VIDEO_PARTICIPANT_BANNED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VIDEO_MUTE_ALL_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VIDEO_BROADCAST_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VIDEO_BREAKOUT_CREATE_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VIDEO_BREAKOUT_MOVE_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VIDEO_WAITING_ROOM_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VIDEO_WAITING_ROOM_ADMIT_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VIDEO_PARTICIPANT_TIER_UPDATE_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VIDEO_INGRESS_CREATE_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VIDEO_RTMP_EGRESS_START_FAILED | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
VIDEO_RECORDING_BACKEND_UNAVAILABLE | varies | Platform-defined error code. See source comment in packages/shared/src/errors.ts for context. |
Video / Rooms (server-side fallback codes)
| Code | HTTP | Description |
|---|---|---|
VIDEO_ROOM_CREATION_FAILED | 500 | 500 — an unexpected server error prevented the request to create the video room; the operation did not complete, so retry the request. |
VIDEO_ROOM_LIMITS_FAILED | 500 | 500 — an unexpected server error prevented the request to load your video room limits; the operation did not complete, so retry the request. |
VIDEO_ROOM_LIST_FAILED | 500 | 500 — an unexpected server error prevented the request to load your video rooms; the operation did not complete, so retry the request. |
VIDEO_ROOM_FETCH_FAILED | 500 | 500 — an unexpected server error prevented the request to load this video room; the operation did not complete, so retry the request. |
VIDEO_ROOM_JOIN_FAILED | 500 | 500 — an unexpected server error prevented the request to generate a join token for this room; the operation did not complete, so retry the request. |
VIDEO_ROOM_END_FAILED | 500 | 500 — an unexpected server error prevented the request to end this video room; the operation did not complete, so retry the request. |
VIDEO_RECORDING_START_FAILED | 500 | 500 — an unexpected server error prevented the request to start the recording; the operation did not complete, so retry the request. |
VIDEO_RECORDING_STOP_FAILED | 500 | 500 — an unexpected server error prevented the request to stop the recording; the operation did not complete, so retry the request. |
VIDEO_RTMP_EGRESS_STOP_FAILED | 500 | 500 — an unexpected server error prevented the request to stop the live stream; the operation did not complete, so retry the request. |
VIDEO_LIVESTREAM_PLAYBACK_FAILED | 500 | 500 — an unexpected server error prevented the request to load the live stream playback URL; the operation did not complete, so retry the request. |
VIDEO_INGRESS_DELETE_FAILED | 500 | 500 — an unexpected server error prevented the request to remove the ingress; the operation did not complete, so retry the request. |
VIDEO_INGRESS_LIST_FAILED | 500 | 500 — an unexpected server error prevented the request to load active ingresses; the operation did not complete, so retry the request. |
VIDEO_INVITE_CREATE_FAILED | 500 | 500 — an unexpected server error prevented the request to create a guest invite; the operation did not complete, so retry the request. |
VIDEO_INVITE_LIST_FAILED | 500 | 500 — an unexpected server error prevented the request to load guest invites for this room; the operation did not complete, so retry the request. |
VIDEO_INVITE_REVOKE_FAILED | 500 | 500 — an unexpected server error prevented the request to revoke this guest invite; the operation did not complete, so retry the request. |
VIDEO_PARTICIPANT_UNMUTE_FAILED | 500 | 500 — an unexpected server error prevented the request to unmute this participant; the operation did not complete, so retry the request. |
VIDEO_PARTICIPANT_BAN_FAILED | 500 | 500 — an unexpected server error prevented the request to ban this participant; the operation did not complete, so retry the request. |
VIDEO_PARTICIPANT_UNBAN_FAILED | 500 | 500 — an unexpected server error prevented the request to lift the ban for this participant; the operation did not complete, so retry the request. |
VIDEO_BAN_LIST_FAILED | 500 | 500 — an unexpected server error prevented the request to load the banned participants for this room; the operation did not complete, so retry the request. |
VIDEO_RECORDING_CONSENT_SET_FAILED | 500 | 500 — an unexpected server error prevented the request to update this participant’s recording consent; the operation did not complete, so retry the request. |
VIDEO_RECORDING_CONSENT_LIST_FAILED | 500 | 500 — an unexpected server error prevented the request to load the recording-consent list for this room; the operation did not complete, so retry the request. |
VIDEO_ROOM_LOCK_FAILED | 500 | 500 — an unexpected server error prevented the request to change the room lock state; the operation did not complete, so retry the request. |
VIDEO_PARTICIPANT_ROLE_UPDATE_FAILED | 500 | 500 — an unexpected server error prevented the request to change this participant’s role; the operation did not complete, so retry the request. |
VIDEO_PARTICIPANT_RECEIVE_CONTROL_FAILED | 500 | 500 — an unexpected server error prevented the request to update this participant’s receive settings; the operation did not complete, so retry the request. |
VIDEO_SPOTLIGHT_SET_FAILED | 500 | 500 — an unexpected server error prevented the request to spotlight this participant; the operation did not complete, so retry the request. |
VIDEO_SPOTLIGHT_CLEAR_FAILED | 500 | 500 — an unexpected server error prevented the request to clear the spotlight; the operation did not complete, so retry the request. |
VIDEO_ROOM_SSO_POLICY_FAILED | 500 | 500 — an unexpected server error prevented the request to update the room’s single sign-on access policy; the operation did not complete, so retry the request. |
VIDEO_INVITE_REDEEM_FAILED | 500 | 500 — an unexpected server error prevented the request to redeem this guest invite; the operation did not complete, so retry the request. |
VIDEO_HAND_RAISE_FAILED | 500 | 500 — an unexpected server error prevented the request to raise your hand; the operation did not complete, so retry the request. |
VIDEO_HAND_LOWER_FAILED | 500 | 500 — an unexpected server error prevented the request to lower your hand; the operation did not complete, so retry the request. |
VIDEO_HAND_QUEUE_LIST_FAILED | 500 | 500 — an unexpected server error prevented the request to load the raised-hand queue; the operation did not complete, so retry the request. |
VIDEO_HAND_QUEUE_CLEAR_FAILED | 500 | 500 — an unexpected server error prevented the request to clear the raised-hand queue; the operation did not complete, so retry the request. |
VIDEO_REACTION_FAILED | 500 | 500 — an unexpected server error prevented the request to send your reaction; the operation did not complete, so retry the request. |
VIDEO_POLL_LAUNCH_FAILED | 500 | 500 — an unexpected server error prevented the request to launch the poll; the operation did not complete, so retry the request. |
VIDEO_POLL_VOTE_FAILED | 500 | 500 — an unexpected server error prevented the request to record your vote; the operation did not complete, so retry the request. |
VIDEO_POLL_CLOSE_FAILED | 500 | 500 — an unexpected server error prevented the request to close the poll; the operation did not complete, so retry the request. |
VIDEO_QA_ASK_FAILED | 500 | 500 — an unexpected server error prevented the request to submit your question; the operation did not complete, so retry the request. |
VIDEO_QA_ANSWER_FAILED | 500 | 500 — an unexpected server error prevented the request to post the answer to this question; the operation did not complete, so retry the request. |
VIDEO_WHITEBOARD_OPEN_FAILED | 500 | 500 — an unexpected server error prevented the request to open the whiteboard; the operation did not complete, so retry the request. |
VIDEO_WHITEBOARD_DRAW_FAILED | 500 | 500 — an unexpected server error prevented the request to sync your drawing to the room; the operation did not complete, so retry the request. |
VIDEO_WHITEBOARD_CLEAR_FAILED | 500 | 500 — an unexpected server error prevented the request to clear the whiteboard; the operation did not complete, so retry the request. |
VIDEO_WHITEBOARD_CLOSE_FAILED | 500 | 500 — an unexpected server error prevented the request to close the whiteboard; the operation did not complete, so retry the request. |
VIDEO_CHAT_SEND_FAILED | 500 | 500 — an unexpected server error prevented the request to send your message; the operation did not complete, so retry the request. |
VIDEO_CHAT_DELETE_FAILED | 500 | 500 — an unexpected server error prevented the request to remove that message; the operation did not complete, so retry the request. |
VIDEO_CHAT_CLEAR_FAILED | 500 | 500 — an unexpected server error prevented the request to clear the chat; the operation did not complete, so retry the request. |
VIDEO_CHAT_BLOCKED_BY_POLICY | 422 | 422 — the chat message was rejected by the room’s proactive content-safety policy (mode=block); it was neither delivered to other participants nor persisted. |
VIDEO_ROOM_CHAT_POLICY_FAILED | 502 | 502 — an unexpected server error prevented persisting the room’s chat content-safety policy; the change did not take effect, so retry the request. |
VIDEO_DIAL_IN_FAILED | 500 | 500 — an unexpected server error prevented the request to load the dial-in details for this room; the operation did not complete, so retry the request. |
VIDEO_TRANSCRIPT_LIST_FAILED | 500 | 500 — an unexpected server error prevented the request to load the transcript for this room; the operation did not complete, so retry the request. |
VIDEO_TRANSCRIPT_DELETE_FAILED | 500 | 500 — an unexpected server error prevented the request to delete the transcript for this room; the operation did not complete, so retry the request. |
VIDEO_TRANSCRIPT_EXPORT_FAILED | 500 | 500 — an unexpected server error prevented the request to export the caption file for this room; the operation did not complete, so retry the request. |
VIDEO_TRANSCRIPT_CORRECT_FAILED | 500 | 500 — an unexpected server error prevented the request to apply that caption correction; the operation did not complete, so retry the request. |
WEBHOOK_HANDLING_FAILED | 500 | 500 — an unexpected error prevented processing the inbound video webhook; the event was not handled and may be retried by the provider. |
Numbers / Provisioning
| Code | HTTP | Description |
|---|---|---|
CARRIER_RATE_LIMITED | 429 | 429 — bulk-number-purchase per-item result code: the carrier rate-limited the batch, so the remaining items were skipped without a carrier call; retry the failed rows in a few seconds. |
LOA_NOT_SIGNED | 409 | 409 — hosted-messaging order submit refused because the LOA has not been signed yet (loa_signed_at is null); sign the LOA before submitting the order to the hosting carrier. |
LOA_URL_INVALID_ORIGIN | 422 | 422 — number-porting create rejected loaFileUrl because it is not a Devotel-issued GCS signed URL (wrong host or path prefix); upload the LoA via POST /files/upload and submit the returned url. |
TFV_LINT_BLOCKED | 422 | 422 — toll-free-verification submit blocked by the pre-submit content lint: one or more sample messages match a disallowed-vertical pattern at error severity; fix the issues in details.lint before resubmitting. |
UNSUPPORTED_MEDIA_TYPE | 415 | 415 — number-document upload rejected because the request body was not multipart/form-data; re-send the document as a multipart file part. |
Compliance (DSAR / RMD / Residency / Traceback)
| Code | HTTP | Description |
|---|---|---|
DSAR_CREATE_FAILED | 500 | 500 — POST /compliance/dsar failed to persist the new GDPR/CCPA data-subject-access request because the DB insert threw; the operation is retry-safe. |
VERIFICATION_NOT_PENDING | 409 | 409 — the DSAR identity-verification step was actioned but the request has no pending verification: it may already have been verified, rejected, or filed under a regime that does not require verification. |
DSAR_CANCEL_FAILED | 500 | 500 — POST /compliance/dsar/:id/cancel failed to withdraw the request because the DB update threw; the operation is retry-safe. |
DSAR_NOT_CANCELLABLE | 409 | 409 — the DSAR cannot be withdrawn because it does not exist or has already completed, failed, expired, or been cancelled. |
DSAR_BUCKET_UNCONFIGURED | 500 | 500 — the decrypted Article-15 export download could not run because no DSAR export storage location is configured on this deployment. |
DSAR_DECRYPT_LIST_FAILED | 502 | 502 — GET /compliance/dsar/:id/decrypted could not list the export’s encrypted files because the storage backend was unreachable; retry-safe. |
DSAR_DECRYPT_NO_ARTIFACTS | 404 | 404 — no encrypted export files were found for this DSAR; the export has likely expired and been removed. |
DSAR_DECRYPT_DOWNLOAD_FAILED | 502 | 502 — an individual encrypted export file failed to download while assembling the decrypted bundle; retry-safe. |
DSAR_DECRYPT_FAILED | 500 | 500 — an export file could not be decrypted, because the encryption key has rotated since the export was generated or the stored file is corrupt. |
DSAR_DECRYPT_TOO_LARGE | 413 | 413 — the combined decrypted bundle is too large to assemble in one response; download the per-file signed URLs individually instead. |
RMD_NOT_FOUND | 404 | 404 — no Robocall Mitigation Database (RMD) registration exists for this organization; create one with POST /compliance/rmd first. |
RMD_INVALID_TRANSITION | 409 | 409 — the requested RMD lifecycle action (submit / certify / remediate / resolve / withdraw) is not allowed from the registration’s current status. |
RMD_LOCKED | 409 | 409 — the RMD registration is in a submitted/certified state and cannot be edited in place; use the lifecycle endpoints (submit / certify / remediation / resolve / withdraw) instead. |
RMD_INCOMPLETE | 409 | 409 — the RMD registration cannot be submitted yet because required fields are missing; error.details lists the outstanding blockers. |
RESIDENCY_LOCKED | 409 | 409 — PUT /compliance/data-residency refused to change the pinned residency region because the current configuration is locked and the transition is not permitted. |
RESIDENCY_NOT_ENFORCED | 409 | 409 — the residency region must be pinned and enforced (PUT /compliance/data-residency with enforced=true) before it can be locked. |
RESIDENCY_REGION_UNAVAILABLE | 409 | 409 — PUT /compliance/data-residency refused to enforce the requested residency region because that region’s storage boundary is not provisioned on the platform (not in the available-regions allowlist); the region may be pinned advisory-… |
ARCHIVAL_CHANNEL_NOT_ENABLED | 409 | 409 — POST /compliance/archival/export refused the run because the requested channel is not enabled in the tenant’s archival policy (or archival is not enabled at all); enable it via PUT /compliance/archival first. |
RESIDENCY_NOT_FOUND | 404 | 404 — no data-residency configuration exists for this organization. |
TRACEBACK_NOT_FOUND | 404 | 404 — no ITG (Industry Traceback Group) traceback case with that id exists for this organization. |
TRACEBACK_INVALID_TRANSITION | 409 | 409 — the requested traceback case transition (e.g. acknowledge) is not allowed from the case’s current status. |
Campaigns / Journeys
| Code | HTTP | Description |
|---|---|---|
AUDIENCE_TOO_LARGE | 400 | 400 — campaign send/schedule refused because the resolved audience size exceeds the per-tenant maximum recipient count from resolveCampaignAudienceLimit; split the campaign or use a smaller audience. |
ALREADY_ENROLLED | 409 | 409 — single-contact journey enrollment refused because the contact already has an active enrollment row for this journey campaign. |
CAMPAIGN_NOT_RUNNING | 400 | 400 — single-contact enrollment refused because the target campaign is not in the running state. |
CAMPAIGN_TYPE_NOT_ENROLLABLE | 400 | 400 — single-contact enrollment is only supported for journey-type campaigns; the target campaign is a different type. |
JOURNEY_VALIDATION_FAILED | 400 | 400 — SCAN-CMP-013 journey resume re-validation failed: the stored journey_definition no longer passes graph validation. |
JOURNEY_DEFINITION_INVALID | 400 | 400 — the campaign steps payload is not a valid journey graph (nodes/edges missing or unparseable). |
JOURNEY_TRIGGER_MISSING | 400 | 400 — the journey graph has no journeyTrigger node, so no entry point can be resolved for enrollment. |
JOURNEY_TRIGGER_DISCONNECTED | 400 | 400 — the journey trigger node has no outgoing edge, so there is no first step to enroll a contact into. |
RESUME_FAILED | 500 | 500 — the journey executor threw while resuming a paused journey; the scheduler increments resume_attempts and backs off / DLQs. |
Contacts / Imports
| Code | HTTP | Description |
|---|---|---|
IMPORT_NOT_CANCELLABLE | 409 | 409 — POST /imports/:jobId/cancel (service cancelImport) refused: the import job exists but is already in a terminal state (succeeded / failed / cancelled), or it lost the concurrent cancel CAS race. |
IMPORT_STILL_RUNNING | 409 | 409 — POST /imports/:jobId/rollback (service rollbackImport) refused: the import is still pending / running, so it cannot be rolled back yet. |
ALREADY_ROLLED_BACK | 409 | 409 — POST /imports/:jobId/rollback refused: the import job already carries a rollback_at stamp, so the contacts it created were already deleted. |
IMPORT_JOB_NOT_FOUND | 404 | 404 — GET /contacts/imports/:id status poll found no import job with the supplied id in the caller’s tenant schema. |
IMPORT_QUEUE_UNAVAILABLE | 503 | 503 — async contact-import enqueue (POST /contacts/imports) could not hand the job to the import queue (queue / Redis offline). |
ERASURE_COOLING_OFF_ACTIVE | 409 | 409 — POST /contacts/:id/gdpr/erasure-request refused because a pending or executing Article-17 erasure request already exists for the contact (partial unique index uq_gdpr_erasure_requests_active). |
AI_INVALID_RULES | 422 | 422 — POST /contacts/segments/suggest-rules (AI natural-language segment builder) refused the LLM-proposed filter rules. |
CDP public ingest (signed-HMAC track API)
| Code | HTTP | Description |
|---|---|---|
CDP_UNAUTHORIZED | 401 | 401 — the public, signed-HMAC CDP ingest endpoint (POST /cdp/v1/{ingest_id}/{track|identify|page|screen|group|alias|batch}) rejected the request because HMAC signature, timestamp, or replay-nonce verification failed. |
CDP_PAYLOAD_TOO_LARGE | 413 | 413 — an inbound CDP ingest payload exceeded the inline byte cap (CDP_INLINE_MAX_BYTES, 1 MB). |
EVENT_PAYLOAD_TOO_LARGE | 413 | 413 — the developer event-ingestion surface refused an event whose properties JSON exceeds the ~1 MiB inline ceiling (CDP_INLINE_MAX_BYTES, 1024×1024 bytes). |
SCHEMA_VALIDATION_FAILED | 422 | 422 — a CDP ingest event failed strict-mode JSON-schema validation (the tenant runs event-schema enforcement in strict mode). |
TRACKING_PLAN_VIOLATION | 422 | 422 — a CDP ingest event was rejected by the tenant’s tracking plan running with enforcement=strict. |
Co-browse (live screen-share)
| Code | HTTP | Description |
|---|---|---|
COBROWSE_NOT_ACTIVE | 404 | 404 — an agent (POST /cobrowse/:conversationId/join, see apps/api/src/routes/cobrowse/cobrowse.controller.ts) or a visitor (apps/api/src/routes/widget/index.ts) asked to join a co-browse room for a conversation that has no live, jo… |
COBROWSE_UNAVAILABLE | 503 | 503 — the co-browse session was joinable, but the co-browse media token could not be minted because the media service is unreachable or not configured on this deployment. |
USER_ALREADY_IN_ORG | 409 | 409 — a Settings → Team invite was declined because the invited email already belongs to an organization; Orbit seats each user in a single organization, so that person can’t accept the invite — ask them to use a different email address. |
ALREADY_ORG_MEMBER | 409 | 409 — a Settings → Team invite was declined because the invited email is already a member of your own workspace, so no action is needed — manage that person from the members list instead of re-inviting them. |
Handling Errors in Code
Node.js
import { Orbit, OrbitApiError } from '@devotel/orbit-sdk'
const orbit = new Orbit({ apiKey: process.env.ORBIT_API_KEY })
try {
await orbit.messages.send({ channel: 'sms', to: 'invalid', body: 'Hi' })
} catch (error) {
if (error instanceof OrbitApiError) {
console.error(`[${error.code}] ${error.message}`)
console.error(`Status: ${error.status}`)
console.error(`Request ID: ${error.requestId}`)
}
}
The
Devotel and DevotelApiError aliases are exported for
compatibility with early-access code but Orbit / OrbitApiError
are the canonical names in @devotel/orbit-sdk v0.2+.A first-party Python SDK is on the roadmap but not yet shipped. Until
then, decode the JSON response body and read
meta.request_id /
error.code / error.message directly from any HTTP client.Always include the
request_id from the error response meta
when contacting Orbit support. This allows us to trace the exact
request through our infrastructure.