Skip to main content

WhatsApp quality and health model

WhatsApp sending capacity on a WhatsApp Business Account (WABA) is not a fixed quota. Meta continuously grades the account — at the account level, at the phone-number level, and per template — and adjusts how much it can send. This page explains how Devotel Orbit reads those Meta signals, what it does on your behalf when quality degrades, and the operator loop for recovering a degraded account.

What Meta grades

Meta grades a WABA from three independent signals, plus two probes Orbit runs to complete the picture. GET /whatsapp/health resolves all of them per connected WABA, and a periodic reconciler re-reads them so the values stay current between dashboard visits.

Account-level probe

A direct Meta read against the WABA reports whether the account can send (health_status.can_send_message), its account review status, its business verification status and account mode, and whether a payment method is attached — the account’s baseline send-health. A field Meta does not return on a given read degrades to unknown and never overwrites a good stored value, so a partial Meta response never looks like a regression. This probe is what the can-send, review status, and funding rows on the Health card show.

Per-template quality scores

Every approved template carries a GREEN / YELLOW / RED score from Meta, reported through the message_template_quality_update webhook. Meta computes it from recipient feedback on that template alone — blocks, “not useful” reports, and read rates — so one bad template does not poison the scores of the others. You read the current score per template on the Templates list, and you can act on it per template with the auto-pause opt-in below.

Per-recipient drop signals

Phone-level quality (GREEN / YELLOW / RED / UNKNOWN, worst across the WABA’s phones) comes back through the account probe; a recipient-level block or “not useful” report on a given template is what feeds its template score. An operator who sees a RED template is really seeing aggregated recipient dissatisfaction — which is why the fix is template content, not send volume.

Where Orbit adds its own checks

Two probes complete the health picture beyond what Meta reports:
  • Inbound subscription check. The health surface verifies the WABA is still subscribed to the inbound messages webhook field — an account can send fine while silently dropping every reply, and nothing on the Meta side warns about it. Check Settings → Channels → WhatsApp → Health.
  • Payment-funding tri-state. Funding is treated as positive-only evidence: the probe only confirms a payment method when Meta returns one. A bare absence never defensively flags the account, because WABAs on consolidated parent-business billing often omit the funding field entirely.

The Health surface, card by card

Open Settings → Channels → WhatsApp → Health. The page renders one card per connected WABA, plus a billing alert on top when a recent send hit a payment block. Each card answers one operator question: Re-run the probes from the same page when you have just changed something on the Meta side, so you are not reading stale values. When a single WABA fails its probe, its card shows the probe error inline and the other WABA cards are unaffected.

Per-template quality and the auto-pause opt-in

The Templates list shows each approved template’s current Meta quality score. Read the three states as an operator:
  • GREEN — recipients are receiving the template well. Keep its sending pattern (audience, frequency, copy) stable.
  • YELLOW — early recipient dissatisfaction. This is the cheapest moment to fix the copy or narrow the audience; nothing is paused yet.
  • RED — Meta’s pre-pause signal. Meta first pauses a RED template (24 hours, then 72 hours) and disables it on a third strike — and a pile of RED templates drags the account’s whole messaging tier down. Continuing to dispatch a RED template until Meta yanks it only deepens the penalty.
Orbit gives you an opt-in guard for the RED case: per template, you can enable auto-pause on RED. When Meta reports a RED score on an opted-in template, Orbit flips it to paused so the send pipeline stops dispatching it before Meta penalizes the account, and fires a whatsapp.template.auto_paused webhook so you are alerted. A template already in a non-sending status (paused, disabled, rejected, archived) is a no-op, so the guard never re-alerts on a template that already stopped. The flag lives on the template’s metadata as auto_pause_on_quality_red and round-trips through PATCH /api/v1/messages/templates/:id:
Set the same flag to false to opt back out.

Deciding which templates to opt in

Walk the Templates list and ask three questions per template:
  1. Would Meta pausing it first be worse than Orbit pausing it? For a revenue-driving template (order updates, appointment reminders), a Meta 24-hour pause plus the tier damage is the expensive outcome — opt in.
  2. Is the traffic recipient-initiated or operator-initiated? Recipient-initiated (utility, authentication) rarely degrades; operator-initiated marketing copy is where RED actually happens. Opt in on marketing templates first.
  3. Is something subscribed to the webhook? Auto-pause without a listener is a silent stop. Either subscribe to whatsapp.template.auto_paused or check the Templates list routinely, so a paused template always reaches a human.

