Skip to main content

How to track template message delivery and message status using Wati webhooks

Summary

When you send template messages using the Wati API, you can track their status - sent, delivered, read, replied, or failed - using webhooks in real time, rather than relying only on Wati's built-in campaign analytics.

After sending campaigns via the API, you can view their performance in Campaign Overview in Wati. Webhooks let you track message status and delivery events through your own systems as they happen.

Note: For full webhook reference documentation, see Wati developer documentation.

Instructions

Send a Template Message

Use the v3 endpoint to send a template message. v3 is recommended for all new integrations.

Endpoint: POST https://live-mt-server.wati.io/api/ext/v3/messageTemplates/send

v3 paths do not include /{tenantId}/. Create a scoped API token at Connector > API > Create API Token with the messagetemplatev3:write scope.

Sample cURL request:

curl --location 'https://live-mt-server.wati.io/api/ext/v3/messageTemplates/send' \
--header 'Authorization: Bearer <Token>' \
--header 'Content-Type: application/json' \
--data '{
"template_name": "update_for_you",
"broadcast_name": "JPTestBroadcast",
"channel_number": "85264318722",
"target": "<whatsappNumber>",
"parameters": []
}'

channel_number is required. Use digits with country code, no "+" (e.g. 85264318722). target accepts a phone number, ContactId, BSUID, or Channel:PhoneNumber.

Sample API response:

{
"result": true,
"error": null,
"templateName": "update_for_you",
"receivers": [
{
"localMessageId": "d38f0c3a-e833-4725-a894-53a2b1dc1af6",
"waId": "<whatsappNumber>",
"isValidWhatsAppNumber": true,
"errors": []
}
],
"parameters": []
}

Important: A 200 response means the request was accepted, not that the message was delivered. Delivery is confirmed by the sentMessageDELIVERED_v2 webhook. Failures are reported by templateMessageFailed.

Key field:

  • localMessageId — Unique identifier for the message. Save this value — it links all outbound status webhook events back to the original message.

Track Message Status Using Webhooks

Once sent, Wati fires webhook events for each status update. Use localMessageId to match events to the original message.

1. Template Message Sent

  • Triggered when: The message is accepted and sent from Wati

  • Event: templateMessageSent_v2

  • Status: SENT

SENT means the message left Wati's system — not that it was delivered to the recipient's device.

Sample payload:

{
"eventType": "templateMessageSent_v2",
"localMessageId": "84689938-5e2-877821d672c2",
"id": "693fd8ee21f81",
"whatsappMessageId": "wamid.HBgNODEYEjQ3RDMzQzM2QjM3QjU1ODQ4RQA=",
"templateId": "6929b",
"templateName": "test_jm4",
"created": "2025-12-15T09:46:23.4083984Z",
"conversationId": "68b68470e93cc",
"ticketId": "693fd6ab545f82",
"text": "Make your messages personal using variables like name and get more replies!",
"operatorEmail": "[email protected]",
"waId": "86151285",
"type": "template",
"statusString": "SENT",
"sourceType": "WEB",
"channelId": null,
"channelPhoneNumber": "174742",
"bsuid": "HK.xxxxxxxxxxxxx",
"parentBsuid": "HK.ENT.xxxxxxxxxxxxx",
"username": "@bob",
"templateContent": {
"header": { "type": "text", "text": "Hello" },
"footer": "Footer text",
"buttons": [
{ "type": "QUICK_REPLY", "text": "Yes" },
{ "type": "URL", "text": "Visit us", "url": "https://example.com" },
{ "type": "CALL", "text": "Call us", "phoneNumber": "+1234567890" }
]
}
}

templateContent fields:

Field

Description

header

Header type and content (text, image, video, or document)

footer

Footer text

buttons

Array of buttons — QUICK_REPLY, URL, and CALL types

Template sent webhook now includes button information

The Template Sent webhook now includes button information configured in the WhatsApp template. This allows you to identify the button text associated with a sent template message.

This feature is available to customers on the Pro, Business, and Enterprise plans.

What button information is included?

The webhook payload can include the following button information from the WhatsApp template:

  • Quick reply button text

  • Link button text

When you retrieve template information through the API, the response also includes the button text configured for the template.

BSUID variant

templateMessageSent_v2_bsuid fires the same event with bsuid, parentBsuid, and username fields to identify contacts by BSUID instead of phone number.

2. Message Delivered

  • Triggered when: The message is delivered to the recipient's device

  • Event: sentMessageDELIVERED_v2

  • Status: Delivered

Sample payload:

{
"eventType": "sentMessageDELIVERED_v2",
"statusString": "Delivered",
"localMessageId": "16bf77ae-79e8-691eb4b",
"id": "693fd65f99391640",
"whatsappMessageId": "wamid.HBgNODYxMzEzMzg4Nzg2MDU0OEM0NTYxRTlBMwA=",
"conversationId": "68cba32b3349e",
"ticketId": "693f7a0a8545f54",
"text": "hello",
"type": "text",
"timestamp": "1765791326",
"assigneeId": "65a105b5cf65262",
"operatorEmail": "derre.ai",
"channelId": null,
"channelPhoneNumber": "17742"
}

