All articles
Guide

WhatsApp API Invalid Phone Number: Fix It India 2026

The digits looked fine but the send failed? Validation proves a number is plausible — only a send proves anyone is there. Four recipient states, decoded.

RichAutomate Editorial
12 min read 0 views
WhatsApp API Invalid Phone Number: Fix It India 2026

An "invalid phone number" error on the WhatsApp Business API is almost never about the recipient being a bad person to message. It means the digits you sent could not be resolved to a WhatsApp identity — and that resolution has four possible outcomes, only one of which is a real send.

The number in your CRM, the number Meta will accept, and the number that actually exists on WhatsApp are three different things. This page is about the gap between them, which is where most Indian contact lists quietly lose 5–15% of their reach.

Direct answer — four recipient states, not one

Teams treat "the number failed" as a single condition. It is four, and each one is fixed somewhere different. Reading the wrong one wastes a week cleaning a list that was never the problem.

StateWhat happenedWhere you see itFix lives in
MalformedThe digits are not a plausible international number at all. Rejected before Meta ever looks for a user.Immediate API error on the send callYour normalisation code
Well-formed, no WhatsApp accountA real, valid number — nobody has registered it on WhatsApp.Accepted, then fails as undeliverableList sourcing
Resolved to a different identityMeta accepts it and answers about a slightly different number than the one you sent.The wa_id in the responseYour matching logic
Valid and reachable, never arrivesNothing wrong with the number. Something else stopped the message.Status webhook, laterNot here — see delivery troubleshooting

Only the first three belong to this page. If the number resolved cleanly and the message still never landed, the number is exonerated and you should be reading why WhatsApp messages are sent but not delivered instead.

The number you send is not the number you get back

This is the single most under-appreciated fact in WhatsApp integrations, and it breaks reconciliation rather than sending.

When a message arrives, the webhook payload carries a wa_id — WhatsApp's own identifier for that user. It is usually identical to the digits you would have sent. It is not guaranteed to be. Our inbound handler matches the profile name by comparing the contact entry's wa_id against the wa_id on the message itself, rather than against whatever number the CRM holds:

// Match profile name from contacts array if available
$profileName = null;
foreach ($contacts as $contactEntry) {
    if (($contactEntry['wa_id'] ?? null) === $waId) {
        $profileName = $contactEntry['profile']['name'] ?? null;
        break;
    }
}

The practical consequence: if you key conversations on the number your CRM stored rather than on the wa_id WhatsApp returned, you will eventually create two conversation rows for one human. They will look like two different contacts, the 24-hour window will be tracked against the wrong one, and a reply will arrive on a thread nobody is watching.

Rule: store the number you sent, but key on the wa_id you received. One is your data, the other is WhatsApp's truth.

What "normalising to E.164" actually has to handle in India

Every integration guide says "normalise to E.164". Almost none of them say what the input looks like in an Indian CRM, which is where the work is. The real inputs, in rough order of frequency:

  • Bare 10 digits9876543210. The default in most Indian web forms and every imported Excel sheet.
  • Trunk-prefixed 11 digits09876543210. The domestic dialling habit, preserved by field staff and call-centre exports.
  • Correct 12 digits919876543210. What you actually want.
  • Doubled country code, 14 digits9191 followed by ten digits. A UI field that already displays +91 concatenated with a number the user typed with 91 in it.
  • Formatted with separators+91 98765 43210, +91-98765-43210. Harmless once stripped, fatal if not.
  • Landline and toll-free numbers sitting in a column labelled "mobile".

The doubled-prefix case is worth dwelling on because it is the one people assume cannot happen. It is unambiguous and therefore safely correctable — India is a 2-digit country code plus a 10-digit subscriber number, so a 14-digit string beginning 9191 can only be the prefix applied twice. Our helper says exactly that in a comment, because the reasoning is not obvious to whoever reads the branch next:

// Double country code: a UI field that already shows +91 concatenated with a
// number the user typed WITH 91 gives 9191XXXXXXXXXX. India is 91 + 10 digits,
// so 14 digits starting 9191 can only be the prefix applied twice.
if (strlen($phone) === 14 && str_starts_with($phone, '9191')) {
    return substr($phone, 2);
}

The mobile-series check most normalisers skip

Stripping separators and adding 91 is the easy half. The half that determines whether your list is clean is deciding what to do with digits that look like a number but cannot be an Indian mobile.

Indian mobile numbers begin with 6, 7, 8 or 9. A 10-digit string starting with 2 or 4 is a landline, and it will normalise into a perfectly well-formed +91 number that no WhatsApp account will ever answer to. A normaliser that only counts digits will pass it through happily; one that checks the series will not:

