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_error422
idempotency_error409 / 422
rate_limit_error429
quota_error402
not_found_error404
upstream_error503
internal_error500

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, or revoked key. Fix your Authorization header.
revoked_api_key401Key was revoked from the dashboard. Create a new one.
expired_api_key401Key past its expiration date. Create a new one.
insufficient_scope403Key lacks the required scope (response includes required_scope).
agent_not_authorized403Key is restricted to specific agents and this one isn't allowlisted.
invalid_agent_id422agent_id isn't a valid UUID.
invalid_phone_number422to isn't a valid E.164 number.
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).
invalid_template_name422template.name is missing or blank.
invalid_request_body422A required field is missing or has the wrong type (response includes param naming the offending field).
idempotency_key_in_progress409Same key + body still processing. Retry after Retry-After.
idempotency_key_in_use_with_different_params422Same key was used previously with a different body (response includes original_correlation_id).
rate_limit_exceeded429Per-key rate limit hit. Backoff and retry after Retry-After.
message_limit_exceeded402(Future) Subscription's message limit reached.
message_not_found404GET /v1/whatsapp/messages/{id} — id doesn't exist or belongs to another organization.
endpoint_not_found404The path doesn't match any /v1/ endpoint. Check for typos.
whatsapp_unavailable503Meta's WhatsApp Cloud API is unreachable. Retry with backoff.
internal_server_error500Our problem. Retry with exponential backoff; if it persists, send us the correlation_id.

What HTTP statuses can the API return?

StatusMeaning
200Synchronous success (e.g. status lookup)
201Resource created
202Accepted for async processing (e.g. message queued for send)
400Malformed request (invalid JSON)
401Authentication failed
402(Future) Quota exceeded
403Authorization failed (scope, agent allowlist)
404Resource not found
409Conflict (idempotency key in progress)
422Validation error
429Rate limit exceeded
500Internal error
503Upstream platform unavailable

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:

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

Max 128 chars, alphanumeric plus _-. We reflect it back 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.