> ## Documentation Index
> Fetch the complete documentation index at: https://docs.whatabot.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Receive real-time notifications when your flow sends messages or performs actions.

## Overview

When a session processes a message, whatabot sends a `POST` request to the **callback URL** configured on your API Key. This is how your system receives the bot's responses — text messages, media, interactive menus, transfers, and session finalization.

## Configuration

The webhook URL is set per **API Key** via the `callbackUrl` field. See [Create API Key](/en/api-reference/api-keys/create-api-key) or [Update API Key](/en/api-reference/api-keys/update-api-key).

<Warning>
  The callback URL must use **HTTPS** and cannot point to `localhost`, loopback
  addresses, or private IP ranges (10.x.x.x, 192.168.x.x, etc.).
</Warning>

## Payload Structure

Every webhook is a `POST` request with the following JSON body:

```json theme={null}
{
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "messageId": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
  "changes": [
    {
      "field": "messages",
      "value": {
        "messages": [
          {
            "type": "text",
            "text": {
              "body": "Hello! How can I help you today?"
            }
          },
          {
            "type": "interactive",
            "interactive": {
              "type": "button",
              "body": { "text": "Choose an option:" },
              "action": {
                "buttons": [
                  { "id": "btn-1", "title": "Track Order" },
                  { "id": "btn-2", "title": "Talk to Agent" }
                ]
              }
            }
          }
        ]
      }
    },
    {
      "field": "function",
      "value": {
        "functions": [
          {
            "type": "transfer",
            "targetType": "sector",
            "targetId": "sector-uuid",
            "timestamp": 1745039000123456
          }
        ]
      }
    },
    {
      "field": "event",
      "value": {
        "events": [
          {
            "domain": "kanban",
            "type": "card.stage.changed",
            "payload": {
              "cardId": "card-uuid",
              "pipelineId": "pipeline-uuid",
              "stageId": "new-stage-uuid",
              "previousStageId": "old-stage-uuid"
            },
            "timestamp": 1745039000234567
          }
        ]
      }
    }
  ]
}
```

### Top-level Fields

| Field       | Type   | Description                                                                        |
| ----------- | ------ | ---------------------------------------------------------------------------------- |
| `sessionId` | string | UUID of the session.                                                               |
| `messageId` | string | UUID of the inbound message that triggered this flow step.                         |
| `changes`   | array  | One or more changes produced by the flow. Each change has a `field` and a `value`. |

### The `changes` Array

The `changes` array tells your system **what happened** during this flow step. There are three possible change types:

| `field`      | When it appears                                    | What `value` contains                                    |
| ------------ | -------------------------------------------------- | -------------------------------------------------------- |
| `"messages"` | The flow produced messages to send to the user.    | `{ "messages": [...] }` — an array of outgoing messages. |
| `"function"` | The flow triggered an action (transfer or finish). | `{ "functions": [...] }` — an array of function calls.   |
| `"event"`    | The flow emitted domain events (e.g., kanban).     | `{ "events": [...] }` — an array of domain events.       |

A single webhook can contain **multiple** change types — for example, when a node sends a message, transfers the conversation, and emits a kanban event in the same step.

***

## Message Types

When `field` is `"messages"`, the `value.messages` array contains one or more messages. Each message has a `type` that determines its structure.

All messages may contain an optional `tags` field (`string[]`) with the tags configured on the flow node that produced the message. Use tags to categorize or route messages in your system.

### Text

A plain text message.

```json theme={null}
{
  "type": "text",
  "tags": ["orders"],
  "text": {
    "body": "Your order #12345 has been shipped!"
  }
}
```

| Field       | Type       | Description                                  |
| ----------- | ---------- | -------------------------------------------- |
| `text.body` | string     | The text content.                            |
| `tags`      | string\[]? | Tags configured on the flow node (optional). |

### Media

A file attachment (image, video, audio, document, or sticker).

```json theme={null}
{
  "type": "media",
  "tags": ["catalog"],
  "media": {
    "type": "image",
    "mimeType": "image/png",
    "url": "https://example.com/catalog.png",
    "caption": "Our latest catalog"
  }
}
```

| Field            | Type       | Description                                          |
| ---------------- | ---------- | ---------------------------------------------------- |
| `media.type`     | string     | `image`, `video`, `audio`, `document`, or `sticker`. |
| `media.mimeType` | string     | MIME type (e.g., `image/png`, `application/pdf`).    |
| `media.url`      | string     | Public URL of the file.                              |
| `media.caption`  | string?    | Optional text displayed with the media.              |
| `tags`           | string\[]? | Tags configured on the flow node (optional).         |

### Template

A pre-approved WhatsApp message template.

