Pular para o conteúdo
  • API
  • desenvolvedores
  • webhooks

Webhooks de nota fiscal: como saber na hora que a NFS-e foi autorizada

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

Neste artigo
  1. Por que a nota não é na hora
  2. Os eventos
  3. O formato
  4. Verificando a assinatura
  5. Um receptor confiável em 5 regras
  6. Reenvio e depuração
  7. Reconciliação: o plano B dos webhooks
  8. Resumo
  9. Perguntas frequentes

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.

Por que a nota não é "na hora"

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:

  • na NFS-e, a nota fica pendente e é reenviada até a autorização;
  • na NFC-e, a nota sai em contingência e é transmitida quando a SEFAZ volta.

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.

Os eventos

EventoQuando
document.createdA nota foi criada e entrou na fila
document.authorizedA nota foi autorizada
document.rejectedA nota foi rejeitada; o motivo vem explicado
document.blockedFalta um dado da empresa (certificado, inscrição…)
document.contingencyNFC-e emitida em contingência
document.cancelledO cancelamento foi registrado
document.cancel_deniedO órgão recusou o cancelamento
certificate.expiringO certificado A1 vence em 30, 15, 7 ou 1 dia
certificate.expiredO certificado A1 venceu

Notas blocked voltam para a fila sozinhas quando o dado chega; você recebe document.authorized depois.

O formato

HTTP
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.

Verificando a assinatura

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:

TypeScript
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:

  1. Use o corpo bruto, exatamente como chegou. Se o seu framework fizer o parse do JSON antes, a assinatura não bate.
  2. Recuse timestamps velhos (a função rejeita mais de 5 minutos de diferença), para evitar replay.

Um receptor confiável em 5 regras

  1. Verifique a assinatura antes de qualquer coisa.
  2. Responda 2xx rápido e processe em segundo plano. Respostas lentas viram reenvio.
  3. Deduplique pelo webhook-id: o mesmo evento pode chegar mais de uma vez.
  4. Não dependa da ordem: use o status da nota em data como verdade, não a sequência dos eventos.
  5. Use a reference para achar o pedido no seu sistema; ela é sua.

Reenvio e depuração

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.

Reconciliação: o plano B dos webhooks

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:

  1. Liste as notas que o seu sistema ainda considera pendentes.
  2. Consulte cada uma no SendNF (GET /v1/documents?reference=… ou pelo id).
  3. Atualize o status local a partir da resposta.

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.

Resumo

  • A emissão é assíncrona; webhooks avisam quando o status muda.
  • Eventos de nota (criada, autorizada, rejeitada, bloqueada, cancelada) e de certificado.
  • Assinatura Standard Webhooks: verifique com o corpo bruto e o segredo whsec_.
  • Responda rápido, deduplique pelo webhook-id e confie no status da nota.

Perguntas frequentes

Por que usar webhook em vez de consultar a 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.

Como verificar se o webhook veio mesmo do SendNF?

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 que acontece se o meu servidor estiver fora do ar?

O SendNF reenvia o evento com espera crescente entre as tentativas. Também dá para reenviar manualmente pelo painel ou pela API.

Posso receber o mesmo evento duas vezes?

Sim, como em qualquer sistema de webhooks com reenvio. Use o webhook-id para ignorar eventos já processados.

Quantos endpoints de webhook posso cadastrar?

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.

Leia também