WhatsApp API Error Codes: What Each One Means
Your logs say (#131049) This message was not delivered to maintain healthy ecosystem engagement. The on-call question is simple: retry, fix something, or give up on this recipient? The answer depends entirely on the number in brackets, and guessing wrong either spams a customer or silently drops a message.
This is a working reference to WhatsApp API error codes on Meta's Cloud API: how errors reach you, what the codes you'll actually see mean, and what to do about each. Every code and description below was checked against Meta's error codes page as of October 2026; we left out codes we couldn't confirm there.
It ends with a small function that turns a code into a next step, so your sender handles errors the same way every time. For the platform overview, see our complete guide to the WhatsApp API.
How Cloud API errors reach you
Errors come back in two places, and sometimes both. A request that's invalid fails synchronously: the HTTP response carries an error object. A problem discovered later, such as a user who can't receive messages, arrives asynchronously in a failed status webhook. Meta recommends watching both.
The synchronous shape, using Meta's own example:
{
"error": {
"message": "(#130429) Rate limit hit",
"type": "OAuthException",
"code": 130429,
"error_data": {
"messaging_product": "whatsapp",
"details": "Cloud API message throughput has been reached."
},
"fbtrace_id": "Az8or2yhqkZfEZ-_4Qn_Bam"
}
}
In webhooks, the same information appears as an errors array on a status (statuses[].errors), on an incoming message of type unsupported, or at the top level of value for system and account problems.
Four rules from Meta's documentation:
- Branch on
codeand readdetails. Titles insidemessagewill eventually be deprecated, so don't string-match them. - Ignore
error_subcode. It's deprecated and not returned from v16.0 onward. - Log
fbtrace_id. Meta support asks for it. - Expect different codes for the same request. Meta runs its validation checks in an order that can change, so a request with two problems may report either one first.
Token and permission errors
These mean the request never got as far as WhatsApp. Retrying won't help until the token is fixed. Paste the token into Meta's Access Token Debugger and check it has whatsapp_business_messaging and whatsapp_business_management.
| Code | Meaning and fix |
|---|---|
0 | Meta couldn't authenticate the app user: the token expired, was invalidated, or access was blocked. Generate a new token. |
3 | Capability or permission issue. Check the token's permissions. |
10 | Permission not granted or removed, or you aren't eligible for this endpoint. Check permissions and eligibility. |
190 | Access token expired. Move from temporary tokens to a system user token; see our access token guide. |
200 | No token sent, on some GET endpoints. Add the Authorization header. |
200-299 | Permission not granted or removed. Same fix as 10. |
131005 | Permission not granted or removed. Same fix. |
Throttling errors
Throttling errors are the ones you should retry, with care. Retrying instantly in a tight loop turns a rate limit into an outage.
| Code | Meaning and fix |
|---|---|
4 | Your app hit its API call rate limit. Check Application Rate Limit in the App Dashboard and slow down. |
80007 | The WhatsApp Business Account hit its rate limit. Back off and reduce call volume. |
130429 | Message throughput reached (80 messages per second per number by default). Queue sends and retry with backoff. |
131056 | Pair rate limit: too many messages to the same user in a short time. Others are unaffected. Meta allows about one message every 6 seconds per user and suggests retrying after 4^X seconds, increasing X each failure. |
131048 | Sending restricted because too many earlier messages were blocked or flagged as spam. Not a retry case: check quality in WhatsApp Manager and fix content and targeting. |
131064 | Messaging limited because of template classification violations, for templates and direct sends. Fix template categories; it lifts after the enforcement period. |
133016 | Too many register or deregister attempts for the number. Wait until it's unblocked. |
Our throughput guide covers queueing and the automatic upgrade to 1,000 messages per second.
Message delivery errors
These are the codes behind most "why didn't it arrive?" tickets.
| Code | Meaning and fix |
|---|---|
131047 | More than 24 hours since the user last messaged you. Send an approved template instead. |
131026 | Undeliverable: the number isn't on WhatsApp, the user hasn't accepted current terms, or their app is very old. Don't retry; reach them another way. |
131049 | Withheld "to maintain healthy ecosystem engagement", usually the per-user marketing limit. Wait at least 24 hours before resending; retrying sooner only produces more errors. |
131050 | The user stopped marketing messages from you. Don't retry. Subscribe to the user_preferences webhook to stay in sync. |
130403 | Your business has blocked this user. Don't retry until you unblock them. |
131021 | Sender and recipient are the same number. |
130472 | Not sent because the user is in a Meta marketing message experiment. Nothing to fix. |
131051 | Unsupported message type. |
131052 | Meta couldn't download media the user sent you, for example a file over 100 MB. Ask them to send it another way. |
131053 | Meta couldn't upload your media, often because the MIME type doesn't match the file. Check it with file -I. |
131057 | Account in maintenance mode, for example during a throughput upgrade. Wait and retry. |
131063 | The template is marketing, but marketing templates are disabled on Cloud API for this account. Use the Marketing Messages API or re-enable them. |
100 | Unsupported or misspelled parameter, or a value over a length limit. Check the endpoint reference. |
131008 | A required parameter is missing. |
131009 | A parameter value is invalid, for example a bad wamid when marking a message as read. |
131000 | Unknown error. Retry; if it persists, open a Direct Support ticket. |
1, 2, 131016 | Invalid request or possible server error (1), temporary downtime (2), service unavailable (131016). Check Meta's status page. Retry 2 and 131016; for 1, also recheck the request format. |
Some of these, 131049 among them, are reported on a failed status webhook rather than in the HTTP response, which is why you watch both. Our undelivered message checklist walks through diagnosing them in order.
Account, template and registration errors
Account and integrity. 368 means the account was restricted or disabled for a policy violation. 130497 means it can't message users in certain countries. 131031 means the account is restricted or disabled, or request data such as a two-step verification PIN didn't match; Meta points to the Health Status API for details. 131042 is a billing problem, such as no payment method attached, a credit line over its limit, or timezone or currency not set. 131045 means the number isn't registered, 131037 means a Meta-provided 555 business number has no approved display name, and 33 means the phone number was deleted.
Template sends. These usually mean your code and the template disagree:
| Code | Meaning and fix |
|---|---|
132000 | Wrong number of parameters for the template. |
132001 | Template doesn't exist in that language or isn't approved. Check the exact language code. |
132005 | Translated text too long. |
132007 | Template content violates policy. |
132012 | Parameter values in the wrong format. |
132015 | Template paused for low quality. Edit it and resend once approved. |
132016 | Paused too many times and now permanently disabled. Create a new one. |
132068, 132069 | The Flow is blocked, or throttled after 10 messages in the last hour. Fix the Flow. |
Template creation. 2388040 is a field over its character limit; 2388047, 2388072 and 2388073 are header, body and footer formatting problems; 2388293 means too many variables for the text length; 2388299 means a variable sits at the very start or end. 2388019 means you've hit the template cap, which Meta sets at 250 per account for unverified portfolios and up to 6,000 for verified ones with an approved display name. For rewrite examples, see why WhatsApp templates get rejected.
Registration. 133005 is a wrong two-step PIN, 133008 and 133009 mean too many or too fast PIN attempts, 133006 means verify the number before registering, 133010 means it isn't registered, 133000 means a previous deregistration failed, and 133015 means a recently deleted number is still being removed; wait 5 minutes.
Turn codes into actions
Don't scatter error handling across your codebase. One function that maps a code to a next step keeps every sender consistent:
const RETRY_WITH_BACKOFF = new Set([2, 4, 80007, 130429, 131000, 131016, 131057, 133004]);
const FIX_THE_REQUEST = new Set([100, 131008, 131009, 131051, 131053, 132000, 132001, 132005, 132012]);
const FIX_THE_TOKEN = new Set([0, 3, 10, 190, 131005]);
const DO_NOT_RETRY = new Set([130403, 131021, 131026, 131050]);
export function nextStep(code) {
if (code === 131047) return "send_template"; // window closed
if (code === 131049) return "wait_24h"; // per-user marketing limit
if (code === 131056) return "slow_down_for_user"; // pair rate limit
if (RETRY_WITH_BACKOFF.has(code)) return "retry_with_backoff";
if (FIX_THE_TOKEN.has(code) || (code >= 200 && code <= 299)) return "fix_token";
if (FIX_THE_REQUEST.has(code)) return "fix_request";
if (DO_NOT_RETRY.has(code)) return "do_not_retry";
return "alert_a_human"; // 368, 131042, 131048, 132015 and anything unknown
}
Three habits make this pay off. Cap retries and add jitter so a throughput error doesn't become a thundering herd. Mark do_not_retry recipients in your CRM so the next campaign skips them. And page a person for alert_a_human codes, because account restrictions, billing failures and paused templates stop every send, not just one.
If a message returns no error at all but never arrives, work through our checklist for WhatsApp API messages not delivered.
Where Tenashi fits
Many of these errors exist because of the official platform's rules: templates, windows, marketing limits, billing. If your WhatsApp traffic is mostly conversations with people who already know your business, Tenashi's API avoids that whole class. It sends from the number your team already uses, linked by QR scan, with no templates, no window and no per-message fees, from $18/mo with the API included.
It has its own small set of errors, all in one shape with string codes you can branch on: invalid_phone, unauthorized, plan_required, number_disconnected, send_blocked (ban protection paused a repeated text), rate_limited, new_chat_limit and media_too_large. It isn't Meta's API and isn't meant for OTPs or high volume.
Read the API docs · Get started
FAQ
What does WhatsApp API error 131047 mean?
It means more than 24 hours have passed since the user last messaged your business number, so the customer service window is closed and free-form messages aren't allowed. Send an approved template instead. If the user replies, a new 24-hour window opens and you can send regular messages again.
What does WhatsApp error 131026 mean?
The message was undeliverable. Meta lists three causes: the number isn't on WhatsApp, the user hasn't accepted WhatsApp's latest terms of service, or they're on a very old app version. Retrying won't help. Contact the customer another way and ask them to check their number, accept the terms or update WhatsApp.
How should I handle error 130429?
It means your number hit its throughput limit, 80 messages per second by default. Put sends behind a queue, retry with exponential backoff and jitter, and keep concurrency below the limit. If you're consistently above it, Meta upgrades eligible numbers to 1,000 messages per second automatically, with no extra charge.
When can I resend after error 131049?
Wait at least 24 hours. The code means WhatsApp withheld the message, usually because the user hit the per-user limit on marketing messages. Meta warns that resending within 24 hours to users at their limit can block further attempts for up to a day and distorts your delivery reporting.
Why does the same request return different error codes?
Meta validates each send through several checks and may run them in a different order over time. A request with two problems can report either one first, so you may see one code, fix it, and then hit another. Branch on the code you receive and log details and fbtrace_id.
A clear map from code to action is most of what reliable sending is. And if template and window errors make up most of your logs, Tenashi's API docs show a send path that has neither.