Errors, limits & health
Errors & limits
How the WhatsApp API reports failures — the response envelope, the actionable send-error codes, the 429 rate-limit shape — and every hard limit that governs media, templates, broadcasts and the 24-hour window. Read this alongside Webhooks & events, where the same failures resurface asynchronously in whatsapp.message.status.
The response envelope
Every WhatsApp endpoint returns the standard Telenow envelope. Success carries data; failure carries a human-readable error string and an HTTP status code.
{ "success": true, "data": { "wamid": "wamid.HBgL…" } }
{ "success": false, "error": "24-hour customer service window has closed — send an approved template instead" }
| Status | When | What to do |
|---|---|---|
400 | Malformed body, wrong/multiple content fields, or an actionable send error (codes below) | Fix the request per the code |
401 | Missing or invalid app key | Check Authorization: Bearer vai_app_… — see Authentication |
403 | App key lacks the required scope | Grant the scope at install — Scopes |
404 | Unknown channelId, template, campaign, or media id | Check the id belongs to your org |
404 | Body error is Native WhatsApp is not enabled on every WhatsApp endpoint (incl. GET /channels) | The native WhatsApp Cloud API isn't enabled on this Telenow deployment — a platform-wide runtime flag, not a bad id. Contact your administrator |
413 | Upload exceeds the media cap for its type | Shrink or re-encode — media caps |
429 | Rate limit exceeded | Back off using retryAfter — rate limits |
500 | An upstream/Meta send failure that doesn't match a known code — returns a generic {"success":false,"error":"Something went wrong"} with no Meta detail (the real error is logged server-side only) | Recover the specific code from the whatsapp.message.status webhook |
The send endpoint validates the body strictly:
POST /sendneeds exactly one content field (message,mediaId,location,reaction,contacts, orinteractive). Zero or two of them is a400before the message ever reaches WhatsApp.
Send error codes
When the failure matches one of the known Meta codes in the table below, Telenow surfaces it as an actionable 400 on the send call — you don't have to wait for a webhook to know it failed; any other upstream/Meta failure returns a generic 500 (see the status table) with no Meta detail — recover the code from the whatsapp.message.status webhook. The same codes also appear in the errors array of a whatsapp.message.status event when a message fails after the API already returned a wamid (async delivery failures).
| Code | Meaning | Fix |
|---|---|---|
131042 | Payment issue — the account can't be billed for this message | Add or fix a payment method in Meta Business Manager |
131047 | 24-hour customer service window has closed | Send an approved template instead of free-form text |
131026 | Message undeliverable — recipient isn't on WhatsApp or is restricted | Verify the number is a real WhatsApp user; drop it from retries |
131056 | Sending too fast to this recipient (pair rate limit) | Back off and retry after a short delay |
368 / 131031 | Number restricted for a policy violation | The number/account is limited by Meta — resolve the policy issue in Business Manager |
132000–132999 | Template problem — approval, missing/extra parameters, or a paused template | Check the template is APPROVED and your variables/components match its placeholders |
Example — sending free-form text after the window closed:
curl -X POST https://api.telenow.ai/api/app-whatsapp/send \
-H "Authorization: Bearer vai_app_…" \
-H "Content-Type: application/json" \
-d '{ "channelId": "9f2c7b1e-…", "to": "+919876543210",
"message": "Just following up!" }'
{ "success": false, "error": "131047: 24-hour window closed — send an approved template" }
The fix is a template send, which is allowed outside the window:
curl -X POST https://api.telenow.ai/api/app-whatsapp/send-template \
-H "Authorization: Bearer vai_app_…" \
-H "Content-Type: application/json" \
-d '{ "channelId": "9f2c7b1e-…", "to": "+919876543210",
"template": "order_update", "language": "en_US", "variables": ["Asha", "#1234"] }'
{ "success": true, "data": { "wamid": "wamid.HBgLMTIxNTU1NTk4NzYVAgERGBI0Rjc5…" } }
Rate limits
The Data API allows roughly 20 requests/second with a burst of 60. Over the limit returns 429 with a retryAfter hint in seconds:
{ "success": false, "error": "Data API rate limit reached — slow down", "retryAfter": 1 }
Respect retryAfter before retrying, and serialize sends per recipient to avoid the per-pair 131056. Request bodies are capped at 2 MB on JSON routes; media upload routes allow up to 101 MB (the file itself is still bound by the per-type media caps below).
No idempotency key. Sends aren't deduplicated server-side by a client token. To make retries safe, key your own dedupe on the returned
wamidand only retry when you did not receive one.
Media caps
Uploads to POST /api/app-whatsapp/channels/{id}/media are capped per media type (inferred from the file's MIME). Over the cap returns 413.
| Type | Max size |
|---|---|
| Image | 5 MB |
| Audio | 16 MB |
| Video | 16 MB |
| Sticker | 500 KB |
| Document | 100 MB |
Template header media (POST /channels/{id}/templates/media) is separately capped at 16 MB and limited to image/jpeg, image/png, video/mp4, application/pdf. See Media and Templates.
Template limits
Enforced at template creation and edit time (POST / PATCH template endpoints, scope whatsapp:templates). A violation returns 400 before the template is submitted to Meta.
| Rule | Limit |
|---|---|
| Body text | ≤ 1024 characters |
| Footer text | ≤ 60 characters |
| Header text | ≤ 60 characters |
| Button text | ≤ 25 characters |
| Buttons per template | ≤ 10 |
| Body count | Exactly one non-empty BODY (marketing/utility) |
| Placeholders | Contiguous {{1}}…{{N}} — no gaps, each needs an example |
name | Lowercase letters, digits and _, ≤ 512 chars |
category | MARKETING · UTILITY · AUTHENTICATION |
Editing a template resets it to PENDING re-approval; name and language are immutable. Full component shapes are in Templates.
Not yet supported: carousel and limited-time-offer templates, and one-tap OTP buttons (authentication templates support COPY_CODE only).
Broadcast limits
Broadcasts (POST /campaigns, scope whatsapp:campaign) are bounded per campaign and per app:
| Rule | Limit |
|---|---|
| Recipients per campaign | ≤ 5000 |
| Active campaigns per app | 50 |
| Default throttle | 60 messages/minute (throttle_per_min) |
Beyond these, your real ceiling is Meta's messaging tier for the number (e.g. TIER_1K, TIER_10K) — watch whatsapp.account.health for tier changes.
Display-name & registration limits
- Display name: you can change your number's WhatsApp display name at most 10 times per 30 days (Meta limit).
- Native channels only. The programmatic WhatsApp API operates on native Cloud API numbers set up through Telenow. Numbers linked via WhatsApp Web (QR) or wrapped cloud providers don't expose these endpoints.
The 24-hour window
WhatsApp only allows free-form messages (text, media, interactive, location, reaction, contacts) within 24 hours of the customer's last inbound message. Outside that window you must send a pre-approved template — free-form sends fail with 131047.
- Every inbound
whatsapp.message.receivedresets the 24-hour clock. - Templates are always allowed, in or out of the window — that's how you re-open a conversation.
- Reading history via threads shows
lastInboundAt; use it to decide whether the window is open before sending free-form.
customer replies ──► 24h window OPEN ──► free-form text OK ──┐
│ 24h elapse, no reply
▼
window CLOSED ──► free-form → 131047
│
└─► send a template to re-open
Reading failure detail from webhooks
A send can succeed synchronously (you got a wamid) yet fail later at Meta — for example, the number turned out to be undeliverable. That surfaces only as a whatsapp.message.status event with status: "failed" and the same numeric codes in its errors array:
{
"event": "whatsapp.message.status",
"wamid": "wamid.HBgLMTIxNTU1NTk4NzYVAgARGBI3Q0Ez…",
"status": "failed",
"recipient": "+919876543210",
"errors": [ {
"code": 131026,
"title": "Message undeliverable.",
"message": "Message undeliverable.",
"error_data": { "details": "Message failed to send because the recipient's phone number is not a WhatsApp phone number." },
"href": "https://developers.facebook.com/docs/whatsapp/cloud-api/support/error-codes/"
} ]
}
Match the wamid to your original send, look the code up in the table above, and take the same corrective action you would for a synchronous 400. Read error_data.details for the actionable specifics — it's more precise than the generic title. See Webhooks & events for wiring, signatures and dedupe.
Account health
Many send failures are downstream of your account's state — an unverified business, a low quality rating, or no payment method. Check a number's live health (dashboard JWT):
curl "https://api.telenow.ai/api/orgs/{orgId}/whatsapp-cloud/channels/{channelId}/health" \
-H "Authorization: Bearer <jwt>" -H "X-Org-Id: {orgId}"
{ "success": true, "data": {
"phone": { "quality_rating": "GREEN", "messaging_limit_tier": "TIER_1K", "name_status": "APPROVED" },
"waba": { "account_review_status": "APPROVED", "business_verification_status": "verified", "health_status": "AVAILABLE" },
"tokenStatus": "active",
"warnings": [
{ "level": "warn", "title": "Complete business verification",
"detail": "Your business isn't verified, which caps your messaging limits.",
"action": "Open Meta Business Manager" }
]
} }
phone/waba— the raw Meta health fields (quality rating GREEN/YELLOW/RED, messaging tier, review and business-verification status).tokenStatus—active, orrevokedif Meta pulled access (you'll need to reconnect the number).warnings— a ready-made, human-readable list; each has alevel(info/warn/error), atitle, adetail, and an optionalaction. The dashboard renders these as the account-health banner on the channel.
The same signals also arrive asynchronously as whatsapp.account.health webhook events — a nudge to re-read this endpoint. A payment method is the most common blocker: without one, sends fail with 131042 — add it in Meta Business Manager (Meta bills you directly).
Related
- Webhooks & events — receive
message.statusfailures and account-health changes. - Send messages · Templates · Media · Broadcasts.
- WhatsApp API — endpoint index.
- Authentication · Scopes & security.