Webhooks are user-defined HTTP callbacks that are triggered by specific events. Whenever that trigger event occurs, the WhatsApp Business API client sees the event, collects the data, and immediately sends a notification (HTTP request) to the Webhook URL specified in the application settings updating the status of sent messages or indicating when you receive a message.

This document covers:

When a customer sends you a message, the WhatsApp Business API client will send an HTTP POST request notification to the Webhook URL with the details that are described in the following documents:

It is important that your Webhook returns an HTTPS 200 OK response to notifications. Otherwise the WhatsApp Business API client will consider that notification as failed and try again after a delay.


To deploy a live Webhook that can receive Webhook events from the WhatsApp Business API, your code must have the following:

  • HTTPS support
  • A valid SSL certificate

For information about uploading and retrieving Webhooks CA Certificate, see the Certificates documentation.

Configure Notifications Settings

Following the instructions in the Application Settings documentation, configure the following settings for Webhooks notifications:

  • webhooks: Provide the URL for your Webhook. REQUIRED when you are using Webhooks. If the Webhook URL is not set, then callbacks will be dropped. See the Sample Testing App for a simple way to see and test your Webhooks.
    Note: You can validate Webhook events by specifying a shared secret as a query parameter when you set the Webhook URL. Example: https://url?auth='[shared_secret]'.
  • sent_status: Specify if you want to receive notifications when a message is received by the server. By default, these notifications are set to off.
  • callback_persist: Select whether to store callbacks on disk until they are successfully acknowledged by the Webhook or not. Notifications that are not successful (no HTTPS 200 response) are retried indefinitely. Use this setting to configure the retry.

Sample Testing App

One way to see the messages sent to your Webhook is to create a cross-platform runtime environment (node.js) and run a server-side JavaScript application (server.js) to implement endpoint handler code to parse the JSON format. The handler will route inbound and outbound message notifications to your Webhook.

