O webhook é o aviso automático: quando a nota é autorizada, recusada, cancelada ou corrigida, a API chama um endereço do seu sistema com a nota no corpo. É opcional, mas evita que o seu sistema fique perguntando "e aí, saiu?".
Configurar
- No painel: API de Nota Fiscal › Chaves e webhook.
- Informe um endereço https público do seu sistema. Endereço interno (rede local, localhost) é recusado.
- Copie o segredo do webhook: ele aparece uma única vez e serve para conferir a assinatura.
O que chega
POST https://seu-sistema.com.br/avisos/nota
X-DataFrontier-Evento: nfe.autorizada
X-DataFrontier-Entrega: 7f3c... (id desta entrega)
X-DataFrontier-Assinatura: t=1727450000,v1=9a1b...
{ "evento": "nfe.autorizada", "entrega": "7f3c...", "ocorridoEm": "...", "nota": { ... } }Os eventos: nfe.autorizada, nfe.rejeitada, nfe.cancelada, nfe.carta-correcao, nfse.autorizada, nfse.rejeitada e nfse.cancelada. A nota vem no mesmo formato da resposta da emissão.
Conferir a assinatura
Qualquer um pode chamar o seu endereço. A assinatura prova que o aviso saiu da Data Frontier e não foi alterado: é um HMAC-SHA256 do texto "t.corpo" com o seu segredo. Confira sempre com o corpo cru, exatamente como chegou, antes de convertê-lo em JSON.
const crypto = require('crypto');
function avisoValido(corpoCru, cabecalho, segredo) {
const partes = Object.fromEntries(cabecalho.split(',').map((p) => p.split('=')));
const idade = Math.abs(Date.now() / 1000 - Number(partes.t));
if (!partes.t || !partes.v1 || idade > 300) return false; // mais de 5 min: recusa
const esperado = crypto.createHmac('sha256', segredo)
.update(`${partes.t}.${corpoCru}`).digest('hex');
return esperado.length === partes.v1.length &&
crypto.timingSafeEqual(Buffer.from(esperado), Buffer.from(partes.v1));
}import hmac, hashlib, time
def aviso_valido(corpo_cru: bytes, cabecalho: str, segredo: str) -> bool:
partes = dict(p.split("=", 1) for p in cabecalho.split(","))
if abs(time.time() - int(partes.get("t", 0))) > 300:
return False
msg = partes["t"].encode() + b"." + corpo_cru
esperado = hmac.new(segredo.encode(), msg, hashlib.sha256).hexdigest()
return hmac.compare_digest(esperado, partes.get("v1", ""))Responder e aguentar repetição
- Responda 2xx rápido e processe depois. Respostas 408, 429 e 5xx são tentadas de novo com espera crescente, até 10 vezes. Outros 4xx não são repetidos.
- O mesmo aviso pode chegar mais de uma vez: guarde o X-DataFrontier-Entrega e ignore o que já processou.
- Avisos podem chegar fora de ordem: decida pela situacao da nota, não pela ordem de chegada. Uma nota cancelada não volta a ser autorizada.
Conhecer a API de nota fiscal Documentação completa
Tutorial escrito pela equipe da API em 29 de setembro de 2026, conferido com a versão v1 no ar. Regra fiscal muda: o enquadramento de imposto da sua empresa é com o seu contador. Viu algo desatualizado? Fale com a gente pelo WhatsApp.