Webhooks Explicados: Payloads Assinados e Retentativas

Backend2026-10-17TryQuickToolBox

Você acabou de integrar um gateway de pagamento. A documentação diz: "Enviaremos um webhook para o seu endpoint quando um pagamento for bem-sucedido." Você configura uma rota simples, testa localmente e faz o deploy. Então, em produção, você percebe eventos duplicados, notificações perdidas e erros 500 misteriosos. Webhooks parecem simples — até não serem.

Este guia explica como os webhooks realmente funcionam, por que payloads assinados são importantes e como construir uma lógica de retentativa que mantém seu sistema sincronizado mesmo quando as coisas dão errado.

O que é um Webhook?

Um webhook é um callback HTTP: um sistema envia uma requisição HTTP POST para uma URL que você fornece quando um evento específico ocorre. Diferente do polling, onde você pergunta repetidamente "Aconteceu alguma coisa?", os webhooks enviam eventos para você quase em tempo real.

Usos comuns incluem:

O remetente (ex.: Stripe, GitHub) é o provedor de webhook; seu servidor é o consumidor de webhook.

Por que Payloads Assinados São Essenciais

Seu endpoint de webhook é publicamente acessível. Qualquer pessoa que saiba a URL pode enviar eventos falsos. Sem verificação, um atacante poderia falsificar um evento de "pagamento bem-sucedido" e você poderia enviar mercadorias gratuitamente.

Payloads assinados resolvem isso incluindo uma assinatura criptográfica nos cabeçalhos da requisição, gerada com um segredo compartilhado conhecido apenas por você e pelo provedor. Quando você recebe um webhook, você recalcula a assinatura e compara. Se corresponderem, o payload é autêntico.

Como Funcionam as Assinaturas HMAC

A maioria dos provedores usa HMAC-SHA256. O provedor calcula:

signature = HMAC-SHA256(secret, payload)

e envia em um cabeçalho como X-Signature. Seu servidor faz o mesmo cálculo e verifica a igualdade. Como o segredo é secreto, apenas o provedor pode gerar uma assinatura válida.

Verificando uma Assinatura na Prática

Aqui está um exemplo mínimo em Node.js usando Express:

const crypto = require('crypto');
const express = require('express');
const app = express();

app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-signature'];
  const secret = process.env.WEBHOOK_SECRET;
  const payload = req.body; // raw Buffer

  const expected = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');

  if (signature !== expected) {
    return res.status(401).send('Invalid signature');
  }

  // Process the event
  const event = JSON.parse(payload);
  console.log('Received event:', event.type);
  res.status(200).send('OK');
});

app.listen(3000);

Importante: Sempre use o corpo bruto da requisição para verificação de assinatura. Se você analisar o JSON primeiro, a string serializada pode diferir (espaços em branco, ordem das chaves) e a verificação da assinatura falhará.

Armadilhas Comuns

Retentativas: Lidando com Falhas de Forma Elegante

Redes falham, servidores reiniciam e implantações acontecem. Provedores de webhook esperam que seu endpoint possa estar temporariamente indisponível, então eles tentam novamente entregas falhas. Mas as retentativas introduzem novos desafios: eventos duplicados, entrega fora de ordem e loops infinitos se você não tomar cuidado.

Como os Provedores Fazem Retentativas

A maioria dos provedores usa backoff exponencial: eles esperam um curto período após a primeira falha, depois intervalos progressivamente maiores. Por exemplo, a Stripe tenta novamente por até 3 dias com atrasos crescentes. O GitHub tenta até 8 vezes. O cronograma exato varia, mas o padrão é consistente.

Seu endpoint deve retornar um código de status 2xx rapidamente para confirmar o recebimento. Qualquer outro status (4xx, 5xx) sinaliza falha e dispara uma retentativa.

Construindo Handlers Idempotentes

Como as retentativas podem entregar o mesmo evento várias vezes, seu handler deve ser idempotente: processar o mesmo evento duas vezes deve ter o mesmo efeito que processá-lo uma vez.

Estratégias comuns:

Exemplo usando um conjunto simples em memória (para ilustração; use um armazenamento persistente em produção):

const processedEvents = new Set();

app.post('/webhook', (req, res) => {
  const event = req.body;
  if (processedEvents.has(event.id)) {
    return res.status(200).send('Already processed');
  }
  // Process event...
  processedEvents.add(event.id);
  res.status(200).send('OK');
});

Respondendo Rapidamente

Provedores frequentemente têm um timeout (ex.: 5 segundos). Se seu handler faz processamento pesado, confirme imediatamente e processe de forma assíncrona. Por exemplo, coloque o evento em uma fila e retorne 200.

Melhores Práticas para Webhooks Confiáveis

  1. Sempre verifique assinaturas usando o corpo bruto e uma comparação de tempo constante.
  2. Use HTTPS para seu endpoint para prevenir interceptação e adulteração.
  3. Implemente idempotência para lidar com entregas duplicadas.
  4. Registre tudo — payloads recebidos, assinaturas e suas respostas — para depuração.
  5. Monitore falhas e configure alertas para erros repetidos.
  6. Teste com eventos reais usando painéis de provedores ou ferramentas de CLI.
  7. Lide com eventos fora de ordem incluindo timestamps ou números de sequência em sua lógica.

Comparação: Polling vs. Webhooks

AspectoPollingWebhooks
LatênciaDepende do intervaloQuase em tempo real
Carga do servidorAlta (requisições constantes)Baixa (apenas em eventos)
ComplexidadeSimples de implementarRequer endpoint, segurança, retentativas
ConfiabilidadeVocê controla as retentativasO provedor controla as retentativas

FAQ

O que é uma assinatura de webhook?

Uma assinatura de webhook é um hash criptográfico (geralmente HMAC-SHA256) do payload, gerado com um segredo compartilhado. Ele permite que o receptor verifique que a requisição veio do remetente esperado e não foi adulterada.

Como lidar com eventos de webhook duplicados?

Torne seu handler idempotente rastreando IDs de eventos ou usando operações de banco de dados que são naturalmente idempotentes. Verifique se um evento já foi processado antes de aplicar alterações.

O que meu endpoint de webhook deve retornar?

Retorne um código de status 2xx (ex.: 200 OK) assim que você receber e validar o evento. Se precisar fazer processamento pesado, confirme imediatamente e lide com o trabalho de forma assíncrona.

Pronto para testar seus payloads de webhook? Use nosso JSON Formatter para inspecionar e validar a estrutura JSON dos eventos recebidos.