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

# Webhooks de saída

> Subscrever eventos de mensagens, conversas, opt-out e modelos. Verificar assinaturas HMAC, tratar tentativas e evitar processamento duplicado.

Os webhooks de saída permitem que os seus sistemas reajam a eventos no Flowella quase em tempo real, sem sondar a API. Configura-se um URL e uma lista de tipos de eventos, e o Flowella envia um payload JSON assinado para esse URL sempre que um desses eventos é disparado.

## Configurando um webhook

É necessário o papel de **Proprietário** ou **Administrador**.

<Steps>
  <Step title="Abrir Definições → Webhooks">
    Na aplicação Flowella, aceda a **Configurações → Webhooks**.
  </Step>

  <Step title="Adicionar um webhook">
    Clique em **Adicionar webhook**, cole o URL HTTPS público do seu endpoint e escolha os tipos de eventos que pretende receber.
  </Step>

  <Step title="Guardar o segredo de assinatura">
    O Flowella gera um segredo de assinatura exclusivo para o webhook. Copie-o - irá utilizá-lo para verificar os pedidos recebidos.
  </Step>

  <Step title="Enviar um teste">
    Clique em **Enviar teste** para enviar um payload `webhook.test` imediatamente. Verifique se o seu ponto final o recebeu e respondeu com um 2xx.
  </Step>
</Steps>

## Tipos de eventos

Pode subscrever qualquer um destes eventos de produto:

| Evento                    | Quando ele é acionado                                                         |
| ------------------------- | ----------------------------------------------------------------------------- |
| `message.received`        | Chegou uma mensagem de entrada WhatsApp de um contacto                        |
| `message.sent`            | O Flowella aceitou a sua mensagem de saída e submeteu-a ao Meta               |
| `message.delivered`       | Meta confirmou que a mensagem foi entregue ao dispositivo do destinatário     |
| `message.read`            | O destinatário abriu a mensagem                                               |
| `message.failed`          | Meta retornou uma falha para a mensagem                                       |
| `conversation.opened`     | Uma conversa passou para o estado aberto                                      |
| `conversation.closed`     | Uma conversa foi encerrada                                                    |
| `optout.created`          | Um contacto optou por sair de um canal específico                             |
| `template.status_updated` | Meta alterou o estado de um modelo (aprovado, rejeitado, pausado, desativado) |

O `webhook.test` é enviado apenas quando clica em **Enviar teste** - não o subscreve explicitamente.

## Formato do pedido

O Flowella envia um corpo JSON para o seu URL com estes cabeçalhos:

```http theme={null}
POST https://your-endpoint.example.com/flowella
Content-Type: application/json
User-Agent: Flowella-Webhooks/1
X-Flowella-Signature: <hex digest>
```

As cargas úteis têm um limite de **256 KB**. Os objectos maiores são resumidos - utilize a API para obter o registo completo por ID, se precisar dele.

A forma do corpo varia consoante o evento, mas inclui sempre:

```json theme={null}
{
  "event": "message.delivered",
  "timestamp": "2025-01-15T14:30:00.000Z",
  "organizationId": "clxxxxxxxxxxxxxxxxxxxxxxxx",
  "data": { "...event-specific fields..." }
}
```

## Verificação de assinaturas

Cada pedido inclui um cabeçalho `X-Flowella-Signature`. O valor é o **HMAC-SHA256 hex digest** do **corpo do pedido em UTF-8 bruto** chaveado com o segredo de assinatura do webhook.

Verifique antes de processar:

```js theme={null}
import { createHmac, timingSafeEqual } from "node:crypto";

function verify(rawBody, signatureHeader, secret) {
  const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(expected, "hex");
  const b = Buffer.from(signatureHeader, "hex");
  return a.length === b.length && timingSafeEqual(a, b);
}
```

```python theme={null}
import hmac, hashlib

def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature_header)
```

<Warning>
  Assine sempre os **bytes do corpo em bruto** antes de qualquer análise JSON ou middleware reformatar a carga útil. Se a sua estrutura re-serializar o JSON, a assinatura não corresponderá.
</Warning>

## Respostas, tentativas e tempos limite

* **Timeout**: O Flowella aguarda até **10 segundos** para que o seu endpoint responda.
* **Success**: qualquer resposta do `2xx` é tratada como uma entrega bem sucedida.
* Tentativas\*\*: as entregas falhadas são repetidas até **3 tentativas** com backoff.
* Desativação automática\*\*: se um webhook acumular **10 falhas consecutivas**, o Flowella desactiva-o. Terá de o reativar a partir de **Configurações → Webhooks** depois de corrigir o seu ponto final.

O seu endpoint deve regressar o mais rapidamente possível - adie qualquer processamento pesado para uma fila em segundo plano do seu lado.

## Idempotência

Os webhooks podem ser repetidos, portanto, o mesmo evento lógico pode chegar mais de uma vez. Para processar com segurança:

* Use o `data.id` do evento (ou uma chave derivada como `event + data.messageId`) como uma chave de idempotência.
* Mantenha uma cache de curta duração das chaves processadas (algumas horas são suficientes para novas tentativas).
* Tratar os duplicados como no-ops.

## Listando e gerenciando entregas

**Configurações → Webhooks** mostra as tentativas de entrega recentes por webhook, incluindo:

* Carimbo de data/hora
* Tipo de evento
* Status da resposta
* Um corpo de resposta truncado (até \~1 KB) para depuração

Se um webhook for desativado devido a falhas repetidas, a mesma página permite-lhe voltar a activá-lo.

## Desenvolvimento local

A maneira mais simples de desenvolver localmente contra webhooks é encaminhar um túnel público (por exemplo, ngrok ou Cloudflare Tunnel) para o seu servidor de desenvolvimento e apontar o URL do webhook para o host do túnel. Use **Send test** para disparar cargas sob demanda sem esperar pela atividade real do WhatsApp.

<Tip>
  Precisa de reagir a eventos que não estão na lista? Diga-nos em [support](https://flowella.io/support) - adicionamos eventos à medida que os clientes os solicitam.
</Tip>

## Relacionado

<CardGroup cols={2}>
  <Card title="Definições → Webhooks" icon="webhook" href="/pt/settings/webhooks">
    Configurar pontos finais, segredos de assinatura e novas tentativas na aplicação.
  </Card>

  <Card title="Introdução à API" icon="code" href="/pt/api-reference/introduction">
    Autenticação, erros, paginação e limites de taxa para a API REST.
  </Card>

  <Card title="Chaves API" icon="key" href="/pt/settings/api-keys">
    Criar e rodar os tokens portadores de que o seu ponto final possa necessitar.
  </Card>

  <Card title="Eventos de notificação" icon="bell" href="/pt/app/notification-events">
    Os mesmos eventos entregues no feed in-app e no e-mail.
  </Card>
</CardGroup>