// 10-digit Indian mobile (starts 6-9).
if (strlen($digits) === 10 && preg_match('/^[6-9]/', $digits)) {
    return '+91'.$digits;
}

// 11 digits with a national trunk 0 prefix (0XXXXXXXXXX).
if (strlen($digits) === 11 && str_starts_with($digits, '0')) {
    $local = substr($digits, 1);
    if (preg_match('/^[6-9]/', $local)) {
        return '+91'.$local;
    }
}

Note the second branch: the trunk zero is stripped and then the series is re-checked. Stripping the zero first and validating never is how 0224xxxxxxx becomes a "valid" mobile.

Two normalisers in one codebase is the normal state

Here is an honest finding from our own repository, because it is the thing that will bite you and no vendor documentation will warn you about it.

We have two phone-normalisation paths. One is length-driven: strip non-digits, drop a leading zero, add 91 to anything exactly ten digits long, and return unchanged for any other length. The other is series-aware and returns null when it cannot produce something plausible. Both are correct for what they were written for. They do not agree on the same input.

Stop overpaying on WhatsApp

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.

DPDP-compliant · India-hosted · 1-min reply
InputLength-driven pathSeries-aware path
9876543210919876543210+919876543210
022400012342240001234 — passed throughnull — rejected
1234512345 — passed throughnull — rejected

The lesson is not "we have a bug". The lesson is that a permissive normaliser and a strict one produce different lists from the same CSV, and if your import path uses one while your send path uses the other, your delivery rate will disagree with your contact count in ways nobody can explain. Pick one function. Route every entry point through it. Whether it is permissive or strict matters far less than whether it is singular.

Validation is not verification

A number can be perfectly valid and still have no WhatsApp account behind it. These are separate questions and only one of them can be answered offline:

  • Validation — is this a plausible number? Answerable from the digits alone, instantly, for free, at import time.
  • Verification — does a WhatsApp account exist here? Answerable only by attempting something and reading the result.

Do all the validation you can at import. Treat verification as a byproduct of sending, not a prerequisite: mark a contact unreachable when a send to it fails as undeliverable, and stop retrying that number. A list that never records its own failures re-attempts the same dead numbers on every campaign forever, which is both wasted spend and a slowly worsening quality signal.

The India-specific traps

Ported and recycled numbers

Mobile number portability means a number can move between operators without changing. That does not affect WhatsApp. What does affect it is recycling — a disconnected number reissued to a new subscriber. Your two-year-old list contains some of these. The number is valid, WhatsApp may well be active on it, and the person is a stranger who never opted in. This is a compliance problem wearing a data-quality costume; see opt-in list hygiene and re-permissioning.

The DND myth

India's Do Not Disturb registry governs telecom SMS and voice. It is not a WhatsApp mechanism and there is no DND flag in the messaging API. Filtering your list against a DND list will not change what WhatsApp delivers, and not filtering it will not make WhatsApp block you. What governs WhatsApp reach is opt-in quality and how recipients respond — a number nobody blocks is worth more than a number that merely passes a registry check.

Multi-number households and shared business numbers

Common in retail and B2B: one WhatsApp account on a number that several people use, or an office number where the person who reads WhatsApp is not the person in your CRM record. Nothing technical fails. Your personalisation does — {{1}} greeting the wrong person is a worse outcome than no name at all. Prefer a neutral greeting when name confidence is low rather than a confidently wrong one.

Test numbers that quietly stay in production lists

Every team seeds a list with a colleague's number during setup. Those rows survive migrations. They inflate counts, they skew read rates, and occasionally they receive a campaign meant for customers.

A decision path

  1. Did the API reject the send outright, before any status webhook? The number never resolved. Check normalisation — length, trunk zero, doubled prefix, separators.
  2. Did it reject only for some recipients while others in the same batch went through? Not an account problem. Your list has mixed formats; find the ones that differ in length from the majority.
  3. Did every recipient in the batch fail identically? Stop looking at the numbers. Look at account-level send blocks.
  4. Did the API accept it and a status webhook later report it undeliverable? The format was fine; there is no WhatsApp account. Mark unreachable, stop retrying.
  5. Was it accepted, and nothing at all came back? Neither format nor account — that is a webhook or delivery issue.
  6. Did it fail with a parameter or template complaint rather than a recipient one? The recipient is irrelevant; see template parameter mismatch at send time.
  7. Is it your own sending number failing rather than the recipient? Different class entirely — see when your WhatsApp API number is not registered.

