Skip to main content

Errors

Every error from the Mojeeb Public API uses the same envelope. Branch on code (stable, forever-additive) — never on message (human-readable, may be reworded without notice).

What does an error response look like?​

{
"error": {
"type": "validation_error",
"code": "invalid_from_phone",
"message": "The 'from' field must be an E.164 phone number...",
"param": "from",
"correlation_id": "req_01KQ..."
}
}
FieldAlways present?Purpose
typeYesStable category for catch blocks
codeYesStable, specific reason — branch on this
messageYesHuman-readable; never use as a key
correlation_idYesTrace id for our logs — quote in support tickets
Extra fieldsSometimesPer-error context (e.g. param, available_phones, original_correlation_id)

What are the error types?​

A small, stable set of categories. Forever-additive — new types may appear, none will be removed:

typeTypical HTTP
authentication_error401
permission_error403
validation_error413, 422
idempotency_error409 / 422
rate_limit_error429
quota_error402
conflict_error409
not_found_error404
internal_error500, 503 (and 401 when the key couldn't be checked)

What's the full code catalog?​

Codes are a stable enum. New codes appear without notice; nothing existing will be renamed or repurposed.

codeHTTPMeaning
invalid_api_key401Missing, malformed, unknown, revoked or expired key. Fix your Authorization header.
insufficient_scope403Key lacks the required scope (response includes required_scope).
agent_not_authorized403Key is restricted to specific agents and this one isn't on its list.
shared_with_other_agents403The knowledge base, or a custom API tool's site login, is also used by agents the key can't act on, so the key can't change it.
feature_not_available403Your plan doesn't include this: custom API tools are on paid plans. Upgrade, or use the endpoints your plan has.
not_note_author403Only a note's author can edit or delete it; a key acts as the person who created it.
system_note_read_only403Notes Mojeeb records, such as lead status changes, can't be edited or deleted.
agent_id_required403A key limited to some agents called a WhatsApp endpoint without a valid agent_id.
agent_not_found404The agent isn't one of your organization's agents.
not_found404The conversation, contact, note, lead, lead field, knowledge base, connection, custom API tool or comment isn't the agent's (a deleted conversation is not found too), a conversation's message you asked for isn't one of its messages, or the connection whose templates you asked for isn't a WhatsApp number. On the usage history, your organization has no subscription.
message_not_found404GET /v1/whatsapp/messages/{id}: the id doesn't exist, belongs to another organization, or was sent through an agent outside the key's agent list.
endpoint_not_found404No /v1/ endpoint matches the method and path, including an id that isn't a UUID. Check for typos.
lead_capture_not_found404The agent has no Capture Lead tool, so it has no lead capture prompt to read or change. Contact Mojeeb support to have the tool added.
invalid_request_body422A field is missing, has the wrong type, breaks a limit or a format (such as a lead phone or contact mobile that isn't E.164), or a query parameter's value isn't valid (response includes param naming it).
invalid_request422A business rule refused the change (for example an unknown lead status or a reserved lead field key), the cursor isn't one the API returned, or a message list's after isn't a message of the conversation or was sent together with cursor (both with param: after). The message says which.
invalid_date_range422The analytics window is out of bounds: to is before from, a date is later than today in UTC, or the window is longer than the endpoint allows. The message says which.
no_settings422A settings or conversation update sent nothing to change.
messaging_window_closed422A reply in a conversation whose customer hasn't written in the last 24 hours: WhatsApp, Facebook and Instagram won't deliver it. Nothing was sent. On WhatsApp, send a template.
channel_not_supported422A reply in a conversation on a channel Mojeeb can't send on yet (TikTok). Nothing was sent.
comment_already_hidden422hideComment on a comment that is hidden already.
comment_not_hidden422unhideComment on a comment that isn't hidden.
platform_hide_failed422Facebook or Instagram refused to hide or show the comment, for example because it was deleted, or couldn't be reached. It can be temporary.
field_not_writable422An agent update sent a value for a field a key can't change: status (so a key can't delete an agent), ai_model, model_provider, avatar_url or language (response includes param naming it). Nothing was changed.
unknown_timezone422time_zone isn't an IANA time zone id in Region/City form, such as Africa/Cairo (UTC is Etc/UTC).
invalid_follow_up_platform422A follow-up channel isn't whatsapp, facebook or instagram.
invalid_follow_up_steps422More steps than allowed, a delay out of range, or two steps with the same delay.
assignee_not_allowed422The teammate can't open the agent (they aren't in your organization, or they're limited to other agents), so the lead or conversation can't be assigned to them. Pick someone with can_open_agent: true on the agent's members list.
system_field422A built-in lead field (built_in: true), the lead statuses included, can't be changed or deleted through the API.
lead_field_limit_reached422The agent already has as many custom lead fields as the API can add. Delete one it no longer needs first.
connection_inactive409The connection is disconnected (active: false), so its settings can't be changed and its templates can't be listed. Reconnect it in the dashboard first.
connection_needs_reconnection409Meta no longer accepts the WhatsApp number's access (it was revoked or expired, or the number left its WhatsApp Business Account), so its templates can't be read. Reconnect the number in the dashboard; retrying won't help.
field_key_taken409The agent already has a lead field with this key, built-in fields included. Nothing was created. A create retried after a lost response lands here too, so list the lead fields and carry on.
no_current_usage_period409No billing period of your subscription covers now, so Mojeeb treats it as not renewed and the AI doesn't reply until a period opens. It clears when the renewal lands; if it lasts, contact support with the correlation_id. GET /v1/organization/usage also answers it when your organization has no subscription at all.
usage_periods_overlap409More than one billing period of your subscription covers now, so Mojeeb can't tell which limits apply. Contact support with the correlation_id.
login_shared409The custom API login you sent differs from the site's saved one, or carries a secret, and other tools use it. Send change_shared_login: true to change it for all of them, or leave login out.
tool_not_tested409A custom API tool can be switched on only after a passing test of its current request. Test it, then switch it on.
request_body_too_large413The request body is larger than 1 MB.
invalid_agent_id422agent_id isn't a valid UUID (WhatsApp endpoints).
invalid_phone_number422to isn't a valid E.164 number (WhatsApp endpoints). A lead phone or contact mobile that isn't E.164 is invalid_request_body.
invalid_from_phone422from isn't a valid E.164 number.
from_phone_not_found_for_agent422from is well-formed but doesn't match any active WhatsApp connection on the agent (response includes available_phones).
template_header_media_url_invalid422template.header_media_url isn't an absolute HTTPS URL.
template_not_found422The connection has no template with that name, whatever its status (response includes available_templates). When Mojeeb can't read the templates from Meta, or the number has more templates than Mojeeb reads and this one isn't among them, this check is skipped and the send is accepted.
template_not_found_for_language422The template has no version in that language, whatever its status (response includes available_languages).
idempotency_key_in_progress409A request with this key is still running, or one with it that was refused or failed after claiming the key (for example a reply's messaging_window_closed) started less than 60 seconds ago, whatever the body. Retry after Retry-After, or send the corrected request with a new key.
idempotency_key_in_use_with_different_params422The key belongs to an earlier accepted request that differs from this one: another body, or another endpoint or conversation (the same text replied in another conversation counts as different). The response includes original_correlation_id.
idempotency_unknown_outcome500An internal fault in the idempotency check (not expected). Retry with the same key and body.
unknown_send_outcome500An internal fault mapping the send result (not expected). Look up the message before sending again.
rate_limit_exceeded429Per-key rate limit hit: the default one, or the lower one of the WhatsApp template list or of replies in a conversation. Back off and retry after Retry-After.
test_rate_limited429Your company ran too many custom API tool tests this minute (30, across its keys and the dashboard). Retry after Retry-After.
message_limit_exceeded402Reserved: the subscription's message limit. Not sent today.
access_unavailable503The access check couldn't run: the key's, or when assigning a lead or a conversation, the teammate's. Retry with backoff.
meta_unavailable503Meta didn't return what was asked, such as a WhatsApp number's templates (an outage, a timeout or Meta's own rate limit). Retry with backoff.
internal_server_error500, 401Our problem: retry with exponential backoff, and if it persists, send us the correlation_id. With 401 it means we couldn't check the key; retry, don't rotate it.

What HTTP statuses can the API return?​

StatusMeaning
200Success with a body (a read, an update or an assignment)
201Resource created (a lead, a note, a knowledge base, a lead field, a custom API tool, a reply in a conversation)
202Accepted for async processing (a message queued for send)
204Success with no body (a delete)
401Authentication failed
402Reserved: quota exceeded
403Authorization failed (scope, agent list, shared knowledge or login, note author, a feature your plan doesn't include)
404Resource not found
409Conflict (idempotency key in progress, a disconnected connection or one that needs reconnecting, a lead field key that already exists, no single current billing period, a shared custom API login, or an untested tool)
413Request body larger than 1 MB
415The body isn't sent as application/json (a standard problem-details body, not the envelope)
422Validation error, including a body that isn't valid JSON
429Rate limit exceeded
500Internal error
503The access check or Meta temporarily unavailable

Which errors should I retry?​

Retry only the temporary ones. Wait for Retry-After on 429 and on 409 idempotency_key_in_progress. Use exponential backoff on 503 errors, on 500 errors except unknown_send_outcome, on 422 platform_hide_failed (Facebook or Instagram may just be unavailable), and on a 401 whose code is internal_server_error. Every other error needs a change before you send the request again.

ErrorWhat to do
409 connection_inactive, 409 connection_needs_reconnectionReconnect the connection in the dashboard, then try again.
409 field_key_takenThe field already exists: list the agent's lead fields and carry on.
409 no_current_usage_periodWait: it clears when the renewal lands. Contact support if it lasts. With no subscription at all it won't clear until you subscribe.
409 usage_periods_overlapContact support with the correlation_id.
409 login_sharedLeave login out, or send change_shared_login: true if every tool on the site should change.
409 tool_not_testedTest the tool, then switch it on in a request of its own.
500 unknown_send_outcomeLook up the message before sending it again.
422 messaging_window_closedWait for the customer to write, or, on WhatsApp, send a template.
422 platform_hide_failedTry again later, with backoff. If it keeps failing, the comment was probably deleted.
422 comment_already_hidden, 422 comment_not_hiddenNothing to fix: the comment is already as you asked. After a 500, it means your first request went through.
Any other 4xxFix the request; the code and message say what to change.

How do I use the correlation_id?​

Save it on every error. When you contact support, paste the correlation_id from the failing response — we can trace the entire request lifecycle in our logs in seconds.

You can also send your own trace id and we'll honor it when it's valid:

curl ... -H "X-Correlation-ID: my-app-trace-abc123"

Up to 128 characters: letters, digits, _ and -. An id that breaks these rules is ignored without an error and we generate one instead, so take the id from the response header rather than assuming yours was kept. We reflect the id in X-Correlation-ID on the response and embed it in any error body. If you don't send one, we generate req_<26-char ULID>.

Common questions​

Why does invalid_api_key cover so many sub-cases?​

A single code keeps client logic simple — your code only needs one branch for "auth failed." The message field disambiguates for humans debugging, but you should never branch on text. Treat any invalid_api_key as "fix the key and retry."

Will you add new error codes later?​

Yes. New code values can appear without notice as we add features. Keep your switch/match statements default-safe — fall back to "unknown error, log and surface to user."

What about field-level errors with multiple invalid fields?​

Currently the API returns the first validation error encountered. We may add a richer multi-error shape later as an additive change (a new optional field on the envelope, never replacing existing fields). For now, fix one error at a time.

What's original_correlation_id?​

Returned on idempotency_key_in_use_with_different_params. It points to the trace id of the request that originally claimed the idempotency key, so you can find that earlier request in your own application logs.

What's available_phones?​

Returned on from_phone_not_found_for_agent. Lists every active WhatsApp number on the agent in E.164 format, so you can self-correct your from value without a second roundtrip to discover what was valid.