API de nota fiscal: o que é e como escolher a certa para o seu sistema
O que uma API de nota fiscal faz, quando vale a pena em vez de integrar direto com a Receita e as prefeituras, e os 10 critérios para comparar fornecedores.
5 min de leitura
Por que a emissão de nota é assíncrona, quais eventos acompanhar, como verificar a assinatura (Standard Webhooks), tratar repetições e montar um receptor confiável.
Equipe SendNFPublicado em 4 min de leituraMarkdown
Webhooks são chamadas que o SendNF faz para o seu sistema quando algo muda numa nota: autorizada, rejeitada, bloqueada por falta de dado, cancelada. Eles existem porque a emissão é assíncrona: a autorização depende da Receita, da prefeitura ou da SEFAZ, que podem responder em segundos ou ficar fora do ar por horas. Em vez de consultar a nota de tempos em tempos, você cadastra uma URL e recebe um POST assinado no padrão Standard Webhooks a cada mudança. Verifique a assinatura, use o webhook-id para não processar o mesmo evento duas vezes e responda 2xx rápido.
Mesmo quando a nota sai em segundos, o caminho tem etapas que você não controla: a fila, a assinatura, a transmissão, a resposta do órgão. Quando o órgão cai:
Um sistema que espera a resposta na mesma requisição ou trava o usuário ou perde a nota. Com webhooks, você responde ao usuário na hora ("nota em emissão") e atualiza quando o evento chegar. Para fluxos interativos, o SendNF também aceita ?wait=true, que espera até cerca de 25 segundos, mas o webhook continua sendo a fonte da verdade.
| Evento | Quando |
|---|---|
document.created | A nota foi criada e entrou na fila |
document.authorized | A nota foi autorizada |
document.rejected | A nota foi rejeitada; o motivo vem explicado |
document.blocked | Falta um dado da empresa (certificado, inscrição…) |
document.contingency | NFC-e emitida em contingência |
document.cancelled | O cancelamento foi registrado |
document.cancel_denied | O órgão recusou o cancelamento |
certificate.expiring | O certificado A1 vence em 30, 15, 7 ou 1 dia |
certificate.expired | O certificado A1 venceu |
Notas blocked voltam para a fila sozinhas quando o dado chega; você recebe document.authorized depois.
POST /webhooks/sendnf HTTP/1.1
webhook-id: 7c1d9a52-3f0e-4c1b-9d6e-2a8f4b7e1c90
webhook-timestamp: 1792512000
webhook-signature: v1,K5oZfzN95Z9UVu1EsfQmfVNQhnkZ2pj9o9NDN/H/pI4=
{
"id": "7c1d9a52-3f0e-4c1b-9d6e-2a8f4b7e1c90",
"type": "document.authorized",
"mode": "live",
"created_at": "2026-10-20T14:32:05.120Z",
"data": { "id": "…", "object": "nfse", "status": "authorized", "reference": "pedido-1042", "nfse_number": "1042" }
}O campo data é a nota no mesmo formato da API, com a sua reference, o número e os links do PDF e do XML. Webhooks de teste e de produção são separados: um endpoint cadastrado com chave de teste só recebe eventos de homologação.
A assinatura segue o padrão Standard Webhooks: HMAC-SHA256 com o segredo do endpoint (whsec_…) sobre id.timestamp.corpo, em base64, prefixado por v1,. Com o SDK:
import { verifyWebhook } from '@sendnf/sdk';
const ok = await verifyWebhook({
secret: process.env.SENDNF_WEBHOOK_SECRET!,
id: req.header('webhook-id')!,
timestamp: req.header('webhook-timestamp')!,
signature: req.header('webhook-signature')!,
body: rawBody,
});Dois cuidados que derrubam muita integração:
webhook-id: o mesmo evento pode chegar mais de uma vez.status da nota em data como verdade, não a sequência dos eventos.reference para achar o pedido no seu sistema; ela é sua.Se o seu endpoint falhar, o SendNF reenvia com espera crescente. No painel (e pela API) você vê cada entrega, o status HTTP recebido, o erro e pode reenviar manualmente. Para testar o receptor, dispare um evento de teste pelo painel ou por POST /v1/webhooks/test.
Por segurança, em produção os webhooks só vão para URLs HTTPS que apontem para endereços públicos.
Mesmo com reenvio, trate os webhooks como a forma rápida de saber, não a única. Uma rotina de reconciliação, rodando algumas vezes por dia, fecha as lacunas:
GET /v1/documents?reference=… ou pelo id).Com isso, um deploy mal feito no seu receptor, ou uma janela de indisponibilidade maior que o período de reenvio, não deixa nota sem status. A reference que você envia na emissão é o elo entre os dois lados: use o id do pedido, da venda ou da fatura.
whsec_.webhook-id e confie no status da nota.Porque a autorização depende de sistemas externos (Receita, prefeitura, SEFAZ) e pode levar de segundos a horas quando eles estão fora do ar. O webhook avisa o seu sistema no momento em que o status muda, sem consultas repetidas.
Pela assinatura no header webhook-signature, calculada com HMAC-SHA256 sobre o id, o timestamp e o corpo, no padrão Standard Webhooks. O SDK do SendNF tem a função verifyWebhook.
O SendNF reenvia o evento com espera crescente entre as tentativas. Também dá para reenviar manualmente pelo painel ou pela API.
Sim, como em qualquer sistema de webhooks com reenvio. Use o webhook-id para ignorar eventos já processados.
Você pode cadastrar mais de um endpoint por modo (teste ou produção) e escolher os eventos de cada um, por exemplo um para o financeiro e outro para o suporte. Cada endpoint tem o próprio segredo de assinatura.
Equipe SendNF
Publicado em
A equipe que mantém o motor fiscal do SendNF: a geração da DPS nacional, a integração com os provedores das prefeituras, a NFC-e e as explicações para cada rejeição que encontramos emitindo notas reais.
O que uma API de nota fiscal faz, quando vale a pena em vez de integrar direto com a Receita e as prefeituras, e os 10 critérios para comparar fornecedores.
5 min de leitura
O que são os ambientes de homologação e produção na NFS-e e na NFC-e, o que muda na nota de teste, a Produção Restrita do padrão nacional e como separar testes no seu sistema.
4 min de leitura
Quando cancelar uma NFS-e, quais motivos informar, como funciona o evento de cancelamento no padrão nacional e nas prefeituras, e o que fazer fora do prazo.
4 min de leitura