Webhooks
A emissão, o cancelamento e a substituição são assíncronos. O webhook avisa o seu sistema quando a Sefin Nacional autoriza, rejeita, cancela ou substitui a nota, e quando o certificado de um contribuinte está para vencer.
Eventos
| Tipo | Quando |
|---|---|
invoice.authorized |
A Sefin Nacional autorizou a NFS-e. |
invoice.rejected |
A Sefin Nacional rejeitou a nota, ou o Nota4You recusou antes do envio (por exemplo, certificado vencido). |
invoice.cancelled |
A Sefin Nacional registrou o cancelamento da nota. |
invoice.substituted |
A Sefin Nacional autorizou a nota substituta. O corpo traz a nota original, com substitute_invoice_id. |
invoice_event.rejected |
A Sefin Nacional recusou um cancelamento. O corpo traz data.invoice_event com os códigos em rejection_codes. |
certificate.expiring |
O certificado de um contribuinte vence em 30, 15, 7, 1 ou 0 dias. Um evento por certificado e por dia de aviso. |
webhook.test |
Você pediu um envio de teste. |
Cadastro
Em Configurações > Webhooks ou pela API (/api/v1/webhook_endpoints, escopo webhooks:manage): endereço https, eventos, descrição e a opção include_personal_data. Até 10 endereços por conta. O segredo (whsec_...) aparece só na criação e na troca. Na tela de cada webhook você vê as entregas, envia um teste e reenvia uma entrega.
O esquema de cada corpo está na seção webhooks do OpenAPI.
Corpo
{
"id": "0f6b2c1e-8f1d-4f7a-9a51-2a3c9b0e7d11",
"type": "invoice.authorized",
"created_at": "2026-10-19T14:32:05-03:00",
"data": {
"invoice": {
"id": "4a77...", "taxpayer_id": "9c1e...", "status": "authorized",
"access_key": "3550308...", "nfse_number": "42", "rejection_codes": [],
"customer": { "id": "8bb9..." }
}
}
}
Sem a opção include_personal_data, o corpo não traz dados pessoais: o tomador vai só com o id. Para os detalhes, consulte GET /api/v1/invoices/:id.
Dados pessoais
Com include_personal_data: true, o corpo traz customer e, quando a nota tiver, recipient e intermediary, cada um com document_type, document, name, email, phone e address. No certificate.expiring, a opção acrescenta subject_document (o CNPJ ou CPF do contribuinte). Ligue só se o seu sistema precisar desses dados e tiver base legal para recebê-los (LGPD). Veja Privacidade.
Certificado vencendo
{
"id": "5c1d...",
"type": "certificate.expiring",
"created_at": "2026-12-11T06:00:00-03:00",
"data": {
"certificate": {
"id": "7645...", "taxpayer_id": "fc3c...",
"not_after": "2027-01-10T12:00:00-03:00", "days_left": 30
}
}
}
Assinatura
Cada envio traz o cabeçalho X-Nota4you-Signature: t=<segundos>,v1=<hex>, onde v1 é HMAC-SHA256(segredo, "<t>.<corpo bruto>"). Confira antes de confiar no corpo e recuse envios com mais de 5 minutos:
timestamp, signature = header.scan(/t=(\d+),v1=(\h+)/).first
expected = OpenSSL::HMAC.hexdigest("SHA256", secret, "#{timestamp}.#{raw_body}")
valid = ActiveSupport::SecurityUtils.secure_compare(expected, signature) &&
Time.at(timestamp.to_i) > 5.minutes.ago
Outros cabeçalhos: X-Nota4you-Event-Id, X-Nota4you-Event-Type, X-Nota4you-Delivery-Attempt.
Novas tentativas
Uma resposta 2xx conclui o envio. Redirecionamentos contam como falha. Tempo limite: 5 s para conectar, 10 s para responder. Depois de uma falha, tentamos de novo em 1 min, 5 min, 30 min, 1 h, 2 h, 4 h, 8 h e 8 h. Todos os envios de um evento têm o mesmo id: use-o para ignorar repetições.