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

# Webhook Event Reference

> Complete reference for every webhook event Chirp delivers, including payloads and trigger behavior

Chirp delivers webhooks as HTTP POST requests to your endpoint whenever a subscribed event occurs. This page documents every event type across SMS, WhatsApp, and Calling, including the payload schema and when each event fires.

<Warning>
  **New events are opt-in.** Existing webhook configurations only receive the events they were created with. To receive any of the events marked **New** below, update your webhook's `events` array via the [Update Webhook](/api_reference/webhooks#update-webhook) endpoint or the dashboard.
</Warning>

## Delivery behavior

All events share the same delivery contract:

| Property       | Value                                                                            |
| -------------- | -------------------------------------------------------------------------------- |
| Method         | `POST`                                                                           |
| Content-Type   | `application/json`                                                               |
| Timeout        | 5 seconds                                                                        |
| Retry attempts | 5 (exponential backoff)                                                          |
| Deduplication  | Events may be delivered more than once; use `event` + payload IDs to deduplicate |

## Event categories

* [SMS Messages](#sms-messages) — inbound, sent, delivered, failed
* [WhatsApp Messages](#whatsapp-messages) — inbound and outbound message status
* [WhatsApp Templates](#whatsapp-templates) — template lifecycle
* [WhatsApp Contacts](#whatsapp-contacts) — contact lifecycle and preferences
* [WhatsApp Groups](#whatsapp-groups) — group lifecycle, participants, and settings
* [WhatsApp Account](#whatsapp-account) — account connected/disconnected, alerts
* [WhatsApp WABA](#whatsapp-waba) — business account capability and review changes
* [WhatsApp Phone Numbers](#whatsapp-phone-numbers) — phone number quality, name, security, deregistration
* [Partner & Payment](#partner--payment) — partner solutions and payment config (log-only)
* [Calling](#calling) — call lifecycle, participants, recordings, voicemails

***

## SMS Messages

SMS message events fire for inbound and outbound SMS/MMS messages.

### `messages.sms.received`

Fires immediately when an inbound SMS or MMS message arrives on one of your phone numbers.

```json icon="json" title="messages.sms.received" theme={null}
{
  "event": "messages.sms.received",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "message": {
      "id": "msg_sms_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "inbound",
      "from": "+15551234567",
      "to": "+15559876543",
      "text": "Hello!",
      "type": "sms",
      "mediaUrl": null,
      "mediaId": null,
      "receivedAt": "2024-01-15T10:30:00.000Z",
      "sentAt": null,
      "completedAt": null,
      "occurredAt": "2024-01-15T10:30:00.000Z"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

For MMS, `type` is `mms` and `mediaUrl` / `mediaId` reference the attached media.

### `messages.sms.sent`

Fires when a message you sent has been accepted by the carrier.

```json icon="json" title="messages.sms.sent" theme={null}
{
  "event": "messages.sms.sent",
  "timestamp": "2024-01-15T10:30:01.000Z",
  "data": {
    "message": {
      "id": "msg_sms_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "from": "+15559876543",
      "to": "+15551234567",
      "text": "Hi back!",
      "type": "sms",
      "mediaUrl": null,
      "mediaId": null,
      "receivedAt": null,
      "sentAt": "2024-01-15T10:30:01.000Z",
      "completedAt": null,
      "occurredAt": "2024-01-15T10:30:01.000Z"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

### `messages.sms.delivered`

Fires when the carrier confirms delivery to the recipient's device.

```json icon="json" title="messages.sms.delivered" theme={null}
{
  "event": "messages.sms.delivered",
  "timestamp": "2024-01-15T10:30:05.000Z",
  "data": {
    "message": {
      "id": "msg_sms_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "from": "+15559876543",
      "to": "+15551234567",
      "text": "Hi back!",
      "type": "sms",
      "mediaUrl": null,
      "mediaId": null,
      "receivedAt": null,
      "sentAt": "2024-01-15T10:30:01.000Z",
      "completedAt": "2024-01-15T10:30:05.000Z",
      "occurredAt": "2024-01-15T10:30:05.000Z"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

### `messages.sms.failed`

Fires when message delivery fails. The `error` field uses the same structure as [API error responses](/api_reference/errors).

```json icon="json" title="messages.sms.failed" theme={null}
{
  "event": "messages.sms.failed",
  "timestamp": "2024-01-15T10:30:05.000Z",
  "data": {
    "message": {
      "id": "msg_sms_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "from": "+15559876543",
      "to": "+15551234567",
      "text": "Hi back!",
      "type": "sms",
      "mediaUrl": null,
      "mediaId": null,
      "receivedAt": null,
      "sentAt": "2024-01-15T10:30:01.000Z",
      "completedAt": null,
      "occurredAt": "2024-01-15T10:30:05.000Z"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" },
    "error": {
      "type": "provider_error",
      "code": "message_undeliverable",
      "message": "Message could not be delivered",
      "provider": {
        "source": "telnyx",
        "code": "40010",
        "message": "Destination unreachable"
      }
    }
  }
}
```

***

## WhatsApp Messages

WhatsApp message events use a single payload shape (`data.message`) for both inbound and outbound messages. The `direction` and timestamp fields tell you which lifecycle stage you're at.

### `messages.whatsapp.received`

Fires immediately when an inbound WhatsApp message arrives on one of your phone numbers.

```json icon="json" title="messages.whatsapp.received" theme={null}
{
  "event": "messages.whatsapp.received",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "message": {
      "id": "msg_wa_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "inbound",
      "recipientType": "individual",
      "from": "+15551234567",
      "to": "+15559876543",
      "text": "Hello!",
      "type": "text",
      "media": null,
      "audio": null,
      "sticker": null,
      "location": null,
      "button": null,
      "contacts": null,
      "reaction": null,
      "interactive": null,
      "order": null,
      "system": null,
      "context": null,
      "receivedAt": "2024-01-15T10:30:00.000Z",
      "sentAt": null,
      "occurredAt": "2024-01-15T10:30:00.000Z",
      "conversationWindow": null
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

For media messages (`type` is `image`, `video`, `audio`, `document`, `sticker`, `location`, `contacts`, `reaction`, `interactive`, `order`, or `system`), the corresponding nested object on `data.message` is populated. See [Receiving WhatsApp messages](/whatsapp/receiving-messages) for examples of every type.

### `messages.whatsapp.sent`

Fires when a message you sent has been accepted by WhatsApp servers.

```json icon="json" title="messages.whatsapp.sent" theme={null}
{
  "event": "messages.whatsapp.sent",
  "timestamp": "2024-01-15T10:30:01.000Z",
  "data": {
    "message": {
      "id": "msg_wa_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "recipientType": "individual",
      "from": "+15559876543",
      "to": "+15551234567",
      "text": "Hi back!",
      "type": "text",
      "sentAt": "2024-01-15T10:30:01.000Z",
      "occurredAt": "2024-01-15T10:30:01.000Z",
      "conversationWindow": null
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

### `messages.whatsapp.delivered`

Fires when WhatsApp confirms the message was delivered to the recipient's device.

```json icon="json" title="messages.whatsapp.delivered" theme={null}
{
  "event": "messages.whatsapp.delivered",
  "timestamp": "2024-01-15T10:30:05.000Z",
  "data": {
    "message": {
      "id": "msg_wa_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "recipientType": "individual",
      "from": "+15559876543",
      "to": "+15551234567",
      "text": "Hi back!",
      "type": "text",
      "sentAt": "2024-01-15T10:30:01.000Z",
      "occurredAt": "2024-01-15T10:30:05.000Z",
      "conversationWindow": {
        "category": "service",
        "expiresAt": "2024-01-16T10:30:05.000Z"
      }
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

### `messages.whatsapp.read`

Fires when the recipient opens and reads the message.

```json icon="json" title="messages.whatsapp.read" theme={null}
{
  "event": "messages.whatsapp.read",
  "timestamp": "2024-01-15T10:30:10.000Z",
  "data": {
    "message": {
      "id": "msg_wa_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "recipientType": "individual",
      "from": "+15559876543",
      "to": "+15551234567",
      "text": "Hi back!",
      "type": "text",
      "sentAt": "2024-01-15T10:30:01.000Z",
      "occurredAt": "2024-01-15T10:30:10.000Z"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

### `messages.whatsapp.failed`

Fires when message delivery fails. The `error` field uses the same structure as [API error responses](/api_reference/errors).

```json icon="json" title="messages.whatsapp.failed" theme={null}
{
  "event": "messages.whatsapp.failed",
  "timestamp": "2024-01-15T10:30:05.000Z",
  "data": {
    "message": {
      "id": "msg_wa_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "recipientType": "individual",
      "from": "+15559876543",
      "to": "+15551234567",
      "text": "Hi back!",
      "type": "text",
      "sentAt": "2024-01-15T10:30:01.000Z",
      "occurredAt": "2024-01-15T10:30:05.000Z"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" },
    "error": {
      "type": "provider_error",
      "code": "message_undeliverable",
      "message": "Message could not be delivered",
      "provider": {
        "source": "meta",
        "code": 131026,
        "message": "Message Undeliverable"
      }
    }
  }
}
```

When Meta returns vague failure codes such as `account_restricted` or `display_name_not_approved`, Chirp enriches the `error.provider` field with Health Status details. See [WhatsApp webhooks](/whatsapp/webhooks-setup#enriched-error-payloads) for the enriched shape.

***

## WhatsApp Templates

Template events fire when Meta updates a template's status, quality, category, or components.

### `templates.whatsapp.created`

Fires when a template is approved or first synced to Chirp.

```json icon="json" title="templates.whatsapp.created" theme={null}
{
  "event": "templates.whatsapp.created",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "template": {
      "id": "wht_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaTemplateId": "123456789012345",
      "name": "order_confirmation",
      "language": "en_US",
      "category": "UTILITY",
      "status": "APPROVED",
      "qualityScore": "GREEN"
    },
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI"
    },
    "apps": [
      { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
    ]
  }
}
```

### `templates.whatsapp.updated`

Fires when any template field changes: status, quality score, category, or components. The `change.type` field describes what changed.

```json icon="json" title="templates.whatsapp.updated (quality change)" theme={null}
{
  "event": "templates.whatsapp.updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "template": {
      "id": "wht_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaTemplateId": "123456789012345",
      "name": "order_confirmation",
      "language": "en_US",
      "category": "UTILITY",
      "status": "PAUSED",
      "qualityScore": "RED"
    },
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI"
    },
    "apps": [
      { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
    ],
    "change": {
      "type": "quality",
      "previousQualityScore": "GREEN",
      "newQualityScore": "RED",
      "pauseInfo": {
        "title": "FIRST_PAUSE",
        "description": "Template paused due to low quality rating"
      }
    }
  }
}
```

### `templates.whatsapp.deleted`

Fires when a template is deleted from Meta.

```json icon="json" title="templates.whatsapp.deleted" theme={null}
{
  "event": "templates.whatsapp.deleted",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "template": {
      "id": "wht_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaTemplateId": "123456789012345",
      "name": "order_confirmation",
      "language": "en_US",
      "category": "UTILITY",
      "status": "REJECTED",
      "qualityScore": null
    },
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI"
    },
    "apps": [],
    "change": {
      "type": "status",
      "statusEvent": "DELETED"
    }
  }
}
```

### `templates.whatsapp.connected`

Fires when an existing Meta template is linked to one of your Chirp apps.

```json icon="json" title="templates.whatsapp.connected" theme={null}
{
  "event": "templates.whatsapp.connected",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "template": {
      "id": "wht_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaTemplateId": "123456789012345",
      "name": "order_confirmation",
      "language": "en_US",
      "category": "UTILITY",
      "status": "APPROVED",
      "qualityScore": "GREEN"
    },
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI"
    },
    "apps": [
      { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
    ]
  }
}
```

***

## WhatsApp Contacts

Contact events track the lifecycle of contacts you've interacted with via WhatsApp.

### `contacts.whatsapp.created`

Fires when Chirp first sees a contact (first message sent or received with that phone number).

```json icon="json" title="contacts.whatsapp.created" theme={null}
{
  "event": "contacts.whatsapp.created",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "contact": {
      "id": "waco_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "phoneNumber": "+15551234567",
      "profileName": "John Doe",
      "firstSeenAt": "2024-01-15T10:30:00.000Z",
      "lastSeenAt": "2024-01-15T10:30:00.000Z"
    },
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

### `contacts.whatsapp.updated`

Fires when a contact's profile name changes.

```json icon="json" title="contacts.whatsapp.updated" theme={null}
{
  "event": "contacts.whatsapp.updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "contact": {
      "id": "waco_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "phoneNumber": "+15551234567",
      "profileName": "Johnny D",
      "firstSeenAt": "2024-01-01T09:00:00.000Z",
      "lastSeenAt": "2024-01-15T10:30:00.000Z"
    },
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" },
    "change": {
      "field": "profile_name",
      "previousValue": "John Doe",
      "newValue": "Johnny D"
    }
  }
}
```

### `contacts.whatsapp.deleted`

Fires when a contact is removed (e.g., opt-out or data deletion).

```json icon="json" title="contacts.whatsapp.deleted" theme={null}
{
  "event": "contacts.whatsapp.deleted",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "contact": {
      "id": "waco_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "phoneNumber": "+15551234567",
      "profileName": "John Doe",
      "firstSeenAt": "2024-01-01T09:00:00.000Z",
      "lastSeenAt": "2024-01-14T18:00:00.000Z"
    },
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

### `whatsapp.contact.preferences_updated` <span style={{color: "#16a34a", fontSize: "0.75rem", fontWeight: 600}}>New</span>

Fires when a contact changes their marketing message preferences (opt-in/opt-out). Meta delivers this in real-time.

```json icon="json" title="whatsapp.contact.preferences_updated" theme={null}
{
  "event": "whatsapp.contact.preferences_updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "contact": {
      "id": "wac_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "phoneNumber": "+15551234567"
    },
    "preferences": {
      "marketing": {
        "status": "stop",
        "updatedAt": "2024-01-15T10:30:00.000Z"
      }
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

`preferences.marketing.status` is `"stop"` when the contact opts out of marketing messages and `"resume"` when they opt back in. **Stop sending marketing messages immediately to remain compliant with WhatsApp's policies.**

### `whatsapp.contact.automatic_event` <span style={{color: "#16a34a", fontSize: "0.75rem", fontWeight: 600}}>New</span>

Fires when a Click-to-WhatsApp (CTWA) ad triggers a conversion event (e.g., Purchase). Used for ads attribution. Meta delivers this in real-time.

```json icon="json" title="whatsapp.contact.automatic_event" theme={null}
{
  "event": "whatsapp.contact.automatic_event",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "eventName": "Purchase",
    "ctwaClid": "AYABCxxx",
    "occurredAt": "2024-01-15T10:30:00.000Z",
    "phoneNumberId": "106540352242922"
  }
}
```

`ctwaClid` is the click ID from the ad — pass it back to Meta's Conversions API to close the attribution loop. It is `null` for Status ad placements.

***

## WhatsApp Groups

Group events fire when WhatsApp groups owned by your phone numbers change. Every payload includes the affected `group`, the owning `whatsappPhoneNumber`, and the `app`. See [WhatsApp Groups](/whatsapp/groups) for the corresponding REST API.

### `groups.whatsapp.created`

Fires when a new group is created and owned by one of your phone numbers.

```json icon="json" title="groups.whatsapp.created" theme={null}
{
  "event": "groups.whatsapp.created",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "group": {
      "id": "wag_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "subject": "Support Team",
      "description": "Customer support group",
      "joinApprovalMode": "auto_approve",
      "inviteLink": "https://chat.whatsapp.com/abc123",
      "suspended": false,
      "totalParticipantCount": 5,
      "createdAt": "2024-01-15T10:30:00.000Z"
    },
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

### `groups.whatsapp.deleted`

Fires when a group is deleted.

The payload shape is identical to `groups.whatsapp.created` with `event` set to `groups.whatsapp.deleted`.

### `groups.whatsapp.suspended`

Fires when WhatsApp suspends a group (e.g., for policy violations).

The payload shape is identical to `groups.whatsapp.created` with `group.suspended` set to `true`.

### `groups.whatsapp.suspension_cleared`

Fires when WhatsApp lifts a previous suspension.

The payload shape is identical to `groups.whatsapp.created` with `group.suspended` set to `false`.

### `groups.whatsapp.participant_added`

Fires when one or more participants join the group.

```json icon="json" title="groups.whatsapp.participant_added" theme={null}
{
  "event": "groups.whatsapp.participant_added",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "group": {
      "id": "wag_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "subject": "Support Team",
      "description": "Customer support group",
      "joinApprovalMode": "auto_approve",
      "inviteLink": "https://chat.whatsapp.com/abc123",
      "suspended": false,
      "totalParticipantCount": 6,
      "createdAt": "2024-01-15T10:30:00.000Z"
    },
    "participants": [
      { "waId": "15551234567", "joinedAt": "2024-01-15T10:30:00.000Z" }
    ],
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

`participants[].waId` is the participant's WhatsApp ID (phone number without the `+`). `joinedAt` may be `null` when WhatsApp does not provide a timestamp.

### `groups.whatsapp.participant_removed`

Fires when one or more participants are removed by an admin.

```json icon="json" title="groups.whatsapp.participant_removed" theme={null}
{
  "event": "groups.whatsapp.participant_removed",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "group": {
      "id": "wag_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "subject": "Support Team",
      "description": "Customer support group",
      "joinApprovalMode": "auto_approve",
      "inviteLink": "https://chat.whatsapp.com/abc123",
      "suspended": false,
      "totalParticipantCount": 5,
      "createdAt": "2024-01-15T10:30:00.000Z"
    },
    "participants": [
      { "waId": "15551234567", "joinedAt": "2024-01-15T10:30:00.000Z" }
    ],
    "initiatedBy": "business",
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

`initiatedBy` is `"business"` when an admin removed the participant, or `"participant"` when the participant left voluntarily (in which case `groups.whatsapp.participant_left` typically fires instead).

### `groups.whatsapp.participant_left`

Fires when a single participant voluntarily leaves the group.

```json icon="json" title="groups.whatsapp.participant_left" theme={null}
{
  "event": "groups.whatsapp.participant_left",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "group": {
      "id": "wag_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "subject": "Support Team",
      "description": "Customer support group",
      "joinApprovalMode": "auto_approve",
      "inviteLink": "https://chat.whatsapp.com/abc123",
      "suspended": false,
      "totalParticipantCount": 4,
      "createdAt": "2024-01-15T10:30:00.000Z"
    },
    "participant": { "waId": "15551234567", "joinedAt": "2024-01-15T10:30:00.000Z" },
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

### `groups.whatsapp.join_request_created`

Fires when someone requests to join a group whose `joinApprovalMode` is `approval_required`.

```json icon="json" title="groups.whatsapp.join_request_created" theme={null}
{
  "event": "groups.whatsapp.join_request_created",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "group": {
      "id": "wag_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "subject": "Support Team",
      "description": "Customer support group",
      "joinApprovalMode": "approval_required",
      "inviteLink": "https://chat.whatsapp.com/abc123",
      "suspended": false,
      "totalParticipantCount": 5,
      "createdAt": "2024-01-15T10:30:00.000Z"
    },
    "joinRequest": {
      "id": "wagjr_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "waId": "15551234567",
      "createdAt": "2024-01-15T10:30:00.000Z"
    },
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

Approve or reject the request via [`POST /v1/whatsapp/groups/{groupId}/join-requests/approve`](/api_reference/whatsapp-groups) or `/reject`.

### `groups.whatsapp.join_request_revoked`

Fires when a pending join request is revoked (either by the requester or the admin).

The payload shape is identical to `groups.whatsapp.join_request_created` with `event` set to `groups.whatsapp.join_request_revoked`.

### `groups.whatsapp.settings_updated`

Fires when the group subject, description, or profile picture changes.

```json icon="json" title="groups.whatsapp.settings_updated" theme={null}
{
  "event": "groups.whatsapp.settings_updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "group": {
      "id": "wag_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "subject": "Customer Support",
      "description": "Customer support group",
      "joinApprovalMode": "auto_approve",
      "inviteLink": "https://chat.whatsapp.com/abc123",
      "suspended": false,
      "totalParticipantCount": 5,
      "createdAt": "2024-01-15T10:30:00.000Z"
    },
    "changes": {
      "subject": {
        "text": "Customer Support",
        "updateSuccessful": true
      }
    },
    "whatsappPhoneNumber": {
      "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "displayPhoneNumber": "+15559876543"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI", "name": "My App" }
  }
}
```

`changes` may contain any of `subject`, `description`, or `profilePicture`. When an update fails, `updateSuccessful` is `false` and the corresponding `errors` array is populated.

***

## WhatsApp Account

Account events fire when a WhatsApp Business Account (WABA) is connected or disconnected via Embedded Signup, or when Meta raises an alert.

### `whatsapp.account.connected`

Fires immediately when a customer completes Embedded Signup and grants your app access to their WABA.

```json icon="json" title="whatsapp.account.connected" theme={null}
{
  "event": "whatsapp.account.connected",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaWabaId": "1234567890",
      "businessName": "My Business"
    },
    "phoneNumbers": [
      {
        "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
        "displayPhoneNumber": "+15551234567"
      }
    ],
    "state": "user_123_signup_abc",
    "metadata": {
      "externalUserId": "user_123",
      "businessName": "Acme Corp"
    }
  }
}
```

`state` and `metadata` are values you passed during the Embedded Signup flow to correlate the event with your internal user.

### `whatsapp.account.disconnected`

Fires when a WABA is disconnected — either by the customer revoking access or by your app removing it.

```json icon="json" title="whatsapp.account.disconnected" theme={null}
{
  "event": "whatsapp.account.disconnected",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaWabaId": "1234567890",
      "businessName": "My Business"
    },
    "phoneNumbers": [
      {
        "id": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
        "displayPhoneNumber": "+15551234567"
      }
    ]
  }
}
```

### `whatsapp.account.alert_raised` <span style={{color: "#16a34a", fontSize: "0.75rem", fontWeight: 600}}>New</span>

Fires when Meta raises a compliance or policy alert against a WABA or phone number. Meta delivers this in real-time.

```json icon="json" title="whatsapp.account.alert_raised" theme={null}
{
  "event": "whatsapp.account.alert_raised",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaWabaId": "1234567890",
      "businessName": "My Business"
    },
    "alert": {
      "entityType": "WABA",
      "entityId": "1234567890",
      "alertType": "ACCOUNT_REVIEW",
      "alertSeverity": "WARNING",
      "alertStatus": "ACTIVE",
      "alertDescription": "Your account is under review."
    }
  }
}
```

Any field in `alert` may be `null` if Meta does not provide it for that alert type.

***

## WhatsApp WABA

### `whatsapp.waba.review_updated` <span style={{color: "#16a34a", fontSize: "0.75rem", fontWeight: 600}}>New</span>

Fires when Meta completes a policy review of the WABA. Meta delivers this in real-time.

```json icon="json" title="whatsapp.waba.review_updated" theme={null}
{
  "event": "whatsapp.waba.review_updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaWabaId": "1234567890",
      "businessName": "My Business"
    },
    "review": {
      "decision": "APPROVED",
      "decidedAt": "2024-01-15T10:30:00.000Z"
    }
  }
}
```

`review.decision` is one of `APPROVED`, `REJECTED`, `PENDING`, or `DEFERRED`.

### `whatsapp.waba.capability_changed` <span style={{color: "#16a34a", fontSize: "0.75rem", fontWeight: 600}}>New</span>

Fires when a WABA capability value changes — for example, when your daily conversation limit is upgraded. Meta delivers this in real-time.

```json icon="json" title="whatsapp.waba.capability_changed" theme={null}
{
  "event": "whatsapp.waba.capability_changed",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaWabaId": "1234567890",
      "businessName": "My Business"
    },
    "capability": "max_daily_conversations_per_business",
    "oldValue": "1000",
    "newValue": "10000"
  }
}
```

`oldValue` is `null` if this is the first time Chirp has observed the capability.

***

## WhatsApp Phone Numbers

Phone number events track quality, name verification, security, and registration changes.

### `whatsapp.phone_number.name_updated` <span style={{color: "#16a34a", fontSize: "0.75rem", fontWeight: 600}}>New</span>

Fires when Meta makes a decision on a display name change request. Meta delivers this in real-time.

```json icon="json" title="whatsapp.phone_number.name_updated" theme={null}
{
  "event": "whatsapp.phone_number.name_updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "phoneNumberId": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
    "metaPhoneNumberId": "123456789",
    "displayPhoneNumber": "+15551234567",
    "nameStatus": "APPROVED",
    "requestedVerifiedName": "My Business Name",
    "nameRejectionReason": null,
    "nameDecisionAt": "2024-01-15T10:30:00.000Z"
  }
}
```

`nameStatus` is one of `APPROVED`, `REJECTED`, `PENDING`, or `DEFERRED`. When `nameStatus` is `REJECTED`, `nameRejectionReason` contains Meta's reason code.

### `whatsapp.phone_number.quality_changed` <span style={{color: "#16a34a", fontSize: "0.75rem", fontWeight: 600}}>New</span>

Fires when Meta updates the quality rating or throughput tier for a phone number. Meta delivers this in real-time.

```json icon="json" title="whatsapp.phone_number.quality_changed" theme={null}
{
  "event": "whatsapp.phone_number.quality_changed",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "phoneNumberId": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
    "displayPhoneNumber": "+15551234567",
    "qualityRating": "GREEN",
    "qualityEvent": "FLAGGED",
    "throughputTier": "STANDARD"
  }
}
```

`qualityRating` is `GREEN`, `YELLOW`, or `RED`, or `null` for newly-onboarded phones with no rating yet. `qualityEvent` describes what triggered the change: `FLAGGED`, `ONBOARDED`, `ONBOARDING`, `UPGRADE`, or `THROUGHPUT_UPGRADE`.

### `whatsapp.phone_number.security_event` <span style={{color: "#16a34a", fontSize: "0.75rem", fontWeight: 600}}>New</span>

Fires when a two-step verification PIN event occurs on a phone number. Meta delivers this in real-time.

```json icon="json" title="whatsapp.phone_number.security_event" theme={null}
{
  "event": "whatsapp.phone_number.security_event",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "phoneNumberId": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
    "displayPhoneNumber": "+15551234567",
    "eventType": "PIN_CHANGED",
    "requester": "61555822107539"
  }
}
```

`eventType` is one of:

* `PIN_CHANGED` — two-step PIN was changed
* `PIN_RESET_REQUEST` — a PIN reset was requested
* `PIN_REQUEST_SUCCESS` — PIN reset completed successfully

`requester` is the Meta Business Suite user ID who triggered the event, or `null` if not provided by Meta.

### `whatsapp.phone_number.deregistered` <span style={{color: "#16a34a", fontSize: "0.75rem", fontWeight: 600}}>New</span>

Fires when Chirp detects that a phone number's verification status has changed from verified to unverified. This event is **poll-driven** — phones with messages in the last 7 days are checked every 15 minutes; idle phones every 6 hours. Delivery may lag by up to \~6 hours for idle numbers.

```json icon="json" title="whatsapp.phone_number.deregistered" theme={null}
{
  "event": "whatsapp.phone_number.deregistered",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "phoneNumberId": "wapn_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
    "metaPhoneNumberId": "123456789",
    "displayPhoneNumber": "+15551234567",
    "previousVerified": true,
    "currentVerified": false
  }
}
```

<Warning>
  A deregistered phone number cannot send or receive WhatsApp messages until it is re-registered. If you receive this event, re-register the phone number via the Chirp API or dashboard as soon as possible.
</Warning>

***

## Partner & Payment

These events are delivered as-is from Meta. Chirp logs them for observability but does not currently take automated action on them.

### `whatsapp.partner_solution.updated` <span style={{color: "#16a34a", fontSize: "0.75rem", fontWeight: 600}}>New</span>

Fires when a Meta multi-partner solution linked to the WABA is created or updated. Meta delivers this in real-time.

```json icon="json" title="whatsapp.partner_solution.updated" theme={null}
{
  "event": "whatsapp.partner_solution.updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "event": "SOLUTION_CREATED",
    "solutionId": "774485461512159",
    "solutionStatus": "ACTIVE"
  }
}
```

### `whatsapp.payment_config.updated` <span style={{color: "#16a34a", fontSize: "0.75rem", fontWeight: 600}}>New</span>

Fires when the payment gateway configuration for the WABA changes. Meta delivers this in real-time.

```json icon="json" title="whatsapp.payment_config.updated" theme={null}
{
  "event": "whatsapp.payment_config.updated",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "whatsappBusinessProfile": {
      "id": "wabp_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "metaWabaId": "1234567890",
      "businessName": "My Business"
    },
    "configurationName": "razorpay-prod",
    "providerName": "razorpay",
    "status": "Active"
  }
}
```

***

## Calling

Calling events track the lifecycle of voice calls. Every payload includes an `eventId` for idempotency and a `data.call` object with the call's identifiers and channel routing. See [Calling Webhooks Setup](/calling/webhooks-setup) for handler examples.

### `calls.initiated`

Fires when a call is created (outbound) or an incoming call is received (inbound).

```json icon="json" title="calls.initiated" theme={null}
{
  "event": "calls.initiated",
  "eventId": "evt_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
  "timestamp": "2024-01-15T10:30:00.000Z",
  "data": {
    "call": {
      "id": "call_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "from": "+15551234567",
      "to": "+15559876543",
      "fromChannel": "pstn",
      "toChannel": "pstn"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI" }
  }
}
```

### `calls.ringing`

Fires when an outbound call is ringing at the destination.

### `calls.answered`

Fires when the call is answered. The `data.call` object includes `answeredAt` and `answeredBy`.

### `calls.completed`

Fires when a call ends normally. The `data.call` object includes `duration`, `endReason`, and `endedAt`.

### `calls.failed`

Fires when a call fails. The payload includes a `data.error` object with `type`, `code`, and `message`.

### `calls.no_answer`

Fires when no one answers a ringing outbound call before it times out.

### `calls.participant_joined`

Fires when a participant joins the call.

```json icon="json" title="calls.participant_joined" theme={null}
{
  "event": "calls.participant_joined",
  "eventId": "evt_0LjJA5OEpQDDVRQzLFz3ZO8uJEQ",
  "timestamp": "2024-01-15T10:30:05.000Z",
  "data": {
    "call": {
      "id": "call_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "from": "+15551234567",
      "to": "+15559876543",
      "fromChannel": "pstn",
      "toChannel": "pstn"
    },
    "participant": {
      "id": "part_abc123",
      "type": "phone",
      "displayName": "John Doe",
      "phoneNumber": "+15559876543",
      "joinedAt": "2024-01-15T10:30:05.000Z"
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI" }
  }
}
```

### `calls.participant_left`

Fires when a participant leaves the call. The `participant` object includes `duration` and `leftAt`.

### `calls.recording.completed`

Fires when a call recording has finished processing and a signed download URL is available.

```json icon="json" title="calls.recording.completed" theme={null}
{
  "event": "calls.recording.completed",
  "eventId": "evt_2NlLC7QGrSFFXTSBNHB5BQ0wLGS",
  "timestamp": "2024-01-15T10:33:00.000Z",
  "data": {
    "call": {
      "id": "call_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "direction": "outbound",
      "from": "+15551234567",
      "to": "+15559876543",
      "fromChannel": "pstn",
      "toChannel": "pstn"
    },
    "recording": {
      "id": "call_rec_2DbBs7GWhGvVNJGrDXr5RG0mBWI",
      "duration": 120,
      "url": "https://storage.buildwithchirp.com/recordings/call_rec_2DbBs7GWhGvVNJGrDXr5RG0mBWI.mp4?signed=...",
      "format": "mp4",
      "size": 1048576
    },
    "app": { "id": "app_2DbBs7GWhGvVNJGrDXr5RG0mBWI" }
  }
}
```

### `calls.voicemail.received`

Fires when a voicemail is left. The payload includes the audio URL and an optional transcription.

<Info>
  Recording and voicemail `url` fields are time-limited signed URLs. To access them later, use the [Recordings API](/calling/recordings#get-recording-details) to mint a fresh URL.
</Info>

***

## Full event list

| Event                                     | Category          | Trigger        | Cadence                        |
| ----------------------------------------- | ----------------- | -------------- | ------------------------------ |
| `messages.sms.received`                   | SMS Messages      | Telnyx webhook | Real-time                      |
| `messages.sms.sent`                       | SMS Messages      | Internal       | Real-time                      |
| `messages.sms.delivered`                  | SMS Messages      | Telnyx webhook | Real-time                      |
| `messages.sms.failed`                     | SMS Messages      | Telnyx webhook | Real-time                      |
| `messages.whatsapp.received`              | WhatsApp Messages | Meta webhook   | Real-time                      |
| `messages.whatsapp.sent`                  | WhatsApp Messages | Internal       | Real-time                      |
| `messages.whatsapp.delivered`             | WhatsApp Messages | Meta webhook   | Real-time                      |
| `messages.whatsapp.read`                  | WhatsApp Messages | Meta webhook   | Real-time                      |
| `messages.whatsapp.failed`                | WhatsApp Messages | Meta webhook   | Real-time                      |
| `templates.whatsapp.created`              | Templates         | Meta webhook   | Real-time                      |
| `templates.whatsapp.updated`              | Templates         | Meta webhook   | Real-time                      |
| `templates.whatsapp.deleted`              | Templates         | Meta webhook   | Real-time                      |
| `templates.whatsapp.connected`            | Templates         | Internal       | Real-time                      |
| `contacts.whatsapp.created`               | Contacts          | Internal       | Real-time                      |
| `contacts.whatsapp.updated`               | Contacts          | Internal       | Real-time                      |
| `contacts.whatsapp.deleted`               | Contacts          | Internal       | Real-time                      |
| `whatsapp.contact.preferences_updated` ✦  | Contacts          | Meta webhook   | Real-time                      |
| `whatsapp.contact.automatic_event` ✦      | Contacts          | Meta webhook   | Real-time                      |
| `groups.whatsapp.created`                 | Groups            | Meta webhook   | Real-time                      |
| `groups.whatsapp.deleted`                 | Groups            | Meta webhook   | Real-time                      |
| `groups.whatsapp.suspended`               | Groups            | Meta webhook   | Real-time                      |
| `groups.whatsapp.suspension_cleared`      | Groups            | Meta webhook   | Real-time                      |
| `groups.whatsapp.participant_added`       | Groups            | Meta webhook   | Real-time                      |
| `groups.whatsapp.participant_removed`     | Groups            | Meta webhook   | Real-time                      |
| `groups.whatsapp.participant_left`        | Groups            | Meta webhook   | Real-time                      |
| `groups.whatsapp.join_request_created`    | Groups            | Meta webhook   | Real-time                      |
| `groups.whatsapp.join_request_revoked`    | Groups            | Meta webhook   | Real-time                      |
| `groups.whatsapp.settings_updated`        | Groups            | Meta webhook   | Real-time                      |
| `whatsapp.account.connected`              | Account           | Internal       | Real-time                      |
| `whatsapp.account.disconnected`           | Account           | Internal       | Real-time                      |
| `whatsapp.account.alert_raised` ✦         | Account           | Meta webhook   | Real-time                      |
| `whatsapp.waba.review_updated` ✦          | WABA              | Meta webhook   | Real-time                      |
| `whatsapp.waba.capability_changed` ✦      | WABA              | Meta webhook   | Real-time                      |
| `whatsapp.phone_number.name_updated` ✦    | Phone Numbers     | Meta webhook   | Real-time                      |
| `whatsapp.phone_number.quality_changed` ✦ | Phone Numbers     | Meta webhook   | Real-time                      |
| `whatsapp.phone_number.security_event` ✦  | Phone Numbers     | Meta webhook   | Real-time                      |
| `whatsapp.phone_number.deregistered` ✦    | Phone Numbers     | Poll           | ≤15 min (active) / ≤6 h (idle) |
| `whatsapp.partner_solution.updated` ✦     | Partner & Payment | Meta webhook   | Real-time                      |
| `whatsapp.payment_config.updated` ✦       | Partner & Payment | Meta webhook   | Real-time                      |
| `calls.initiated`                         | Calling           | Internal       | Real-time                      |
| `calls.ringing`                           | Calling           | Internal       | Real-time                      |
| `calls.answered`                          | Calling           | Internal       | Real-time                      |
| `calls.completed`                         | Calling           | Internal       | Real-time                      |
| `calls.failed`                            | Calling           | Internal       | Real-time                      |
| `calls.no_answer`                         | Calling           | Internal       | Real-time                      |
| `calls.participant_joined`                | Calling           | LiveKit        | Real-time                      |
| `calls.participant_left`                  | Calling           | LiveKit        | Real-time                      |
| `calls.recording.completed`               | Calling           | LiveKit        | Near real-time                 |
| `calls.voicemail.received`                | Calling           | Internal       | Real-time                      |

✦ New events — must be explicitly added to your webhook's `events` array to receive.
