Skip to main content
Toda entrega de webhook segue uma política de reentrega previsível: a primeira tentativa sai imediatamente e cada falha agenda a próxima por um cronograma exponencial fixo. Esgotadas as tentativas, a entrega vai para dead-letter, de onde fica consultável e pode ser reenfileirada por replay manual, sem prazo. Esta página cobre o ciclo de retry, o que conta como sucesso ou falha, o dead-letter, o log de entregas e como reenviar. Para o formato do envelope e a assinatura do header, veja Visão geral e Assinatura.

O que conta como sucesso

Uma tentativa é considerada bem-sucedida quando seu endpoint responde com HTTP 2xx (200 a 299). Qualquer outra coisa conta como falha e dispara o retry:
  • Status HTTP fora da faixa 2xx (3xx, 4xx, 5xx). Redirects não são seguidos (redirect: manual). Um 3xx é falha.
  • Timeout de conexão ou resposta. O timeout por tentativa é de 10 segundos.
  • Erro de rede / conexão recusada.
Responda 2xx o mais rápido possível e processe o evento de forma assíncrona. Se o seu handler demorar mais de 10s para responder, a tentativa é abortada e tratada como falha, mesmo que você acabe processando o evento.
O corpo da resposta é registrado no log de entregas truncado a 2 KB (apenas para diagnóstico). Ele não afeta o resultado, que depende só do status.

Cronograma de retry

A política é exponencial com 7 tentativas no total. A primeira sai imediatamente; cada falha agenda a próxima pelo offset abaixo, contado a partir da falha anterior: Da criação à 7ª tentativa transcorrem cerca de 38,5 horas. Falhando a 7ª, a entrega entra em dead_letter. Cada entrega (id whdl_...) carrega o estado atual e o contador de tentativas:
string
Um de pending, attempting, succeeded, failed, dead_letter.
integer
Número de tentativas já concluídas (0 a 7).
string (ISO-8601)
Quando a próxima tentativa está agendada. Mantém o último valor nos estados terminais (succeeded, dead_letter).
object
{ statusCode?, body?, error? } da última tentativa, body truncado a 2 KB.
integer
Latência da última tentativa, em milissegundos.
A entrega é at-least-once: reentregas após falha ou replay são esperadas. Deduplique pelo id do evento (evt_...) no envelope: o mesmo evento pode chegar mais de uma vez. Veja Visão geral e Idempotência.

Auto-desativação por taxa de falha

Para proteger endpoints persistentemente quebrados, a saúde do endpoint é avaliada sempre que uma entrega vai para dead-letter. Considerando a janela de 72 horas de tentativas concluídas (succeeded + failed + dead_letter):
  • Se houver amostra mínima de 20 tentativas e a taxa de falha for ≥ 95%, o endpoint é desativado automaticamente.
  • O endpoint passa a status: disabled com disabledReason: failure_rate e é emitido o evento webhook_endpoint.disabled (com windowHours: 72, total e failures no payload).
Um endpoint disabled não recebe novos eventos e recusa replay. Reative-o com PATCH /webhook-endpoints/{id} definindo status: active (isso limpa o disabledReason).
Amostras abaixo de 20 tentativas nunca desativam o endpoint: 19 dead-letters não bastam. Assim, endpoints novos ou de baixo volume não são desativados por um pico isolado de falhas.

Log de entregas

Cada endpoint mantém um log das suas entregas dos últimos 30 dias , com request, response, status e latência. Use o log para diagnosticar falhas e confirmar entregas.
Filtre por status para isolar problemas, e pagine por cursor (limit, starting_after). A janela de 30 dias é aplicada implicitamente.
string
Filtra por estado: pending, attempting, succeeded, failed ou dead_letter.
integer
Itens por página (1 a 100, default 25). Veja Paginação.
string
Cursor de paginação (id whdl_... da última entrega da página anterior).
A resposta segue o padrão de listas ({ data, hasMore }), em ordem decrescente (mais recente primeiro):
Entregas succeeded e failed com mais de 30 dias são purgadas automaticamente. Dead-letters não são purgados: ficam disponíveis para replay sem prazo.

Dead-letter

Uma entrega entra em dead_letter quando:
  • Esgota as 7 tentativas sem nunca receber um 2xx; ou
  • O endpoint é desativado ou removido enquanto a entrega estava na fila (a tentativa encerra com response.error: "endpoint_disabled_or_missing"); ou
  • É uma entrega de teste que falhou (one-shot, não entra na fila de retry).
A fila de dead-letter é consultada por um endpoint próprio, sem a janela de 30 dias:
Aceita apenas limit (1 a 100, default 25) e starting_after para paginação por cursor, sem filtro de status (a fila já é só de dead_letter) e sem a janela de 30 dias. Veja Paginação.

Replay manual

Depois de corrigir o problema no seu endpoint, reenvie uma entrega exaurida com POST /deliveries/{deliveryId}/replay. O replay cria uma nova entrega pending (com replayOfId apontando para a original) e a submete ao cronograma de retry completo. A entrega original permanece intacta no log.
Resposta 202 Accepted com a nova entrega:
O POST aceita Idempotency-Key: reenviar a mesma chave devolve a resposta armazenada (Idempotent-Replay: true), sem criar uma segunda entrega. Veja Idempotência.

Regras e erros do replay

Replay para um endpoint disabled retorna 409 conflict. Reative o endpoint (PATCH status=active) antes de reenviar.
Retorna 404 resource_not_found. Recursos de outra organização também retornam 404 (consultas são escopadas por organização). Veja Erros.
O log é imutável: a entrega original mantém seu estado (failed ou dead_letter); a nova nasce pending referenciando-a por replayOfId.

Resumo das regras

  • Retry exponencial em 0s, 30s, 5m, 30m, 2h, 12h, 24h (7 tentativas). Esgotadas, vai para dead-letter (consultável, com replay manual). Endpoint com falha ≥ 95% em 72h (amostra mínima de 20) é desativado automaticamente.
  • Log de entregas (request, response, status, latência) disponível por 30 dias; dead-letters retidos sem prazo.

Visão geral

Como funcionam os webhooks, envelope e entrega at-least-once.

Assinatura

Valide o header Repass-Signature (HMAC-SHA256) das entregas.

Catálogo de eventos

A taxonomia de eventos que você pode assinar por endpoint.

Idempotência

Deduplique entregas reentregues e replays seguros.