Receiving messages

This documentation describes how to setup webhooks for the WhatsApp Business API.

If you are using On-Premise API, remember that it is being discontinued by Meta. No new signups will be allowed with this type of integration from May 15, 2024.

Numbers registered before this date will still be supported, but should start planning a change of hosting type as soon as possible.

Webhooks is a mechanism which enables applications to communicate with each other programmatically. It allows you to send real-time data from one application to another whenever a given event occurs. You can use the webhook to determine which endpoint we should forward the real-time data (aka Notifications). Whenever a specific event occurs, the WhatsApp Business API Client sees the event, collects the data, and immediately sends a notification (user-defined HTTP callbacks) to the webhook URL specified.

There are 3 main objects you can receive via webhooks:

  • messages: Used to notify you when you get a new message and what is in the new message.

  • statuses: Used to notify you when there's a status change in a message you sent.

  • errors: When there are any out-of-band errors that occur in the normal operation of the application, this array provides a description of the error.

Webhook Response Requirements

Ensure your webhook servers can handle 3x the outgoing message traffic capacity and 1x the expected incoming message traffic capacity. For example, if you're sending 1000 messages per second with a 30% expected response rate, your servers should process up to 3000 message status webhooks and an additional 300 incoming message webhooks. See more information about throughput here.

Configure and load test your webhook server to handle concurrent requests with the following latency standards:

  • Median latency should not exceed 250ms.

  • Less than 1% of latency should exceed 1 second.

The API will attempt to re-deliver failed webhooks for up to 7 days with exponential backoff. Failure to meet these guidelines may result in delays in processing incoming messages due to the exponential backoff mechanism.

For a Webhook Notification to be considered by WhatsApp to be 'successfully delivered', ensure that your Webhook URL returns an HTTPS 200 OK response to notifications.

If any other status code is returned, or if the client fails to correctly set up the endpoint to accept Notifications, the WhatsApp Business API Client considers it to be a 'failed delivery' and adds the Notification to its callback queue. 360dialog also has a hard limit rule of 5 seconds for the client to return a 200 status code, after which it will register as a failed delivery.

To deploy a live webhook that can receive events from the WhatsApp Business API client, your code must have HTTPS support and a valid SSL certificate.

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 you can process the data.

All incoming messages will automatically show as delivered (two grey ticks). To make them appear as read (two colored ticks), you have to mark the messages as read.

Recommendations

For stable functioning of WABA it is recommended make the webhook performance as fast as possible. That means:

  • Design your service to respond as quickly, and as close to your network speed as possible.

  • Respond with a 200 status code immediately after receiving a notification and storing it. The callback's payload should not be processed before responding as this can lead to unacceptable delays; instead, send the response first then (asynchronously) process the payload.

  • Reduce network latency by setting up your webhook server closer to 360dialog's datacenters (Central and Eastern Europe).

  • Sending one message as opposed to getting one causes up to three callback notifications (sent, delivered and read). It means that the speed of processing concurrent requests should increases in accordance with the load of the number. In addition to a direct increase in the speed of processing notifications, we recommend to make your webhook process as many parallel requests as possible. Otherwise, this can lead to the occurrence and overflow of the message queue.

Set Webhook URL

The webhook URL is a resource address to which the WhatsApp Servers sends notifications, which are triggered by specific events. A suitable webhook URL must be supplied by you or by your Partner Software Provider / ISV.

You only need to set your Webhook URL once. Although you can update it or remove it at any time.

If you generate a new API-KEY, the webhook URL for that number will be removed. So you must reset it using the new API-KEY.

Example setting webhook with Basic Auth:

If the webhook URL needs to be authorized by user, USER and PASS should be provided in the header Authorization that contains Basic base64(USER:PASS).

Request body example for USER=testuser and PASS=testpass

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

Set Webhook URL for phone number

Previously, webhook for Cloud API numbers could only be configured at a WABA Level. This limitation has been lifted and, from April 2024, the Set Webhook URL for phone number endpoint can set Webhook at a phone number level, regardless of the integration type.

We recommend using this configuration to ensure the highest performance possible.

Webhook URLs or headers for Cloud API do not support "_"(underscore) or ":xxxx"(port)in (sub)domain names.

Invalid webhook URL: https://your_webhook.example.com Valid webhook URL: https://yourwebhook.example.com

Invalid webhook URL:https://subdomain.your_webhook.example.com:3000 Valid webhook URL: https://subdomain.yourwebhook.example.com

If you are still using On-premise API, webhooks are configured only at the Phone Number level. In this case, the endpoint will be https://waba.360dialog.io/v1/configs/webhook

POST https://waba-v2.360dialog.io/v1/configs/webhook

Send a POST request and store the URL from the response.

Request example

{
  "url": "string",
  "headers": {
    "header_1": "string",
    "header_2": "string"
  }
}

Headers

NameTypeDescription

Content-Type

string

application/json