You can use any tool of your choosing to see your Webhook in action. We have provided a sample node.js application created in Glitch that you can replicate. Upon "remixing" the project, you will have a new project that uses Express to expose Webhook endpoints that the WhatsApp Business API Client can send to. Follow the steps below to see this in action!

  1. Click this Remix on Glitch button:
    Remix on Glitch
  2. Once the project is created, the URL will be in the form of https://<project-name>.glitch.me (or simply click Show App at the top to navigate to the URL).
  3. Select server.js in the left navigation pane to see the Webhook endpoint implementation.
  4. Click on the Status button in the left navigation pane. You will see that your app is listening on a specific port.
  5. Use the Application Settings to set the Webhook URL to point to your newly created project (Step 2 above). Append /webhook to the project URL as that is the endpoint being exposed (i.e., https://<project-name.glitch.me/webhook).
  6. Send a message or send yourself a test message to see the notification. The following example of the log shows a received text message with a body of "Hi" and a sent message with updated status of sent, then delivered, then read.
    Incoming webhook: {"messages":[{"from":"1234567890","id":"ABGGhSkIc2B_Ago-sDy5BNm-1gI5","text":{"body":"Hi"},"timestamp":"1529381066","type":"text"}]}
    Incoming webhook: {"statuses":[{"id":"gBGGhSkIc2B_AgkXDygfSDwgG5s","recipient_id":"1234567890","status":"sent","timestamp":"1529381072"}]}
    Incoming webhook: {"statuses":[{"id":"gBGGhSkIc2B_AgkXDygfSDwgG5s","recipient_id":"1234567890","status":"delivered","timestamp":"1529381072"}]}
    Incoming webhook: {"statuses":[{"id":"gBGGhSkIc2B_AgkXDygfSDwgG5s","recipient_id":"1234567890","status":"read","timestamp":"1529381076"}]}

General Format of a Webhook

A Webhook will have a top level array field indicating what is being communicated. The members of the array will be JSON objects with detailed fields relevant to the Webhook.

NameObject contents


Inbound message notifications


Message status updates


Serious out-of-band errors

Wherever possible names are kept constant across functions. For example, all timestamps are called timestamp.

Format of the Notifications Webhook

All possible fields of the notifications webhook are shown below. As discussed in the Sample Testing App, you will create a endpoint handler that is triggered by the sending or receiving of a message. As detailed above, full documentation is available here for the two main webhooks: inbound notifications and message statuses. See below for errors.

  "contacts": [ {
    "profile": {
        "name": "sender-profile-name"
    "wa_id": "wa-id-of-contact"
  } ],
  "messages": [
    "context": {
         "from": "sender-wa-id-of-context-message",
         "id": "message-id-of-context-message",
         "mentions": [ "wa-id1", "wa-id2" ],
         "forwarded": true | false,
         "frequently_forwarded": true | false
    "from": "sender-wa-id",
    "id": "message-id",
    "timestamp": "message-timestamp",
    "type": "audio | document | image | location | system | text | video | voice",

    # If there are any errors the errors field (array) will be present.
    # The errors field can be returned as part of any callback event.
    "errors": [ { ... } ],
    "audio": {
        "file": "absolute-filepath-on-coreapp",
        "id": "media-id",
        "link": "link-to-audio-file",
        "mime_type": "media-mime-type",
         "sha256": "checksum"

    "document": {
        "file": "absolute-filepath-on-coreapp",
        "id": "media-id",
        "link": "link-to-document-file",
        "mime_type": "media-mime-type",
        "sha256": "checksum",
        "caption": "document-caption"

    "image": {
        "file": "absolute-filepath-on-coreapp",
        "id": "media-id",
        "link": "link-to-image-file",
        "mime_type": "media-mime-type",
        "sha256": "checksum",
        "caption": "image-caption"

    "location": {
        "address": "1 Hacker Way, Menlo Park, CA, 94025",    
        "latitude": latitude,
        "longitude": longitude,
        "name": "location-name"
    "system": {
        "body": "system-message-content"
    "text": {
        "body": "text-message-content"

    "video": {
        "file": "absolute-filepath-on-coreapp",
        "id": "media-id",
        "link": "link-to-video-file",
        "mime_type": "media-mime-type",
        "sha256": "checksum"
    "voice": {
        "file": "absolute-filepath-on-coreapp",
        "id": "media-id",
        "link": "link-to-audio-file",
        "mime_type": "media-mime-type",
        "sha256": "checksum"

Notifications Errors

When there are any out-of-band errors that occur in the normal operation of the application, the errors array will provide a description of the error. This type of error can be caused by transient network connectivity errors, invalid credentials, management controllers in unavailable status, etc. See Errors and Status Messages for more information on any errors you receive.



    "errors": [ {
       "code": <error-code>,
       "title": "<error-title>",
       "details": "<error-description>",
       "href": "location for error detail"

The errors Object

The errors object contains the following parameters:

Field NameDescriptionType


Error code



Error title



Optional. Error details provided, if available/applicable



Optional. Location for error detail.



If a Webhook event isn't delivered for any reason (e.g., the client is offline) or if the Webhook request returns a HTTP status code other than 200, we will retry the webhook delivery. We will continue retrying delivery with increasing delays up to a certain timeout (typically 24 hours, though this may vary), or until the delivery succeeds.

The WhatsApp Business API Client sends the Webhook callbacks to you via the Coreapp container. Therefore, your Webhook endpoint needs to be configured to accept inbound requests from the Coreapp.

If a Webhook fails to send a callback, the callback is put into a retry queue. Any callbacks sent after the initial callback failure will not be received. It is only after the initial failed callback succeeds that the rest will follow.

Duplicates messages can be sent to a WhatsApp Webhook as the only guarantee provided is that messages will be received at least once (as opposed to exactly once). If this is affecting how messages are processed on your end, then we suggest dedup-ing Webhook messages based on the message ID.

Double-check your pass_through application setting. You won't receive any read status callbacks if you have enabled pass_through with WhatsApp Business API client v2.29.1 or higher.

If you'd like to receive the read status callback, disable the pass_through application setting. Note that by disabling pass_through, your database storage could grow quickly. See the Database Management documentation for more information on managing your database.