We use cookies to improve your experience and analyze site traffic. By clicking “Accept”, you agree to our use of cookies.

Learn more about our privacy practices
Corvo
English

Recebendo webhooks

Formato das chamadas de saída, verificação de assinatura e política de repetição.

A Corvo envia um POST JSON para a URL cadastrada. Responda com HTTP 2xx em até 10 segundos; processamento demorado deve ser enfileirado pelo receptor.

Formato da requisição

  • Método: POST.
  • Headers: Content-Type: application/json, X-Corvo-Signature: sha256=<hex>.
  • Corpo: envelope JSON com id, type, environment, createdAt e data.

json

{
  "id": "evt_identificador",
  "type": "nfse.invoice.authorized",
  "environment": "test",
  "createdAt": "2026-10-10T14:00:00.000Z",
  "data": {
    "invoiceId": "UUID_DA_NOTA",
    "companyId": "UUID_DA_EMPRESA",
    "environment": "test",
    "status": "authorized",
    "documentsStatus": "pending",
    "emailStatus": null,
    "stage": "authorized",
    "accessKey": "CHAVE_DE_ACESSO",
    "nfseNumber": 123
  }
}

data varia por evento. No fluxo fiscal, inclui identificação e estado da nota; autorização acrescenta accessKey/nfseNumber, rejeição acrescenta errorCode/errorMessage, revisão manual acrescenta reason, documentos prontos acrescenta accessKey/nfseNumber/documentsReadyAt, email enviado acrescenta sentAt. O evento de teste contém { "message": "This is a test webhook event" }.

Tipos de evento

Evento`data` acrescenta ao estado da nota
nfse.invoice.authorizedaccessKey, nfseNumber.
nfse.invoice.rejectederrorCode, errorMessage.
nfse.invoice.failedIdentificação e estado da nota.
nfse.invoice.reconciliation_requiredIdentificação e estado da nota.
nfse.invoice.manual_reviewreason.
nfse.invoice.documents_readyaccessKey, nfseNumber, documentsReadyAt.
nfse.invoice.email_sentsentAt.
nfse.invoice.email_failedIdentificação e estado da nota.
nfse.invoice.fiscal_discrepancyinvoiceId, status e differences[] (field, local, authorized, delta, kind): diferença entre o cálculo da Corvo e a NFS-e autorizada, acima de R$ 0,01 por tributo. O XML autorizado não é alterado.
nfse.invoice.cancelledA nota foi cancelada; inclui reason.
nfse.invoice.cancellation_rejectedA Sefin recusou o cancelamento; a nota volta a authorized; inclui errorCode e errorMessage.
webhook.test{ "message": "This is a test webhook event" }.

Verificação de assinatura

A assinatura é HMAC-SHA256 do corpo JSON enviado, com o secret da configuração, em hexadecimal. Verifique os bytes brutos do corpo recebido — não faça parse e stringify antes de verificar.

javascript

import { createHmac, timingSafeEqual } from 'node:crypto';

export function verifyWebhook(rawBody, signatureHeader, secret) {
  if (typeof signatureHeader !== 'string') return false;
  const match = /^sha256=([a-f0-9]{64})$/.exec(signatureHeader);
  if (!match) return false;
  const received = Buffer.from(match[1], 'hex');
  const expected = createHmac('sha256', secret).update(rawBody).digest();
  return timingSafeEqual(received, expected);
}

Repetição e idempotência

  • O receptor pode receber novamente o mesmo evento: deduplique por id do envelope.
  • Retries preservam o payload original.
  • O outbox usa até 5 tentativas, com intervalos após falha de 60 segundos, 160 segundos, 15 minutos e 30 minutos; a execução depende do worker.
  • Não assuma ordem global de entrega.