Errors
Errors from the send, read, media, and API-key routes use this JSON shape:
{
"error": {
"code": "send_outcome_unknown",
"message": "provider outcome unknown; the message may have been sent"
}
}
Branch on error.code, not message. The message is fixed English text for logs and display and may change. Errors never echo your request input, WhatsApp's response, or secrets.
401 responses carry WWW-Authenticate: Bearer. Errors you can retry carry Retry-After in seconds. A wrong HTTP method returns an Allow header.
Send and read errors: was it sent?
Unpoll never retries a send for you. Retrying after an unknown outcome can deliver the message twice. The final column below describes the outcome of a send request, not webhook delivery.
| Status | error.code | Meaning | Sent? |
|---|---|---|---|
400 | invalid_request | Invalid request body, field, or path. | No |
401 | invalid_api_key | Missing, unknown, or revoked API key. | No |
403 | recipient_not_allowed | WhatsApp refused the recipient: an agent may only message its creator. | No |
404 | not_found | The agent does not exist, or the key belongs to another agent. | No |
405 | method_not_allowed | Wrong HTTP method; see the Allow header. | No |
409 | agent_disconnected | The agent is disconnected. | No |
409 | provider_credentials_rejected | WhatsApp rejected the agent's token. Update it in the dashboard. | No |
413 | body_too_large | The body is over 64 KiB. | No |
422 | provider_rejected | WhatsApp rejected the request, for example a reply_to from another conversation. | No |
429 | rate_limited | Over 12 sends, or separately 12 read calls, per minute for this agent, here or at WhatsApp. Retry after Retry-After. | No |
429 | send_in_progress | An earlier send for this agent is still running. Retry after Retry-After. | No |
502 | send_outcome_unknown | WhatsApp failed or timed out mid-send, or returned a broken response. The message may have been sent. Sends only. | Maybe |
503 | provider_unavailable | WhatsApp did not accept the request (503 / provider code 131016). Retry after Retry-After. | No |
503 | unavailable | Unpoll is unavailable, or a read call failed at WhatsApp. Retry after Retry-After. | No |
On 502 send_outcome_unknown, wait for a corresponding message.status webhook before sending again, or accept that a retry may duplicate the message. An interrupted request or timeout at your own client can also leave the outcome unknown. Do not add an indiscriminate retry loop around sending.
Repeating a read call is harmless. Respect retry delays even when an operation is safe to repeat.
Media errors
Media downloads use the same JSON shape, with additional media_not_found, media_too_large, and media_unavailable codes. See the complete media error table for statuses, meanings, and retry guidance.
API-key management errors
The key-management routes require a Firebase ID token, not an agent API key. They can also return dashboard authentication errors such as unauthorized, email_unverified, rate_limited, and unavailable. Creating a key when the agent already has 10 active keys returns 409 api_key_limit.
Event history and manual redelivery also use dashboard authentication and the JSON error shape; an agent API key cannot access them.