
# Webhooks

Os webhooks permitem que o <span data-t="appName">Your AI Connector</span> notifique automaticamente as suas outras ferramentas de negócio sempre que algo importante acontece — um novo contacto criado, um agendamento marcado, uma mensagem recebida. Em vez de verificar manualmente por atualizações, os seus sistemas ligados recebem uma notificação instantânea no momento em que algo acontece.


---

## O que são Webhooks?

Pense num webhook como uma mensagem de texto automática entre duas aplicações. Quando algo acontece no <span data-t="appName">Your AI Connector</span> (como um novo contacto a registar-se), a plataforma envia instantaneamente uma notificação para outro sistema à sua escolha. Fornece um endereço web (chamado "URL de webhook") para onde estas notificações devem ser enviadas — este é normalmente fornecido pelo seu CRM, plataforma de automatização ou programador.

> **Os Webhooks apenas enviam dados PARA FORA do <span data-t="appName">Your AI Connector</span>.** Um webhook é uma via de sentido único *do* <span data-t="appName">Your AI Connector</span> *para* as suas outras ferramentas. **Não existe nenhum URL de webhook que envie leads, contactos ou mensagens PARA DENTRO da plataforma.** Para inserir uma nova lead — a partir de um formulário de site, do seu CRM ou do GoHighLevel — o seu sistema faz, em vez disso, uma **chamada de API**. Consulte [Acesso à API](api-access.md) (a operação *Criar um Contacto*) e [Funis](funnels.md). A única coisa de que necessita para a direção de entrada é a sua **chave de API**, que se encontra na sua própria secção — consulte [Acesso à API](api-access.md#generating-your-api-key). A página de **Webhooks** aqui descrita é exclusivamente para a direção de saída.

::: note
**Nota:** A configuração de webhooks envolve alguma configuração técnica. Se não se sentir à vontade com isto, partilhe esta página com o seu programador ou utilize uma plataforma de automatização como o Zapier, Make ou Pabbly, que fornecem URLs de webhook sem necessidade de programação.
:::


As utilizações comuns incluem:

- Sincronizar novos contactos com o seu CRM.
- Acionar um fluxo de trabalho no Zapier, Make ou Pabbly quando uma etiqueta é aplicada.
- Notificar a sua equipa no Slack quando um humano é alertado.
- Atualizar o seu sistema de calendário quando uma reunião é agendada.
- Registar resumos de conversas na sua base de dados.

---

## Configurar Webhooks

1. Na barra lateral esquerda, clique em **Definições** (ícone de engrenagem).
2. Na barra lateral de Definições, sob o grupo **Integrações**, clique em **Webhooks**.


Numa conta sem webhooks configurados, a página tem este aspeto:


3. Clique em **New webhook**, no canto superior direito. Abre-se um formulário na página:


4. Preencha:
   - **URL de Endpoint** — o endereço web para o qual o <span data-t="appName">Your AI Connector</span> enviará notificações de eventos. Obtém este endereço do seu sistema externo (CRM, plataforma de automatização ou servidor personalizado).
   - **Nome** — uma etiqueta que reconhecerá mais tarde (por exemplo, "Alertas Slack" ou "Sincronização CRM"). Apenas para sua referência.

> **O seu URL de webhook deve ser um endereço `https://` publicamente acessível.** Endereços `http://` simples, `localhost` ou endereços de rede privada e endereços internos da plataforma são rejeitados ao guardar. Para testar a partir da sua própria máquina, utilize um túnel público (webhook.site ou ngrok) em vez de localhost.

5. Em **Eventos**, clique nos eventos que pretende que este webhook receba — todos os 22 estão listados em [Os 22 Eventos de Webhook](#the-22-webhook-events).
6. *(Opcional)* Ative **Tentar novamente entregas falhadas** se quiser que o <span data-t="appName">Your AI Connector</span> continue a tentar em caso de falha temporária — consulte [Tentar Novamente Entregas Falhadas](#retrying-failed-deliveries).
7. Clique em **Criar webhook**. Ele aparece na lista abaixo do formulário e pode clicar em **Testar** na sua linha a qualquer momento para disparar um payload de exemplo para o seu endpoint.

> **Permissão necessária.** Adicionar, editar ou testar webhooks requer a permissão de "edição" de Integrações (os membros da equipa com permissão apenas de visualização verão um aviso de leitura apenas em vez do formulário).

> **Assinar um webhook** requer que este já tenha sido guardado primeiro — abra a linha de um webhook existente para o editar e o painel **Segredo de assinatura** aparecerá na parte inferior do formulário de edição. Um rascunho novo e não guardado ainda não tem opção de assinatura — consulte [Payloads Assinados](#signed-payloads-verifying-a-webhook-really-came-from-us) abaixo.

---

## Um Webhook para Todas as Suas Contas de Cliente (Agências)

Se gere uma agência, não precisa de recriar o mesmo webhook em cada conta de cliente. Na conta de agência, o formulário de webhook tem um botão de alternância adicional: **Também disparar para todas as contas de cliente**. Ative-o e este webhook receberá também eventos que ocorram em todas as contas de cliente sob a sua agência — um endpoint, toda a agência.

Como funciona:

- **O bloco `user` indica-lhe a que cliente pertence um evento.** Cada notificação já contém um bloco `user` que identifica a conta onde o evento ocorreu, para que a sua automatização possa encaminhar por cliente.
- **As definições do seu webhook aplicam-se a todo o lado.** Os eventos que selecionou, o segredo de assinatura e a definição de nova tentativa são também utilizados para as entregas das contas de cliente.
- **Sem entregas duplicadas.** Se uma conta de cliente tiver o seu próprio webhook a apontar para o mesmo URL, esse será utilizado para os eventos dessa conta — o mesmo evento nunca chega duas vezes ao mesmo endpoint.
- **Os clientes não o veem.** O webhook não aparece na página de Webhooks da própria conta do cliente e os clientes não o podem desativar — é da sua responsabilidade geri-lo.
- **A fiabilidade é monitorizada por conta de cliente.** Se o seu endpoint continuar a falhar, é automaticamente desativado para a conta cujas entregas falharam (consulte [Fiabilidade do Webhook](#webhook-reliability)), e não para toda a agência de uma só vez.

O botão de alternância apenas aparece em contas de agência. A sua configuração através da API também é suportada — consulte o campo `apply_to_sub_accounts` na [API de Webhooks](../api/webhooks.md#one-subscription-for-all-client-accounts-agencies).

---

## Eventos de Acionamento Disponíveis

Pode ativar ou desativar cada um dos 22 eventos de webhook de forma independente. Quando um evento é disparado, o <span data-t="appName">Your AI Connector</span> envia uma notificação para o seu URL de webhook com os dados relevantes. Cada evento, o seu significado e o código `event` que coloca no payload estão listados em conjunto em [Os 22 Eventos de Webhook](#the-22-webhook-events) mais abaixo nesta página.

> **É bom saber:** **Tarefa Criada**, **Tarefa Atualizada** e **Tarefa Concluída** são totalmente selecionáveis e guardam corretamente. **Resumo Diário Criado** é também uma adição recente. Consulte [Webhook de Tarefa Concluída](#task-completed-webhook) abaixo para ver a estrutura desse payload.

---

## Acionadores de Webhook Baseados em Etiquetas

O `subscribed_to_tags` não limita os eventos de um webhook a uma etiqueta. Apenas restringe quais as etiquetas que produzem uma notificação de resumo de conversação. Para obter um pedido quando uma etiqueta específica é aplicada, defina um URL de webhook nessa etiqueta no separador **Etiquetas** do agente (ou campanha).

O formulário de webhook em si não tem um seletor de etiquetas, nem ao criar um novo webhook nem ao editar um existente, pelo que o `subscribed_to_tags` só pode ser lido ou alterado através da [API de Webhooks](../api/webhooks.md), ou pedindo ao suporte.

> **É bom saber:** editar um webhook existente que tenha uma lista `subscribed_to_tags` (mudar o nome, alterar os eventos, alternar as tentativas) já não limpa essa lista — uma vez que o formulário não tem um seletor de etiquetas para enviar de volta, guardar a partir desta página deixa agora a lista existente intacta. (Isto era um erro real antes de **21 de julho de 2026**: guardar a partir do formulário de webhook costumava apagar a lista porque enviava sempre uma lista de etiquetas vazia. Se um webhook perdeu a sua lista `subscribed_to_tags` antes dessa data, terá de ser reconfigurado através da API.)

### Gerar Resumo para Contactos Etiquetados

Onde um webhook tem uma lista `subscribed_to_tags`, pode ativar **Gerar Resumo**. Quando ativado, o <span data-t="appName">Your AI Connector</span> gera automaticamente um resumo da conversação para o contacto quando uma dessas etiquetas é aplicada e inclui-o nos dados do webhook — contexto completo sem necessidade de um pedido separado.

---

## Testar o seu Webhook

1. Abra **Definições → Integrações → Webhooks**.
2. Na linha do seu webhook, clique em **Testar**.
3. Verifique o seu sistema externo para confirmar que recebeu os dados de teste.
4. Reveja o formato dos dados para garantir que o seu sistema os consegue analisar corretamente.

Para um teste completo de ponta a ponta, envie uma mensagem que acionaria um dos seus eventos configurados (uma difusão ou uma mensagem recebida num canal ligado) e verifique se o webhook é acionado com os dados reais.

::: tip
**Dica:** Utilize uma ferramenta como o [webhook.site](https://webhook.site) ou o [RequestBin](https://requestbin.com) durante o desenvolvimento para inspecionar os dados brutos do webhook antes de ligar o seu sistema de produção.
:::


### O que conta como uma entrega bem-sucedida

Quer clique em **Testar** ou o evento seja disparado a sério, enviamos a mesma coisa:

- Um pedido **POST** (nunca GET), com o corpo em JSON e `Content-Type: application/json`.
- Os cabeçalhos listados em [Payloads Assinados](#signed-payloads-verifying-a-webhook-really-came-from-us). Os cabeçalhos de assinatura só são incluídos depois de definir um segredo de assinatura.

Consideramos a entrega bem-sucedida quando:

- O seu endpoint responde com **qualquer estado 2xx** (200, 201, 204 — tudo serve).
- Responde **dentro de 30 segundos**.

Algumas coisas que surpreendem as pessoas:

- **O corpo da resposta é ignorado.** Não precisa de devolver qualquer JSON específico. Um 200 vazio é suficiente.
- **Os redirecionamentos contam como uma falha.** Não os seguimos, por isso um 301 ou 302 (incluindo um redirecionamento de barra final, ou de http para https) é registado como uma entrega falhada. Guarde o URL final, não um que redirecione.
- **As query strings são totalmente suportadas.** `https://your-app.com/hook?token=abc123` é enviado exatamente como o guardou, por isso colocar um token na query string funciona tão bem como colocá-lo no caminho.
- **O seu URL deve ser `https://` e publicamente acessível.** Endereços que pertencem à própria infraestrutura da <span data-t="appName">Your AI Connector</span> são rejeitados, mas os seus próprios endpoints no Google Cloud Functions, Cloud Run, App Engine, Firebase Hosting ou em qualquer outro lugar são aceites.
- **Uma firewall ou camada de proteção contra bots à frente do seu endpoint pode bloquear-nos.** O caso mais comum é o Cloudflare: se a sua zona tiver o Bot Fight Mode ou um desafio gerido ativado, o nosso pedido recebe uma página de desafio "Just a moment..." com um 403 em vez de chegar ao seu servidor — e um pedido servidor-para-servidor nunca pode passar um desafio de navegador, pelo que tanto o botão **Testar** como os eventos reais falham da mesma forma. O botão Testar dir-lhe-á quando isto estiver a acontecer ("Cloudflare is showing a bot challenge to our request"). Corrija-o no Cloudflare com uma regra de Segurança / WAF que ignore os desafios para o seu caminho de webhook (ou para o agente de utilizador `Webhook-Delivery/1.0`), e depois clique em **Testar** novamente.
- **Se a sua firewall precisar de uma lista de permissões de IP em vez disso** (por exemplo, o plano gratuito do Cloudflare, onde o Bot Fight Mode simples não pode ser ignorado por uma regra WAF, mas uma Regra de Acesso IP definida como Permitir é executada antes), podemos ajudar: cada entrega, seja a partir do botão **Testar** ou de um evento em direto, é enviada a partir de um endereço IPv4 fixo (sem intervalos, sem IPv6, sem rotação). Contacte o suporte e dar-lhe-emos o endereço para adicionar à lista de permissões. Mantenha a [verificação de assinatura](#signed-payloads-verifying-a-webhook-really-came-from-us) como a sua verificação de confiança real, uma vez que valida cada payload independentemente de onde veio.
- **O resultado do Teste diz-lhe exatamente o que o seu endpoint respondeu.** Um teste falhado mostra agora a razão real (o estado HTTP que o seu endpoint devolveu, um tempo limite, ou que não conseguimos chegar ao endereço de todo) em vez de um erro genérico, e um teste num webhook guardado é enviado assinado quando a assinatura está ativada, exatamente como um evento em direto.

### Utilizar o n8n, Make ou Zapier ("Test URL" vs "Production URL")

As plataformas de automação fornecem normalmente dois endereços de webhook diferentes, e isto causa confusão:

- Um **URL de Teste** (no n8n contém `/webhook-test/`). Este apenas recebe dados enquanto estiver a observar ativamente o canvas e tiver acabado de clicar em **Ouvir evento de teste** (ou **Testar fluxo de trabalho**). Captura um único evento e depois para de ouvir — por isso, clicar em **Testar** no <span data-t="appName">Your AI Connector</span> várias vezes seguidas apenas apanha o primeiro, e apenas se a janela de escuta estiver ativa nesse preciso momento. Para testar: clique primeiro em **Ouvir evento de teste** no n8n, depois volte ao <span data-t="appName">Your AI Connector</span> e clique em **Testar** uma vez.
- Um **URL de Produção** (no n8n contém `/webhook/`, sem `-test`). Este é o que deve colar no <span data-t="appName">Your AI Connector</span> para eventos em direto. Só funciona quando o seu fluxo de trabalho estiver definido como **Ativo**. Se o fluxo de trabalho não estiver ativo, o n8n rejeita o pedido com um erro "404 / webhook not registered", mesmo que o <span data-t="appName">Your AI Connector</span> tenha enviado os dados corretamente.

Em resumo: teste com o URL de Teste enquanto ouve, mas para que o webhook continue a funcionar com contactos reais, guarde o **URL de Produção** no <span data-t="appName">Your AI Connector</span> e certifique-se de que o fluxo de trabalho está **Active**.

---

## Formato de Dados do Webhook

Quando um webhook é disparado, o <span data-t="appName">Your AI Connector</span> envia dados estruturados (JSON) para o seu URL de webhook. Se estiver a utilizar uma plataforma de automatização como o Zapier ou o Make, esta analisa estes dados automaticamente por si. Se estiver a criar uma integração personalizada:

```json
{
  "event": "contactCreated",
  "contact": { "id": "<contact-id>", "first_name": "Jane", "...": "..." },
  "campaign": { "id": "<campaign-id>", "name": "AI Receptionist", "status": "Live" },
  "agent": { "id": "<agent-id>", "name": "Front Desk" },
  "user": { "id": "<account-id>", "email": "owner@example.com" }
}
```

| Campo | Descrição |
|---|---|
| `event` | A string exata do evento que disparou a notificação (por exemplo, `contactCreated`, `booked`). Este **não** é o rótulo de visualização mostrado na lista de eventos; cada rótulo e o seu código correspondente encontram-se em [Os 22 Eventos de Webhook](#the-22-webhook-events). |
| `contact` | O contacto a que o evento se refere, ou `null` para eventos não ligados a um contacto (como `creditsRecharged`). |
| `campaign` | A campanha a que o contacto pertence, ou `null` se não existir nenhuma. |
| `agent` | O agente que gere a conversação, ou `null` se não existir nenhum. |
| `user` | Informações básicas de identidade da conta que detém os dados. |

> **`campaign` ou `agent` — normalmente um, não ambos.** Se a sua conta utiliza agentes, os seus contactos estão associados a um agente em vez de a uma campanha, pelo que `campaign` chega como `null` e `agent` indica-lhe qual deles tratou do assunto. As contas mais antigas baseadas em campanhas veem o inverso. Leia o campo que estiver preenchido; não assuma que `campaign` está sempre presente.

> **O bloco `agent` chegou a 15 de agosto de 2026.** Situa-se ao lado de `campaign` nos eventos ligados a uma conversação — um chat concluído, não incomodar, uma retoma, um desarquivamento, uma pausa de IA, uma nova mensagem, um resumo de conversação e o webhook que pode definir numa etiqueta — e transporta o `id` e `name` do agente responsável, ou `null` quando não está envolvido nenhum agente. É puramente aditivo: todos os campos que já recebe permanecem inalterados, pelo que um recetor que tenha criado antes dessa data continuará a funcionar sem necessidade de atualizações.

Alguns eventos adicionam o seu próprio bloco de nível superior extra. Por exemplo, **Appointment Booked** (Marcação Agendada) adiciona um bloco `appointment` (ver [Webhook de Marcação Agendada](#appointment-booked-webhook)), **New Message** (Nova Mensagem) adiciona um bloco `message` completo com o texto (ver [Webhook de Nova Mensagem](#new-message-webhook)), e **Deliveries** (Entregas) e **Reads** (Leituras) adicionam um bloco `message` curto apenas com o ID e o estado da mensagem (ver [Webhook de Entregas e Leituras](#deliveries-and-reads-webhook)).

> **As Entregas e Leituras indicam-lhe qual a mensagem, mas não o seu conteúdo.** Contêm um bloco `message` com o `id` e o `status` da mensagem — e esse `id` é o mesmo `messageId` que o [endpoint de envio de mensagem](../api/messages.md#send-a-message) devolve, para que possa fazer corresponder um recibo de entrega ou leitura à mensagem exata que enviou — mas não contêm o corpo da mensagem. **Replies** (Respostas) não contém qualquer bloco `message`. Se precisar das palavras que foram enviadas ou recebidas, subscreva **New Message** (Nova Mensagem) em conjunto com estes.

> **Duas coisas a saber antes de escrever o seu recetor.** Não existe um campo `timestamp`, nem um wrapper `data`. Cada bloco situa-se ao nível superior do objeto JSON, como mostrado acima.

### Os 22 Eventos de Webhook

Os 22 eventos de webhook, com o rótulo de visualização que seleciona na aplicação e o código `event` enviado no payload. O código `event` é uma string curta que **não** corresponde ao rótulo de visualização, por isso configure o seu recetor com base no código, não no rótulo:

| Etiqueta de visualização (na aplicação) | Código `event` no payload | O que significa |
|---|---|---|
| Contact Created | `contactCreated` | Um novo contacto é adicionado à sua conta (manualmente, via importação ou via API). |
| Contact Paused | `contact_paused` | Uma conversação com um contacto é pausada (o bot deixa de responder). |
| Contact Resumed | `contact_resumed` | Uma conversação com um contacto pausada é retomada. |
| Contact Do Not Disturb | `contact_do_not_disturb_changed` | A definição de Não Incomodar de um contacto é ativada. |
| Contact Unarchived | `contact_unarchived` | Um contacto arquivado envia uma nova mensagem, trazendo-o de volta para a sua caixa de entrada ativa. |
| New Message | `new_message` | Qualquer mensagem é adicionada a uma conversação em qualquer canal — tanto as mensagens que o seu contacto lhe envia como as mensagens que a sua IA ou a sua equipa lhe enviam. Este é o único evento que contém o texto real da mensagem (ver [Webhook de Nova Mensagem](#new-message-webhook)). |
| Replies | `replied` | Um contacto responde a uma mensagem. |
| Reads | `read` | Um contacto lê uma mensagem (em canais que suportam recibos de leitura). Contém o ID da mensagem que foi lida — ver [Webhook de Entregas e Leituras](#deliveries-and-reads-webhook). |
| Deliveries | `delivered` ou `undelivered` | Uma mensagem é entregue com sucesso a um contacto (`undelivered` quando a entrega falha). Contém o ID da mensagem — ver [Webhook de Entregas e Leituras](#deliveries-and-reads-webhook). |
| Human Alerted | `humanAlerted` | O bot de IA determina que não consegue gerir uma conversação e sinaliza-a para atenção humana. |
| Chat Concluded | `chat_concluded` | O bot de IA decide que uma conversação chegou ao fim (marcação feita, lead desqualificado, etc.). |
| Appointment Booked | `booked` | Um contacto marca uma reunião através do sistema de marcações. |
| Credits Spent | `creditsSpent` | São deduzidos créditos da sua conta. |
| Credits Recharged | `creditsRecharged` | São adicionados créditos à sua conta via recarga automática ou compra manual. |
| Low Credit Balance | `lowCreditBalance` num envio de **Teste**, `Low Credit Balance` num real | Um aviso prévio de que o seu saldo de créditos caiu abaixo do seu limite de alerta (100 créditos, a menos que defina o seu próprio). Destinado a agências, cujas subcontas gastam todas a partir de um fundo comum. Contém `balance`, `threshold` e `account_email` em vez de um bloco de contacto, é enviado no máximo uma vez a cada 24 horas enquanto o saldo se mantiver baixo, e reativa-se assim que o saldo volta a subir acima do limite. |
| Task Created | `taskCreated` | Uma tarefa é criada. |
| Task Updated | `taskUpdated` | Uma tarefa é alterada sem passar para uma fase de conclusão. |
| Task Completed | `taskCompleted` | Uma tarefa passa para uma fase configurada como fase de conclusão. |
| Daily Summary Created | `dailySummaryCreated` | O seu relatório de resumo diário é gerado. |
| Channel Connected | `channelConnected` | **Ainda não enviado — selecionável, mas nada o emite hoje. Não desenvolva com base nisto.** Destinado a quando um canal de mensagens termina a ligação. |
| Broadcast Started | `broadcastStarted` | Uma transmissão começa a ser enviada (o seu estado muda para Sending). Dispara uma vez por início, incluindo quando uma transmissão pausada é retomada. Contém um bloco `broadcast` em vez de um bloco de contacto: id, nome, canal, estado, estado anterior, a lista a que se destina (`list_id`, `list_name`, `is_smart_list`), `scheduled_at`, `total_contacts`. |
| Broadcast Completed | `broadcastCompleted` | Uma transmissão termina (o seu estado muda para Sent ou Failed). O mesmo bloco `broadcast` mais `completed_at` e, quando disponível, `completion_summary` (`total_sent`, `permanently_failed`, `unique_replied`, `failure_rate`, `had_errors`). Utilize estes dois para ligar uma Lista de Transmissão Inteligente a ferramentas externas. |

Dois outros códigos nunca aparecem nessa lista porque não subscreve esses eventos: `contact_tags_updated`, enviado por um URL de webhook definido numa etiqueta individual, e `summary_generated`, enviado quando um resumo de chat é escrito para uma etiqueta na lista `subscribed_to_tags` de um webhook.

> **Canal Ligado ainda não é enviado.** Aparece na lista de eventos, mas nada o emite atualmente. Não desenvolva com base nele.

As notificações baseadas em etiquetas e tarefas utilizam as suas próprias formas separadas. Consulte [Etiquetas de Contacto Atualizadas](#contact-tags-updated-webhook) e [Tarefa Concluída](#task-completed-webhook).

---

## Webhook de Contacto Criado

Enviado quando o evento **Contacto Criado** é acionado (um novo contacto é adicionado manualmente, via importação ou via API).

### Nome do evento

`contactCreated`

### Formato do payload

```json
{
  "event": "contactCreated",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null,
    "is_bot_active": true,
    "ad_referral": null
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  }
}
```

| Campo | Descrição |
|---|---|
| `event` | Sempre `contactCreated` para este evento. |
| `contact.id` | O ID único do novo contacto. |
| `contact.email` / `contact.phone_number` | O e-mail e telefone do contacto, se conhecidos (qualquer um pode estar vazio dependendo do canal). |
| `contact.first_name` / `contact.last_name` | O nome do contacto, se conhecido. |
| `contact.human_alerted` / `contact.human_alert_reason` | Se o contacto está sinalizado para atenção humana, e porquê. |
| `contact.is_bot_active` | Se o bot de IA está atualmente ativo neste contacto. |
| `contact.ad_referral` | Atribuição de anúncio Meta Click-to-WhatsApp, ou `null` — consulte [Atribuição de Anúncios Click-to-WhatsApp](click-to-whatsapp-attribution.md). |
| `campaign` | A campanha sob a qual o contacto foi criado, ou `null`. |
| `agent` | O agente atribuído ao contacto, ou `null`. |
| `user` | Informações básicas de identidade da conta proprietária do contacto. |

> **A amostra de "Teste" e um evento real parecem ligeiramente diferentes.** O botão de teste envia dados de marcador de posição (John Doe, uma campanha de amostra). Um evento real de Contacto Criado transporta os detalhes reais do contacto, e alguns campos podem estar vazios dependendo do canal.

---

## Webhook de Nova Mensagem

Este webhook é disparado sempre que uma mensagem é adicionada a uma conversa, em qualquer canal. Abrange ambas as direções: mensagens que o seu contacto lhe envia e mensagens que a sua IA, a sua equipa ou uma campanha lhe envia. É o único webhook que inclui o texto da mensagem, por isso é o que deve utilizar quando pretende espelhar conversas num sistema externo.

### Nome do evento

`new_message`

### Formato do payload

```json
{
  "event": "new_message",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null,
    "is_bot_active": true,
    "ad_referral": null
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<message-id>",
    "body": "Hi, are you open on Saturday?",
    "direction": "inbound",
    "status": "received",
    "created_at": "2026-07-30T17:27:06.000Z",
    "channel": "whatsapp_web"
  }
}
```

| Campo | Descrição |
|---|---|
| `event` | Sempre `new_message` para este evento. Note que esta é a string exata enviada — não é a etiqueta de visualização "New Message". |
| `contact` | O contacto a cuja conversação a mensagem pertence. Com a mesma forma que em [Contact Created](#contact-created-webhook). |
| `agent` | O agente que gere a conversação (`id` e `name`), ou `null` se não estiver envolvido nenhum agente. |
| `user` | Informação de identidade básica da conta que detém a conversação. |
| `message.id` | O ID único da mensagem. |
| `message.body` | O texto da mensagem. Vazio para uma mensagem que contém apenas um anexo (imagem, nota de voz, documento). |
| `message.direction` | `inbound` para uma mensagem do contacto, `outbound` para uma enviada pela sua IA ou pela sua equipa a partir da caixa de entrada, e `outbound-api` para uma enviada por uma campanha, uma transmissão, um envio de modelo ou a API. |
| `message.status` | Onde a mensagem se encontra no seu ciclo de vida: `received` para recebidas, e `queued` / `sent` / `delivered` / `read` / `failed` / `undelivered` para enviadas. Este é o estado no momento em que a mensagem foi criada, pelo que uma mensagem enviada chega aqui normalmente como `queued` ou `sent` e atinge `delivered` posteriormente — utilize os eventos **Deliveries** e **Reads** se precisar dessas transições posteriores. Contêm o mesmo `message.id` que este bloco, para que possa fazer corresponder a transição a esta mensagem (ver [Webhook de Entregas e Leituras](#deliveries-and-reads-webhook)). |
| `message.created_at` | Quando a mensagem foi criada, em UTC (ISO 8601). |
| `message.channel` | O canal pelo qual a mensagem passou, por exemplo `whatsapp`, `whatsapp_web`, `sms`, `instagram`, `messenger`, `telegram`, `email` ou `custom`. |

> **Ainda não existe um bloco `campaign` neste payload.** O New Message envia `contact`, `agent`, `user` e `message`. O bloco `agent` foi adicionado a **15 de agosto de 2026** e indica-lhe qual o agente que gere a conversação; se também precisar do contexto da campanha, procure o contacto através da API utilizando `contact.id`.

> **Os registos internos da IA não disparam este webhook.** Juntamente com as mensagens reais, a plataforma mantém as suas próprias linhas de registo numa conversa (as chamadas de ferramentas da IA e registos internos de turnos). Essas nunca são enviadas — apenas recebe mensagens que foram genuinamente enviadas ou recebidas.

---

## Webhook de Entregas e Leituras

Estes dois eventos reportam o que aconteceu a uma mensagem depois de ter saído de <span data-t="appName">Your AI Connector</span>: **Deliveries** (Entregas) dispara quando uma mensagem chega ao contacto (ou falha ao chegar), e **Reads** (Leituras) dispara quando o contacto a abre, nos canais que suportam recibos de leitura.

Ambos contêm um bloco `message` com o ID da mensagem a que o evento se refere, para que possa fazer corresponder a atualização à mensagem exata que enviou.

### Nomes de eventos

`delivered` e `undelivered` para **Deliveries** (Entregas), `read` para **Reads** (Leituras).

### Formato do payload

```json
{
  "event": "delivered",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "ad_referral": null
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<message-id>",
    "status": "delivered"
  }
}
```

| Campo | Descrição |
|---|---|
| `event` | `delivered` ou `undelivered` para **Deliveries** (Entregas), `read` para **Reads** (Leituras). |
| `contact` | O contacto para quem a mensagem foi enviada. |
| `campaign` | A campanha a que o contacto pertence, ou `null`. |
| `agent` | O agente que gere a conversação, ou `null`. |
| `user` | Informação de identidade básica da conta que detém os dados. |
| `message.id` | O ID da mensagem a que esta atualização se refere. É o mesmo valor que o [endpoint de envio de mensagem](../api/messages.md#send-a-message) devolve como `messageId`, e o mesmo `message.id` que uma notificação de [New Message](#new-message-webhook) contém. |
| `message.status` | O novo estado, sempre a mesma string que `event` (`delivered`, `undelivered` ou `read`). |

> **Como fazer corresponder uma atualização à mensagem que enviou.** Guarde o `messageId` que recebe quando envia uma mensagem através da API. Quando chegar uma notificação de **Deliveries** ou **Reads**, procure esse ID guardado em `message.id` no payload — esse é o seu recibo de entrega ou leitura para essa mensagem exata.

> **Não existe texto de mensagem aqui.** O bloco `message` contém apenas o ID e o estado. Subscreva [New Message](#new-message-webhook) se também precisar do corpo da mensagem.

> **O bloco `message` só está presente quando sabemos de que mensagem se tratava.** Na rara atualização que não conseguimos associar a uma mensagem guardada, o bloco é omitido em vez de ser enviado vazio — por isso, verifique se `message` existe antes de ler `message.id`.

> **Uma notificação por alteração de estado.** Uma única mensagem enviada produz normalmente uma notificação `delivered` e, depois, em canais com recibos de leitura, uma notificação `read`. Um envio falhado produz `undelivered` em vez disso.

---

## Webhook de Marcação Agendada

É acionado quando um contacto marca uma reunião. É acionado da mesma forma, quer a IA a tenha marcado durante uma conversa, quer a tenha marcado manualmente, ou tenha chegado através da API.

### Nome do evento

`booked`

### Formato do payload

```json
{
  "event": "booked",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith"
  },
  "campaign": {
    "id": "<campaign-id>",
    "name": "AI Receptionist",
    "status": "Live"
  },
  "user": {
    "id": "<account-id>",
    "email": "owner@example.com"
  },
  "appointment": {
    "appointment_id": "<appointment-id>",
    "start_time": "2026-07-20T15:00:00.000Z",
    "end_time": "2026-07-20T15:30:00.000Z",
    "status": "confirmed",
    "room_name": "Room 1",
    "description": "Discovery call",
    "summary": "30 min intro",
    "google_calendar_event_id": null,
    "event": {
      "id": "<service-id>",
      "event_name": "Intro Call",
      "slot_duration": 30,
      "location": "Zoom",
      "meeting_link": "https://...",
      "event_type": "online"
    }
  }
}
```

| Campo | Descrição |
|---|---|
| `event` | Sempre `booked` para este evento. |
| `contact` | A pessoa que efetuou a marcação. `email` e `phone_number` podem estar vazios dependendo do canal. |
| `appointment.appointment_id` | O ID único da marcação. |
| `appointment.start_time` / `end_time` | Início e fim do período marcado, em UTC (ISO 8601). |
| `appointment.status` | O estado atual da marcação. |
| `appointment.room_name` | A sala onde a marcação foi efetuada, se utilizada. |
| `appointment.description` / `summary` | Detalhes de texto livre capturados com a marcação. |
| `appointment.google_calendar_event_id` | O ID do Google Calendar para o evento sincronizado. É frequentemente `null` no webhook de Marcação Agendada, porque o evento do calendário é criado no mesmo momento em que a notificação é enviada — volte a obter a marcação pelo seu `appointment_id` um momento depois se precisar, e espere um `null` permanente em contas sem Google Calendar ligado. |
| `appointment.event` | O serviço que foi marcado: nome, duração do período, localização, link da reunião, tipo. |

> **O `google_calendar_event_id` é frequentemente `null` neste webhook, e isso é normal.** O evento do Google Calendar é criado no mesmo momento em que esta notificação é enviada, pelo que o ID geralmente ainda não está pronto. Volte a obter a marcação pelo seu `appointment_id` um momento depois, se precisar dele. Permanece `null` permanentemente se a conta não tiver um Google Calendar ligado, por isso não espere por ele indefinidamente.

> **O botão "Testar" não inclui o bloco `appointment`.** Utilize-o para confirmar que o seu endpoint responde, depois faça uma marcação real para ver o payload completo.

> **Dois casos em que este webhook não é disparado:** marcações importadas de um calendário externo e reservas que chegam através da integração Formitable.

---

## Webhook de Etiquetas de Contacto Atualizadas

É acionado quando uma etiqueta é **aplicada** a um contacto e essa etiqueta tem um URL de webhook configurado no agente ou na campanha a que o contacto pertence.

### Nome do evento

`contact_tags_updated`

### Quando é acionado

- É aplicada uma etiqueta a um contacto que tem um agente atribuído, uma campanha atribuída ou ambos.
- Pelo menos uma das etiquetas aplicadas tem um URL de webhook definido no separador Etiquetas desse agente ou campanha.

Se o contacto tiver ambos e as etiquetas da campanha tiverem URLs de webhook, esses prevalecem; caso contrário, são usados os do agente.

Se forem aplicadas várias etiquetas com URLs de webhook diferentes na mesma atualização, é enviado um pedido por URL, contendo cada um apenas as etiquetas que correspondem a esse URL.

**A remoção de uma etiqueta nunca envia um pedido.** A maioria das pessoas aponta estes URLs para uma ação — cobrar um depósito, reservar um horário, alertar um representante — pelo que uma etiqueta removida de um contacto costumava voltar a executar essa ação. Já não o pode fazer. Uma remoção continua a aparecer em `removed_tags` quando ocorre na mesma atualização que uma aplicação que vai para o mesmo URL, pelo que uma automatização que lê ambos os arrays mantém a visão completa; o que nunca verá é um pedido causado apenas por uma remoção. (Alterado a **12 de agosto de 2026**. Antes dessa data, as remoções também enviavam um pedido.)

### Formato do payload

```json
{
  "event": "contact_tags_updated",
  "contact": {
    "id": "<contact-id>",
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "is_bot_active": true,
    "ad_referral": {
      "ctwa_clid": "ARAbc123...",
      "source_id": "120210000000000",
      "source_type": "ad",
      "source_url": "https://fb.me/xxxx",
      "headline": "Get 20% off today",
      "body": "Message us now to claim your discount",
      "channel": "whatsapp"
    }
  },
  "added_tags": ["qualified-lead"],
  "removed_tags": ["new-lead"],
  "agent": {
    "id": "<agent-id>",
    "name": "Front Desk"
  },
  "user": {
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  }
}
```

| Campo | Descrição |
|---|---|
| `event` | Sempre `contact_tags_updated` para este webhook. |
| `contact.id` | O ID único do contacto cujas etiquetas foram alteradas. |
| `contact.email` / `contact.phone_number` | O e-mail/telefone do contacto, se conhecido. |
| `contact.first_name` / `contact.last_name` | O nome do contacto. |
| `contact.human_alerted` | Se o contacto está atualmente sinalizado para atenção humana. |
| `contact.is_bot_active` | Se o bot de IA está atualmente ativo na conversação deste contacto. |
| `contact.ad_referral` | Presente apenas quando o contacto o contactou pela primeira vez através de um anúncio ou publicação Meta Click-to-WhatsApp (CTWA). `null` caso contrário. |
| `added_tags` | Matriz de nomes de etiquetas aplicadas nesta atualização. Nunca vazia — uma aplicação é o que aciona o pedido. |
| `removed_tags` | Matriz de nomes de etiquetas removidas na mesma atualização, se houver. Uma remoção por si só não envia nada. |
| `agent` | O agente que gere a conversação do contacto (`id` e `name`), ou `null` se não estiver envolvido nenhum agente. Adicionado a **15 de agosto de 2026**. |
| `user` | Informações básicas de identidade da conta à qual pertence o contacto. |

### Testar um webhook de etiqueta

Junto ao campo do URL do webhook no separador Etiquetas, existe um botão **Testar**. Este envia imediatamente um payload de exemplo para esse URL, para que possa confirmar que a sua automatização o recebe antes de esperar por uma conversa real.

O teste envia a mesma estrutura `contact_tags_updated` apresentada acima, utilizando um contacto de marcador de posição, com a etiqueta que está a testar em `added_tags` e um `removed_tags` vazio. O que a sua automatização vê no teste é o que verá em produção.

Duas coisas a saber:

- **Guarde a etiqueta primeiro.** O teste procura a etiqueta pelo seu nome guardado, por isso uma etiqueta nova ou uma renomeação não guardada ainda não pode ser testada. O botão permanece cinzento até que o nome no ecrã corresponda ao guardado.
- **Um teste falhado não conta contra o seu webhook.** Os testes nunca contribuem para a desativação automática após falhas repetidas descrita em [Fiabilidade do Webhook](#webhook-reliability).

Se o teste falhar, a mensagem indica-lhe o que o seu endpoint respondeu (por exemplo, um `404` ou `500`), o que é geralmente suficiente para detetar um URL incorreto ou um fluxo de trabalho que não está ativado.

---

## Webhook de Tarefa Concluída

> **Apenas para referência.** Os webhooks de Tarefas (como dados) estão documentados aqui para programadores; os eventos **Tarefa Criada**, **Tarefa Atualizada** e **Tarefa Concluída** são selecionáveis na lista de eventos padrão no formulário de webhook como qualquer outro evento — consulte [Eventos de Disparo Disponíveis](#available-trigger-events) e [Os 22 Eventos de Webhook](#the-22-webhook-events).

Este payload é enviado quando uma tarefa transita para uma fase marcada como fase de conclusão. Uma tarefa que se mova entre fases que não sejam de conclusão envia o formato `taskUpdated` em vez disso.

### Nome do evento

`taskCompleted`

### Quando é acionado

- Uma tarefa é atualizada.
- O seu valor `stage` mudou em comparação com o valor anterior.
- A nova fase está configurada como uma fase de conclusão nas definições de fase de tarefas da conta.

### Formato do payload

```json
{
  "event": "taskCompleted",
  "contact": {
    "email": "jane@example.com",
    "phone_number": "+15551234567",
    "first_name": "Jane",
    "last_name": "Smith",
    "human_alerted": false,
    "human_alert_reason": null
  },
  "user": {
    "email": "owner@example.com",
    "first_name": "Alex",
    "last_name": "Doe"
  },
  "message": {
    "id": "<task-id>",
    "title": "Follow up with Jane",
    "description": "Confirm pricing and send proposal",
    "type": "follow_up",
    "priority": "high",
    "stage": "<stage-id>",
    "due_date": "2026-01-20T15:00:00Z",
    "source": "ai",
    "source_detail": "<source-detail>",
    "campaign_id": "<campaign-id>",
    "linked_human_alert": "<human-alert-id>",
    "tags": ["qualified-lead"],
    "notes": "Customer requested a callback"
  }
}
```

| Campo | Descrição |
|---|---|
| `event` | Sempre `taskCompleted` para este webhook. O mesmo formato de payload é enviado como `taskUpdated` quando uma tarefa muda sem entrar numa fase de conclusão. |
| `contact` | O contacto associado à tarefa, se existir. `null` quando não está associado. |
| `contact.human_alert_reason` | O motivo pelo qual o contacto foi sinalizado para atenção humana, se aplicável. |
| `user` | Informações básicas de identidade da conta à qual a tarefa pertence. |
| `message.id` | O ID único da tarefa. |
| `message.title` / `description` | O título e a descrição da tarefa. |
| `message.type` | O tipo de tarefa (por exemplo, `follow_up`, `call`, `custom`). |
| `message.priority` | A prioridade da tarefa (`low`, `medium`, `high`). |
| `message.stage` | O ID da fase em que a tarefa se encontra agora. |
| `message.due_date` | A data de conclusão da tarefa, se definida. |
| `message.source` | O que criou a tarefa (`ai`, `manual`, `api`). |
| `message.source_detail` | Detalhes adicionais sobre a origem. |
| `message.campaign_id` | O ID da campanha associada, ou `null`. |
| `message.linked_human_alert` | O ID do alerta humano associado, se existir. |
| `message.tags` | Etiquetas aplicadas à tarefa. |
| `message.notes` | Notas de formato livre sobre a tarefa. |

---

## Desativar (ou Eliminar) um Webhook

Cada webhook tem um interruptor de ligar/desligar, diretamente na sua linha. Desligar um **desativa** a receção de eventos, mas mantém tudo o que configurou — o URL, os eventos, qualquer segredo de assinatura. Volte a ligá-lo e ele retoma de onde parou; nada do que aconteceu enquanto estava desligado será entregue posteriormente.

Utilize esta opção quando pretender interromper as entregas durante algum tempo: o seu endpoint está a ser reconstruído, está a depurar uma integração ruidosa ou a pausar uma automatização.

**Eliminar** um webhook (o ícone do caixote do lixo na sua linha) remove-o permanentemente, incluindo o seu segredo de assinatura. Se apenas pretende que as entregas parem, desligue-o em vez disso — a eliminação serve para quando já não precisa do endpoint.

> **Isto não é o mesmo que um webhook ser desligado automaticamente.** Se desativarmos o seu webhook após falhas repetidas (consulte [Fiabilidade de Webhooks](#webhook-reliability)), o interruptor acima não o voltará a ativar. Assim que o seu endpoint estiver corrigido, edite o webhook e guarde-o com um URL alterado (qualquer alteração de URL reativa-o), ou chame o [endpoint de reativação](../api/webhooks.md) através da API — ou peça ao suporte e nós reativá-lo-emos por si.

---

## Payloads Assinados (Verificar se um Webhook veio realmente de nós)

Qualquer pessoa que descubra o seu URL de webhook pode enviar-lhe um pedido falso. Se atua com base em webhooks automaticamente — atualizando faturação, criando registos de CRM — ativar a **assinatura** permite-lhe verificar se cada pedido veio genuinamente da nossa parte.

A assinatura é **opcional e desativada por predefinição**, e ativa-a por webhook, a partir da vista de edição desse webhook (abra a linha de um webhook guardado).

### Ativar a assinatura

1. Abra o webhook (Definições → Integrações → Webhooks → clique na linha do seu webhook).
2. Na secção **Segredo de assinatura**, clique em **Gerar**.
3. Copie o segredo (começa com `whsec_`) e guarde-o no seu sistema recetor. Trate-o como uma palavra-passe.

Pode voltar e revelar, copiar, rodar ou desativar o segredo a qualquer momento a partir deste mesmo painel.

### O que enviamos

Assim que a assinatura estiver ativa, cada entrega para esse webhook transporta estes dois cabeçalhos HTTP adicionais:

| Cabeçalho | Significado |
|---|---|
| `X-Webhook-Signature` | A assinatura, sob a forma `v1=<hex>`. |
| `X-Webhook-Timestamp` | Quando o enviámos, como um carimbo de data/hora Unix em segundos. |

Estes três estão em **todas** as entregas, assinadas ou não:

| Cabeçalho | Significado |
|---|---|
| `X-Webhook-Delivery` | Um ID único para este evento. Mantém-se igual em todas as tentativas, por isso é o que utiliza para a desduplicação. |
| `X-Webhook-Attempt` | Qual a tentativa atual (`1` é a primeira tentativa). |
| `X-Webhook-Event` | O nome do evento, para que possa encaminhar sem ler o corpo. |

### Como verificar

A assinatura é um HMAC-SHA256 da string `<timestamp>.<raw request body>`, utilizando o seu segredo de assinatura como chave.

**Verifique contra o corpo do pedido bruto — os bytes exatos que recebeu.** Se o seu framework analisar o JSON e o voltar a serializar antes de verificar, os bytes podem mudar e a assinatura não corresponderá.

Exemplo em Node.js:

```js
const crypto = require("crypto");

function verify(rawBody, headers, secret) {
  const timestamp = headers["x-webhook-timestamp"];
  const signature = headers["x-webhook-signature"]; // "v1=<hex>"

  // Reject anything older than 5 minutes so a captured request can't be replayed later.
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;

  const expected = crypto.createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");

  return crypto.timingSafeEqual(Buffer.from(signature.replace("v1=", "")), Buffer.from(expected));
}
```

Exemplo em Python:

```python
import hashlib, hmac, time

def verify(raw_body: bytes, headers, secret: str) -> bool:
    timestamp = headers["X-Webhook-Timestamp"]
    signature = headers["X-Webhook-Signature"].replace("v1=", "")

    # Reject anything older than 5 minutes so a captured request can't be replayed later.
    if abs(time.time() - int(timestamp)) > 300:
        return False

    expected = hmac.new(secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256).hexdigest()

    return hmac.compare_digest(signature, expected)
```

> **Compare assinaturas com uma função segura contra ataques de temporização** (`timingSafeEqual` / `compare_digest`), não `==`. Não tem qualquer custo e evita uma classe subtil de ataques.

### Rotação do segredo

Clique em **Rodar** para substituir o segredo. A mudança é imediata: a entrega seguinte é assinada apenas com o novo segredo. Se o seu endpoint estiver ativo, aceite **ambos** os segredos (o antigo e o novo) durante alguns minutos enquanto implementa o novo.

Desativar a assinatura simplesmente impede o envio dos cabeçalhos de assinatura.

---

## Repetição de Entregas Falhadas

Por predefinição, uma entrega que falha não é repetida — se o seu sistema estiver em baixo nesse momento, esse evento é perdido.

Ative a opção **Tentar novamente entregas falhadas** num webhook (no formulário de criação/edição) e continuaremos a tentar:

| Tentativa | Quando |
|---|---|
| 1 | Imediatamente |
| 2 | 1 minuto depois |
| 3 | 5 minutos depois |
| 4 | 30 minutos depois |
| 5 | 2 horas depois |

Isso abrange cerca de **2 horas e 40 minutos**, pelo que um webhook pode sobreviver a uma janela de manutenção ou a uma breve interrupção do seu lado.

**O que é repetido:** problemas temporários — o seu servidor a devolver um erro 5xx, um timeout ou uma falha de ligação.

**O que não fazemos:** se o seu endpoint rejeitar o pedido (qualquer erro 4xx), não tentamos novamente — enviar o mesmo pedido repetidamente apenas produziria a mesma rejeição.

**Quais os eventos que tentam novamente:** webhooks de etiquetas (`contact_tags_updated`), os três eventos de tarefa e o resumo diário. Os restantes são enviados uma vez, pelo que, para esses, o interruptor não tem qualquer efeito. Todos os eventos transportam `X-Webhook-Delivery`, pelo que uma regra de desduplicação cobre todos eles.

> **Ative as tentativas de reenvio apenas se o seu endpoint for idempotente.** As tentativas de reenvio significam que o mesmo evento pode chegar mais do que uma vez. Utilize o cabeçalho `X-Webhook-Delivery` para reconhecer uma repetição: este permanece igual em todas as tentativas para um evento, pelo que pode ignorar com segurança um ID que já tenha processado.

As tentativas de reenvio interagem com a desativação automática após falhas repetidas (consulte [Fiabilidade do Webhook](#webhook-reliability)) da forma que pretende: o contador de falhas conta uma **entrega completa**, apenas após todas as tentativas de reenvio terem sido esgotadas — e não cada tentativa individual.

---

## Fiabilidade do Webhook

- O <span data-t="appName">Your AI Connector</span> envia webhooks através de uma ligação segura (HTTPS). Certifique-se de que o endereço web que fornece utiliza HTTPS.
- Se o seu sistema devolver um erro, a entrega é considerada falhada.
- Monitorize o tempo de atividade do seu sistema recetor para evitar perder eventos.
- Para fluxos de trabalho críticos, ative [Tentar Novamente Entregas Falhadas](#retrying-failed-deliveries) e considere também um mecanismo de redundância.

> **Os webhooks são desligados automaticamente após falhas repetidas.** Se o URL do seu webhook falhar repetidamente (cerca de 5 erros seguidos, ou 3 seguidos para erros de configuração), o <span data-t="appName">Your AI Connector</span> para automaticamente de enviar eventos para esse URL. Para o reativar assim que o seu endpoint estiver operacional: edite o webhook e guarde-o com um URL alterado (qualquer alteração de URL reativa-o), ou utilize o [endpoint de reativação](../api/webhooks.md) através da API — guardar novamente com o mesmo URL não é suficiente. O suporte também pode reativá-lo por si.

---

## Resolução de Problemas

| Problema | Solução |
|---|---|
| O webhook não é disparado | Primeiro, verifique se o webhook não está **desativado** na sua linha. Depois, confirme se os eventos corretos estão selecionados e se o seu URL é acessível a partir da internet. |
| O evento de teste funciona, mas os eventos reais não | Certifique-se de que o tipo de evento específico está ativado. Se esperava um pedido quando uma etiqueta é aplicada, note que `subscribed_to_tags` não limita os eventos de um webhook a uma etiqueta — apenas restringe quais as etiquetas que produzem uma notificação de resumo de conversação. Para obter um pedido quando uma etiqueta específica é aplicada, defina um URL de webhook nessa etiqueta no separador **Etiquetas** do agente (ou campanha) — consulte [Webhook de Etiquetas de Contacto Atualizadas](#contact-tags-updated-webhook). |
| Não chega nada ao n8n / Make / Zapier | Provavelmente está a usar o **URL de Teste** da plataforma, que apenas escuta um único evento logo após clicar em "Ouvir evento de teste". Para eventos em tempo real, guarde o **URL de Produção** e altere o fluxo de trabalho para **Ativo**. |
| A receber eventos duplicados | Verifique se existem vários webhooks a apontar para o mesmo URL. Se a opção **Tentar novamente entregas falhadas** estiver ativa, é esperado um reenvio sempre que o seu endpoint aceitou um evento mas não respondeu a tempo — deduplique em `X-Webhook-Delivery`. |
| A verificação da assinatura falha sempre | Quase sempre porque o corpo foi re-serializado antes da verificação. Verifique contra o corpo do pedido **raw**, assine `<timestamp>.<body>`, e confirme se está a usar o segredo atual caso o tenha renovado recentemente. |
| As tentativas de reenvio não estão a ocorrer | As tentativas de reenvio estão desativadas, a menos que sejam ativadas nesse webhook específico. Não tentamos reenviar respostas 4xx. |
| O bloco `campaign` é sempre `null` | Esperado se a sua conta usar agentes: os contactos ficam com um agente em vez de uma campanha. Leia o bloco `agent` em alternativa — consulte [Formato de Dados do Webhook](#webhook-data-format). |
| Os dados estão vazios ou mal formatados | Verifique se o seu sistema recetor aceita JSON. Verifique os registos do seu servidor para erros de análise. |
| O URL do webhook devolve erros | Teste o seu URL com uma ferramenta como o Postman ou [webhook.site](https://webhook.site). |
| O webhook parou de disparar completamente após uma falha | Falhas repetidas desativam automaticamente um webhook. Guardar novamente não o reativa — corrija o seu endpoint e, em seguida, contacte o suporte. |
| Guardar ou Testar dá um erro de permissão | Precisa da permissão de "editar" Integrações. Peça ao proprietário da conta para a conceder. |
| A lista `subscribed_to_tags` de um webhook voltou vazia | `subscribed_to_tags` não limita os eventos de um webhook a uma etiqueta — apenas restringe quais as etiquetas que produzem uma notificação de resumo de conversação. Editar a partir do formulário de webhook já não limpa essa lista (corrigido a 21 de julho de 2026). Se um webhook perdeu a sua lista antes dessa data, defina `subscribed_to_tags` novamente através da [API de Webhooks](../api/webhooks.md) — consulte [Acionadores de Webhook Baseados em Etiquetas](#tag-based-webhook-triggers). |

---

## Próximos Passos

- [Integração GoHighLevel](ghl-integration.md) — utilize webhooks para integrar o <span data-t="appName">Your AI Connector</span> com o GHL.
- [Acesso à API](api-access.md) — combine webhooks com a API para automatizações poderosas.
- [Utilizar Etiquetas para Identificar Contactos](../get-started/creating-tags.md) — configure etiquetas que disparam os seus webhooks.