D360-API-KEY

string

Request Body

NameTypeDescription

URL

string

www.example.com/webhook

{
  "url": URL,
  "headers": {
    "header_1": string,
    "header_2": string
  }
}

When Insights is used with an On-premise hosted setup, any custom headers that include UPPERCASE letters or underscores (_) will have these characters converted to lowercase letters and hyphens (-).

Examples:

curl -i -X POST \
   -H "Content-Type:application/json" \
   -H "Custom_Header_1:value1" \ //Custom header with _ and UPPERCASE
   -H "Custom_Header_2:0123456789" \
   -d \
'{}' \
 ''

Will be converted to:

curl -i -X POST \
   -H "Content-Type:application/json" \
   -H "custom-header_1:value1" \ //Custom header with - and lowercase
   -H "custom-header_2:0123456789" \
   -d \
'{}' \
 ''

Therefore, please avoid using UPPERCASE letters and underscores in webhook custom headers to prevent unintended alterations.

Set Webhook per WABA (Cloud API)

Webhooks for Cloud API can be set at the WABA level, although this configuration is not recommended since it can decrease the messaging performance of the channels.

This webhook URL will receive callbacks for all Cloud API numbers associated with that WABA, but not for any On-premise numbers on the same WABA.

POST https://waba-v2.360dialog.io/waba_webhook

Send a POST request and store the URL from the response.

Request example

curl --location 'https://waba-v2.360dialog.io/waba_webhook' \
--header 'Content-Type: application/json' \
--header 'D360-API-KEY: ' \
--data '{
    "url": "string",
    "headers": {
        "header_1": "string"
    },
    "override_all": "boolean"
}'

When this endpoint is used with the override_all parameter set to false, it configures the supplied webhook for Cloud API numbers missing a specific phone number webhook setting. If override_all is true, the webhook applies across all Cloud API numbers within the WABA.

Headers

NameTypeDescription

Content-Type

string

application/json

D360-API-KEY

string

Request Body

NameTypeDescription

URL*

string

www.example.com/webhook

headers*

string

override_all

boolean

Optional.

Indicates if the supplied webhook should override current phone number webhooks for all phone numbers belonging the same WABA

Default value isfalse

{
    "message": "Webhook will be set for waba_id: 123065260884961"
}

>> This message means that the Webhook URL will be set within the next 15-20 seconds. 
Please confirm by fetching the current webhook URL before messaging. <<

A typical inbound notification for WABA Webhook looks like the following:

{
  "object": "whatsapp_business_account",
  "entry": [{
    "id": "WHATSAPP-BUSINESS-ACCOUNT-ID",
    "changes": [{
      "value": {
         "messaging_product": "whatsapp",
         "metadata": {
           "display_phone_number": "PHONE-NUMBER",
           "phone_number_id": "PHONE-NUMBER-ID"
         },
      # Additional arrays and objects
         "contacts": [{...}]
         "errors": [{...}]
         "messages": [{...}]
         "statuses": [{...}]
      },
      "field": "messages"
    }]
  }]
}

Components (contacts, errors, messages, statuses) are inside entry.changes.value.

Delivery prioritization

Cloud API allows configuring webhooks at a Phone Number and WABA Webhook level. For callback delivery, webhooks are prioritized as below:

  • Primary is Phone Number Webhook: This is the preferred route. If set, it overrides any other webhook configuration for callbacks.

  • Secondary is WABA Webhook: This route is used for callback delivery only if the primary phone number webhook is not configured.

  • Fallback: No Webhook Configured - If neither webhook is set, the system will return an empty response when attempting callbacks.

GET Webhook URL

GET phone number Webhook URL

If the phone number webhook URL is set, make a GET request to retrieve the existing resource.

GET https://waba-v2.360dialog.io/v1/configs/webhook

GET https://waba.360dialog.io/v1/configs/webhook

Request example

D360-API-KEY: {{api_key}}
Content-Type: application/json

Path Parameters

NameTypeDescription

Content-Type

string

application/json

D360-API-Key

string

unique API-Key

{
  "url": URL,
  "headers": {
    "header_1": string,
    "header_2": string
  }
}

GET WABA Webhook URL

Use the GET endpoint below to check the current webhook URL:

GET https://waba-v2.360dialog.io/waba_webhook

Request example

curl --location 'https://waba-v2.360dialog.io/waba_webhook'
--header 'd360-api-key:{{api-key}}'

Headers

NameTypeDescription

Content-Type

string

application/json

D360-API-KEY

string

{
    "waba_id": 123456,
    "numbers_on_this_waba": ["12345678910", "11223344"],
    "url": "URL",
    "headers": {
        "key": "HEADERS"
    }
}

Receiving notifications for incoming messages

When a customer replies, or sends a message to the business, the WhatsApp Business API client will send an HTTP POST request notification to the number webhook URL with the details described in our documentation below:

Webhook Events and Notifications

Last updated