Dev

WhatsApp Webhook não chega: localhost, ngrok e n8n

Quando o webhook do WhatsApp não chega, a causa quase sempre está em um de cinco lugares: a URL não é pública, o HTTPS falha, o evento certo não está ligado, o endpoint responde devagar ou erra, ou o n8n está com a URL de teste. Dá para descobrir qual é em poucos minutos, nessa ordem, usando o endpoint de teste e a lista de entregas recentes da API. Este guia segue essa ordem, com os comandos.

Publicado em · 7 min de leitura

Este artigo também está disponível em: English · Español

Por onde começar o diagnóstico?

Separe o problema em duas perguntas. A primeira: o evento está saindo da ZapZap? A segunda: ele chega ao seu sistema e é processado? A API responde a primeira com a lista de entregas recentes, que mostra por evento se foi entregue, o status HTTP e a latência. Se a lista está vazia para mensagens reais, o problema está antes do envio (evento desligado ou instância desconectada). Se há entregas com status de erro, o problema está no seu endpoint.

Antes de tudo, confirme a instância. Consulte o status da instância: se não estiver conectada, não há mensagem nova para gerar evento. Depois confirme a configuração com ver webhook: a URL, se está habilitado e quais eventos estão selecionados.

Quatro comandos de diagnóstico

BASE="https://api.zapzapapi.com/api/v1"
H1="x-api-key: $ZAPZAP_API_KEY"
H2="x-api-secret: $ZAPZAP_API_SECRET"

curl "$BASE/$INSTANCE_ID/instance/status" -H "$H1" -H "$H2"                     # conectada?
curl "$BASE/instances/$INSTANCE_ID/webhook" -H "$H1" -H "$H2"                   # URL, enabled, events
curl "$BASE/instances/$INSTANCE_ID/webhook/deliveries?limit=20" -H "$H1" -H "$H2" # o que saiu e com qual status
curl "$BASE/$INSTANCE_ID/webhook/errors" -H "$H1" -H "$H2"                      # motivos de falha

Posso usar localhost ou 127.0.0.1 como URL do webhook?

Não. O servidor da ZapZap está na internet e não enxerga a sua máquina. Além disso, a API recusa endereços locais e privados ao salvar a configuração (localhost, 127.0.0.1, 192.168.x.x e semelhantes), então a chamada de configuração já devolve erro de validação. A URL precisa ser HTTPS, pública e acessível de fora.

Ao salvar, a API também faz uma checagem de alcance na sua URL (uma requisição HEAD com limite de tempo curto). Qualquer resposta HTTP, mesmo 404 ou 405, conta como alcançável. Se o servidor não responde nesse prazo, a configuração falha com mensagem de URL inacessível. Se você recebeu esse erro, o endpoint estava fora do ar, atrás de firewall ou lento demais naquele instante.

Como testar localmente com ngrok ou outro túnel?

Um túnel publica a sua porta local em uma URL HTTPS pública. O fluxo é: suba o servidor, abra o túnel apontando para a porta, copie a URL HTTPS gerada e configure como webhook_url. Ferramentas como ngrok e o cloudflared (Cloudflare Tunnel) fazem isso. Cada uma tem as suas regras de conta e de URL, então confira a documentação delas.

Duas armadilhas comuns. Primeira: a URL do túnel muda quando você reinicia (em planos sem domínio fixo), e o webhook configurado passa a apontar para o vazio. Reconfigure sempre que subir um túnel novo. Segunda: o túnel parado ou o servidor local fora do ar gera falhas, e falhas seguidas podem desativar o webhook.

Para validar o caminho completo, use o teste de webhook logo depois de configurar. Ele envia um evento assinado e devolve status e latência. Se o teste funciona e as mensagens reais não, volte para o item de eventos ligados.

Subir o túnel e configurar a URL (exemplo com ngrok)

# terminal 1: servidor local na porta 3000
node server.js

# terminal 2: túnel HTTPS para a porta 3000
ngrok http 3000
# copie a URL https://....ngrok-free.app e use abaixo

curl -X PUT "https://api.zapzapapi.com/api/v1/instances/$INSTANCE_ID/webhook" \
  -H "x-api-key: $ZAPZAP_API_KEY" \
  -H "x-api-secret: $ZAPZAP_API_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"webhook_url":"https://SEU-SUBDOMINIO.ngrok-free.app/webhooks/zapzap","enabled":true,"events":["messages","connection"]}'

Por que o webhook do n8n não recebe nada?

O nó Webhook do n8n tem duas URLs: a de teste (Test URL) e a de produção (Production URL). A de teste só escuta enquanto você clica em 'Listen for test event' no editor, e ela fica ativa por pouco tempo. A de produção só funciona com o workflow ativado. O erro clássico é cadastrar a URL de teste na ZapZap e depois fechar o editor: a partir daí nada chega.

