Entrega e retentativas
As regras
| Parâmetro | Valor |
|---|---|
| Sucesso | Qualquer resposta 2xx |
| Timeout | 20 segundos |
| Tentativas | 6 — uma imediata e cinco retentativas |
| Intervalos | 60s · 5min · 30min · 2h · 6h |
| Desativação automática | Após 50 falhas consecutivas |
Qualquer coisa que não seja 2xx conta como falha: 3xx, 4xx, 5xx, timeout, erro de
DNS, TLS inválido. Redirecionamentos não são seguidos — um 301 é falha.
Esgotadas as seis tentativas, a entrega fica em failed e não é mais tentada
automaticamente. O tempo total entre a primeira e a última é de cerca de 9 horas.
Por que responder rápido
O timeout vale para a resposta inteira, headers e corpo. Um handler que processa antes de responder tem 20 segundos para tudo — e um pico de tráfego derruba isso fácil.
// Errado
app.post('/webhooks', async (req, res) => {
await salvarNoBanco(req.body);
await chamarCrm(req.body);
await notificarEquipe(req.body);
res.sendStatus(200); // pode nunca chegar a tempo
});
// Certo
app.post('/webhooks', (req, res) => {
res.sendStatus(200);
fila.enfileirar(req.body);
});
Idempotência
Como uma entrega pode ser repetida, o mesmo evento vai chegar mais de uma vez. Não é exceção: é o comportamento normal quando o seu servidor responde devagar ou oscila.
Duas chaves de deduplicação:
X-Joinotify-Delivery— estável entre as retentativas daquela entrega- O
wamidda mensagem — estável mesmo se você reenviar manualmente
const jaProcessado = await redis.set(`webhook:${deliveryId}`, '1', { NX: true, EX: 86400 });
if (!jaProcessado) {
return; // repetição, ignore
}
Desativação automática
Cada falha incrementa failureCount; qualquer sucesso zera. Chegando a 50 falhas
consecutivas, o endpoint é desativado: active: false, disabledAt preenchido, e as
entregas seguintes são marcadas como failed com "Endpoint is inactive.".
Isso protege os dois lados — nós paramos de bater num servidor que claramente não está lá, e você não recebe uma avalanche quando ele voltar.
# Reativar: o contador zera junto
curl -X PATCH https://api.joinotify.com/webhook-endpoints/whe_01J8ZK... \
-H 'Authorization: Bearer sk_live_xxx' \
-H 'Content-Type: application/json' \
-d '{ "active": true }'
Monitore failureCount antes de chegar a 50. Um endpoint com 30 falhas já está com
problema.
Investigando
curl 'https://api.joinotify.com/webhook-endpoints/deliveries?status=failed&limit=20' \
-H 'Authorization: Bearer sk_live_xxx'
{
"data": [
{
"id": "whd_01J8ZM...",
"endpointId": "whe_01J8ZK...",
"field": "messages",
"status": "failed",
"attempt": 6,
"responseStatus": 500,
"responseBody": "Internal Server Error",
"error": null,
"durationMs": 18412,
"nextRetryAt": null,
"createdAt": "2026-07-27T14:02:11.482Z"
}
]
}
| Campo | O que revela |
|---|---|
responseStatus | O que o seu servidor devolveu — null significa que nem respondeu |
responseBody | O corpo da resposta, truncado em 2000 caracteres |
error | Falha de transporte: DNS, TLS, timeout |
durationMs | Perto de 20000 indica timeout |
attempt | Em qual das seis tentativas parou |
responseStatus: null com error preenchido é problema de rede ou certificado, não
de código. durationMs perto de 20000 é handler lento.
Reenviando
curl -X POST https://api.joinotify.com/webhook-endpoints/deliveries/whd_01J8ZM.../redeliver \
-H 'Authorization: Bearer sk_live_xxx'
Cria uma entrega nova em vez de reciclar a antiga, preservando o histórico da falha original. O ciclo de seis tentativas recomeça.
Para reprocessar em massa depois de um incidente, liste as falhas do período e reenvie uma a uma:
curl 'https://api.joinotify.com/webhook-endpoints/deliveries?status=failed&limit=200' \
-H 'Authorization: Bearer sk_live_xxx' \
| jq -r '.data[].id' \
| while read id; do
curl -sS -X POST "https://api.joinotify.com/webhook-endpoints/deliveries/$id/redeliver" \
-H 'Authorization: Bearer sk_live_xxx' > /dev/null
done
Rede de segurança
Mesmo com retentativas, um evento pode se perder — endpoint fora do ar por mais de nove
horas, por exemplo. Para dados críticos, vale uma reconciliação periódica contra
GET /events, que guarda o histórico bruto independentemente das entregas.