Webhooks
Webhooks notificam seu sistema em tempo real quando algo acontece com seus documentos fiscais — sem precisar ficar consultando a API.
Eventos
| Evento | Quando dispara |
|---|---|
document.authorized | A NF-e/NFC-e/NFS-e foi autorizada pela SEFAZ/prefeitura |
document.rejected | A emissão foi rejeitada pelo fisco |
document.cancelled | Um documento autorizado foi cancelado |
document.inutilized | Um intervalo de numeração foi inutilizado |
Cadastrar um endpoint
Crie um endpoint via API (escopo webhooks:write) ou pela tela
Webhooks no painel. Selecione os eventos desejados — sem nenhum selecionado,
o endpoint recebe todos.
curl -X POST https://api.conttrole.io/v1/webhooks \
-H "Authorization: Bearer ck_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://seu-sistema.com/webhooks/conttrole",
"description": "Integração ERP",
"events": ["DOCUMENT_AUTHORIZED", "DOCUMENT_CANCELLED"]
}'A resposta traz o secret de assinatura uma única vez — guarde-o.
A URL precisa ser https e apontar para um host público — endereços internos/privados (localhost, IPs de rede interna, metadata de cloud) são recusados por segurança (proteção contra SSRF).
Formato da entrega
Cada evento é um POST JSON no seu endpoint:
{
"id": "evt_9f3a...",
"type": "document.authorized",
"createdAt": "2026-06-10T12:00:00.000Z",
"data": {
"documentId": "ckv...",
"type": "NFE",
"series": 1,
"number": 123,
"accessKey": "3526...",
"protocolNumber": "135...",
"totalValue": "199.90"
}
}Headers enviados:
| Header | Conteúdo |
|---|---|
X-Conttrole-Event | O tipo do evento (ex: document.authorized) |
X-Conttrole-Delivery | Id único da entrega |
X-Conttrole-Signature | t=<timestamp>,v1=<assinatura> |
Validar a assinatura
A assinatura é o HMAC-SHA256 de "<timestamp>.<corpo cru>", usando o
secret do endpoint. Recalcule e compare antes de confiar no payload.
import { createHmac, timingSafeEqual } from "crypto";
function verify(rawBody: string, header: string, secret: string): boolean {
const parts = Object.fromEntries(
header.split(",").map((kv) => kv.split("=")),
);
const expected = createHmac("sha256", secret)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
return timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}Entregas e retries
- Respostas 2xx marcam a entrega como entregue.
- Qualquer outra resposta (ou timeout de 10s) agenda novas tentativas com backoff exponencial (até 5 tentativas). Esgotadas, a entrega fica falha.
- Reenvio automático: ao esgotar as tentativas imediatas, a entrega é reagendada automaticamente com atraso crescente (até ~24h), caso seu endpoint volte do ar — sem você fazer nada.
- Reenvio manual: reenvie uma entrega específica via
POST /v1/webhooks/{id}/deliveries/{deliveryId}/redeliverou pelo botão Reenviar na tela Webhooks do painel. - Consulte as entregas recentes em
GET /v1/webhooks/{id}/deliveriesou na tela Webhooks do painel. - Use o
iddo evento (evt_...) para deduplicar no seu lado — a mesma entrega pode chegar mais de uma vez em cenários de retry.
Testar
Envie um evento de teste (webhook.test) sem emitir nada:
curl -X POST https://api.conttrole.io/v1/webhooks/{id}/test \
-H "Authorization: Bearer ck_live_..."A referência completa de todos os endpoints está em Referência da API.