Webhooks
Em vez de polling, receba um POST do Notavia quando um job conclui (emissão, cancelamento,
CC-e ou inutilização — sucesso ou falha).
Configuração
Em Administração → Integração → Webhook (papel Admin):
- URL — endpoint HTTPS do seu sistema.
- Segredo — opcional, usado para assinar o corpo (recomendado).
O que chega
POST {sua-url}
Content-Type: application/json
X-Assinatura: 7F0E9A2B... (se houver segredo)
{
"evento": "job.concluido",
"jobId": "0e63b9a4-...",
"tipo": "Emissao",
"status": "Concluido",
"referenciaExterna": "pedido-1001",
"notaId": "53afd044-...",
"eventoId": null,
"dceId": null,
"nfseId": null,
"erro": null
}
tipo reflete o job: Emissao, Cancelamento, CartaCorrecao, Inutilizacao, EmissaoDce,
CancelamentoDce, EmissaoNfse ou CancelamentoNfse. O payload traz os identificadores
(notaId/eventoId/dceId/nfseId) — para obter a chave de acesso, o protocolo e as URLs de
download, faça o GET do job (/emissoes/{jobId}, /eventos/{jobId}, /dce/{jobId} ou
/nfse/{jobId}). Use referenciaExterna para casar com o registro no seu sistema.
Verificando a assinatura
X-Assinatura é o HMAC-SHA256 do corpo bruto da requisição, com o segredo configurado, em
hexadecimal maiúsculo. Sempre valide antes de confiar no payload:
// C#
var esperado = Convert.ToHexString(
HMACSHA256.HashData(Encoding.UTF8.GetBytes(segredo), corpoBruto));
var valido = CryptographicOperations.FixedTimeEquals(
Encoding.UTF8.GetBytes(esperado), Encoding.UTF8.GetBytes(header));
# Python
import hmac, hashlib
esperado = hmac.new(segredo.encode(), corpo_bruto, hashlib.sha256).hexdigest().upper()
valido = hmac.compare_digest(esperado, header)
Calcule sobre os bytes brutos do corpo, antes de qualquer parse/re-serialização do JSON.
Entrega e retries
- Sucesso = qualquer resposta 2xx. Responda rápido (idealmente
200imediato) e processe assíncrono do seu lado. - Falha (não-2xx, timeout, DNS…) → reentrega com backoff: 1 min, 5 min, 30 min, 2 h, 12 h. Esgotadas as 5 tentativas, a entrega é marcada como falha definitiva (fica auditável).
- Possível duplicidade: se seu endpoint demorar e o Notavia considerar timeout, a reentrega
gera o mesmo evento de novo. Trate o consumo de forma idempotente (dedup por
jobId). - Sem garantia de ordem entre jobs diferentes — use o
jobId/referenciaExterna, não a ordem de chegada.
Checklist do endpoint
- HTTPS com certificado válido.
- Responde 2xx em < 10 s (enfileire e responda).
- Valida
X-Assinatura(comparação em tempo constante). - Idempotente por
jobId. - Mesmo recebendo webhook, mantenha um polling de segurança de baixa frequência para jobs muito antigos sem resposta — redes falham.