Atualizado em .
Webhooks
Para não travar o ERP aguardando resposta da SEFAZ, a plataforma envia mudanças de status por webhook. O endpoint pode ser cadastrado por empresa e receberá os eventos assinados pela plataforma.
https://fiscal.contora.com.br/api/v1/webhooks?page=1&per_page=20&is_active=1
https://fiscal.contora.com.br/api/v1/webhooks
{
"company_id": "uuid-da-empresa",
"url": "https://seu-erp.com.br/webhooks/fiscal",
"secret": "segredo-para-assinatura",
"events": [
"document.queued",
"document.processing_started",
"document.authorized",
"document.rejected",
"document.cancelled",
"document.cancellation_rejected",
"document.failed",
"nfe.received"
]
}
Catálogo de eventos suportados
O ciclo de vida de todos os documentos fiscais emitidos pela plataforma (NF-e modelo 55, NFC-e modelo 65, NFS-e, CT-e e MDF-e) é unificado sob o prefixo document.*. Eventos de documentos recebidos de fornecedores utilizam o prefixo nfe.*, e eventos de gestão cadastral utilizam company.*.
document.authorizeddocument.rejectedlast_error_code, last_error_message e o status code devolvido pela SEFAZ no context.document.cancelledcancellation_protocol, cancellation_status_code e data de cancelamento.document.cancellation_rejecteddocument.faileddocument.queueddocument.processing_startednfe.receivedcompany.certificate_expiringcompany.certificate_expireddocument.*) e de notas recebidas (nfe.received), a propriedade data.environment contém sempre as strings literais em minúsculas: producao ou homologacao. Eventos administrativos como company.certificate_* não possuem o campo environment pois são vinculados diretamente ao cadastro da empresa.
Cadastro no console
Se a equipe ainda estiver em onboarding, o caminho mais simples é cadastrar o endpoint pelo próprio console da plataforma. Hoje o painel ja permite criar, ativar, testar e reenfileirar entregas com falha.
Histórico operacional
As listagens de endpoints, deliveries e pings de teste seguem o mesmo padrão paginado da API, com
meta e links. Isso facilita auditoria, telas administrativas e sincronizacao
incremental no ERP integrador.
GET https://fiscal.contora.com.br/api/v1/webhooks/{endpoint}/deliveries?page=1&per_page=20&status=failed&event=document.authorized
GET https://fiscal.contora.com.br/api/v1/webhooks/{endpoint}/tests?page=1&per_page=20&status=failed
Rotação de secret
Se o secret do webhook for comprometido ou precisar ser rotacionado por política de segurança, use o endpoint dedicado. O novo secret é retornado apenas uma vez na resposta.
https://fiscal.contora.com.br/api/v1/webhooks/{endpoint}/rotate-secret
POST https://fiscal.contora.com.br/api/v1/webhooks/{endpoint}/rotate-secret
{
"ok": true,
"message": "Secret rotacionado com sucesso. Atualize seu endpoint em até 24 horas.",
"data": {
"id": "uuid-do-endpoint",
"secret": "novo-secret-gerado-automaticamente",
"secret_rotated_at": "2026-07-11T10:30:00-03:00",
"migration_deadline": "2026-07-12T10:30:00-03:00",
"signature_migration": {
"primary_header": "X-Fiscal-Signature",
"next_header": "X-Fiscal-Signature-Next"
}
}
}
X-Fiscal-Signature usa o secret anterior e X-Fiscal-Signature-Next usa o novo. Depois do prazo, o novo passa a ser a assinatura principal.
webhook.secret_rotated é enfileirado para o próprio endpoint.
X-Fiscal-Signature-Next com o novo secret. Ao fim das 24 horas,
X-Fiscal-Signature passará automaticamente a usar esse novo secret.
Estratégia de retry
A plataforma utiliza backoff exponencial com jitter para retries de webhooks falhos. Isso evita sobrecarga no endpoint do integrador em caso de falhas temporárias.
https://fiscal.contora.com.br/api/v1/webhooks/{endpoint}/retry-info
GET https://fiscal.contora.com.br/api/v1/webhooks/{endpoint}/retry-info
{
"ok": true,
"data": {
"endpoint_id": "uuid-do-endpoint",
"retry_strategy": {
"pattern": [30, 60, 120, 240, 480, 960, 1920, 3600],
"description": "Backoff exponencial com jitter: ~30s, ~60s, ~120s, ~240s, ~480s, ~960s, ~1920s, ~3600s",
"total_max_wait_seconds": 7410
},
"max_attempts": 8,
"rules": {
"server_errors": "Repete em caso de status 5xx",
"rate_limits": "Repete em caso de status 429",
"timeouts": "Repete em caso de status 408",
"client_errors": "Não repete em caso de status 4xx (exceto 429 e 408)"
}
}
}
Headers e assinatura
Os webhooks da v1 usam os cabeçalhos abaixo.
X-Fiscal-EventX-Fiscal-Delivery-IdX-Fiscal-Idempotency-KeyX-Fiscal-AttemptX-Fiscal-TimestampX-Fiscal-Signaturetimestamp.body usando o segredo do endpoint.assinatura = hex(hmac_sha256(timestamp + "." + body, secret))
Exemplo 1: NF-e Autorizada (document.authorized)
POST /webhooks/fiscal HTTP/1.1
Content-Type: application/json
User-Agent: Fiscal-Contora-Webhook/1.0
X-Fiscal-Event: document.authorized
X-Fiscal-Delivery-Id: 4812
X-Fiscal-Idempotency-Key: delivery-4812
X-Fiscal-Attempt: 1
X-Fiscal-Timestamp: 2026-10-21T08:55:25-03:00
X-Fiscal-Signature: c8f3...
{
"id": 9931,
"event": "document.authorized",
"created_at": "2026-10-21T08:55:25-03:00",
"data": {
"document_id": "80851398-6707-42a2-9fb5-89fee809b9f2",
"document_type": "nfe",
"status": "authorized",
"processing_status": "completed",
"environment": "producao",
"series": 1,
"number": 5622,
"access_key": "35261016834821000163550010000056221267987067",
"protocol": "135264472169093",
"cancellation_status": null,
"cancellation_protocol": null,
"cancellation_status_code": null,
"cancellation_status_message": null,
"cancelled_at": null,
"correction_status": null,
"correction_sequence": 0,
"correction_protocol": null,
"correction_status_code": null,
"correction_status_message": null,
"corrected_at": null,
"last_error_code": null,
"last_error_message": null,
"artifacts": {
"xml_unsigned": "https://fiscal.contora.com.br/api/v1/nfe/drafts/80851398-6707-42a2-9fb5-89fee809b9f2/artifacts/xml_unsigned",
"xml_signed": "https://fiscal.contora.com.br/api/v1/nfe/drafts/80851398-6707-42a2-9fb5-89fee809b9f2/artifacts/xml_signed",
"xml_authorized": "https://fiscal.contora.com.br/api/v1/nfe/drafts/80851398-6707-42a2-9fb5-89fee809b9f2/artifacts/xml_authorized",
"pdf": "https://fiscal.contora.com.br/api/v1/nfe/drafts/80851398-6707-42a2-9fb5-89fee809b9f2/artifacts/pdf_danfe"
}
},
"context": {
"action": "authorize",
"sefaz_status_code": "100",
"protocol": "135264472169093"
}
}
Exemplo 2: NF-e Rejeitada pela SEFAZ (document.rejected)
POST /webhooks/fiscal HTTP/1.1
Content-Type: application/json
User-Agent: Fiscal-Contora-Webhook/1.0
X-Fiscal-Event: document.rejected
X-Fiscal-Delivery-Id: 4813
X-Fiscal-Idempotency-Key: delivery-4813
X-Fiscal-Attempt: 1
X-Fiscal-Timestamp: 2026-10-21T08:55:31-03:00
X-Fiscal-Signature: e4a1...
{
"id": 9932,
"event": "document.rejected",
"created_at": "2026-10-21T08:55:31-03:00",
"data": {
"document_id": "3fa296c9-072e-414e-913b-f30016172054",
"document_type": "nfe",
"status": "error",
"processing_status": "completed",
"environment": "producao",
"series": 1,
"number": 466,
"access_key": "35261056390185000142550010000004661056506881",
"protocol": null,
"cancellation_status": null,
"cancellation_protocol": null,
"cancellation_status_code": null,
"cancellation_status_message": null,
"cancelled_at": null,
"correction_status": null,
"correction_sequence": 0,
"correction_protocol": null,
"correction_status_code": null,
"correction_status_message": null,
"corrected_at": null,
"last_error_code": "732",
"last_error_message": "Rejeição: CFOP de operação interestadual e idDest <> 2",
"artifacts": {
"xml_unsigned": "https://fiscal.contora.com.br/api/v1/nfe/drafts/3fa296c9-072e-414e-913b-f30016172054/artifacts/xml_unsigned",
"xml_signed": "https://fiscal.contora.com.br/api/v1/nfe/drafts/3fa296c9-072e-414e-913b-f30016172054/artifacts/xml_signed",
"pdf": "https://fiscal.contora.com.br/api/v1/nfe/drafts/3fa296c9-072e-414e-913b-f30016172054/artifacts/pdf_danfe"
}
},
"context": {
"action": "authorize",
"sefaz_status_code": "732",
"sefaz_status_message": "Rejeição: CFOP de operação interestadual e idDest <> 2"
}
}
Exemplo 3: NF-e Recebida de Fornecedor via DF-e (nfe.received)
POST /webhooks/fiscal HTTP/1.1
Content-Type: application/json
User-Agent: Fiscal-Contora-Webhook/1.0
X-Fiscal-Event: nfe.received
X-Fiscal-Delivery-Id: 4814
X-Fiscal-Idempotency-Key: delivery-4814
X-Fiscal-Attempt: 1
X-Fiscal-Timestamp: 2026-10-21T08:56:00-03:00
X-Fiscal-Signature: 7b29...
{
"id": "e229be60-d621-4f1b-bd63-bfa6403597d3",
"event": "nfe.received",
"created_at": "2026-10-21T08:56:00-03:00",
"company_id": "4e72ce53-a553-4877-bb89-72f1076f8e77",
"data": {
"received_id": "993a4087-3ce9-4dc6-b51c-ca04bfdf2146",
"environment": "producao",
"access_key": "31261000000000000191550010000001231000001234",
"emitter_document": "12345678000195",
"emitter_name": "FORNECEDOR INDUSTRIAL LTDA",
"total_amount": 14500.50,
"issued_at": "2026-10-21T07:30:00-03:00",
"has_full_xml": false,
"manifest_type": null
}
}
X-Fiscal-Idempotency-Key e não permita regressão do estado conhecido. A plataforma não publica uma allowlist fixa de IPs; a autenticidade vem da assinatura HMAC. Como proteção anti-replay, recomendamos rejeitar timestamps com diferença superior a 5 minutos, depois de validar a assinatura.
Exemplo de Validação em PHP:
<?php
$secret = 'seu_webhook_secret';
$timestamp = $_SERVER['HTTP_X_FISCAL_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_FISCAL_SIGNATURE'] ?? '';
$body = file_get_contents('php://input');
$payload = $timestamp . '.' . $body;
$expectedSignature = hash_hmac('sha256', $payload, $secret);
if (hash_equals($expectedSignature, $signature)) {
// Assinatura válida, processe o evento com segurança!
http_response_code(200);
} else {
// Assinatura inválida!
http_response_code(401);
}
Exemplo de Validação em Node.js (Express):
const crypto = require('crypto');
const express = require('express');
const app = express();
app.post('/webhooks/fiscal', express.raw({type: 'application/json'}), (req, res) => {
const secret = 'seu_webhook_secret';
const timestamp = req.headers['x-fiscal-timestamp'];
const signature = req.headers['x-fiscal-signature'];
const body = req.body;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(timestamp + '.')
.update(body)
.digest('hex');
const validLength = typeof signature === 'string' && signature.length === expectedSignature.length;
const valid = validLength && crypto.timingSafeEqual(
Buffer.from(expectedSignature, 'hex'),
Buffer.from(signature, 'hex')
);
if (!valid) return res.sendStatus(401);
res.sendStatus(200);
});
Resiliência, Workers Isolados & Circuit Breaker
O pipeline de entrega de webhooks da Fiscal Contora foi projetado para operar em alta escala sem criar gargalos operacionais ou dependências cruzadas com o faturamento.
fiscal-webhooks, com workers dedicados e separados da fila de emissão fiscal-documents. Lentidões ou indisponibilidades no seu servidor receptor nunca afetam nem atrasam a autorização de notas fiscais na SEFAZ.
PATCH /webhooks/{id} com {"is_active": true}.
Endpoints disponíveis
GET /webhooksPOST /webhooksGET /webhooks/{id}PATCH /webhooks/{id}POST /webhooks/{id}/rotate-secretGET /webhooks/{id}/retry-infoPOST /webhooks/{id}/testGET /webhooks/{id}/testsGET /webhooks/{id}/deliveriesPOST /webhooks/{id}/deliveries/{delivery}/redeliverUso recomendado
- Responder rapidamente com HTTP 200 para evitar retries desnecessários.
- Validar assinatura do payload com o segredo configurado.
- Usar idempotência no ERP consumidor.
- Rotacionar secret periodicamente ou quando houver suspeita de comprometimento.
- Monitorar entregas falhas e reenfileirar quando necessário.
- Considerar a estratégia de retry ao projetar o endpoint (timeout de 60s recomendado).