BSUID variant: sentMessageDELIVERED_v2_bsuid

3. Message Read

  • Triggered when: The recipient reads the message

  • Event: sentMessageREAD_v2

  • Status: Read

Sample payload:

{
"eventType": "sentMessageREAD_v2",
"statusString": "Read",
"localMessageId": "16bf77ae-79e691eb4b",
"id": "693fd65f961dc81779391640",
"whatsappMessageId": "wamid.HBgNODYxMzEABEYEjVCNzg2MDU0OEM0NTYxRTlBMwA=",
"conversationId": "68cba3db12b3349e",
"ticketId": "693fd64d1d45f54",
"text": "hello",
"type": "text",
"timestamp": "17651326",
"assigneeId": "65a10905cf65262",
"operatorEmail": "[email protected]",
"channelId": null,
"channelPhoneNumber": "174742"
}

BSUID variant: sentMessageREAD_v2_bsuid

4. Message Replied

  • Triggered when: The recipient replies to the message

  • Event: sentMessageREPLIED_v2

  • Status: Replied

Sample payload:

{
"eventType": "sentMessageREPLIED_v2",
"statusString": "Replied",
"localMessageId": "16bf77ae-79e691eb4b",
"id": "693fd65f961dc81779391640",
"whatsappMessageId": "wamid.HBgNODYxMzEABEYEjVCNzg2MDU0OEM0NTYxRTlBMwA=",
"conversationId": "68cba3db12b3349e",
"ticketId": "693fd64d1d45f54",
"text": "hello",
"type": "text",
"timestamp": "17651326",
"assigneeId": "65a10905cf65262",
"operatorEmail": "[email protected]",
"channelId": null,
"channelPhoneNumber": "174742"
}

BSUID variant: sentMessageREPLIED_v2_bsuid

5. Message Received

  • Triggered when: A user sends a message to your Wati number

  • Event: message

  • Status: Received

Use cases:

  • Track incoming messages from users

  • Capture quick reply button clicks from template messages

  • Detect replies to a specific outbound message using replyContextId

Incoming messages do not carry a localMessageId. To link a reply to the original template message, use replyContextId — it contains the whatsappMessageId of the original outbound message.

Sample payload — text message:

{
"eventType": "message",
"statusString": "Received",
"whatsappMessageId": "wamid.HBgMOAE4NjY4NDkzNjAxFAIAERgSOTEENzFCNjEwMkNDNENGQUJGAA==",
"replyContextId": "wamid.HBgNODEYEjQ3RDMzQzM2QjM3QjU1ODQ4RQA=",
"text": "Hello, I need help!",
"timestamp": "1665645642",
"operatorEmail": "[email protected]"
}

Sample payload — quick reply button click:

{
"eventType": "message",
"statusString": "Received",
"whatsappMessageId": "wamid.HBgMOAE4NjY4NDkzNjAxFAIAERgSOTEENzFCNjEwMkNDNENGQUJGAA==",
"buttonReply": {
"id": "btn_yes",
"title": "Yes"
},
"timestamp": "1665645642",
"operatorEmail": "[email protected]"
}

6. Template Message Failed

  • Triggered when: The message fails to send

  • Event: templateMessageFailed

  • Status: Failed

Sample payload:

{
"eventType": "templateMessageFailed",
"statusString": "Failed",
"localMessageId": "fd29c1f-9033-59b2-7d72-5ac964c4c8a7",
"failedCode": "131026",
"failedDetail": "Message undeliverable",
"id": "66b2531d4931581381944612",
"whatsappMessageId": "wamid.HBgMOAE4NjY4NDkzNjAxFAIAERgSOTEENzFCNjEwMkNDNENGQUJGAA==",
"conversationId": "66b1fb044045cedb1f19538e",
"ticketId": "66bdfba190194752bb7326d7",
"text": null,
"type": "template",
"timestamp": "1665645642",
"assigneeId": null,
"operatorEmail": "[email protected]"
}

channelPhoneNumber is only included in this payload when the webhook is bound to a specific number.

How to Set Up Webhooks in Wati

Via the Wati UI:

  • Go to Connector > Webhooks.

  • Click Add Webhook.

  • Enter your webhook URL and set status to Enabled.

  • Select the events to subscribe to:

    • Template Message Sent

    • Delivered

    • Read

    • Replied

    • Failed

Via API:

Create a webhook (v2):

POST https://live-mt-server.wati.io/{tenantId}/api/v2/webhookEndpoints

List, get, update, and delete webhooks (v3 — recommended):

https://live-mt-server.wati.io/api/ext/v3/webhooks

v3 webhook endpoints do not include /{tenantId}/ in the path.

Final Notes

  • Always store the localMessageId from the send response — it links all outbound status events to the original message.

  • For inbound messages, use replyContextId to link a reply to the original outbound message.

  • Use buttonReply to detect quick reply button interactions.

  • Combine multiple webhook events to build a complete message lifecycle view.

Did this answer your question?