# Webhooks

**Webhooks** are a mechanism that allows one system to automatically send real-time data to another system when a specific event happens. Instead of repeatedly asking a server whether something changed (polling), a webhook lets the server push updates instantly. In the WhatsApp Business API, webhooks are core infrastructure, not optional.&#x20;

A valid Webhook URL is required to receive messages. The WhatsApp Business Platform sends notifications to this URL whenever an event occurs. The platform detects the event, collects the relevant data, and immediately sends a notification payload.

Webhook notifications contain three primary objects:

* **messages** – sent when a new inbound message is received, including message content.
* **statuses** – sent when the status of a previously sent message changes.
* **errors** – sent when operational or delivery issues occur outside normal message flow.

### Webhook Delivery Behaviour

Webhook notifications are delivered in real time and must be acknowledged by the receiving server.

A notification is considered successfully delivered when the Webhook URL returns an `HTTP 200 OK`  response within **5 seconds**. Any other response, or failure to respond in time, is treated as a failed delivery and added to a retry queue.

Meta retries failed webhooks for up to **7 days** using exponential backoff. Poor webhook performance can therefore delay message processing.

A production Webhook URL must support HTTPS and use a valid SSL certificate.

### Webhook Performance Requirements

Webhook infrastructure must be sized according to messaging throughput. Sending a single outbound message can generate multiple callbacks, typically sent, delivered, and read events.

Webhook servers should be able to process approximately three times the outbound message volume as status notifications, in addition to inbound message traffic.

Recommended capacity:

* Handle **3× outgoing message traffic** as status callbacks.
* Handle **1× incoming message traffic** as inbound message callbacks.

Example:

If sending 1,000 messages per second with a 30% reply rate:

* Up to 3,000 status webhooks per second
* Approximately 300 inbound message webhooks per second

Latency targets:

* Median latency should not exceed 250 ms.
* Less than 1 percent of requests should exceed one second.

Webhook handlers should acknowledge requests immediately and process payloads asynchronously. Business logic should not run before returning the `HTTP 200 OK` response, as this increases retry risk and queue buildup.

For stable operation, webhook services should respond as quickly as possible, support parallel request handling, and minimise network latency. Hosting webhook infrastructure geographically closer to 360dialog data centres in Central or Eastern Europe can improve performance.

{% hint style="warning" %}
**Only use asynchronous handling of webhooks**

Do not process incoming messages and notifications in the webhook handler;  acknowledge immediately after receiving the webhook (with status 200), then process the data.
{% endhint %}

## Message Statuses

Message status updates are delivered through the `statuses` webhook object and reflect delivery progress between businesses and WhatsApp users.

<table><thead><tr><th width="111.22216796875">Status</th><th>Description</th></tr></thead><tbody><tr><td><code>sent</code> </td><td><p></p><p>Indicates the message was successfully sent from Meta servers.</p><ul><li>WhatsApp UI equivalent: One checkmark.</li></ul></td></tr><tr><td><code>delivered</code> </td><td><p></p><p>Indicates message was successfully delivered to the WhatsApp user’s device.</p><ul><li>WhatsApp UI equivalent: Two checkmarks.</li></ul></td></tr><tr><td><code>read</code> </td><td><p></p><p>Indicates the message was displayed in an open chat thread in the WhatsApp user’s device.</p><ul><li>WhatsApp UI equivalent: Two blue checkmarks.</li></ul></td></tr><tr><td><code>failed</code></td><td><p></p><p>Indicates failure to send or deliver the message to the WhatsApp user’s device.</p><ul><li>WhatsApp UI equivalent: Red error triangle.</li></ul></td></tr><tr><td><code>played</code> </td><td><p></p><p>Indicates the first time a voice message is played by the WhatsApp user’s device.</p><ul><li>WhatsApp UI equivalent: Blue microphone.</li></ul></td></tr></tbody></table>

## Marking Messages as Read

To mark a message as read, send a request using the message ID received in the inbound webhook notification.

<mark style="color:orange;">`POST`</mark> `/messages`

**Headers**

| Name          | Value              |
| ------------- | ------------------ |
| Content-Type  | `application/json` |
| Authorization | `D360-API-KEY`     |

**Body Example**

```json
{
  "messaging_product": "whatsapp",
  "status": "read",
  "message_id": "<WHATSAPP_MESSAGE_ID>"
}
```

**Response**

{% tabs %}
{% tab title="200" %}

```json
{ "success": true }
```

{% endtab %}
{% endtabs %}

## Webhook URL Configuration

The Webhook URL defines where event notifications are delivered. It only needs to be configured once but can be updated or removed at any time in the [360dialog Hub UI](https://docs.360dialog.com/docs/hub/webhook-url) or [using the API.](https://docs.360dialog.com/docs/messaging-api/api-reference/webhooks)

Webhooks can be configured at two levels: phone number level or WhatsApp Business Account (WABA) level.

Webhook URLs must follow domain validation rules. Domain names cannot contain underscores or explicit ports.

Invalid examples:

```
https://your_webhook.example.com
https://subdomain.your_webhook.example.com:3000
```

Valid examples:

```
https://yourwebhook.example.com
https://subdomain.yourwebhook.example.com
```

### Webhook Delivery Priority

Callback delivery follows this priority order:

1. Phone Number Webhook – Primary and recommended configuration. Receives webhook notifications only for events related to that specific number
2. WABA Webhook – Used if no phone number webhook exists. Receives notifications for all numbers associated with the WABA.
3. No Webhook Configured – Callbacks return empty responses.

### Set Webhook URL with Basic Auth&#x20;

If the webhook URL should be authorized by user, `USER` and `PASS` should be provided in the header `Authorization` that contains `Basic base64(USER:PASS)`.&#x20;

Request body example for USER=`testuser` and PASS=`testpass`

{% tabs %}
{% tab title="Body" %}

```javascript
{
  "url": "https://www.example.com/webhook",
  "headers": {
    "Authorization": "Basic dGVzdHVzZXI6dGVzdHBhc3M="
  }
}
```

{% endtab %}
{% endtabs %}
