Webhooks

Receba notificações em tempo real de mensagens recebidas e status de entrega.

Visão Geral

Webhooks permitem receber callbacks do provider WhatsApp quando mensagens chegam ou o status de entrega muda. O WhatsApp é multi-provider: cada aplicação usa Twilio ou Meta Cloud API, e o endpoint de webhook difere conforme o provider:

Todos os endpoints de webhook são públicos (sem autenticação por credencial), mas validados por assinatura do provider. Requisições com assinatura inválida são rejeitadas.

Twilio — Mensagem Recebida

POST

/api/webhooks/whatsapp/webhook

Content-Type: application/x-www-form-urlencoded

ParâmetroTipoDescrição
MessageSidstringIdentificador único da mensagem
AccountSidstringID da conta Twilio
FromstringNúmero do remetente (formato: whatsapp:+5511...)
TostringNúmero do destinatário (seu número WhatsApp)
BodystringConteúdo da mensagem
ProfileNamestringNome do perfil WhatsApp do remetente
NumMediaintegerQuantidade de mídias anexadas
MediaUrl0stringURL da primeira mídia anexada Opcional
O webhook sempre retorna HTTP 200, mesmo em caso de erro interno, para evitar retentativas do Twilio.

Twilio — Status de Entrega

POST

/api/webhooks/whatsapp/status
ParâmetroTipoDescrição
MessageSidstringIdentificador da mensagem
MessageStatusstringStatus: queued, sent, delivered, read, failed, undelivered
ErrorCodestringCódigo de erro (quando status é failed/undelivered) Opcional
ErrorMessagestringDescrição do erro Opcional

Teste de Webhook

POST

/api/webhooks/whatsapp/webhook/test

Endpoint para testar se os webhooks estão acessíveis.

{ "status": "ok", "message": "Webhook funcionando", "params_recebidos": 0 }

Configuração no Twilio

As URLs de webhook devem ser configuradas no console do Twilio ou via auto-configuração do painel admin.

URLs de webhook:

A URL de webhook precisa ser acessível publicamente pelo Twilio. Em ambientes sem domínio público, utilize um túnel reverso (ex: ngrok) durante a configuração inicial.

Validação de Assinatura (Twilio)

O Twilio assina cada requisição com HMAC-SHA1 no header X-Twilio-Signature. O servidor valida automaticamente usando o Auth Token configurado.

Atrás de proxy reverso (nginx, ALB), os headers X-Forwarded-Proto e X-Forwarded-Host são usados para reconstruir a URL original.

Se o Auth Token não estiver configurado, a validação de assinatura é desabilitada automaticamente.

Meta Cloud API

Quando a aplicação usa a Meta WhatsApp Cloud API (Graph API direta), há um único endpoint por aplicação, identificado pelo {slug} na URL, que atende tanto o handshake de verificação quanto o recebimento de eventos (mensagens e status).

Base URL: /api/webhooks/whatsapp/meta/{slug}

Verificação (handshake)

GET

/api/webhooks/whatsapp/meta/{slug}

Ao cadastrar a URL no App da Meta, a plataforma envia uma requisição de verificação. O servidor devolve o hub.challenge quando o hub.verify_token confere com o token configurado nas credenciais Meta da aplicação (slug).

ParâmetroTipoDescrição
{slug}pathSlug da aplicação Avizuaí
hub.modequeryValor subscribe
hub.verify_tokenqueryToken configurado nas credenciais Meta da aplicação
hub.challengequeryValor a ser devolvido no corpo da resposta
Retorna 200 com o hub.challenge quando o token confere; caso contrário 403 Forbidden.

Eventos (mensagens e status)

POST

/api/webhooks/whatsapp/meta/{slug}

Content-Type: application/json

Recebe o payload de eventos da Cloud API (mensagens recebidas em entry[].changes[].value.messages[] e status de entrega em statuses[]). A plataforma normaliza internamente para o mesmo fluxo do Twilio.

ParâmetroTipoDescrição
{slug}pathSlug da aplicação Avizuaí
X-Hub-Signature-256headerAssinatura HMAC SHA-256 do corpo, no formato sha256=<hex>, calculada com o App Secret da aplicação
BodyJSONPayload de eventos da Meta Cloud API (byte-exato para validação da assinatura)
Retorna sempre 200 quando a assinatura é válida (a Meta não reentrega em 2xx). Assinatura inválida retorna 401.

Webhooks de Entrada (Inbound)

Além de receber callbacks do Twilio, a plataforma aceita webhooks de sistemas externos (n8n, Zapier, Make, integrações próprias) para acionar fluxos internos.

POST

/api/v1/webhooks/inbound/{slug}/{fluxo}

Content-Type: application/json

ParâmetroTipoDescrição
{slug}pathSlug da aplicação Avizuaí destino
{fluxo}pathNome livre do fluxo (para roteamento e auditoria)
X-Avizuai-SignatureheaderAssinatura HMAC SHA-256 do payload, no formato sha256=<hex>. Exigida quando a aplicação tem subscription com secret configurado.
BodyJSON livrePayload arbitrário entregue aos listeners internos

Validação HMAC

Se a aplicação destino possui ao menos uma subscription ativa com secretHmac configurado, o header X-Avizuai-Signature torna-se obrigatório.

A assinatura é calculada como HMAC-SHA256(payload_json, secret) e enviada no formato sha256=<hex_lowercase>. O servidor calcula a mesma assinatura com cada secret cadastrado e aceita se houver qualquer coincidência.

Se nenhuma subscription tem secret, o endpoint aceita sem assinatura (modo permissivo, útil para testes).

Códigos de Retorno

StatusQuando
200 OKWebhook aceito e enfileirado para processamento interno
401 UnauthorizedAssinatura HMAC ausente ou inválida (quando obrigatória)
404 Not FoundAplicação não encontrada para o slug informado
400 Bad RequestPayload JSON inválido

Resposta de Sucesso

{ "aceito": true, "aplicacao": "minha-app", "fluxo": "novo-lead" }

Próximos Passos