"Why is my WhatsApp message not delivered?" is the single most expensive question an Indian sender asks in 2026. A campaign shows 100,000 messages submitted, the dashboard reports them as sent, and then the delivered count quietly stalls at 84,000. The other 16,000 are not lost — they are stuck somewhere in a status lifecycle most senders never learn to read. Each non-delivered message is a paid Meta conversation that produced nothing, a customer who never saw the OTP or the order update, and, at scale, a quality-rating signal that can drag an entire WhatsApp Business Account (WABA) into the Yellow or Red band. This guide is the diagnostic forensics layer: not the tier mechanics (see our companion deliverability tier graduation guide), but the decision tree a sender actually walks when messages show sent-but-not-delivered, pending, or failed — every webhook status decoded, the common Cloud API error codes mapped to a concrete fix, the India-specific nuances (DLT legacy expectations, marketing-template-limit experiments, festival-surge throttling), and an illustrative cohort that cut undelivered from 11% to 2.8%. Error codes here are described as per the Meta Cloud API error reference and should be verified against current docs before you wire automated handling — Meta revises these.
The Status Lifecycle: Where a Message Can Stall
Every WhatsApp Business message moves through a status lifecycle reported back to you via webhook events. You cannot diagnose a delivery failure until you know which stage stalled. The four stages, plus the implicit "accepted" handoff:
- accepted (API 200). Your POST to the Cloud API
/messagesendpoint returned a message ID. This only means Meta accepted the request for processing. It is NOT delivery. A 200 with awamidis the start, not the finish — many senders mistake this for success. - sent. Webhook
statuses[].status = "sent". Meta has dispatched the message toward the recipient's device. One grey tick. If a message sits at sent and never progresses, the recipient's phone is offline, unreachable, or Meta is retrying. - delivered. Webhook
status = "delivered". The message reached the recipient's device (two grey ticks). This is the metric that actually matters for billing-value and reach. - read. Webhook
status = "read"(two blue ticks) — only if the recipient has read receipts enabled. Absence of read does NOT mean non-delivery; many users disable read receipts. - failed. Webhook
status = "failed"with anerrors[]array carrying a code + title. This is the most actionable status — the error code tells you the root cause.
The critical insight: sent and delivered are different events separated by the recipient's reachability and Meta's retry window. A message accepted at the API but never marked delivered is the classic "stuck" case, and it splits into two very different root causes — a phone that is merely offline (Meta keeps retrying for up to roughly 72 hours per the Cloud API behaviour, verify against current docs) versus a hard undeliverable (recipient has no WhatsApp, number invalid) that fails fast.
Read the webhook, not the dashboard. Many BSP dashboards collapse "submitted" and "sent" into one green number, hiding the sent-to-delivered gap. Always reconcile against the raw statuses[] webhook payload — count distinct delivered events against distinct sent events per campaign. The gap, not the headline number, is your deliverability problem.
The Root-Cause Decision Tree for "Not Delivered"
When delivered < sent, walk this tree top to bottom. The first matching branch is almost always your cause.
- Did the message even get accepted? If the API call returned a 4xx/5xx (no
wamid), it never entered the lifecycle. Check payload validity, access token, andphone_number_id. A wrongphone_number_idsilently sends from the wrong (or a non-existent) number context. - Recipient has no WhatsApp / number invalid. The number is not registered on WhatsApp, or is malformed (missing country code, leading zero retained). Fails fast as undeliverable. Fix: validate E.164 format (+91XXXXXXXXXX, no leading 0) and clean lists.
- Phone offline / unreachable. Valid WhatsApp number but device is off or has no connectivity. Sits at sent; Meta retries within the ~72h window. No action needed unless it persists — then treat as undeliverable.
- Outside the 24-hour session window without a template. You can only send free-form messages within 24 hours of the user's last inbound message. Outside that window you MUST use an approved template. Sending free-form here fails with a re-engagement error.
- Template paused, rejected, or disabled. A template flagged for low quality gets paused (or disabled after repeated flags). Sends against it fail. Fix: check template status in the Manager, fix the offending content, resubmit.
- Category mismatch. A marketing message sent under a utility/auth template (or vice versa) can be rejected or reclassified. Meta's 2024-2026 category enforcement is strict. Fix: align template category to actual intent.
- Messaging limit (tier) hit. Your WABA has a per-24h unique-recipient cap (1K / 10K / 100K / unlimited tiers). Once hit, further marketing sends are throttled or rejected until the window rolls. Fix: pace sends, or graduate the tier via quality + volume.
- Quality rating Red-flagged. A Red quality rating throttles or blocks marketing throughput. Delivered rate collapses. Fix: pause marketing, fix opt-in + content, let the rating recover.
- Number blocked by the user. The recipient blocked your business. Messages to them fail or silently never deliver. No fix beyond list hygiene — stop sending.
- WABA flagged or restricted. Policy violation can restrict or disable the WABA. All sends degrade. Fix: resolve the flag in Business Manager, appeal if warranted.
- Meta outage. Rare, broad, and not your fault. Check the Meta platform status / WhatsApp Business Platform status page before deep-diagnosing a sudden global delivery drop.
- Rate-limited / pair rate-limit. Too many messages too fast — globally or to a single recipient pair. Fix: respect throughput limits, add backoff, smooth bursts.
- Payment / credit issue on the BSP. If your BSP wallet is empty or Meta billing is unconfigured, sends can be blocked. Fix: top up the wallet / confirm the Meta payment method.
Status x Likely-Cause x Fix
| Observed status | Most likely cause | Fix / next action |
|---|---|---|
| API 200, never appears in webhook | Webhook misconfigured or not subscribed to messages field | Verify webhook URL + subscribe to message-status events; check signature |
Stuck at sent for hours | Recipient phone offline; Meta retrying within ~72h | Wait; if it persists past the window, mark undeliverable + suppress |
Many sent never reaching delivered | List quality (invalid / non-WhatsApp numbers) or quality-rating throttle | Validate E.164, clean list, check quality rating band |
failed with re-engagement error | Outside 24h window, free-form attempted | Switch to approved template; design a re-opt-in flow |
failed on a marketing blast at scale | Tier limit hit or marketing-limit experiment (130472) | Pace by tier; spread sends; raise tier via quality |
Sudden global delivered collapse | Quality Red flag, WABA restriction, or Meta outage | Check WABA status + Meta status page before code changes |
| Single recipient always fails | User blocked you, or invalid number | Suppress that contact; do not retry |
Common Cloud API Error Codes Mapped to a Fix
When a message returns status = "failed", the errors[] array carries a numeric code. The codes below are described as per the Meta Cloud API error reference — verify against current docs, as Meta revises codes and adds new ones. Treat this as a triage starting point, not a frozen contract.
| Code (verify vs docs) | What it generally means | Action |
|---|---|---|
| 131049 | Message not sent as part of Meta healthy-ecosystem / per-user marketing experiment — recipient is in a limited cohort | Reduce marketing frequency to that user; prioritise utility/auth; do not hammer-retry |
| 131047 | Re-engagement required — more than 24h since the user last messaged you, no valid template path | Send an approved template; build a re-opt-in / re-engagement flow |
| 131026 | Message undeliverable — recipient may not have WhatsApp, number invalid, or device cannot receive | Validate the number; suppress hard-undeliverable contacts |
| 131048 | Spam rate limit hit — sending behaviour flagged as spammy for this number | Improve opt-in quality + content; slow down; let reputation recover |
| 131056 | (Business, recipient) pair rate limit — too many messages to one recipient in a short window | Add per-recipient throttling + backoff |
| 130472 | User is in a Meta marketing-message-limits experiment group; marketing message dropped | Expected at times; lean on utility/auth, vary frequency, monitor share affected |
| 132xxx family | Template errors — paused, does not exist, parameter mismatch, wrong language/format | Check template status + parameter count + language code in the Manager |
| 368 / policy violation | Account or message violated WhatsApp Business policy; temporary block possible | Review policy; fix content; appeal restriction in Business Manager |
| 80007 / 4xx rate | Throughput / API rate limit exceeded | Implement exponential backoff + smooth send bursts |
The 130472 nuance most senders miss. Code 130472 is tied to Meta's marketing-message-limits experiment: a slice of users is placed in a cohort that receives fewer marketing messages, and your marketing send to them is intentionally not delivered. This is not a bug and not a list problem — it is a platform experiment. The fix is not to retry harder. The fix is to (a) keep marketing frequency low and relevant, (b) shift genuinely transactional content to utility/auth categories where it belongs, and (c) measure the affected share so you do not mistake it for a quality collapse. Always confirm 130472 semantics against the current Cloud API error reference, as experiment behaviour changes.
Get a 1-minute BSP audit on WhatsApp
Drop your WhatsApp number — we line-item your current invoice against Meta India rates in under 60 seconds. India-hosted, DPDP-compliant.
India-Specific Nuances: DLT Legacy, Festival Surge, Category
Three India-specific factors distort delivery diagnosis and trip up teams migrating from SMS:
- DLT legacy expectations. Teams coming from SMS expect TRAI DLT (Distributed Ledger Technology) template + header registration to govern delivery. WhatsApp does NOT use DLT — it uses Meta's own template approval + category system. If you are debugging WhatsApp non-delivery with a DLT mental model, you will look in the wrong place. (For the migration mindset, see our SMS-to-WhatsApp coverage.) The governing controls are Meta template status, category correctness, and quality rating — not a DLT scrubbing engine.
- Festival-surge throttling. During Diwali, New Year, and big sale windows, aggregate marketing volume across all senders spikes. Meta's quality + marketing-limit systems get more aggressive, and per-user marketing caps bite harder. A campaign that delivered fine in a quiet week can see undelivered spike during festival surge purely from cohort experiments + frequency caps. Plan festival sends as utility/auth where legitimate, and pre-warm quality.
- Category enforcement. Meta's 2024-2026 marketing/utility reclassification means a "your order shipped" message wrongly templated as marketing can be capped or dropped for users in a marketing-limit cohort, while the same content as a utility template delivers. Category correctness is now a delivery lever, not just a billing one.
Prevention Checklist: Stop Non-Delivery Before It Starts
| Lever | What to do | Why it lifts delivered rate |
|---|---|---|
| Opt-in hygiene | Only message users with explicit, recent opt-in; log consent timestamp + source | Cuts blocks + spam flags that crater quality rating |
| List cleaning | Validate E.164 (+91, no leading 0); suppress hard-bounced + repeatedly-undeliverable numbers | Removes 131026 undeliverables that pollute your sent-to-delivered ratio |
| Template quality | Clear value, no spammy phrasing, correct parameters; monitor per-template quality | Avoids pauses (132xxx) + protects WABA quality band |
| Category correctness | Map each template to true intent — utility/auth vs marketing | Transactional content escapes marketing-limit cohorts (130472) |
| Window awareness | Track each contact's 24h session window; use templates outside it | Eliminates 131047 re-engagement failures |
| Send-time + pacing | Spread sends, respect tier caps, add backoff; avoid 6am mega-bursts | Prevents rate-limit (131048/131056) + tier-limit rejections |
| Frequency control | Cap marketing touches per user per week | Reduces blocks + marketing-experiment suppression |
Illustrative Cohort: From 11% Undelivered to 2.8%
The following cohort is illustrative — a composite of typical Indian D2C sender patterns, not a single named client. A mid-market D2C brand running ~600,000 WhatsApp messages/month was seeing 11% undelivered (sent-but-never-delivered + failed combined), eroding both reach and quality rating. A four-week forensic pass:
| Metric | Before | After | Delta |
|---|---|---|---|
| Undelivered rate (sent-but-not-delivered + failed) | 11.0% | 2.8% | -8.2pp |
| 131026 undeliverable (invalid / non-WhatsApp) | 4.1% | 0.6% | list cleaning + E.164 validation |
| 131047 re-engagement failures | 2.9% | 0.4% | 24h-window-aware sending + templates |
| 130472 marketing-limit suppression | 2.4% | 0.9% | category fixes + frequency caps |
| Quality rating band | Yellow | Green | opt-in hygiene + content fixes |
| Effective delivered reach / month | ~534,000 | ~583,000 | +49,000 real conversations |
The three levers that moved the number most: (1) list hygiene — validating E.164 and suppressing repeatedly-undeliverable numbers killed most of the 131026 noise; (2) window-aware sending — tracking each contact's 24h window and switching to approved templates outside it eliminated re-engagement failures; (3) template-category fixes — moving genuinely transactional sends out of the marketing category let them escape marketing-limit cohorts. None of this required more spend — it required reading the webhook and fixing root causes instead of retrying blindly.
Build a Standing Delivery-Forensics Runbook
- Instrument the webhook. Persist every
statuses[]event (sent / delivered / read / failed) withwamid, timestamp, recipient, template, category, and any error code. You cannot diagnose what you do not log. - Compute the sent-to-delivered gap per campaign + per template. This is your primary deliverability KPI — not the API-200 count.
- Bucket failures by error code. A weekly histogram of 131026 / 131047 / 130472 / 132xxx tells you which root cause to attack first.
- Auto-suppress hard undeliverables. After N consecutive 131026 / undeliverable results, move the contact to a suppression list. Never let a dead number drag your ratio.
- Alarm on quality-band changes. Wire an alert on Yellow/Red transitions so you pause marketing before the band collapses delivery.
- Reconcile billing. Each delivered conversation is what you pay for value on — see client-pay vs SaaS-pay billing for how per-message economics interact with your delivered rate, and pricing for the current rate card.
For high-volume senders. If one WABA number routinely hits tier caps or rate limits during peaks, the forensics often point to an architecture problem, not just list hygiene. A clean delivery-forensics dashboard is also the prerequisite for choosing the right CRM + inbox layer — see best WhatsApp CRM in India 2026 for how delivery telemetry should surface in your daily ops view.
Compliance + Platform Guardrails
- DPDP Act 2023: re-engagement and re-opt-in flows must honour consent — do not use a "fix" for 131047 as a backdoor to message users who never opted in. Log consent source + timestamp.
- Meta WhatsApp Business Policy: repeated sends to blocking / non-consenting users degrade quality and risk WABA restriction. Suppress, do not retry.
- TRAI / DLT: WhatsApp delivery is governed by Meta template + category + quality, not DLT — diagnose on the correct system.
- Error-code handling: all codes here are as per the Cloud API error reference and must be verified against current Meta documentation before you automate retry/suppression logic.
Stop guessing why messages do not deliver. Diagnose it on RichAutomate.
RichAutomate persists every webhook status (sent / delivered / read / failed) with its Cloud API error code, computes your real sent-to-delivered gap per campaign + per template, buckets failures by root cause (131026 undeliverable, 131047 re-engagement, 130472 marketing-limit, 132xxx template), auto-suppresses hard-undeliverable numbers, and alarms on Yellow/Red quality-band transitions before they collapse your reach. 24h-window-aware sending + template-category correctness + E.164 list validation built in. Illustrative cohort cut undelivered 11% to 2.8% and lifted Green-band reach by ~49,000 conversations/month with zero extra spend. ₹0 platform fee, ₹0 setup — usage only: Client Pay ₹0.10/msg + Meta direct, or SaaS Pay ₹1.20 marketing / ₹0.30 utility-auth. 14-day free trial + 100 credits. Talk to us on WhatsApp at 917434901027 or book a slot at https://calendly.com/inrichdaddy/30min.