Para uma automação em uso, cadastre a Production URL e ative o workflow. Para desenvolver, cadastre a Test URL, clique em escutar e mande uma mensagem de verdade no número. No n8n em Docker ou atrás de proxy reverso, o endereço que ele mostra pode ser interno (localhost:5678). Defina a variável de ambiente WEBHOOK_URL do n8n com o seu domínio HTTPS público, senão ele exibe uma URL que a ZapZap não consegue alcançar. Também confira se o proxy repassa o corpo e não bloqueia o POST.

Se preferir começar de um fluxo pronto, a página de integração com n8n traz tutorial e templates para importar, e os templates de n8n já vêm com o gatilho de webhook montado.

O evento certo está ligado?

Os eventos do webhook vêm desativados por padrão e você escolhe quais receber. Se você ligou apenas connection, mensagens nunca chegam. Para receber mensagens, ligue messages. Para saber se foi entregue ou lida, ligue messages_update. O catálogo completo está em configurar webhook.

Outro filtro que surpreende: excludeMessages. Se você marcou para excluir mensagens próprias, as enviadas por você não geram evento no webhook, o que é desejado em bots, mas confunde quem procura o eco do próprio envio. Revise esse campo na resposta de ver webhook.

Meu endpoint responde, mas as entregas aparecem com erro. E agora?

Leia a lista de entregas. Um status 4xx ou 5xx significa que o seu servidor respondeu erro; veja os logs dele. Um timeout significa que a resposta passou do limite de 10 segundos por tentativa. A causa quase sempre é trabalho pesado antes do res.send: chamada de IA, escrita lenta em banco ou envio de mensagem dentro da requisição. Responda 200 primeiro e processe depois, como no guia de webhook em produção.

Falhas são reenviadas por uma escada de retentativas, e falhas seguidas e permanentes podem levar à desativação do webhook. Se o webhook foi desativado, corrija a causa, rode o teste de webhook e configure a URL de novo. Um 401 ou 403 do seu lado costuma ser validação de assinatura feita sobre o JSON já parseado em vez do corpo bruto, ou segredo desatualizado.

Se tudo isso estiver certo e ainda não chegar, fale com o suporte levando o delivery_id de uma entrega, que identifica o evento nos dois lados.

Checklist rápido para quando nada chega

[ ] A instância está conectada (status connected)

[ ] A URL é HTTPS, pública e responde em poucos segundos, sem passar por login ou firewall

[ ] A configuração foi salva sem erro e o ver webhook mostra a URL e enabled verdadeiro

[ ] Os eventos messages (e connection, se quiser avisos de queda) estão na lista

[ ] O teste de webhook devolve status 2xx e latência baixa

[ ] As entregas recentes mostram tentativas com status 2xx para mensagens reais

[ ] No n8n: Production URL com workflow ativo, ou Test URL com o editor escutando

[ ] O seu servidor não valida a assinatura sobre o JSON já parseado

Se um item falhar, corrija e repita o teste antes de seguir. Mudanças de domínio, certificado vencido e regras novas de firewall são causas frequentes de webhook que funcionava e parou. Em time, registre a URL do webhook e o responsável pelo certificado, porque certificado expirado derruba o HTTPS e as entregas começam a falhar sem aviso no seu lado.

Resumo rápido

  • localhost e IPs privados são recusados. A URL do webhook precisa ser HTTPS, pública e alcançável.
  • Use um túnel HTTPS para desenvolver e reconfigure a URL toda vez que o túnel mudar.
  • No n8n, a URL de teste só escuta durante o 'Listen for test event'. Em produção use a Production URL com o workflow ativo.
  • Confira os eventos ligados (messages, messages_update, connection) e o filtro excludeMessages.
  • Diagnostique com o status da instância, o ver webhook, as entregas recentes e os erros do webhook.

Perguntas frequentes

Por que o webhook do WhatsApp não chega no meu localhost?

Porque o servidor da API não enxerga a sua máquina e, além disso, a configuração recusa endereços locais e privados. Use um túnel HTTPS (ngrok, cloudflared) ou um servidor de homologação com URL pública.

Salvei a URL e deu erro de URL inacessível. O que fazer?

Ao salvar, a API faz uma checagem de alcance com limite de tempo curto. Garanta que o servidor está no ar, com HTTPS válido, sem firewall bloqueando e respondendo rápido à requisição.

O webhook do n8n funciona no modo de teste?

Só enquanto você clica em escutar evento de teste no editor. Para uso contínuo, ative o workflow e cadastre a Production URL na ZapZap. Em Docker ou proxy, defina WEBHOOK_URL com o domínio público.

Recebo o evento de conexão, mas não as mensagens. Por quê?

Porque o evento messages não está ligado na configuração do webhook. Atualize a lista de eventos com messages e, se quiser status de entrega e leitura, messages_update.

Como vejo se a ZapZap tentou entregar?

Pelo endpoint de entregas recentes da instância: ele lista evento, status HTTP, latência e número da tentativa. Os erros do webhook mostram o motivo das falhas mais recentes.

Teste o webhook com um evento assinado

Crie a conta, verifique o telefone e receba o crédito de boas-vindas, sem depositar (um por telefone, sujeito à campanha vigente). Conecte um número e rode o teste de webhook para ver a latência da sua URL.