> For the complete documentation index, see [llms.txt](https://docs.360dialog.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.360dialog.com/docs/mba/webhooks.md).

# Webhooks

Webhooks are how you follow what happens on a number running Meta Business Agent — the customer's messages, the agent's replies, control changes, and delivery receipts. This page explains what you'll receive and how MBA conversations map to webhook fields.

## Webhook setup is handled for you

**You don't need to set anything up to receive MBA events.** They're delivered to the same 360dialog webhook you already use for your number's messages, signed with `x-360dialog-signature`. You'll receive three fields:

* **`messages`** — consumer messages that arrive while **you** hold the conversation.
* **`standby`** — the **agent's** conversation: consumer messages *and* the agent's replies while **the agent** holds the conversation.
* **`messaging_handovers`** — fired whenever control of a conversation changes between the agent and you.

You just need to handle these fields on your existing webhook — see how they map to conversations below.

## How conversations map to fields

When your agent is enabled it is the **primary responder** and holds the conversation by default. Which field a consumer's message arrives on depends on who holds control at that moment:

| Who holds control                | Consumer message arrives on | Agent replies arrive on       |
| -------------------------------- | --------------------------- | ----------------------------- |
| **The agent** (default)          | `standby`                   | `standby` (as message echoes) |
| **You** (after you take control) | `messages`                  | n/a — you send them           |

You **take control** simply by sending a message to the conversation. To hand control **back** to the agent, use the [Thread Control  `release` action](/docs/mba/api-ref/operate/release-thread-control.md). Every control change also produces a [`messaging_handovers` event](#the-messaging_handovers-payload).

## The `standby` payload

The `standby` field uses the standard WhatsApp webhook envelope. Inside `value.standby` you get the full agent conversation:

* **`standby.messages[]`** — the consumer's inbound messages.
* **`standby.message_echoes[]`** — the agent's replies. These are **bizai-tagged**: `message.biz_opaque_callback_data` contains `{"originator":"bizai", ...}`, which is how you tell an agent-generated message apart from your own.

Route on the phone number using `value.metadata.phone_number_id` (or the WABA id at `entry[].id`).

**Consumer inbound** (`standby.messages[]`):

```json
{
  "object": "whatsapp_business_account",
  "entry": [{ "id": "<WABA_ID>", "changes": [{
    "field": "standby",
    "value": {
      "messaging_product": "whatsapp",
      "metadata": { "display_phone_number": "551146733503", "phone_number_id": "<PHONE_NUMBER_ID>" },
      "standby": {
        "contacts": [{ "profile": { "name": "Grzegorz G" }, "wa_id": "48883042025" }],
        "messages": [{
          "from": "48883042025",
          "id": "wamid...",
          "timestamp": "1784107832",
          "text": { "body": "Do you repair ebikes?" },
          "type": "text"
        }]
      }
    }
  }]}]
}
```

**Agent reply** (same `standby` field, `standby.message_echoes[]`):

```json
{
  "object": "whatsapp_business_account",
  "entry": [{ "id": "<WABA_ID>", "changes": [{
    "field": "standby",
    "value": {
      "messaging_product": "whatsapp",
      "metadata": { "display_phone_number": "551146733503", "phone_number_id": "<PHONE_NUMBER_ID>" },
      "standby": {
        "message_echoes": [{
          "id": "wamid...",
          "timestamp": "1784296217",
          "message": {
            "to": "34680989836",
            "type": "text",
            "biz_opaque_callback_data": {
              "originator":"bizai",
              "channel":"ent"
            },
            "text": { "body": "I'm sorry, but we don't offer bike rentals at Pedala Bikes. ..." }
          }
        }]
      }
    }
  }]}]
}
```

{% hint style="success" %}

## Where `standby` is delivered

**The agent's conversation now arrives on your number's own webhook.** Meta delivers `standby` only to a single account-wide destination, so 360dialog routes each number's `standby` events to that number's webhook and re-signs them with `x-360dialog-signature`. You validate them with your existing webhook secret — nothing to configure on your side.

This means you now receive the full agent conversation over webhooks: consumer inbound (`standby.messages[]`), agent replies (`standby.message_echoes[]`), `messaging_handovers`, and `bizai`-tagged delivery statuses. You can build monitoring and logging on top of it.
{% endhint %}

## The `messaging_handovers` payload

A `messaging_handovers` event fires whenever control of a conversation changes. Use it to know when the agent has handed a conversation to you (or vice versa).

The key fields: `value.type` describes what happened (e.g. `control_passed`), and `value.control_passed.previous_owner_app_role` tells you who held control before the change. When that role is **`meta_business_agent`**, the agent has just passed control to you — your side is now responsible for the conversation. `value.sender.phone_number` is the consumer, and `value.recipient.phone_number_id` identifies your number.

```json
{
  "object": "whatsapp_business_account",
  "entry": [{ "id": "<WABA_ID>", "changes": [{
    "field": "messaging_handovers",
    "value": {
      "messaging_product": "whatsapp",
      "recipient": { "display_phone_number": "551146733503", "phone_number_id": "<PHONE_NUMBER_ID>" },
      "sender": { "phone_number": "34680989836" },
      "timestamp": "1784296293",
      "type": "control_passed",
      "control_passed": {
        "previous_owner_app_role": "meta_business_agent",
        "metadata": "unknown"
      }
    }
  }]}]
}
```

## Signature validation

MBA webhooks 360dialog forwards to you are signed exactly like your normal message callbacks — with the **`x-360dialog-signature`** header. Validate them with your existing webhook secret; no new secret or verification path is needed.

## Delivery receipts

Delivery and read receipts for the agent's messages are **bizai-tagged** (the same `originator: bizai` marker). They arrive on your webhook already, so you can track delivery of agent messages without any extra setup.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.360dialog.com/docs/mba/webhooks.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
