> ## 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

> Receba notificações em tempo real quando seu fluxo envia mensagens ou executa ações.

## Visão geral

Quando uma sessão processa uma mensagem, o whatabot envia uma requisição `POST` para a **URL de callback** configurada na sua Chave de API. É assim que seu sistema recebe as respostas do bot — mensagens de texto, mídia, menus interativos, transferências e finalização de sessão.

## Configuração

A URL do webhook é definida por **Chave de API** através do campo `callbackUrl`. Consulte [Criar Chave de API](/api-reference/api-keys/create-api-key) ou [Atualizar Chave de API](/api-reference/api-keys/update-api-key).

<Warning>
  A URL de callback deve usar **HTTPS** e não pode apontar para `localhost`,
  endereços de loopback ou faixas de IP privadas (10.x.x.x, 192.168.x.x, etc.).
</Warning>

## Estrutura do Payload

Todo webhook é uma requisição `POST` com o seguinte corpo JSON:

```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
          }
        ]
      }
    }
  ]
}
```

### Campos de Nível Superior

| Campo       | Tipo   | Descrição                                                                             |
| ----------- | ------ | ------------------------------------------------------------------------------------- |
| `sessionId` | string | UUID da sessão.                                                                       |
| `messageId` | string | UUID da mensagem de entrada que disparou esta etapa do fluxo.                         |
| `changes`   | array  | Uma ou mais mudanças produzidas pelo fluxo. Cada mudança tem um `field` e um `value`. |

### O Array `changes`

O array `changes` informa ao seu sistema **o que aconteceu** durante esta etapa do fluxo. Existem três tipos possíveis de mudança:

| `field`      | Quando aparece                                            | O que `value` contém                                       |
| ------------ | --------------------------------------------------------- | ---------------------------------------------------------- |
| `"messages"` | O fluxo produziu mensagens para enviar ao usuário.        | `{ "messages": [...] }` — um array de mensagens de saída.  |
| `"function"` | O fluxo disparou uma ação (transferência ou finalização). | `{ "functions": [...] }` — um array de chamadas de função. |
| `"event"`    | O fluxo emitiu eventos de domínio (ex: kanban).           | `{ "events": [...] }` — um array de eventos de domínio.    |

Um único webhook pode conter **múltiplos** tipos de mudança — por exemplo, quando um nó envia uma mensagem, transfere a conversa e emite um evento kanban na mesma etapa.

***

## Tipos de Mensagem

Quando `field` é `"messages"`, o array `value.messages` contém uma ou mais mensagens. Cada mensagem tem um `type` que determina sua estrutura.

Todas as mensagens podem conter um campo opcional `tags` (`string[]`) com as tags configuradas no nó do fluxo que gerou a mensagem. Use as tags para categorizar ou rotear mensagens no seu sistema.

### Texto

Uma mensagem de texto simples.

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

| Campo       | Tipo       | Descrição                                    |
| ----------- | ---------- | -------------------------------------------- |
| `text.body` | string     | O conteúdo de texto.                         |
| `tags`      | string\[]? | Tags configuradas no nó do fluxo (opcional). |

### Mídia

Um anexo de arquivo (imagem, vídeo, áudio, documento ou sticker).

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

| Campo            | Tipo       | Descrição                                           |
| ---------------- | ---------- | --------------------------------------------------- |
| `media.type`     | string     | `image`, `video`, `audio`, `document` ou `sticker`. |
| `media.mimeType` | string     | Tipo MIME (ex: `image/png`, `application/pdf`).     |
| `media.url`      | string     | URL pública do arquivo.                             |
| `media.caption`  | string?    | Texto opcional exibido com a mídia.                 |
| `tags`           | string\[]? | Tags configuradas no nó do fluxo (opcional).        |

### Template

Uma mensagem de template (modelo pré-aprovado pelo WhatsApp).

```json theme={null}
{
  "type": "template",
  "tags": ["boas-vindas"],
  "template": {
    "id": "welcome_message",
    "params": ["João", "12345"]
  }
}
```

| Campo             | Tipo       | Descrição                                                |
| ----------------- | ---------- | -------------------------------------------------------- |
| `template.id`     | string     | ID do template cadastrado no WhatsApp Business.          |
| `template.params` | string\[]  | Parâmetros interpolados na ordem definida pelo template. |
| `tags`            | string\[]? | Tags configuradas no nó do fluxo (opcional).             |

### Interativo — Botão

Uma mensagem com botões clicáveis (até 3).

```json theme={null}
{
  "type": "interactive",
  "tags": ["atendimento"],
  "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" }
      ]
    }
  }
}
```

| Campo                        | Tipo       | Descrição                                     |
| ---------------------------- | ---------- | --------------------------------------------- |
| `interactive.type`           | string     | Sempre `"button"`.                            |
| `interactive.body.text`      | string     | Texto principal da mensagem.                  |
| `interactive.footer.text`    | string?    | Texto opcional do rodapé.                     |
| `interactive.action.buttons` | array      | Array de objetos de botão com `id` e `title`. |
| `tags`                       | string\[]? | Tags configuradas no nó do fluxo (opcional).  |

### Interativo — Lista

Uma lista rolável com seções e linhas.

```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"
            }
          ]
        }
      ]
    }
  }
}
```

