Errors
Every error has the same shape, with a stable machine-readable code:
{
"error": {
"code": "SESSION_NOT_CONNECTED",
"message": "Session is not connected",
"status": 409,
"requestId": "req_3f1c9a7e2b4d4c0e8a1b2c3d"
}
}
- Branch on
code, not on message. Messages are for humans and may change.
- Extra fields: some errors add context, such as
retryAfter (seconds), limit, used,
messageId, or details for validation errors.
- Support: include
requestId when you contact support.
Status codes
| HTTP |
Meaning |
400 |
Bad input (bad phone number, missing content…) |
401 |
Missing or invalid API key |
402 |
Your plan doesn't allow it right now: expired, a limit reached, or a feature not included |
403 |
Not allowed with this key (e.g. a session key used for an account-wide action) |
404 |
Doesn't exist, or isn't yours: other accounts' ids always look like 404 |
409 |
Conflict with the current state (session not connected, paused…) |
422 |
Validation failed: the body doesn't match the schema |
429 |
Too many requests, or a quota was reached. Wait Retry-After seconds |
5xx |
Our side, or WhatsApp is unreachable. Safe to retry with backoff (use an Idempotency-Key on sends) |
Codes
Auth and keys
| Code |
HTTP |
|
INVALID_API_KEY |
401 |
Missing, mistyped or revoked key |
KEY_SCOPE |
403 |
A session key used for an account-wide action |
TENANT_SUSPENDED |
403 |
The account is suspended. Contact support |
MISSING_SESSION_ID |
400 |
Several sessions and no sessionId |
SESSION_NOT_FOUND |
404 |
No such session in your account |
Sending
| Code |
HTTP |
|
VALIDATION_ERROR |
422 |
The body is invalid. See details[].field |
INVALID_MESSAGE |
400 |
No text and no media |
INVALID_JID |
400 |
to isn't a valid number or JID |
SESSION_NOT_CONNECTED |
409 |
The session is offline or not linked yet |
SESSION_PAUSED |
409 |
Sending is paused for this session |
RATE_LIMITED |
429 |
The safety engine's pacing (per number, or per recipient) |
WARMUP_RESTRICTED |
429 |
A new number's warm-up cap or requirements. See Safety |
CONTENT_BLOCKED |
429 |
A link-only message, a banned term, or duplicate text |
SESSION_AT_RISK |
429 |
Sending stopped to protect a number in trouble |
WORKER_TIMEOUT |
504 |
WhatsApp didn't answer in time; the message may or may not have been sent |
SESSION_UNAVAILABLE / CAPACITY_EXHAUSTED |
503 |
Temporary. Retry shortly |
IDEMPOTENCY_KEY_REUSED |
422 |
This Idempotency-Key was used with a different body |
IDEMPOTENCY_IN_PROGRESS |
409 |
The first request with this key is still running |
INVALID_IDEMPOTENCY_KEY |
400 |
1–255 printable ASCII characters |
MESSAGE_NOT_FOUND |
404 |
Unknown message id |
MESSAGE_NOT_CANCELABLE |
409 |
Already sending or finished |
Async results (message.failed and error.code)
An async message fails with one of the sending codes above, or with one of these:
| Code |
|
EXPIRED |
Not sent before expiresAt |
DELIVERY_UNKNOWN |
It might have been sent. Not retried, so it is never duplicated |
Sessions
| Code |
HTTP |
|
QR_PENDING |
202 |
The QR code is being generated. Retry in a moment |
QR_NOT_AVAILABLE |
404 |
Connect the session first |
ALREADY_AUTHENTICATED |
409 |
Already linked |
INVALID_PHONE |
400 |
Bad pairing-code phone number |
PAIRING_NOT_READY |
504 |
Retry the pairing-code request |
Plan and billing
| Code |
HTTP |
|
SUBSCRIPTION_REQUIRED |
402 |
No active plan |
SUBSCRIPTION_EXPIRED |
402 |
The trial or plan expired: sessions are disconnected (still linked) and sending is stopped during the grace period |
SUBSCRIPTION_SUSPENDED |
402 |
Grace is over: sessions are paused until you renew |
TRIAL_NOT_AVAILABLE |
402 |
This number or account already used a free trial |
PLAN_LIMIT_SESSIONS / PLAN_LIMIT_WEBHOOKS / PLAN_LIMIT_API_KEYS |
402 |
You hit your plan's count. limit says how many |
PLAN_FEATURE_UNAVAILABLE |
402 |
Needs a higher plan (e.g. multi-number pooling) |
DAILY_LIMIT_REACHED / MEDIA_LIMIT_REACHED |
429 |
Today's quota. Resets at 00:00 UTC |
PERIOD_LIMIT_REACHED |
429 |
Your plan's messages-per-period quota |
API_RATE_LIMITED |
429 |
Your plan's API requests per minute |
Webhooks
| Code |
HTTP |
|
INVALID_WEBHOOK_URL |
400 |
Not a public http(s) URL |
INVALID_EVENT |
400 |
Unknown event type |
WEBHOOK_NOT_FOUND / DELIVERY_NOT_FOUND |
404 |
|
WEBHOOK_DISABLED |
409 |
Enable the webhook before re-sending |
PAYLOAD_NOT_KEPT |
409 |
The delivery's message content was not kept (we never store it), so it can't be re-sent |