- Webhooks & events
- Practitioner
- Developers
- Marketers
Template Status Webhook
Also called: message_template_status_update · Template status update · Template approval webhook
The message_template_status_update webhook reports each change in a template's state — approved, rejected, paused, disabled, archived — with the reason.
Reviewed
What is the template status webhook?
The template status webhook is the message_template_status_update field. Meta sends it whenever a message template changes state: approved or rejected after review, paused or disabled because of quality, flagged, appealed, archived after long inactivity, or deleted. Each notification carries event (the new state), message_template_id, message_template_name, message_template_language, reason and message_template_category, inside an entry whose id is the WABA.
Meta's reference lists more than a dozen event values — APPROVED, REJECTED, PENDING, PAUSED, DISABLED, FLAGGED, IN_APPEAL, REINSTATED, LOCKED, LIMIT_EXCEEDED, ARCHIVED, UNARCHIVED, DELETED and PENDING_DELETION — and adds new ones over time. reason is NONE (used on pauses), INVALID_FORMAT, ABUSIVE_CONTENT, PROMOTIONAL, SCAM, INCORRECT_CATEGORY or TAG_CONTENT_MISMATCH (the older CATEGORY_NOT_AVAILABLE is deprecated), and null for a scheduled deletion. Three optional objects add detail: rejection_info with a reason and a recommendation, only for INVALID_FORMAT; disable_info.disable_date on a disable; and other_info with a title (FIRST_PAUSE, SECOND_PAUSE, RATE_LIMITING_PAUSE, UNPAUSE or DISABLED) and a human-readable description on pause-related events.
Template approval describes the review process; this webhook is the event that reports its outcome — an approval, a template rejection or a template appeal under way — and everything that happens to the message template afterwards, such as template pausing. It is also distinct from its two siblings: the template quality webhook reports score moves between GREEN, YELLOW and RED, and the template category update webhook reports a move between marketing, utility and authentication. All three go to the app's default callback URL, whatever overrides are set.
Key takeaways
- The template status webhook (
message_template_status_update) reports every change in a template's state, from approval to deletion. - Route on
event:APPROVEDreleases sends,PAUSEDis temporary,DISABLEDis final andREJECTEDcarries areason. - A
rejection_infoobject with a fix recommendation appears only onINVALID_FORMATrejections. - Review is automatic and can take up to 24 hours, so schedule campaigns on the
APPROVEDwebhook, not the create call. - Templates unused for 12 months are archived, then deleted 28 days later unless unarchived.
Interactive stop
Walk through a template status handler
export async function onTemplateStatus(entry, change) { const v = change.value; const tpl = await templates.byId(v.message_template_id); await tpl.recordStatus(v.event, v.reason, v.message_template_category, entry.time); switch (v.event) { case "APPROVED": case "REINSTATED": case "UNARCHIVED": await campaigns.release(tpl.id); break; case "PAUSED": // other_info.title: FIRST_PAUSE, SECOND_PAUSE or RATE_LIMITING_PAUSE await campaigns.hold(tpl.id, v.other_info?.title); break; case "DISABLED": await campaigns.cancel(tpl.id, v.disable_info?.disable_date); break; case "REJECTED": await alerts.notify(tpl.owner, { reason: v.reason, // e.g. INVALID_FORMAT, PROMOTIONAL detail: v.rejection_info?.reason, // only for INVALID_FORMAT fix: v.rejection_info?.recommendation, }); break; case "FLAGGED": await alerts.warn(tpl.owner, "Negative feedback: may be disabled soon"); break; default: // PENDING, IN_APPEAL, ARCHIVED, DELETED... await audit.log("message_template_status_update", v); }}Step 6 of 6 · lines 29–30
PENDING, IN_APPEAL, LOCKED, LIMIT_EXCEEDED, ARCHIVED, DELETED and new values are logged, never dropped.
Handler (Node.js), step 6 of 6, lines 29–30: PENDING, IN_APPEAL, LOCKED, LIMIT_EXCEEDED, ARCHIVED, DELETED and new values are logged, never dropped.
How does the template status webhook work?
Subscribe on the default callback
Tick
message_template_status_updatein the app's webhook fields. It is not affected by WABA or phone-number overrides, so the default endpoint must stay live.Store IDs at creation
Creating a template returns its
id, status and category. Store the ID per language; status webhooks reference it, and one name can exist in many languages.Gate sends on state
Let campaigns use a template only after
APPROVED(orREINSTATED/UNARCHIVED). Review is automatic and can take up to 24 hours, so schedule launches with that margin.Hold on pauses, replace on disables
PAUSEDis temporary — 3 hours the first time, 6 the second — so hold, and resume only when a later status event lifts the pause (Meta marks it withother_info.title: UNPAUSE), not on a timer.DISABLEDis final: switch automations to an approved replacement.Show rejections to the author
Surface
reasonand, forINVALID_FORMAT,rejection_info.recommendationin your template editor, then let the author fix and resubmit or appeal (appeals are decided within 24 hours).Decide on archived templates
ARCHIVEDmeans 12 months without use; the template is deleted 28 days later unless unarchived. Unarchive the ones automations still need.
The template status webhook: key facts and limits
- Webhook field
- message_template_status_update
- Event values
- More than a dozen (APPROVED, REJECTED, PAUSED, DISABLED…)
- Rejection detail
- rejection_info only for INVALID_FORMAT
- Pause titles
- FIRST_PAUSE, SECOND_PAUSE, RATE_LIMITING_PAUSE, UNPAUSE, DISABLED
- Review time
- Automatic, up to 24 hours
- Archiving
- After 12 months unused; deleted 28 days later unless unarchived
- Callback override
- Not supported: always the app's default URL
The template status webhook in code
export async function onTemplateStatus(entry, change) {const v = change.value;const tpl = await templates.byId(v.message_template_id);await tpl.recordStatus(v.event, v.reason, v.message_template_category, entry.time);switch (v.event) {case "APPROVED":case "REINSTATED":case "UNARCHIVED":await campaigns.release(tpl.id);break;case "PAUSED":// other_info.title: FIRST_PAUSE, SECOND_PAUSE or RATE_LIMITING_PAUSEawait campaigns.hold(tpl.id, v.other_info?.title);break;case "DISABLED":await campaigns.cancel(tpl.id, v.disable_info?.disable_date);break;case "REJECTED":await alerts.notify(tpl.owner, {reason: v.reason, // e.g. INVALID_FORMAT, PROMOTIONALdetail: v.rejection_info?.reason, // only for INVALID_FORMATfix: v.rejection_info?.recommendation,});break;case "FLAGGED":await alerts.warn(tpl.owner, "Negative feedback: may be disabled soon");break;default: // PENDING, IN_APPEAL, ARCHIVED, DELETED...await audit.log("message_template_status_update", v);}}
Record the state, then release, hold, cancel or explain — and log anything else.
Common mistakes with the template status webhook
Launching on creation instead of approval
A template returned by the create call is usually
PENDING. Sending it fails. Schedule campaigns against theAPPROVEDwebhook, not the create response.Treating PAUSED and DISABLED alike
Cancelling a campaign on a 3-hour pause wastes a working template; retrying a disabled one fails every time. Hold on
PAUSED, replace onDISABLED.Ignoring FLAGGED
FLAGGEDmeans negative feedback that may lead to a disable. It is the last cheap moment to cut frequency or tighten the audience for that template.Assuming reason is always set
reasonis null for a template scheduled for deletion, andNONEon pauses. Code that switches onreasonalone mislabels these events; route oneventfirst.
Example: A festive template that launched itself, Jaipur
A Jaipur travel agency submits a Navratri package template at 6 pm, with a 10 am campaign scheduled for the next day. At 6:40 pm a REJECTED webhook arrives with reason: INVALID_FORMAT and a rejection_info.recommendation pointing out that the body starts with a variable. The editor shows the note, the marketer moves {{1}} after a greeting and resubmits. At 8:15 pm an APPROVED webhook releases the scheduled campaign, which goes out at 10 am as planned.
Template Status Webhook FAQs
How long after submitting will I get the status webhook?+
Why is reason NONE when my template was paused?+
How is this different from the template quality webhook?+
Can I check a template's status without the webhook?+
Why does the template status webhook matter?
Templates are the only way to start a conversation on WhatsApp, so a template's state decides whether a campaign or an automation can run at all. Reacting to this webhook lets a system launch a campaign the minute its template is approved, hold it during a pause instead of failing thousands of sends, switch to a backup when a template is disabled, and show authors exactly why Meta rejected their copy — without anyone polling the templates list.
Best practices for the template status webhook
- Keep one approved backup template for every critical automation, such as OTPs and order updates.
- Show the latest status and its reason next to each template in your editor, not just in logs.
- Count rejections by reason per author to target copy guidelines where they help most.
- Alert a person on DISABLED and FLAGGED; most other events can go straight to automation.
Talk to InfiQ
From definition to your first message
InfiQ is an official Meta Business Partner. Start a 7-day free trial — no card needed — and see this running on your own number.