Entrega e retentativas
Ciclo de vida de uma entrega, idempotência, backoff exponencial, desativação automática e diagnóstico.
Cada evento assinado vira uma entrega (delivery): uma linha com histórico próprio, visível no painel em Configurações > WebHooks, na aba Histórico do endpoint.
Ciclo de vida
| Status | O que significa |
|---|---|
| Pendente | A entrega foi criada e aguarda o primeiro envio |
| Processando | O envio está em curso |
| Entregue | O seu servidor respondeu 2xx |
| Falhou | A tentativa não deu certo e há uma nova agendada |
| Esgotado | As tentativas acabaram. Não haverá reenvio automático |
O detalhe de cada entrega registra as tentativas feitas, o status HTTP e o corpo da sua resposta (primeiros 1.024 caracteres), o tempo de resposta e a mensagem de erro quando houve falha de conexão.
Idempotência é obrigatória
O bitERP garante entrega pelo menos uma vez, não exatamente uma vez. Uma resposta 2xx que se perca na rede, um timeout do seu lado que na verdade processou, um reenvio manual — todos produzem uma segunda chegada do mesmo evento.
Use o id do payload (idêntico ao header x-biterp-webhook-id) como chave de deduplicação. Ele é estável entre todas as tentativas do mesmo evento, inclusive nos reenvios manuais.
// Guarde o id antes de processar; ignore o que já viu
const known = await db.webhookEvents.findUnique({ where: { id: event.id } })
if (known) return res.status(200).send("duplicate")
await db.webhookEvents.create({ data: { id: event.id, type: event.event_type } })A ordem não é garantida
Entregas são independentes e podem ser processadas em paralelo, com retentativas em momentos diferentes. Um sales-orders.update que falhou e voltou duas horas depois chega depois de um update mais recente do mesmo pedido.
A consequência prática: não reconstrua estado a partir da sequência de eventos. Trate cada evento como um convite a buscar o estado atual via API de Integrações — o GET sempre devolve a versão mais recente, o que torna a ordem de chegada irrelevante. Se você precisa descartar processamento obsoleto, compare o updated_at do recurso com o que já gravou, não o timestamp do evento.
Retentativas e backoff
Toda tentativa que não resulte em 2xx dentro de 10 segundos agenda a próxima, com espera exponencial a partir de 1 minuto e teto de 6 horas:
| Tentativa | Espera até a próxima |
|---|---|
| 1 | 1 minuto |
| 2 | 2 minutos |
| 3 | 4 minutos |
| 4 | 8 minutos |
| 5 | 16 minutos |
| 6 | 32 minutos |
| 7 | 1 hora e 4 minutos |
| 8 | 2 horas e 8 minutos |
| 9 | 4 horas e 16 minutos |
| 10 em diante | 6 horas (teto) |
São 20 tentativas no total, o que estende a entrega por cerca de 2 dias e 20 horas. Depois disso a entrega fica Esgotada e só volta a ser enviada por reenvio manual.
Uma indisponibilidade curta do seu servidor é absorvida sem perda. Uma queda mais longa que essa janela exige ação no painel.
Desativação automática (circuit breaker)
Falhas consecutivas em um endpoint — de qualquer entrega — incrementam um contador. Qualquer entrega bem-sucedida zera esse contador.
| Falhas consecutivas | O que acontece |
|---|---|
| 10 | Os administradores da empresa recebem um aviso no painel, uma vez por episódio |
| 20 | O endpoint é desativado automaticamente e os administradores são notificados |
Enquanto o endpoint está desativado, nenhuma entrega nova é criada — os eventos daquele período não ficam em fila esperando. É por isso que o aviso aos 10 existe: ele dá margem para corrigir antes do desligamento.
Ao reativar o endpoint no painel, o bitERP executa um backfill da janela em que ele esteve fora e gera as entregas que faltaram. A recuperação alcança até 90 dias, limitada pela retenção da trilha de auditoria, e processa um volume máximo por execução — em janelas longas ou de muito movimento, parte dos eventos pode não ser recuperada. Reative o quanto antes.
Reenviar manualmente
Na aba Histórico do endpoint, entregas com status Falhou ou Esgotado têm a ação Reenviar. Ela devolve a entrega ao início do ciclo: o contador de tentativas volta a zero e o envio é refeito imediatamente.
O id do evento não muda no reenvio — a sua deduplicação continua funcionando, e um evento já processado com sucesso do seu lado será corretamente ignorado.
Retenção do histórico
Entregas são apagadas após 30 dias, independentemente do status. O histórico serve para diagnóstico recente, não como registro permanente: se a sua integração precisa de trilha de auditoria, guarde os eventos do seu lado ao recebê-los.
Diagnóstico
| Sintoma | Onde olhar | Ação |
|---|---|---|
| Nenhuma entrega aparece no histórico | Status do endpoint | Se estiver desativado, reative — o backfill recupera a janela |
| Nenhuma entrega para um recurso específico | Lista de eventos assinados | O evento pode não estar na assinatura, ou o recurso pode não ser assinável |
| Entregas param de repente em horários de pico | Volume por hora | O teto de 1.000 entregas por hora foi atingido; reduza os eventos assinados |
Todas as entregas com status 401 | Sua verificação de assinatura | Ver erros comuns |
| Entregas com timeout e tempo de resposta próximo de 10 s | Seu handler | Responda 2xx antes de processar |
| Entregas com erro de conexão e sem status HTTP | DNS e certificado do endpoint | Confirme que a URL resolve para um IP público e que o certificado TLS é válido |
| Eventos duplicados no seu sistema | Sua deduplicação | Use o id do evento, não o resource.id |
Quando abrir um chamado de suporte, informe o id do evento (x-biterp-webhook-id): ele identifica a entrega exata no histórico.