Recipient-hygiene checklist

  1. One normalisation function. Every import, form, API and campaign path calls it.
  2. Normalise at write time, not read time — store the canonical form, never re-derive it per send.
  3. Strip the trunk zero, then re-validate the series. Not the other way round.
  4. Reject 10-digit strings that do not start 6–9 rather than prefixing them.
  5. Detect the 14-digit doubled 9191 case explicitly; it is unambiguous and cheap to fix.
  6. Key conversations on the wa_id WhatsApp returns, not the number your CRM stored.
  7. Record undeliverable outcomes against the contact and stop retrying automatically.
  8. Never bulk-import a column labelled "mobile" without checking what fraction of it is landlines.
  9. Keep opt-in source and timestamp on every row — it is the only defence for an old list.
  10. Flag and exclude internal test numbers before the first real campaign, not after.

Further reading

Lists that fail loudly instead of quietly

Bad numbers are not expensive because they fail. They are expensive because they fail silently, get retried forever, and drag a quality score down while the dashboard reports a healthy send count. RichAutomate normalises on write through a single path, keys conversations on the identity WhatsApp returns rather than the one you typed, and records per-recipient outcomes so a dead number stops costing you on the next campaign instead of the tenth. If your delivered count has never matched your contact count and nobody can say why, talk to us.

Before a number can be rejected it has to survive the upload — see why CSV rows vanish during a WhatsApp contact import.

Ready to ship this?

Get the full migration playbook on WhatsApp

A founder-led 1-minute reply with the migration steps, template approval timeline, and a 14-day pilot offer. DPDP-compliant. India-hosted. No spam.

DPDP-compliant · India-hosted · 1-min reply
Tagged
WhatsApp Business APIContact DataCloud APITroubleshootingIndia
Written by
RichAutomate Editorial
Editorial team at RichAutomate. We build the WhatsApp Business automation platform Indian D2C brands, fintechs, and agencies use to ship campaigns and flows on the official Meta Cloud API.
FAQ

Frequently asked questions

Why does the WhatsApp API say a phone number is invalid when it works on my phone?
Because your phone dials it and the API resolves it. Dialling tolerates a leading zero, spaces and a missing country code; the API needs full international digits. The most common causes in India are a retained trunk zero (09876543210), a bare 10-digit number with no 91 prefix, and a doubled country code where a form that already shows +91 is given a number that also contains 91.
What is wa_id and why is it different from the number I sent?
wa_id is WhatsApp's own identifier for a user account. It is usually the same digits you would send, but it is not guaranteed to be, and it is the value returned in webhook payloads. Store the number you sent, but key your conversations on the wa_id you receive — matching on your stored number instead is how one person ends up with two conversation threads and a 24-hour window tracked against the wrong one.
Can I check whether a number is on WhatsApp before sending?
You can validate the format offline, instantly and for free, but existence of an account is only confirmed by attempting something and reading the result. Treat verification as a byproduct of sending rather than a prerequisite: mark a contact unreachable when a send fails as undeliverable and stop retrying that number. Lists that never record their own failures re-attempt dead numbers on every campaign.
Does India's DND registry affect WhatsApp Business API messages?
No. DND governs telecom SMS and voice, and there is no DND flag in the WhatsApp messaging API. Filtering a list against DND will not change what WhatsApp delivers, and not filtering it will not cause WhatsApp to block you. WhatsApp reach is governed by opt-in quality and how recipients react — a number nobody blocks is worth more than one that merely passes a registry check.
Should a 10-digit Indian number that starts with 2 be prefixed with 91?
No. Indian mobile numbers begin with 6, 7, 8 or 9. A 10-digit string starting with 2 or 4 is a landline, and prefixing it produces a perfectly well-formed +91 number that no WhatsApp account will ever answer. A normaliser that only counts digits passes these through; one that checks the mobile series rejects them. This is the single highest-value validation rule for Indian contact lists.
Why do my delivery numbers disagree with my contact count?
Usually because more than one normalisation function exists in the stack. A permissive normaliser that passes unusual lengths through unchanged and a strict one that rejects them produce different lists from the same CSV. If the import path uses one and the send path uses the other, counts will never reconcile. Route every entry point through a single function — whether it is permissive or strict matters far less than whether it is singular.
RichAutomate · WhatsApp BSP for India 2026

Ship WhatsApp campaigns + flows on a transparent, compliance-ready BSP.

₹0 platform fee. DPDP audit log included. Visual flow builder. Multi-tenant from day one.

Start free trial
Want this for your brand?

Get a free 24-hour BSP audit

Send us your last invoice. We line-item it against Meta's published rates and benchmark against three alternatives.

Limited Spots Available

Get a Free
Automation Audit

Stop leaving revenue on the table. Get a custom roadmap to automate your growth.

Secure & Confidential