The message_template_status_update field reports lifecycle changes for an existing WhatsApp template. It is the primary webhook field for approval, rejection, pause, disablement, archive, deletion, and appeal status.
What message_template_status_update Reports
This field identifies the template and reports the current lifecycle event, category, language, and any reason or extra metadata available for that event.
It is especially important for:
- moving newly created templates from pending to approved or rejected,
- detecting templates that were paused, disabled, or flagged,
- showing rejection reasons and recommendations,
- keeping archived or deleted template state in sync.
When It Fires
Meta sends it when a template is approved, rejected, disabled, archived, unarchived, paused, flagged, locked, reinstated, deleted, or enters appeal.
Event Values
Common event values include:
| Event | Meaning |
|---|---|
APPROVED | Template can be sent. |
REJECTED | Template failed review. Check reason and possibly rejection_info. |
PENDING | Template is still in review. |
FLAGGED | Negative feedback puts the template at risk. |
PAUSED | Template is temporarily paused. |
DISABLED | Template has been disabled due to feedback or policy. |
LOCKED | Template cannot be edited. |
IN_APPEAL | Template is in the appeal process. |
REINSTATED | Template is usable again. |
ARCHIVED / UNARCHIVED | Template was archived for inactivity, or restored to its previous status. Archived templates are deleted after 28 days unless unarchived. |
DELETED / PENDING_DELETION | Template was deleted, or deleted through WhatsApp Manager and pending removal. |
LIMIT_EXCEEDED | The WABA reached its template limit. |
Payload Shape
{
"object": "whatsapp_business_account",
"entry": [
{
"id": "<WABA_ID>",
"time": 1751247548,
"changes": [
{
"field": "message_template_status_update",
"value": {
"event": "REJECTED",
"message_template_id": 1689556908129835,
"message_template_name": "abandoned_cart",
"message_template_language": "en",
"reason": "INVALID_FORMAT",
"message_template_category": "MARKETING",
"rejection_info": {
"reason": "Variables are not clearly separated.",
"recommendation": "Add descriptive text between variables."
}
}
}
]
}
]
}
Optional nested objects:
| Object | Used for |
|---|---|
disable_info | Disable date when the template is disabled. |
other_info | Pause, unpause, lock, or unlock details. |
rejection_info | Detailed invalid-format rejection reason and recommendation. |
reason values are ABUSIVE_CONTENT, INCORRECT_CATEGORY, INVALID_FORMAT, NONE (paused), PROMOTIONAL, SCAM, and TAG_CONTENT_MISMATCH. CATEGORY_NOT_AVAILABLE is deprecated. other_info.title is FIRST_PAUSE, SECOND_PAUSE, RATE_LIMITING_PAUSE, UNPAUSE, or DISABLED.
Dualhook Handling
Dualhook subscription: subscribed and forwarded. Dualhook's Meta app subscribes to message_template_status_update. Meta does not allow Webhook Override for template fields, so it arrives on Dualhook's app-level callback.
Dualhook uses the event to update template status in the dashboard, show review outcomes, classify template problems, and forward the management event to your configured endpoint. ARCHIVED, UNARCHIVED, PENDING_DELETION, and LIMIT_EXCEEDED update the stored status, REINSTATED sets it back to APPROVED, and DELETED removes the template from the dashboard. FLAGGED and LOCKED leave the stored status unchanged.
Only template metadata and operational delivery status are stored. Outbound message bodies may transit the allowlisted runtime but are not persisted, cached, or body-logged.
Implementation Notes
- Treat
message_template_idplus language as the safest identity pair. Meta usually sends the ID as a JSON number but sometimes as a string, so normalize it to a string before comparing. - For
REJECTED, show bothreasonandrejection_infowhen present. - For
PAUSED,FLAGGED, andDISABLED, slow or stop sends that use the affected template. - Keep unknown
eventvalues. Meta adds lifecycle events over time. - Do not assume
reasonis always a string; scheduled deletion events can reportnull.