Quando um webhook nunca chega

Percorre o problema por ordem - o registo de entregas, o nome do evento, a firewall, a assinatura. O separador Deliveries diz-te logo se a Didit o enviou, o que divide o problema ao meio.

Short answer

Começa pelo separador Deliveries do destino. Se a Didit nunca tentou a entrega, é um problema de subscrição ou de destino. Se tentou e falhou, o código de resposta diz-te qual: 404 significa que a tua rota não estava acessível nesse URL, uma discrepância de assinatura significa que assinaste os bytes errados.

#Passo 1: a Didit tentou enviá-lo?

Abre o destino em API & Webhooks e olha para o separador Deliveries. Cada tentativa é registada individualmente, com a resposta.

A página de webhooks na consola Didit a mostrar o estado de entrega por destino
  1. Last sent diz-te se a Didit sequer tentou.
  2. View stats mostra as tentativas e falhas desse destino.
  3. Uma entrega de teste separa o teu endpoint do próprio evento.
  4. Um destino que continua a falhar pode ser desativado enquanto o corriges.
Tudo o que é preciso para distinguir um evento em falta de um endpoint a falhar está nesta página.

Essa única verificação divide o problema ao meio:

  • Nenhuma tentativa registada → o evento nunca foi gerado para esse destino. Passa ao passo 2.
  • Tentativa registada, falhou → a Didit enviou-o e o teu lado rejeitou-o ou não o recebeu. Passa ao passo 3.
  • Tentativa registada, 2xx → foi entregue com sucesso. O problema está dentro do teu handler, não na entrega.

#Passo 2: nenhuma tentativa foi registada

Por ordem de probabilidade:

  1. O evento não está subscrito. Não existe wildcard - cada família de eventos tem de ser listada explicitamente. E um nome que não existe (session.status.updated, kyc.completed) não recebe nada, silenciosamente. Verifica na lista de eventos.
  2. Aplicação errada. Os destinos pertencem a uma aplicação. Se as tuas sessões correrem numa aplicação diferente da do destino, nenhum evento chegará alguma vez até ele. Esta é a causa mais comum quando tudo parece corretamente configurado.
  3. Nada mudou de facto. Os webhooks disparam por alteração. Uma sessão que não avançou, ou uma re-triagem de monitorização AML que não encontrou nada acima do limiar, produz corretamente nenhum evento.
  4. O estado que estás à espera ainda não aconteceu. Uma sessão em In Progress não está terminada. Consulta quando uma sessão nunca termina.

#Passo 3: a entrega foi tentada e falhou

Um 404 significa que o pedido chegou a algo que não tinha a tua rota. Verifica:

  • O caminho exato, incluindo uma barra final. Uma framework que redireciona /hook para /hook/ pode transformar um endpoint que funciona num 404 ou num corpo perdido.
  • Se o URL é público. Um anfitrião local ou de staging que não é acessível a partir da internet falha desta forma.
  • Se um proxy, balanceador de carga, ou router baseado em caminho à frente da tua aplicação está a enviar esse caminho para outro lado.

Um 5xx significa que o teu handler rebentou. Regista o corpo em bruto antes de o analisares, para veres o que ele realmente recebeu.

Um timeout significa que não respondeste suficientemente depressa. Devolve 2xx primeiro, processa depois.

Nada de todo / ligação recusada significa que o teu edge o bloqueou. A Didit entrega a partir do IP estático 18.203.201.92 com um user agent DiditWebhook/2.0. Se estiveres atrás do Cloudflare ou de uma WAF com uma postura de negação por defeito, permite esse IP para o nome do anfitrião recetor.

#O clássico: a entrega automática dá 404 mas o Resend funciona

Este surge com frequência suficiente para merecer nome próprio. A entrega automatizada falha com um 404, e depois clicar em Resend no mesmo evento tem sucesso.

Essa combinação significa que o payload e o teu endpoint estão ambos bem - por isso a diferença é de tempo ou de caminho, não de conteúdo. Verifica:

  • Um deploy ou reinício no momento da entrega original. O Resend tem sucesso mais tarde porque a aplicação já está de novo em pé.
  • Um cold start que excedeu o timeout da tua plataforma - comum em serverless com uma primeira invocação lenta.
  • Um encaminhamento baseado em caminho que mudou entre as duas tentativas, ou uma regra que só corresponde a alguns pedidos.
  • Limitação de taxa ou proteção contra bots no teu edge que deixou passar o reenvio manual porque chegou sozinho em vez de numa rajada.

O separador Deliveries tem ambas as tentativas com os respetivos carimbos de hora - compara-os com os teus próprios registos de deploy e de erro desse minuto.

#A verificação de assinatura a falhar

Quase sempre uma destas três coisas:

  1. Assinaste JSON re-serializado. Faz o HMAC dos bytes em bruto do pedido, exatamente como recebidos. Analisar e voltar a converter em string muda os espaços e a ordem das chaves, e a assinatura não vai corresponder. A maioria das frameworks precisa de configuração explícita para te dar o corpo em bruto.
  2. Segredo errado. O segredo de assinatura é por destino, e não é a tua chave de API. Dois destinos têm dois segredos diferentes.
  3. Suposição de codificação errada. Se não tiveres a certeza se o segredo é usado como string literal ou descodificado primeiro, não adivinhes - segue exatamente a referência de verificação de assinatura, e regista o corpo em bruto enquanto depuras, para poderes comparar.
Important

Nunca "corrijas" uma discrepância de assinatura saltando a verificação. Um endpoint de webhook não verificado vai aceitar uma aprovação forjada de qualquer pessoa que encontre o URL, o que transforma um atalho de depuração num caminho para a apropriação da conta.

#Duas repetições não são uma fila

Num 5xx, 404, timeout, ou falha de ligação, a Didit repete duas vezes - cerca de 1 minuto depois e depois mais 4 minutos - e depois abandona a entrega. Se o teu endpoint esteve em baixo mais tempo do que isso, esses eventos perderam-se para sempre.

Constrói um caminho de reconciliação: no arranque, faz polling ao endpoint de decisão para qualquer sessão para a qual não tenhas um estado terminal. Trata os webhooks como o caminho rápido e o polling como a rede de segurança.

#Testar sem correr verificações

Try Webhook na página do destino envia um evento totalmente formado do tipo que escolheres - aprovado, recusado, em revisão, KYB, entidade, transação. Usa-o para comprovar que o teu endpoint, a verificação de assinatura e o handler funcionam antes de uma sessão real depender deles.

O sandbox é a outra metade disto: uma sessão em sandbox emite webhooks reais com "environment": "sandbox", por isso consegues exercitar todo o caminho, de ponta a ponta, sem custos. Consulta testar em sandbox.