# Meta Webhooks

> The webhook events Meta sends about your WhatsApp number - messages, statuses, templates, quality, calls, Coexistence sync, Flows - with example payloads.

Source: https://docs.theavoxai.com/whatsapp/webhooks

Meta tells Avox about everything that happens on your WhatsApp number by sending **webhook events**:
a customer's message, a delivery receipt, a template decision, a call. This page lists every event
type Avox handles, what Avox does with it, and an example of what Meta sends.

Meta sends these events to Avox, not to your server. Avox checks Meta's signature on every delivery,
stores the events, answers Meta straight away, then processes them in the order they arrived for
your Switchboard. If Meta delivers the same event twice, it's stored once. You can see every event
your account received in [Logs](https://docs.theavoxai.com/logs).

To get customers' incoming messages on your own server, turn on
[Message forwarding](https://docs.theavoxai.com/connections/webhook-override): Avox sends each new customer message there,
signed, with retries, in Avox's own forwarding format (described on that page). What reached your
server is listed on the **Received** tab of **API logs**.

## The envelope

Every event arrives as a `POST` with this outer shape. `entry[].id` is your WhatsApp Business Account
(WABA) ID, and `changes[].field` names the event type:

```json
{
  "object": "whatsapp_business_account",
  "entry": [
    {
      "id": "102290129340398",
      "changes": [
        {
          "field": "messages",
          "value": { "...": "the event itself - see each type below" }
        }
      ]
    }
  ]
}
```

One delivery can carry several entries and changes. In [Logs](https://docs.theavoxai.com/logs), Avox shows each change as its own
event, with its payload as `waba_id`, `field`, and `value`.

Examples on this page are trimmed to the fields that matter; Meta may include more. IDs and numbers are
made up.

## Event types at a glance

| Field | What it's about | What Avox does |
| --- | --- | --- |
| `messages` | Customer messages, delivery statuses, Flow responses | Fills the [Inbox](https://docs.theavoxai.com/inbox), creates contacts, updates statuses, runs [automations](https://docs.theavoxai.com/automation), saves [Flow](https://docs.theavoxai.com/flows) responses |
| `message_template_status_update` | Meta's decision on a template | Updates the template's status; emails Admins about problems |
| `phone_number_quality_update` | Quality rating and messaging limit | Adds a row to Quality history on [Health](https://docs.theavoxai.com/health) |
| `calls` | WhatsApp call events | Logs the call on [Calls](https://docs.theavoxai.com/calls) |
| `history` | Coexistence chat history import | Adds past messages to the Inbox |
| `smb_app_state_sync` | Coexistence contact sync | Creates contacts and updates their names |
| `smb_message_echoes` | Messages sent from the WhatsApp Business app | Adds them to the customer's conversation |
| `account_alerts` | Alerts about your account | Emails the Owner |
| `account_update` | Changes to your account | Emails the Owner |
| `flows` | WhatsApp Flow status changes | Updates the Flow's status; emails Admins about problems |

Every event in this table also refreshes the connection's **Last active** heartbeat on
[Health](https://docs.theavoxai.com/health). Other fields Meta may send are kept in [Logs](https://docs.theavoxai.com/logs) as they arrived.

## Messages

The `messages` field carries three different things: new customer messages, status updates for
messages you sent, and submitted Flow forms.

### A new customer message

```json
{
  "field": "messages",
  "value": {
    "messaging_product": "whatsapp",
    "metadata": {
      "display_phone_number": "15550783881",
      "phone_number_id": "106540352242922"
    },
    "contacts": [
      { "profile": { "name": "Maria Lopez" }, "wa_id": "15551234567" }
    ],
    "messages": [
      {
        "from": "15551234567",
        "id": "wamid.HBgLMTU1NTEyMzQ1NjcVAgASGBQzQTdGRDA2QzQ1MTk1NkU2NDhCRgA=",
        "timestamp": "1760090400",
        "type": "text",
        "text": { "body": "Hi! Is my order on the way?" }
      }
    ]
  }
}
```

What Avox does:

- Creates a [contact](https://docs.theavoxai.com/contacts) for the number if it's new.
- Sends it to your server, when [Message forwarding](https://docs.theavoxai.com/connections/webhook-override) is on for the
  connection.
- Adds the message to the customer's conversation in the [Inbox](https://docs.theavoxai.com/inbox), at the time Meta says it
  was sent - once, even if Meta sends it again.
- Runs any matching [automation](https://docs.theavoxai.com/automation) (keyword replies, first-message greetings, and so on).
  A message Avox has already stored never runs automations a second time.

Text messages show their text. A button or list reply, or a tap on a template's quick reply button,
shows the chosen option's text. Other types (`image`, `audio`, `video`, `document`, `location`,
`sticker`, `contacts`, and so on) show as a short label such as `[image]`.

A reply to one of your buttons looks like this:

```json
{
  "from": "15551234567",
  "id": "wamid.HBgLMTU1NTEyMzQ1NjcVAgASGBQ0RkE3MTI0QjY4MjU4NTlGMUIA",
  "timestamp": "1760090460",
  "type": "interactive",
  "interactive": {
    "type": "button_reply",
    "button_reply": { "id": "track_order", "title": "Track my order" }
  }
}
```

### A delivery status

When a message you sent changes status, Meta sends a `statuses` entry. Its `id` matches the message
you sent:

```json
{
  "field": "messages",
  "value": {
    "messaging_product": "whatsapp",
    "metadata": {
      "display_phone_number": "15550783881",
      "phone_number_id": "106540352242922"
    },
    "statuses": [
      {
        "id": "wamid.HBgLMTU1NTEyMzQ1NjcVAgARGBI5QTNDQTVCM0Q0Q0Q2RTY3RTcA",
        "status": "delivered",
        "timestamp": "1760090520",
        "recipient_id": "15551234567"
      }
    ]
  }
}
```

`status` moves through `sent`, `delivered`, and `read`, or becomes `failed` (with an `errors` list -
see [Meta error codes](https://docs.theavoxai.com/meta-error-codes)). Avox updates the message, and the new status shows in the
Inbox and on the delivery charts on [Overview](https://docs.theavoxai.com/overview), [Analytics](https://docs.theavoxai.com/analytics), and
[Health](https://docs.theavoxai.com/health).

### A submitted Flow

When a customer completes a [WhatsApp Flow](https://docs.theavoxai.com/whatsapp/flows), the answers arrive as an `nfm_reply`.
`response_json` is a JSON string of the form's fields:

```json
{
  "from": "15551234567",
  "id": "wamid.HBgLMTU1NTEyMzQ1NjcVAgASGBQ2QkU5RkQ0RTkyMzU5RDdDNTQA",
  "timestamp": "1760090600",
  "type": "interactive",
  "interactive": {
    "type": "nfm_reply",
    "nfm_reply": {
      "name": "flow",
      "body": "Sent",
      "response_json": "{\"flow_token\":\"booking-123\",\"date\":\"2026-10-14\",\"time\":\"10:30\"}"
    }
  }
}
```

Avox saves it as a Flow response, linked to the contact. It counts toward **Responses (30d)** on
[Overview](https://docs.theavoxai.com/overview). To work with a Flow's answers live on your own server, give the Flow a data
endpoint - see [WhatsApp Flows](https://docs.theavoxai.com/integrations/whatsapp-flows).

## Template status updates

Sent when Meta approves, rejects, pauses, disables, or flags one of your templates:

```json
{
  "field": "message_template_status_update",
  "value": {
    "event": "REJECTED",
    "message_template_id": 1180934417063922,
    "message_template_name": "order_update",
    "message_template_language": "en_US",
    "reason": "INVALID_FORMAT"
  }
}
```

Avox updates the template's status on [Templates](https://docs.theavoxai.com/templates), including the rejection reason. For
`REJECTED`, `PAUSED`, `DISABLED`, and `FLAGGED`, every Admin also gets one email per change while
**WhatsApp account alerts** is on in [Compliance](https://docs.theavoxai.com/compliance). See [Approval](https://docs.theavoxai.com/templates/approval).

## Quality updates

Sent when your number's quality rating or messaging limit changes:

```json
{
  "field": "phone_number_quality_update",
  "value": {
    "display_phone_number": "15550783881",
    "event": "FLAGGED",
    "current_limit": "TIER_1K"
  }
}
```

Avox adds a row to **Quality history** on [Health](https://docs.theavoxai.com/health): `event` as the **Quality event** and
`current_limit` as the **Messaging tier**. A `FLAGGED` event also raises an insight on Health. See
[Quality and limits](https://docs.theavoxai.com/whatsapp/quality-and-limits).

## Calls

Sent as a WhatsApp call progresses, when [Calling](https://docs.theavoxai.com/connections/calling) is on for your number. A call
being set up:

```json
{
  "field": "calls",
  "value": {
    "messaging_product": "whatsapp",
    "metadata": {
      "display_phone_number": "15550783881",
      "phone_number_id": "106540352242922"
    },
    "calls": [
      {
        "id": "wacid.HBgLMTU1NTEyMzQ1NjcVAgARGBI2RDhGNEQ4QjM1QjQ5ODQ3QjgA",
        "from": "15551234567",
        "to": "15550783881",
        "event": "connect",
        "timestamp": "1760090700",
        "direction": "USER_INITIATED"
      }
    ]
  }
}
```

And when it ends, with the duration in seconds:

```json
{
  "id": "wacid.HBgLMTU1NTEyMzQ1NjcVAgARGBI2RDhGNEQ4QjM1QjQ5ODQ3QjgA",
  "from": "15551234567",
  "to": "15550783881",
  "event": "terminate",
  "timestamp": "1760090834",
  "direction": "USER_INITIATED",
  "status": "COMPLETED",
  "duration": 134
}
```

Avox logs each event on [Calls](https://docs.theavoxai.com/calls) - `connect` as **Connected**, `terminate` as **Ended** with its
duration - and creates a contact for a new caller. `direction` decides whether the call is shown as
**Inbound** (`USER_INITIATED`) or **Outbound** (`BUSINESS_INITIATED`). See
[Calling on WhatsApp](https://docs.theavoxai.com/whatsapp/calling).

## Chat history import

With a [Coexistence](https://docs.theavoxai.com/connections/coexistence) connection, if you chose to share your chat history
during signup, Meta sends it in batches shortly after you connect:

```json
{
  "field": "history",
  "value": {
    "messaging_product": "whatsapp",
    "metadata": {
      "display_phone_number": "15550783881",
      "phone_number_id": "106540352242922"
    },
    "history": [
      {
        "metadata": { "phase": 0, "chunk_order": 1, "progress": 40 },
        "threads": [
          {
            "id": "15551234567",
            "messages": [
              {
                "from": "15551234567",
                "id": "wamid.HBgLMTU1NTEyMzQ1NjcVAgASGBQ3MjBFQkY3QjJENTU4NUQ2QzQA",
                "timestamp": "1757412000",
                "type": "text",
                "text": { "body": "Do you deliver on Sundays?" }
              }
            ]
          }
        ]
      }
    ]
  }
}
```

Avox adds the past messages to each customer's conversation in the [Inbox](https://docs.theavoxai.com/inbox), once each, at
the time they were really sent. Both sides of each chat come in: the customer's messages and the
replies your team sent from the app. Imported history is past activity, so automations stay quiet
for it.

## Contact sync

With a Coexistence connection, Meta syncs the WhatsApp Business app's contacts:

```json
{
  "field": "smb_app_state_sync",
  "value": {
    "messaging_product": "whatsapp",
    "metadata": {
      "display_phone_number": "15550783881",
      "phone_number_id": "106540352242922"
    },
    "state_sync": [
      {
        "type": "contact",
        "action": "add",
        "contact": {
          "full_name": "Maria Lopez",
          "first_name": "Maria",
          "phone_number": "15551234567"
        },
        "metadata": { "timestamp": "1760090900" }
      }
    ]
  }
}
```

For an `add` (Meta also sends `add` when a contact is edited), Avox creates the contact if it's new
and uses the contact's full name as its name in [Contacts](https://docs.theavoxai.com/contacts). A `remove` only means the
contact left the phone's address book, so Avox keeps the contact and its history.

## Messages sent from the phone app

With a Coexistence connection, when your team sends a message from the WhatsApp Business app, Meta
sends a copy so Avox can show it:

```json
{
  "field": "smb_message_echoes",
  "value": {
    "messaging_product": "whatsapp",
    "metadata": {
      "display_phone_number": "15550783881",
      "phone_number_id": "106540352242922"
    },
    "message_echoes": [
      {
        "from": "15550783881",
        "to": "15551234567",
        "id": "wamid.HBgLMTU1NTEyMzQ1NjcVAgARGBJBRjNCMjE5RDlFNkU0QzE4NzMA",
        "timestamp": "1760091000",
        "type": "text",
        "text": { "body": "Yes - it arrives tomorrow morning." }
      }
    ]
  }
}
```

Avox adds the message to the customer's conversation in the [Inbox](https://docs.theavoxai.com/inbox), so the whole team sees
replies sent from the phone.

## Account alerts and updates

Meta sends `account_alerts` and `account_update` when something about your WhatsApp Business Account
needs attention or has changed - for example a review decision or a policy issue:

```json
{
  "field": "account_update",
  "value": {
    "phone_number": "15550783881",
    "event": "ACCOUNT_VIOLATION",
    "violation_info": { "violation_type": "SCAM" }
  }
}
```

Avox emails the Switchboard's Owner (its first Admin) a summary with a link to
[Connections](https://docs.theavoxai.com/connections), at most once a week for the same alert. These emails follow **WhatsApp
account alerts** on [Compliance](https://docs.theavoxai.com/compliance).

## Flow status changes

Sent when one of your published [Flows](https://docs.theavoxai.com/flows) changes status:

```json
{
  "field": "flows",
  "value": {
    "event": "FLOW_STATUS_CHANGE",
    "message": "Flow Webhook Status changed",
    "flow_id": "1032761984725371",
    "old_status": "PUBLISHED",
    "new_status": "THROTTLED"
  }
}
```

Avox updates the Flow's status on [Flows](https://docs.theavoxai.com/flows), including when it recovers to `PUBLISHED`. For
`BLOCKED`, `THROTTLED`, and `DEPRECATED`, every Admin also gets an email (unless **WhatsApp account alerts** is off). Other `flows` events, such as endpoint performance alerts, are kept in
[Logs](https://docs.theavoxai.com/logs). See [Flows on WhatsApp](https://docs.theavoxai.com/whatsapp/flows).

## Good practice for your own webhook receiver

Avox follows these rules for Meta's events, and they work just as well for the messages
[Message forwarding](https://docs.theavoxai.com/connections/webhook-override) sends to your server:

- Answer every `POST` with a `2xx` straight away, then do the slow work.
- Expect the same message more than once and skip repeats using its id (Meta's `wamid`, or the
  event id on a forwarded message).
- Check the request really came from the sender - Meta signs its events, and Avox signs forwarded
  messages with your signing secret.
- Ignore fields and event types you don't use - new ones get added over time.
