---
title: Webhooks | API Docs
description: Register endpoints, verify deliveries, rotate secrets, and replay safely.
---

Register a destination with `POST /v1/webhook_endpoints`. The created response returns signing-secret material once; store it immediately in a secret manager. Endpoint reads expose configuration and health, never the secret value.

Verify every request against the exact raw body before parsing JSON. Respond quickly after durable acceptance in your system, and process asynchronously. Use the event ID as the deduplication key.

Deliveries to one endpoint and chat are sent in the order their events were recorded. A `message.received` for a message with attachments can be recorded once its attachments are captured or have failed, or ten minutes after the message arrived, so it can follow deliveries for later messages of the same chat with a lower `data.seq_from`. Never discard it as stale: deduplicate by event ID and order the chat by `data.seq_from`. See [Events and recovery → Messages with attachments](/channel/whatsapp/guides/events#messages-with-attachments/index.md).

`GET /v1/webhook_deliveries` exposes delivery attempts and outcomes. If a bounded historical range needs redelivery, create a replay under the endpoint and poll that replay’s status. Replay creation has its own idempotency key; use a stable key when retrying the same replay request.

Adding a signing secret starts a rotation window. Deploy verification for both active secrets before retiring the old one. Disabling an endpoint is a cutoff, not a pause: events produced while disabled are not silently queued for later.

## Scope an endpoint to specific numbers

By default an endpoint receives events for every number the account has now and adds later; endpoint reads report `phone_number_ids` as `null`. To narrow it, pass `phone_number_ids` on `POST /v1/webhook_endpoints` or `PATCH /v1/webhook_endpoints/{endpoint}`: up to 100 exact ids from `GET /v1/phone_numbers` (see the [phone numbers guide](/channel/whatsapp/guides/phone-numbers/index.md)). The endpoint then receives only the chat events of those numbers. Account-wide events that carry no phone number reach only unscoped endpoints, so keep one unscoped endpoint if you need them.

An id the account cannot use — unknown, another account’s, the other mode’s, or not an active number of this account — is refused with HTTP `422` and `error.code` [1041](/channel/whatsapp/error/codes/1xxx/1041/index.md). The pointer is the list, `/phone_number_ids`, never the id, so a refusal does not say whose number it is; only a malformed id (empty, or over 128 bytes) is pointered at its own index, `/phone_number_ids/{i}`. Either way nothing is created or changed.

An update replaces the list outright; an empty array restores every current and future number. The change affects only events fanned out after the update: deliveries already queued keep their destination, and a replay accepted earlier keeps the scope it was accepted under. Field details are on the [create](/channel/whatsapp/api/resources/webhook_endpoints/methods/create/index.md) and [update](/channel/whatsapp/api/resources/webhook_endpoints/methods/update/index.md) reference pages.
