Webhooks

Configure endpoints para receber eventos em tempo real, eliminando a necessidade de polling. O sistema faz até 5 tentativas com backoff exponencial antes de marcar uma entrega como falha.

Eventos Disponíveis

nfse.issued

NFS-e emitida com sucesso. Contém chNFSe e nNFSe.

nfse.error

Falha na emissão. Contém errorCode e errorMessage.

nfse.cancelled

NFS-e cancelada com sucesso. Contém cancelledAt (timestamp ISO 8601).

nfse.documents_ready

Documentos cacheados no CDN. Contém xmlUrl, pdfUrl, cancelXmlUrl (para notas canceladas), documentStatus e cachedAt.

batch.completed

Lote finalizado. Contém total, issued, errors.

Estrutura do Payload

Todos os eventos seguem a mesma estrutura de envelope. O campo data varia por evento.

{
  "event": "nfse.issued",
  "deliveryId": "del_xyz789",
  "timestamp": "2026-03-12T19:00:00.000Z",
  "data": {
    "invoiceId": "inv_abc123",
    "chNFSe": "4321000001234",
    "nNFSe": "00001"
  }
}

Headers enviados com cada requisição:

HeaderValor
Content-Typeapplication/json
X-Notaas-EventNome do evento (ex: nfse.issued)
X-Notaas-DeliveryID único da entrega (UUID)
X-Notaas-SignatureHMAC-SHA256 do body — presente apenas se o endpoint tiver secret configurado

⚠️ Assinatura HMAC

O header X-Notaas-Signature só é enviado quando o endpoint tem um secret configurado. Configure o secret no Dashboard → Developers → Webhooks → Editar endpoint.

ℹ️ Compatibilidade

Campos adicionais podem ser incluídos nos payloads de webhook sem aviso prévio. Seu código deve ignorar campos desconhecidos para manter compatibilidade futura (Postel's Law).

Validar Assinatura (HMAC)

O valor do header X-Notaas-Signature é calculado como sha256=HMAC-SHA256(secret, rawBody). Você deve recalcular a assinatura no seu servidor e comparar com timing-safe equality.

import crypto from 'crypto';

app.post('/webhook/notaas', (req, res) => {
  // IMPORTANTE: req.rawBody deve ser a string bruta antes do JSON.parse
  const rawBody = req.rawBody;
  const received = req.headers['x-notaas-signature'] ?? '';

  const expected =
    'sha256=' +
    crypto
      .createHmac('sha256', process.env.NOTAAS_WEBHOOK_SECRET)
      .update(rawBody)
      .digest('hex');

  const valid = crypto.timingSafeEqual(
    Buffer.from(received),
    Buffer.from(expected),
  );

  if (!valid) return res.status(401).send('Assinatura inválida');

  // Idempotência: evitar reprocessar em retries
  const deliveryId = req.headers['x-notaas-delivery'];
  if (alreadyProcessed(deliveryId)) return res.status(200).send('ok');

  const payload = JSON.parse(rawBody);
  console.log(payload.event, payload.data);

  res.status(200).send('ok');
});

Retry Policy

Uma entrega é considerada falha quando o endpoint retorna status não-2xx ou ocorre erro de rede/timeout (10s). O sistema tenta novamente até 5 vezes com delays crescentes:

TentativaDelay
Imediato
1 minuto
5 minutos
30 minutos
2 horas

Após 5 tentativas falhas, a entrega é marcada como failed. Você pode consultar o histórico em Dashboard → Webhooks → Histórico.

Configurar Endpoint via API

curl -X POST https://platform.notaas.com.br/api/v1/webhooks/endpoints \
  -H "Content-Type: application/json" \
  -H "x-api-key: ntaas_XXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
  -d '{
    "url": "https://minha-api.com/webhooks/notaas",
    "events": ["nfse.issued", "nfse.error"],
    "secret": "meu-secret-para-assinar"
  }'

Parâmetros do Endpoint

Use o header X-Notaas-Delivery para garantir idempotência — armazene os IDs processados e ignore repetições em caso de retry.

POST /webhooks/endpoints

CampoTipoReq?Descrição
urlstringsimURL HTTPS que receberá o POST
eventsstring[]simLista de eventos: nfse.issued, nfse.error, nfse.cancelled, nfse.documents_ready, batch.completed
secretstringnãoSecret para assinar payloads com HMAC-SHA256 (opcional, mas recomendado em produção)
activebooleannãoAtivo por padrão (true)