| Campo                         | Tipo       | Descrição                                       |
| ----------------------------- | ---------- | ----------------------------------------------- |
| `interactive.type`            | string     | Sempre `"list"`.                                |
| `interactive.body.text`       | string     | Texto principal da mensagem.                    |
| `interactive.footer.text`     | string?    | Texto opcional do rodapé.                       |
| `interactive.action.button`   | string     | Rótulo do botão que abre a lista.               |
| `interactive.action.sections` | array      | Array de seções, cada uma com `title` e `rows`. |
| `rows[].id`                   | string     | Identificador da linha.                         |
| `rows[].title`                | string     | Rótulo da linha.                                |
| `rows[].description`          | string?    | Texto secundário opcional.                      |
| `tags`                        | string\[]? | Tags configuradas no nó do fluxo (opcional).    |

### Interativo — CTA URL

Uma mensagem com um botão de link.

```json theme={null}
{
  "type": "interactive",
  "tags": ["site"],
  "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"
      }
    }
  }
}
```

| Campo                                        | Tipo       | Descrição                                    |
| -------------------------------------------- | ---------- | -------------------------------------------- |
| `interactive.type`                           | string     | Sempre `"cta_url"`.                          |
| `interactive.body.text`                      | string     | Texto principal da mensagem.                 |
| `interactive.action.parameters.display_text` | string     | Rótulo do botão.                             |
| `interactive.action.parameters.url`          | string     | URL que o botão abre.                        |
| `tags`                                       | string\[]? | Tags configuradas no nó do fluxo (opcional). |

***

## Tipos de Função

Quando `field` é `"function"`, o array `value.functions` contém uma ou mais ações disparadas pelo fluxo.

### Transferência

A conversa foi transferida para um agente humano ou setor.

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

| Campo        | Tipo   | Descrição                                                         |
| ------------ | ------ | ----------------------------------------------------------------- |
| `type`       | string | Sempre `"transfer"`.                                              |
| `targetType` | string | `"sector"` ou `"agent"`.                                          |
| `targetId`   | string | UUID do setor ou agente de destino.                               |
| `timestamp`  | number | Microssegundos desde o epoch Unix. Garante ordenação sem colisão. |

### Finalização

A sessão foi finalizada.

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

| Campo       | Tipo   | Descrição                                                         |
| ----------- | ------ | ----------------------------------------------------------------- |
| `type`      | string | Sempre `"finish"`.                                                |
| `timestamp` | number | Microssegundos desde o epoch Unix. Garante ordenação sem colisão. |

***

## Tipos de Evento

Quando `field` é `"event"`, o array `value.events` contém eventos de domínio emitidos durante o processamento do fluxo. Cada evento tem `domain`, `type`, `payload` e `timestamp`.

### Kanban

Eventos emitidos quando o fluxo interage com o kanban (nó Kanban Move) ou quando operações são feitas em cards vinculados a sessões ativas.

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

| `type`               | Quando                                        |
| -------------------- | --------------------------------------------- |
| `card.created`       | Um card foi criado pelo fluxo.                |
| `card.stage.changed` | Um card foi movido para outro estágio.        |
| `card.updated`       | Valores ou tags de um card foram atualizados. |
| `card.deleted`       | Um card foi removido.                         |

| Campo       | Tipo   | Descrição                                                         |
| ----------- | ------ | ----------------------------------------------------------------- |
| `domain`    | string | Sempre `"kanban"` para eventos de kanban.                         |
| `type`      | string | Tipo do evento (ver tabela acima).                                |
| `payload`   | object | Dados específicos do evento (IDs do card, pipeline, estágio).     |
| `timestamp` | number | Microssegundos desde o epoch Unix. Garante ordenação sem colisão. |

***

## Exemplo Completo

Um webhook típico onde o bot envia uma saudação e apresenta botões:

```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" }
                ]
              }
            }
          }
        ]
      }
    }
  ]
}
```

Um webhook onde o bot transfere a conversa:

```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
          }
        ]
      }
    }
  ]
}
```

Um webhook com evento kanban (card criado e movido durante o fluxo):

```json theme={null}
{
  "sessionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "messageId": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
  "changes": [
    {
      "field": "messages",
      "value": {
        "messages": [
          {
            "type": "text",
            "text": {
              "body": "Seu pedido foi registrado no pipeline de vendas."
            }
          }
        ]
      }
    },
    {
      "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
          }
        ]
      }
    }
  ]
}
```

***

## Entrega

| Propriedade      | Valor                                             |
| ---------------- | ------------------------------------------------- |
| **Método**       | `POST`                                            |
| **Content-Type** | `application/json`                                |
| **Timeout**      | 5 segundos por tentativa                          |
| **Tentativas**   | 3 tentativas com backoff exponencial (1s, 2s, 4s) |

<Warning>
  Seu endpoint deve responder em **no máximo 5 segundos**. Após esse tempo, a
  requisição será considerada como falha e será tentada novamente. Certifique-se
  de que o processamento no seu servidor seja rápido ou utilize filas para
  processar os dados de forma assíncrona.
</Warning>

<Warning>
  Seu endpoint deve responder com um código de status **2xx**. Respostas
  diferentes de 2xx são tratadas como falhas e serão tentadas novamente até 3
  vezes.
</Warning>
