Webhooks: receba eventos sem duplicar operações
Aprenda a autenticar eventos, responder com segurança, tratar duplicatas e recuperar falhas em integrações orientadas a webhooks.
Quando usar um webhook
Um webhook é uma chamada HTTP enviada por um serviço para avisar sua aplicação sobre um evento. Ele pode informar um pagamento confirmado, uma mudança em um pedido ou uma atividade no repositório. Sua aplicação oferece um endpoint; o provedor envia o evento para o endereço cadastrado.
Isso reduz a necessidade de consultar a API continuamente, mas exige um receptor preparado para falhas de rede. Antes de implementar, confira os tipos de evento, o formato do corpo, a versão, o mecanismo de autenticação e a política de reenvio do provedor. Cada serviço tem um contrato próprio.
Valide a origem antes de processar
Um endpoint público pode receber requisições de qualquer origem. Valide a assinatura ou o mecanismo oficial de autenticação do provedor antes de confiar nos dados. Use uma biblioteca oficial ou uma implementação mantida para o esquema exigido; não aplique uma fórmula de outro serviço.
Muitos esquemas de assinatura usam o corpo original da requisição. Interpretar o JSON e serializá-lo novamente pode alterar os bytes e invalidar a assinatura. Preserve o corpo bruto, mantenha o segredo no servidor e aplique o controle de timestamp previsto pelo esquema para reduzir o risco de replay.
Separe recebimento e execução
O receptor deve validar a requisição e registrar o evento de forma durável antes de confirmar o recebimento. Depois, um worker pode executar tarefas mais lentas, como consultar uma API ou atualizar outro sistema. Essa separação permite controlar a concorrência e recuperar trabalho interrompido.
Responda dentro do prazo documentado pelo serviço. No GitHub, a orientação é devolver 2xx em até dez segundos. Na Stripe, a recomendação é responder rapidamente antes da lógica complexa. Se o evento válido ainda não foi salvo e o armazenamento falhar, não confirme como se ele estivesse pronto para processamento.
// Fluxo conceitual: adapte ao contrato do seu provedor.
// As funções abaixo representam componentes da aplicação.
async function receiveWebhook(request) {
const rawBody = await request.readRawBody();
const event = verifyProviderSignature(rawBody, request.headers);
// Restrição única no banco: (provedor, conta, event.id).
// Salve o evento como "pendente" em uma transação durável.
await inbox.insertIfAbsent({
provider: 'provedor',
account: event.account,
id: event.id,
payload: event,
status: 'pending'
});
return { status: 200 };
}
// Um worker consulta a inbox e executa operações idempotentes.
// Marque "concluído" somente após a confirmação do resultado.Trate duplicatas e a ordem dos eventos
A Stripe documenta que um evento pode ser entregue mais de uma vez e que a ordem de entrega não é garantida. Outros provedores podem ter regras diferentes. A assinatura comprova a origem; ela não garante que o evento seja novo nem que seus efeitos ainda não tenham sido aplicados.
Use o identificador estável do evento junto ao provedor e à conta para deduplicar. Evite apenas consultar se o ID existe e depois inserir: duas entregas concorrentes podem passar pela consulta. Prefira uma restrição única no armazenamento. Para o efeito de negócio, use operações idempotentes ou uma chave documentada pela API de destino.
Recupere falhas de forma observável
Defina estados de processamento como pendente, em execução, concluído e falha. Guarde o número de tentativas e uma mensagem de erro sem segredos. Configure limites de retentativa e uma fila ou área de revisão para eventos que não puderam ser processados.
A recuperação é uma decisão operacional: determine quem pode reprocessar, como verificar efeitos já aplicados e quando consultar o estado atual do recurso no provedor. Um replay manual deve passar pela mesma deduplicação. Para dados críticos, planeje uma rotina de reconciliação que detecte divergências entre os sistemas.
Teste os cenários que quebram integrações
Teste assinatura inválida, corpo alterado, evento desconhecido, duas entregas simultâneas, evento repetido depois de concluído e falha do armazenamento. Simule também uma operação externa que termina antes de o worker perder a conexão: a próxima tentativa precisa verificar o resultado.
Use os eventos de teste e as ferramentas locais do provedor quando disponíveis. Acompanhe o tempo de confirmação, a idade dos eventos pendentes e a taxa de falhas. Inscreva o endpoint apenas nos tipos de evento necessários e retenha os payloads pelo tempo adequado à operação e à sensibilidade dos dados.
Fontes e referências oficiais
Consulte o contrato e as recomendações da plataforma que você está integrando. Os detalhes variam por serviço e podem evoluir.