Catálogo de eventos de webhook
A NFE.io publica eventos de webhook em duas famílias: eventos de saída — o que a sua conta emite (NFS-e, NF-e, NFC-e, guias e regras fiscais) — e eventos de entrada — documentos de terceiros que a NFE.io captura contra o seu CNPJ (NF-e, CT-e, NFS-e recebidas). Esta página indexa as duas.
Política de entrega
- Entrega: at-least-once. Garanta idempotência — nunca assuma que um evento chega uma única vez.
- Retry: reentrega automática em falha de rede ou resposta HTTP fora da faixa 2xx, até 16 tentativas com intervalo exponencial — exceto nos códigos de recusa definitiva, que não geram reentrega (veja abaixo).
- Timeout: 10 segundos nas três primeiras tentativas e 100 segundos a partir da quarta. Responda 2xx rápido e processe de forma assíncrona — retornar erro faz a NFE.io reenviar o mesmo evento, desde que o código não seja de recusa definitiva (veja abaixo).
- Assinatura: todo evento é assinado por HMAC no cabeçalho. Valide antes de processar — veja Dúvidas frequentes.
Quantas tentativas e em que intervalo
Em condições normais são 16 tentativas de entrega, contando a primeira. O intervalo cresce exponencialmente, e a última tentativa acontece cerca de 45 horas e 30 minutos depois do evento.
Os tempos da tabela contam só o intervalo entre tentativas. Se o seu endpoint não responde (em vez de recusar), some o timeout de cada tentativa — cerca de 20 minutos no total, o que empurra a última para perto de 45 h 50 min.
| Tentativa | Tempo desde o evento | Tentativa | Tempo desde o evento |
|---|---|---|---|
| 1 | imediato | 9 | 20 min 35 s |
| 2 | imediato | 10 | 41 min 50 s |
| 3 | 5 s | 11 | 1 h 24 min |
| 4 | 20 s | 12 | 2 h 50 min |
| 5 | 55 s | 13 | 5 h 40 min |
| 6 | 2 min 10 s | 14 | 11 h 22 min |
| 7 | 4 min 45 s | 15 | 22 h 44 min |
| 8 | 10 min | 16 | 45 h 29 min |
O cabeçalho X-Hook-Attempts traz quantas tentativas já falharam antes desta — ou seja, é 0 na primeira entrega, 1 na primeira reentrega e 15 na décima sexta e última. Para distinguir uma reentrega da entrega original, teste X-Hook-Attempts > 0.
Esgotadas as tentativas, o evento para de ser reenviado automaticamente — ele fica retido internamente, e um reenvio manual depende de acionar o suporte. O cadastro do webhook não é desativado — não existe desativação automática por falhas consecutivas, e os eventos seguintes continuam sendo entregues normalmente.
Respostas que interrompem a reentrega
Nem toda resposta fora da faixa 2xx gera nova tentativa. Estes códigos são tratados como recusa definitiva e o evento é descartado na hora, sem retentativa:
| Código | Significado |
|---|---|
400 Bad Request | o endpoint rejeitou o corpo do evento |
401 Unauthorized | credencial ausente ou inválida |
403 Forbidden | acesso negado ao endpoint |
404 Not Found | a URL cadastrada não existe |
405 Method Not Allowed | o endpoint não aceita POST |
422 Unprocessable Entity | o endpoint entendeu o corpo e o recusou |
422 numa falha temporária custa o eventoSe o seu endpoint responde 422 quando não consegue processar um evento, ele não será reenviado. Para que a reentrega aconteça, responda 500 — ou outro código de erro fora da lista acima — nas falhas temporárias do seu lado.
O código 410 Gone é a exceção no sentido oposto: é contabilizado como entrega aceita, e não como falha.
O cronograma e os timeouts acima são os vigentes hoje. São parâmetros de operação e podem ser ajustados — dimensione com margem e trate a janela como ordem de grandeza, não como garantia contratual.
Como descobrir qual evento chegou
| Origem | O que traz |
|---|---|
Cabeçalho X-Hook-Event | o eventType (ex.: service_invoice), sem a ação |
Cabeçalho X-Hook-Id | identificador único da entrega — use para deduplicar |
Cabeçalho X-Hook-Attempts | quantas tentativas já falharam antes desta — 0 na primeira entrega |
Corpo (action) | a ação do evento, sem o prefixo do tipo (ex.: issued_successfully) — use para saber o que aconteceu |
Corpo (flowStatus/status) | o estado da nota |
Os dois envelopes
Todo corpo traz o campo action na raiz, com a ação do evento sem o prefixo do tipo (ex.: issued_successfully, não service_invoice.issued_successfully). Isso vale para todos os eventTypes. O que muda entre eles é onde ficam os campos do documento:
| eventType | Família | Envelope |
|---|---|---|
service_invoice | Saída (NFS-e) | {"action": "...", "payload": {...}} |
product_invoice | Saída (NF-e) | achatado na raiz |
consumer_invoice | Saída (NFC-e) | achatado na raiz |
product_tax, tax_payment_form | Saída (outros) | achatado na raiz |
product_invoice_inbound, *_summary | Entrada | achatado na raiz |
transportation_invoice_inbound | Entrada | achatado na raiz |
service_invoice_inbound | Entrada | achatado na raiz (envelope próprio com document) |
Nos tipos achatados, action é mais uma chave da raiz, ao lado dos campos do documento. Se o webhook tiver properties cadastradas, elas chegam na chave properties, também na raiz. O ping (PUT /v2/webhooks/{id}/pings) chega com "action": "ping" e os dados do webhook na chave webHook.
Eventos de saída
O que a sua conta emite. 24 eventos cobertos, agrupados por produto:
| Página | Produto | Eventos |
|---|---|---|
| Catálogo de saída — NFS-e | Nota Fiscal de Serviço | 7 — emissão, cancelamento (sucesso e falha) |
| Catálogo de saída — NF-e | Nota Fiscal Eletrônica | 11 — emissão, cancelamento, inutilização, Carta de Correção |
| Catálogo de saída — NFC-e | Nota Fiscal de Consumidor | 5 — emissão, cancelamento |
| Catálogo de saída — Outros eventos | Regras fiscais e guias | 4 — product_tax, tax_payment_form |
Eventos de entrada
O que a NFE.io captura contra o seu CNPJ. 10 eventos, em uma única página de referência:
| Página | Cobre |
|---|---|
| Catálogo de entrada — Documentos recebidos | NF-e, resumo de NF-e, CT-e e NFS-e recebidos, incluindo manifestação do destinatário |
Para o guia didático dos eventos de entrada — com contexto de uso e exemplos de parsing — veja Payloads de webhooks de documentos recebidos.
Como validar a assinatura
Veja o exemplo de validação de HMAC em Dúvidas frequentes.