> ## Documentation Index
> Fetch the complete documentation index at: https://developers.tanvik.io/llms.txt
> Use this file to discover all available pages before exploring further.

# WhatsApp Webhook

> Payload shapes for WhatsApp-specific webhook events

This page covers the exact payload for each WhatsApp event. Register your endpoint and verify signatures as described in the general [Webhooks](/webhooks-overview) guide first.

Every event is wrapped the same way:

```json theme={null}
{
  "event": "message.received",
  "data": { ... }
}
```

## message.received

Fired when a customer sends you a WhatsApp message.

```json theme={null}
{
  "event": "message.received",
  "data": {
    "message_id": "5a9e6f1c-9e2f-4b1c-8a5c-7e8f9a0b1c2d",
    "wamid": "wamid.HBgMOTE5ODc2NTQzMjEwFQIAEhg...",
    "from": "+919876543210",
    "type": "text",
    "text": "What are your store hours?",
    "timestamp": "2026-07-14T18:22:04Z"
  }
}
```

`message_id` is Tanvik's internal ID (same one `GET /v1/messages/{id}` uses); `wamid` is WhatsApp's own message ID.

## message.status

Fired on each status transition of a message you sent via the API.

```json theme={null}
{
  "event": "message.status",
  "data": {
    "message_id": "5a9e6f1c-9e2f-4b1c-8a5c-7e8f9a0b1c2d",
    "status": "delivered",
    "timestamp": "2026-07-14T18:22:41Z"
  }
}
```

`status` is one of `sent`, `delivered`, `read`, `failed`. On `failed`, an additional `error` string is included with the reason.

## otp.verified

Fired when a customer successfully verifies an OTP.

```json theme={null}
{
  "event": "otp.verified",
  "data": {
    "otp_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "to": "+919876543210",
    "verified_at": "2026-07-14T18:24:10Z"
  }
}
```

<Note>
  This only fires on success. A wrong or expired code doesn't trigger a webhook — check the [Verify OTP](/whatsapp/verify-otp) response directly for that.
</Note>

## template.status

Fired when a submitted template transitions to `approved` or `rejected`. It does not fire on every sync check — only on the actual status change.

```json theme={null}
{
  "event": "template.status",
  "data": {
    "template_id": "9c858901-8a57-4791-81fe-4c455b099bc9",
    "name": "order_shipped",
    "status": "approved"
  }
}
```

On `rejected`, a `rejection_reason` string is included with Meta's explanation.