```json theme={null}
{
  "type": "template",
  "tags": ["welcome"],
  "template": {
    "id": "welcome_message",
    "params": ["John", "12345"]
  }
}
```

| Field             | Type       | Description                                                   |
| ----------------- | ---------- | ------------------------------------------------------------- |
| `template.id`     | string     | ID of the template registered in WhatsApp Business.           |
| `template.params` | string\[]  | Interpolated parameters in the order defined by the template. |
| `tags`            | string\[]? | Tags configured on the flow node (optional).                  |

### Interactive — Button

A message with tappable buttons (up to 3).

```json theme={null}
{
  "type": "interactive",
  "tags": ["support"],
  "interactive": {
    "type": "button",
    "body": {
      "text": "How can we help you?"
    },
    "footer": {
      "text": "Choose an option"
    },
    "action": {
      "buttons": [
        { "id": "btn-1", "title": "Track Order" },
        { "id": "btn-2", "title": "New Purchase" },
        { "id": "btn-3", "title": "Talk to Agent" }
      ]
    }
  }
}
```

| Field                        | Type       | Description                                    |
| ---------------------------- | ---------- | ---------------------------------------------- |
| `interactive.type`           | string     | Always `"button"`.                             |
| `interactive.body.text`      | string     | Main message text.                             |
| `interactive.footer.text`    | string?    | Optional footer text.                          |
| `interactive.action.buttons` | array      | Array of button objects with `id` and `title`. |
| `tags`                       | string\[]? | Tags configured on the flow node (optional).   |

### Interactive — List

A scrollable list with sections and rows.

```json theme={null}
{
  "type": "interactive",
  "tags": ["menu"],
  "interactive": {
    "type": "list",
    "body": {
      "text": "Browse our departments:"
    },
    "footer": {
      "text": "Tap to see options"
    },
    "action": {
      "button": "View Departments",
      "sections": [
        {
          "title": "Sales",
          "rows": [
            {
              "id": "row-1",
              "title": "New Orders",
              "description": "Place a new order"
            },
            {
              "id": "row-2",
              "title": "Promotions",
              "description": "Current deals"
            }
          ]
        }
      ]
    }
  }
}
```

| Field                         | Type       | Description                                      |
| ----------------------------- | ---------- | ------------------------------------------------ |
| `interactive.type`            | string     | Always `"list"`.                                 |
| `interactive.body.text`       | string     | Main message text.                               |
| `interactive.footer.text`     | string?    | Optional footer text.                            |
| `interactive.action.button`   | string     | Label of the button that opens the list.         |
| `interactive.action.sections` | array      | Array of sections, each with `title` and `rows`. |
| `rows[].id`                   | string     | Row identifier.                                  |
| `rows[].title`                | string     | Row label.                                       |
| `rows[].description`          | string?    | Optional secondary text.                         |
| `tags`                        | string\[]? | Tags configured on the flow node (optional).     |

### Interactive — CTA URL

A message with a link button.

```json theme={null}
{
  "type": "interactive",
  "tags": ["website"],
  "interactive": {
    "type": "cta_url",
    "body": {
      "text": "Visit our website for more details"
    },
    "action": {
      "name": "cta_url",
      "parameters": {
        "display_text": "Open Website",
        "url": "https://example.com"
      }
    }
  }
}
```

| Field                                        | Type       | Description                                  |
| -------------------------------------------- | ---------- | -------------------------------------------- |
| `interactive.type`                           | string     | Always `"cta_url"`.                          |
| `interactive.body.text`                      | string     | Main message text.                           |
| `interactive.action.parameters.display_text` | string     | Button label.                                |
| `interactive.action.parameters.url`          | string     | URL the button opens.                        |
| `tags`                                       | string\[]? | Tags configured on the flow node (optional). |

***

## Function Types

When `field` is `"function"`, the `value.functions` array contains one or more actions triggered by the flow.

### Transfer

The conversation was transferred to a human agent or sector.

```json theme={null}
{
  "type": "transfer",
  "targetType": "sector",
  "targetId": "sector-uuid",
  "timestamp": 1745039000123456
}
```

| Field        | Type   | Description                                                     |
| ------------ | ------ | --------------------------------------------------------------- |
| `type`       | string | Always `"transfer"`.                                            |
| `targetType` | string | `"sector"` or `"agent"`.                                        |
| `targetId`   | string | UUID of the target sector or agent.                             |
| `timestamp`  | number | Microseconds since Unix epoch. Ensures collision-free ordering. |

### Finish

The session was finalized.

```json theme={null}
{
  "type": "finish",
  "timestamp": 1745039000234567
}
```

