Pular para o conteúdo principal

Webhooks

Webhooks avisam sua aplicação quando uma operação muda de estado, reduzindo a necessidade de consultas repetidas.

Informe a URL na própria emissão:

{
"cpf_cnpj": "60772432000142",
"webhook_url": "https://seu-sistema.com.br/webhooks/conota",
"nota": { "...": "..." }
}

Fluxo

1. Seu sistema envia a emissão -> 202 { job_id }
2. O Conota processa
3. O Conota chama o seu webhook (POST, JSON)
4. Seu sistema responde 2xx rapidamente
5. Seu sistema persiste o novo estado

Headers da notificação

POST /webhooks/conota
Content-Type: application/json
X-Qualyfiscal-Signature: sha256=<hmac_hex>
X-Qualyfiscal-Job-Id: 6f8dc295-...
X-Qualyfiscal-Tentativa: 1
Por que o header não se chama X-Conota-*

Esses nomes são contrato, não marca. O código dos clientes já lê X-Qualyfiscal-Signature para conferir a assinatura; renomear quebraria a validação de toda integração existente — e a falha apareceria do lado deles, silenciosamente. Se um dia mudar, os dois nomes conviverão por bastante tempo antes.

Validando a assinatura

A assinatura é um HMAC-SHA256 do corpo bruto, em hexadecimal, prefixado por sha256=.

const crypto = require('crypto')

function assinaturaValida(corpoBruto, headerRecebido, segredo) {
const esperado = 'sha256=' + crypto
.createHmac('sha256', segredo)
.update(corpoBruto)
.digest('hex')

const a = Buffer.from(esperado)
const b = Buffer.from(headerRecebido || '')
// timingSafeEqual exige mesmo tamanho — compare o tamanho antes.
return a.length === b.length && crypto.timingSafeEqual(a, b)
}
Use o corpo BRUTO, não o JSON reserializado

JSON.parse seguido de JSON.stringify pode reordenar chaves e mudar espaçamento — e a assinatura deixa de bater. Guarde o body cru antes do parse.

Retentativas

Se o seu endpoint não responder, o Conota tenta de novo:

Tentativas3 no total
Timeout por tentativa10 segundos
Intervalos30s, depois 60s

O número da tentativa vem em X-Qualyfiscal-Tentativa.

Seu endpoint deve

  • usar HTTPS;
  • responder rápido (menos de 10s) e processar o trabalho pesado de forma assíncrona;
  • validar a assinatura antes de confiar no conteúdo;
  • ser idempotente — o mesmo evento pode chegar mais de uma vez;
  • registrar o job_id para auditoria.

Webhook não substitui consulta

Uma notificação perdida não pode travar a sua operação

Se o seu servidor estiver fora do ar durante as três tentativas, a notificação se perde. Sua aplicação precisa conseguir reconciliar o estado mesmo assim.

Mantenha uma rotina de recuperação que varra jobs sem estado final e consulte POST /v1/jobs/consultar-lote. Webhook é o caminho rápido; a consulta é a rede de segurança.