Skip to main content
O endpoint de webhook tem um trabalho só: conferir a assinatura e aceitar. Tudo o que demora — liberar cadastro, chamar antifraude interno, mandar e-mail — acontece depois, num worker.

Confira o exemplo

Os arquivos desta POC, com o destino de cada um.

Por que separar

A Legitimuz reentrega o que não responde 2xx, em intervalos crescentes. Se o seu handler processa dentro do request, dois problemas aparecem juntos: uma tarefa lenta vira timeout e a entrega é reenviada; e o seu retry passa a ser o retry da Legitimuz, que não conhece o seu banco. Separar deixa cada lado com a retentativa que ele entende.

O endpoint

app/api/webhooks/legitimuz/route.ts
O jobId substitui a tabela de deduplicação das outras POCs. Um id só existe uma vez na fila, então a segunda entrega do mesmo evento não cria um segundo job.

O worker

workers/outcome.ts
Lançar dentro do worker é o caminho certo de erro: o BullMQ conta a tentativa e reprograma. Um try/catch que engole a exceção marca o job como concluído e o desfecho se perde em silêncio.

Ordem não é garantida

Dois eventos da mesma verificação podem chegar fora de ordem. Se a sua lógica depende disso, use o occurred_at do corpo e descarte o que for mais antigo que o estado já gravado:
Ignorar evento atrasado

Antes de rodar

.env
Use uma integração sandbox. Nenhum dos três valores vai para o browser ou para o app. Esta POC precisa também de um Redis:
.env

O que esta POC não faz

POC é código para entender o fluxo, não para copiar em produção. Em todas elas, authenticate() é um stub, db é um objeto de mentira e não há migration, observabilidade nem retentativa própria.
  • Sem dead-letter queue. Depois de 5 tentativas o job fica em failed e ninguém é avisado.
  • Sem métrica de profundidade da fila.
  • Sem lock por ref_id: dois eventos da mesma verificação podem rodar em paralelo.

Próximo passo

Receptor de webhook

A conferência da assinatura, linha a linha.

Retomada e expiração

O que fazer quando o titular some no meio.