Pular para o conteúdo

Webhooks

Os webhooks de saída avisam o seu sistema quando uma nota fiscal muda de status, sem você precisar consultar a API em loop. A Nive faz um POST com JSON na URL que você cadastrar.

Evento Quando
fiscal.document.authorized Nota autorizada pela SEFAZ
fiscal.document.rejected Nota rejeitada (veja rejection.code e rejection.message)
fiscal.document.cancelled Cancelamento homologado
fiscal.document.contingency Nota emitida em contingência, aguardando transmissão
fiscal.document.failed Falha local antes da SEFAZ (montagem ou assinatura do XML)

Venda criada, estoque e outros eventos não geram webhook. Para eles continue consultando a API.

A chave de API precisa de permissão fiscal (fiscal.view para consultar, fiscal.manage para cadastrar e alterar destinos). O escopo padrão Vendas, estoque e cadastros não inclui o módulo fiscal: crie a chave com permissions personalizadas (veja autenticação).

Janela do terminal
curl -X POST https://api.nivesistemas.com.br/outbound-webhooks \
-H "Authorization: Bearer sl_live_..." \
-H "X-Store-Slug: sua-loja" \
-H "Content-Type: application/json" \
-d '{"url":"https://seu-sistema.com.br/hooks/nive","description":"CRM"}'

A resposta traz o segredo (whsec_...) uma única vez. Guarde-o em um cofre. Se perder, gere outro com POST /outbound-webhooks/:id/rotate-secret.

Em produção a URL deve ser https e pública; endereços internos ou privados são recusados. Cada loja pode ter até 5 destinos. Use POST /outbound-webhooks/:id/test para enviar um evento webhook.test.

Header Conteúdo
X-Nive-Event Nome do evento
X-Nive-Delivery Identificador da entrega (use para deduplicar)
X-Nive-Timestamp Segundos desde 1970
X-Nive-Signature v1= + HMAC-SHA256 hexadecimal

Corpo:

{
"id": "…",
"event": "fiscal.document.authorized",
"createdAt": "2026-10-31T15:00:00.000Z",
"data": {
"documentId": "…",
"saleId": "…",
"model": 65,
"series": 1,
"number": 10,
"accessKey": "42…",
"status": "AUTHORIZED",
"protocol": "…",
"environment": "PRODUCTION",
"issuedAt": "2026-10-31T14:59:58.000Z",
"qrCodeUrl": "https://…",
"rejection": null,
"contingency": null,
"cancellation": null,
"links": {
"document": "/fiscal/documents/…",
"xml": "/fiscal/documents/…/xml",
"pdf": "/fiscal/documents/…/pdf"
}
}
}

Os links são caminhos da API: baixe o XML e o DANFE com a sua chave.

A assinatura é o HMAC-SHA256 do texto {timestamp}.{corpo bruto} com o segredo whsec_. Calcule sobre o corpo exatamente como recebido e compare em tempo constante. Rejeite timestamps com mais de 5 minutos de diferença.

import { createHmac, timingSafeEqual } from "node:crypto";
function valid(secret, timestamp, rawBody, signature) {
const expected = "v1=" + createHmac("sha256", secret)
.update(timestamp + "." + rawBody).digest("hex");
const a = Buffer.from(expected), b = Buffer.from(signature);
return a.length === b.length && timingSafeEqual(a, b);
}
  • Responda 2xx em até 10 segundos. Qualquer outra resposta, ou timeout, conta como falha.
  • Redirecionamentos não são seguidos.
  • Em falha, a Nive reenvia após 1 min, 5 min, 15 min, 1 h, 3 h, 6 h, 12 h e 24 h. Esgotadas as tentativas, a entrega fica como FAILED.
  • A entrega é pelo menos uma vez: pode chegar repetida. Deduplique por X-Nive-Delivery ou por documentId + status.
  • A ordem não é garantida entre documentos. Trate contingency seguido de authorized como o fluxo normal da contingência.

Consulte as últimas entregas em GET /outbound-webhooks/:id/deliveries e reenvie uma falha com POST /outbound-webhooks/:id/deliveries/:deliveryId/retry.

Use o webhook como aviso e a consulta (GET /fiscal/documents/by-sale/:saleId) como conferência: se o seu sistema ficou fora do ar por mais de 24 horas, reconcilie por consulta.