The webhook loop

When auto-pause fires, Orbit dispatches whatsapp.template.auto_paused to every webhook endpoint subscribed in organizations that own the WABA. Meta reports the event per WABA, so the payload carries the WABA id and the templates that were paused on this event:
A template that was already in a non-sending status never appears here, and Meta’s repeated RED reports on the same template do not re-fire the event — one pause, one alert. The billing side has its own loop. When a send fails with Meta error 131042 (payment / business-eligibility block) inside the trailing 24-hour window, the dashboard shows the “WhatsApp sends blocked — payment issue on Meta” banner. The banner follows a success-after-failure rule, not elapsed time: the moment Meta accepts a send from an affected sender after the most recent rejection, the banner clears. You do not have to wait out the 24-hour window once the payment method is fixed — send one small test message after updating billing in Meta Business Manager, and the banner clears on that first accept.

The recovery loop, worked end to end

Recovery is deliberately manual-after-guard: Orbit stops the bleeding, you fix the cause. A typical full arc:
  1. RED arrives. Meta reports a RED score on promo_october_drop through the template-quality webhook. Because you opted the template in, Orbit flips it to paused immediately; because you subscribed to the webhook, your operations channel receives whatsapp.template.auto_paused with the template name, language, and the YELLOW → RED transition minutes later — not after the next campaign report.
  2. Fix the content. Edit the template for what Meta flagged — a misleading first line, an offer recipients did not expect, an opt-out that is hard to find — then re-submit it for review. The paused original stops dispatching in the meantime, so no further recipient damage accrues.
  3. Re-approval. Meta approves the replacement template. Numbers that suppressed the old template’s sends see the new, better copy instead.
  4. Score recovery in days. Meta re-scores as recipients react to the new traffic; a healthy replacement typically restores a template-level GREEN in days, not weeks. While that happens you watch the Templates list: new template GREEN, old template still paused.
  5. Account recovery in days-to-weeks. Account-level quality recovers the same shape on a slower clock — sustained good recipient behaviour lifts the messaging tier back. The thing to watch during this phase is the Health card: phone quality back to GREEN, the dynamic daily limit ticking up, the can-send flag steady.
If the account is also under review or unverified, fix that in parallel — template quality cannot lift an account Meta has blocked at the review layer. For payment blocks, fix the payment method on the Meta business; once Meta accepts another send, the banner clears on its own.

What you can check

  • Dashboard → Settings → Channels → WhatsApp → Health. Per connected WABA: can-send, review status, messaging tier and the dynamic daily limit, phone quality, and the inbound-subscription check, with probes re-run on demand.
  • Templates list. Each template’s current quality score and its auto-pause opt-in status.
  • Webhooks. Subscribe to whatsapp.template.auto_paused for degradation alerts, and watch for Meta’s WHATSAPP_TEMPLATE_PAUSED / WHATSAPP_ACCOUNT_QUALITY_LOW send errors (documented on Troubleshooting: WhatsApp templates).
  • API. GET /whatsapp/health returns the same per-WABA health object, and GET /whatsapp/quality returns the quality card (cached briefly per connection to stay inside Meta’s per-WABA call budget).

Billing-health interplay

Payment blocks are a separate, faster-moving signal from quality. Three facts to hold together:
  • 131042 is the trigger. A send rejected with Meta error 131042 (payment / business-eligibility) inside the trailing 24-hour window raises the dashboard banner.
  • Success clears it. The banner uses the success-after-failure rule from the webhook loop above: one accepted send after the latest rejection clears it immediately, instead of waiting out the window.
  • The probe and the banner are independent axes. A WABA that shows a funding issue on the health probe is surfaced on two axes — the probe’s per-WABA funding signal, and the live 131042 failure signal that drives the banner. An unknown funding read with no 131042 failures is not a finding; consolidated parent-business billing routinely looks like that.
Worked example: a send batch fails at 09:12 with 131042 because the card on the Meta business expired. The banner appears. Finance attaches a new card in Meta Business Manager at 09:40. You re-run the health probe, send a single test template at 09:41 — Meta accepts it — and the banner clears at 09:41, not at 09:12 the next day.

See also