WhatsApp Cloud send blocks¶
The symptom¶
A WhatsApp Cloud number is connected and receiving normally. Agents can chat with it from their own phones. But every outbound message — free-form text and approved templates — fails with:
This reads like a ConnectGain bug. It is not: Meta gates sending on the phone
number's display name review, and inbound traffic is unaffected. A number can
therefore go from "sends fine" to "refuses everything" with no visible change on
our side — typically because someone just submitted or changed the display name
in WhatsApp Manager, putting name_status into PENDING_REVIEW.
Real timeline from the incident that prompted this page (WhatsApp-provided test
number +1 555-962-8162):
| Time (UTC) | Event |
|---|---|
| 15:13 | Template hello sent → DELIVERED → READ |
| ~15:15 | Display name submitted for review in WhatsApp Manager |
| 15:16 → 15:25 | Four sends (text and template) fail with 131037 |
| throughout | 10 inbound messages arrive normally |
GET /{phone-number-id}?fields=name_status returned PENDING_REVIEW — the only
place that state was visible.
Number-level vs message-level failures¶
Meta's error codes mix two very different things, and ConnectGain now separates them:
| Scope | Meaning | Examples |
|---|---|---|
number |
Nothing can be sent from this number until an admin fixes something | 131037 display name, 131042 billing, 131031/368 restricted, 133xxx registration, 190 token |
conversation |
This thread is blocked, others are fine | 131047 (24-hour window), 131056 |
message |
This message was rejected; the next may go through | 131026, 131049, 131051, 132xxx templates |
Only number-scope failures raise a channel alert. Retrying them is pointless,
which is exactly what agents did before ConnectGain said so.
What ConnectGain does¶
- Classifies the failure.
whatsapp-cloud-sendandwhatsapp-cloud-webhookboth run Meta's code through the shared classifier, storingmetadata.failure_reason(machine-readable) andmetadata.user_message(what the inbox shows) alongside the raw provider text. - Records a send block. A
number-scope failure stampschannel_accounts.settings.health.send_blockand raises one unacknowledgedchannel_alertsrow (alert_type = number_send_blocked) — five failed sends produce one banner, not five. - Warns before the next send. The app-wide header (
ChannelHealthBanner) names the blocked number on every page, for every user — a payment block reads "Meta blocked it over a payment issue".WhatsAppNumberStatusrenders the detail on the channel card (Settings → Channels — always, including the display name and its review status) and at the top of the inbox thread (only when the number cannot send). A billing block also says plainly that the block is Meta's, not ConnectGain's, shows when it started, and links to Meta's billing hub. - Reads the truth from Meta. ConnectGain fetches
verified_name, name_status, new_name_status, status, quality_rating, code_verification_statusfor the number, stores it undersettings.health.phone_number, and raises or clears the block accordingly. The channel card probes it on mount when the stored snapshot is stale (> 10 minutes) or a block stands; "Check again" forces a probe. - Clears itself on proof, never on hope: Meta's
phone_number_name_updatewebhook (display-name blocks), a health check (display-name and token blocks only — it cannot see billing or restrictions), or adelivered/readreceipt for a message created after the block was detected — which also acknowledges the open alert.
Meta accepting a message is not proof the number can send. For a WhatsApp Business Account with no usable payment method, Meta first accepts each message and then fails it a few seconds later with 131042 "Business eligibility payment issue". So the warning stays up through retries and only clears once a message is actually delivered. "Check again" also keeps a payment block on screen: Meta does not report billing problems to that check, so only a delivered message can prove the block is over.
name_status values¶
| Value | Can send? |
|---|---|
APPROVED, AVAILABLE_WITHOUT_REVIEW |
Yes |
PENDING_REVIEW |
Unknown — review in progress, usually hours (up to 48) |
DECLINED |
Unknown — submit a compliant name |
EXPIRED |
Unknown — re-submit the display name |
NONE |
Unknown — no display name set yet |
The display name status alone never blocks a number. Numbers with a declined or missing name often send normally, so the channel card shows the status without "This number cannot send messages". The display-name block appears only when Meta rejects a send with error 131037, which Meta returns only for a WhatsApp-provided (auto-generated) number that still needs a name approved. If an earlier health check or name-review notification raised that warning from the status alone, "Check again" removes it.
An undocumented value is reported as "unknown" rather than a false all-clear.
Setting the display name from ConnectGain¶
Settings → Channels → the WhatsApp Cloud card shows the number's display name and its review state, with a Change action (owner/admin only). The dialog:
- checks the name against Meta's published guidelines before submitting —
Meta's documented rules (minimum 3 characters, no Meta product names, no
"Official"/"Verified" claims, no phone numbers, no bare generic terms) disable
the button; heuristics BSPs report as rejection causes (emoji, ALL CAPS,
www., prices, slogans, a name unrelated to the organization) are shown as warnings only, because a real brand must still be able to submit; - states the requirements no validator can settle: branding consistency with your website, Meta business verification, and that the number cannot send while the review runs;
- submits via
POST /{phone-number-id}?new_display_name=…and shows Meta's own rejection text when Meta refuses.
Meta remains the only authority, so the validator never blocks on a rule that is not Meta's own.
After a display name is approved, Meta may require the number to be re-registered (
POST /{phone-number-id}/register) before it sends again. If sending is still refused after approval, re-run activation for the number.
Enable the approval webhook¶
phone_number_name_update tells us the moment Meta approves or declines a name,
which is what clears the block without anyone polling. It is handled in
whatsapp-cloud-webhook, but the field must be ticked for the
whatsapp_business_account object in the Meta App dashboard → Webhooks. Without
it, the block still clears — just later, on the next health check or successful
send.
Fixing it as an admin¶
- WhatsApp Manager → Account tools → Phone numbers.
- Check the display name status for the number.
PENDING_REVIEW: wait. Nothing to reconnect in ConnectGain — sending resumes on its own, and the banner clears on the next successful send or health check.DECLINED: submit a name that matches the business (see Meta's display name guidelines). WhatsApp-provided test numbers (+1 555…) always need an approved display name before they can send anything.- Not a display name problem? The banner names the actual block — billing (WhatsApp Manager → Settings → Billing & payments), an account restriction (Account tools → Insights), or an expired token (reconnect the channel).
Checking a number by hand¶
curl -s "https://graph.facebook.com/v22.0/<PHONE_NUMBER_ID>\
?fields=verified_name,name_status,new_name_status,display_phone_number,status,quality_rating" \
-H "Authorization: Bearer <ACCESS_TOKEN>"
{
"verified_name": "Appgain",
"name_status": "PENDING_REVIEW",
"display_phone_number": "+1 555-962-8162",
"status": "CONNECTED",
"quality_rating": "GREEN"
}
status: CONNECTED and a GREEN quality rating say nothing about whether the
number may send — only name_status does.