| Field       | Type   | Description                                                     |
| ----------- | ------ | --------------------------------------------------------------- |
| `type`      | string | Always `"finish"`.                                              |
| `timestamp` | number | Microseconds since Unix epoch. Ensures collision-free ordering. |

***

## Event Types

When `field` is `"event"`, the `value.events` array contains domain events emitted during flow processing. Each event has `domain`, `type`, `payload`, and `timestamp`.

### Kanban

Events emitted when the flow interacts with the kanban (Kanban Move node) or when operations are performed on cards linked to active sessions.

```json theme={null}
{
  "domain": "kanban",
  "type": "card.created",
  "payload": {
    "cardId": "card-uuid",
    "pipelineId": "pipeline-uuid",
    "stageId": "stage-uuid"
  },
  "timestamp": 1745039000345678
}
```

| `type`               | When                               |
| -------------------- | ---------------------------------- |
| `card.created`       | A card was created by the flow.    |
| `card.stage.changed` | A card was moved to another stage. |
| `card.updated`       | Card values or tags were updated.  |
| `card.deleted`       | A card was removed.                |

| Field       | Type   | Description                                                     |
| ----------- | ------ | --------------------------------------------------------------- |
| `domain`    | string | Always `"kanban"` for kanban events.                            |
| `type`      | string | Event type (see table above).                                   |
| `payload`   | object | Event-specific data (card, pipeline, stage IDs).                |
| `timestamp` | number | Microseconds since Unix epoch. Ensures collision-free ordering. |

***

## Complete Example

A typical webhook where the bot sends a greeting and presents buttons:

```json theme={null}
{
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "messageId": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
  "changes": [
    {
      "field": "messages",
      "value": {
        "messages": [
          {
            "type": "text",
            "text": {
              "body": "Welcome to Acme Store! 👋"
            }
          },
          {
            "type": "interactive",
            "interactive": {
              "type": "button",
              "body": { "text": "What would you like to do?" },
              "footer": { "text": "Select an option" },
              "action": {
                "buttons": [
                  { "id": "btn-track", "title": "Track Order" },
                  { "id": "btn-support", "title": "Talk to Support" }
                ]
              }
            }
          }
        ]
      }
    }
  ]
}
```

A webhook where the bot transfers the conversation:

```json theme={null}
{
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "messageId": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
  "changes": [
    {
      "field": "messages",
      "value": {
        "messages": [
          {
            "type": "text",
            "text": {
              "body": "Transferring you to our support team..."
            }
          }
        ]
      }
    },
    {
      "field": "function",
      "value": {
        "functions": [
          {
            "type": "transfer",
            "targetType": "sector",
            "targetId": "550e8400-e29b-41d4-a716-446655440000",
            "timestamp": 1745039000123456
          }
        ]
      }
    }
  ]
}
```

A webhook with kanban events (card created and moved during the flow):

```json theme={null}
{
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "messageId": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
  "changes": [
    {
      "field": "messages",
      "value": {
        "messages": [
          {
            "type": "text",
            "text": {
              "body": "Your order has been added to the sales pipeline."
            }
          }
        ]
      }
    },
    {
      "field": "event",
      "value": {
        "events": [
          {
            "domain": "kanban",
            "type": "card.created",
            "payload": {
              "cardId": "550e8400-e29b-41d4-a716-446655440000",
              "pipelineId": "660e8400-e29b-41d4-a716-446655440000",
              "stageId": "770e8400-e29b-41d4-a716-446655440000"
            },
            "timestamp": 1745039000345678
          },
          {
            "domain": "kanban",
            "type": "card.stage.changed",
            "payload": {
              "cardId": "550e8400-e29b-41d4-a716-446655440000",
              "pipelineId": "660e8400-e29b-41d4-a716-446655440000",
              "stageId": "880e8400-e29b-41d4-a716-446655440000",
              "previousStageId": "770e8400-e29b-41d4-a716-446655440000"
            },
            "timestamp": 1745039000456789
          }
        ]
      }
    }
  ]
}
```

***

## Delivery

| Property         | Value                                            |
| ---------------- | ------------------------------------------------ |
| **Method**       | `POST`                                           |
| **Content-Type** | `application/json`                               |
| **Timeout**      | 5 seconds per attempt                            |
| **Retries**      | 3 attempts with exponential backoff (1s, 2s, 4s) |

<Warning>
  Your endpoint must respond within **5 seconds**. After that, the request is
  considered a failure and will be retried. Make sure your server processes
  requests quickly or use queues to handle the data asynchronously.
</Warning>

<Warning>
  Your endpoint must respond with a **2xx** status code. Non-2xx responses are
  treated as failures and will be retried up to 3 times.
</Warning>
