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

# Real-Time Webhooks: Message Events from Pilot Status

> Pilot Status sends webhooks to your URL within milliseconds of message events. Learn the event types, payload structure, and how to verify and handle them.

Webhooks deliver real-time events to your URL as JSON `POST` requests. You configure webhooks per number on the **Webhooks** page in the dashboard or via `POST /v1/webhooks` — see the [Receive Messages guide](/guides/receive-messages) for setup and the [Events reference](/api/webhooks/events) for full payload schemas.

## Events overview

| Group                   | Events                                                                                                                |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------- |
| Outbound status         | `message.sent`, `message.delivered`, `message.read`, `message.failed`                                                 |
| Inbound                 | `message.received`, `message.reply`, `message.group`, `message.newsletter`                                            |
| Number lifecycle        | `number.created`, `number.connected`, `number.disconnected`, `number.removed`                                         |
| Voice calls (Meta only) | `call.ringing`, `call.connected`, `call.ended`, `call.missed`, `call.permission_updated`, `calls` (raw Meta envelope) |

A webhook only fires for events in its `events` list. An **empty list dispatches nothing**; use `"*"` to subscribe to every event.

## Payload schema (v3)

Every `message.*` / `number.*` event arrives as:

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

All `data` fields are **camelCase**. Phone numbers are always **E.164 with `+`** (no device suffix, no `@s.whatsapp.net`/`@lid`). Timestamps are **ISO 8601** in a single `createdAt` field. Normalized `call.*` events are flat (no `data` wrapper).

## Correlation with the 202 response

`POST /v1/messages/send` responds `HTTP 202` with `id` and `correlationId`. Use these to tie webhooks back to your send:

| `202` field        | Webhook equivalent                                                                            |
| ------------------ | --------------------------------------------------------------------------------------------- |
| `id`               | `id` on `message.sent` / `delivered` / `read` / `failed` (same value)                         |
| `correlationId`    | Repeats on outbound status events and on `message.reply` / `message.received` when correlated |
| *(not in the 202)* | WhatsApp `messageId` — first appears on `message.sent`                                        |

On `message.reply`, `quotedMessageId` equals the `messageId` of your original `message.sent`, and `contentReplied` carries the quoted text.

<Note>
  The `message.read` event (and **Read** status in logs) only occurs when the recipient has **WhatsApp read receipts** enabled. Otherwise the lifecycle stops at `message.delivered`.
</Note>

## Delivery notes

* `number.disconnected` is emitted after a health check confirms the disconnect — not on every brief connection flap.
* With data retention off ([PII modes](/trust/data-retention)), conditional fields such as `content` may be empty; IDs and timestamps always exist.
* Events the number's provider cannot emit are silently dropped from a subscription.

## Related

* [Receive Messages guide](/guides/receive-messages)
* [Webhook Events reference](/api/webhooks/events)
* [Configure Webhooks](/api/webhooks/configure)
