API Notafly

Emita NFS-e automaticamente a cada venda. Um endpoint REST, certificado criptografado, sem burocracia.

REST · JSONmTLS + AES-256São Paulo ativoNFS-e Nacional em breve
~3s
tempo médio de emissão
99.9%
uptime dos últimos 90 dias
R$ 0
custo por nota emitida

Base URL

endpoint
https://api.notafly.com.br/api

Integrações comuns

🟠
Hotmart
PURCHASE_APPROVED → nota emitida
🟣
Kiwify
order.approved → NFS-e automática
🟦
Stripe
invoice.payment_succeeded
🔴
n8n
Qualquer trigger → emissão
Zapier
Webhook → POST /api/emit
🛠
API própria
Qualquer sistema com HTTP

Cobertura municipal

O Notafly emite para São Paulo via sistema municipal próprio (SOAP + mTLS) e está preparado para o NFS-e Nacional — o padrão da Receita Federal que cobre mais de 1.000 municípios.

MunicípioSistemaStatus
São Paulo – SPsistema municipal SOAP Ativo
Campinas, Guarulhos, Osasco e outrosNFS-e Nacional REST Em breve
Demais municípios conveniadosNFS-e Nacional REST Em breve
ℹ️

Se o CNPJ da emissora for de um município ainda não suportado, a API retorna 422 MUNICIPIO_NAO_SUPORTADO imediatamente — nenhuma cobrança é feita.


Autenticação

Todas as requisições precisam de uma API Key no header Authorization.

header
Authorization: Bearer nfly_live_sk_xxxxxxxxxxxxxxxxxxxxxxxx

As chaves começam com nfly_live_sk_ seguido de 32 caracteres aleatórios. A chave é exibida uma única vez na criação.

nfly_live_sk_••••••••••••••••••••••••••••••••
⚠️

Nunca exponha sua API Key no frontend ou repositório público. Use sempre variáveis de ambiente no servidor.


Como funciona

Você envia os dados da nota. O Notafly assina o XML com seu certificado A1, envia à Prefeitura ou Receita Federal, e retorna o número autorizado.

📤
seu sistema
POST /api/emit
✍️
notafly
assina XML (xmldsig)
🔐
notafly
mTLS → Prefeitura
resposta
número + PDF
  • 200 OK — nota autorizada em até 30s. Contém número, código de verificação e link do PDF.
  • 202 Accepted — prefeitura lenta. Nota entra na fila e é processada automaticamente.
  • 422 — nota rejeitada. Campo detail contém o código exato da prefeitura.

Rate limits

Cada API Key tem limite de 60 requisições por minuto. Ao exceder retorna 429 Too Many Requests. Planos Enterprise têm limites customizados.

response headers
X-RateLimit-Limit:     60
X-RateLimit-Remaining: 57
X-RateLimit-Reset:     1709823600  # Unix timestamp

Emitir NFS-e

POST/emit🔑 API Key
Emite uma NFS-e. Síncrono por até 30s — autorizada retorna 200, ainda processando retorna 202.

Parâmetros

CampoTipoDescrição
empresaCnpjobrigatóriostringCNPJ da empresa emissora (14 dígitos). Deve estar cadastrado no Notafly com certificado A1.
tomadorCnpjcondicionalstringCNPJ do tomador (PJ). Obrigatório se não informar tomadorCpf.
tomadorCpfcondicionalstringCPF do tomador (PF). Obrigatório se não informar tomadorCnpj.
tomadorEmailopcionalstringE-mail do tomador.
tomadorNomeopcionalstringNome ou razão social do tomador.
valorServicoobrigatórionumberValor do serviço em reais (ex: 497.00).
discriminacaoobrigatóriostringDescrição do serviço prestado.
referenciaopcionalstringID do seu sistema. Permite consultar a nota sem guardar o ID do Notafly.
dataCompetenciaopcionalstringFormato YYYY-MM. Padrão: mês atual.

Exemplos

curl
curl -X POST https://api.notafly.com.br/api/emit \
  -H "Authorization: Bearer nfly_live_sk_xxx" \
  -H "Content-Type: application/json" \
  -d '{"empresaCnpj":"14099269000181","tomadorCnpj":"47715268000173","tomadorEmail":"cliente@empresa.com","valorServico":497.00,"discriminacao":"Assinatura mensal - Plano Pro - Marco/2026","referencia":"invoice_1234567"}'
javascript
const nota = await fetch('https://api.notafly.com.br/api/emit', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.NOTAFLY_API_KEY}` },
  body: JSON.stringify({ empresaCnpj: '14099269000181', tomadorCnpj: '47715268000173', valorServico: 497.00, discriminacao: 'Assinatura mensal - Plano Pro', referencia: 'invoice_1234567' })
}).then(r => r.json());
// nota.numero  → '000042851'  /  nota.linkPdf → URL do PDF
python
import requests, os
nota = requests.post("https://api.notafly.com.br/api/emit",
  headers={"Authorization": f"Bearer {os.environ['NOTAFLY_API_KEY']}", "Content-Type": "application/json"},
  json={"empresaCnpj": "14099269000181", "tomadorCnpj": "47715268000173", "valorServico": 497.00, "discriminacao": "Assinatura mensal", "referencia": "invoice_1234567"}
).json()
print(nota["numero"], nota["linkPdf"])
php
$ch = curl_init('https://api.notafly.com.br/api/emit');
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'Authorization: Bearer ' . $_ENV['NOTAFLY_API_KEY']],
  CURLOPT_POSTFIELDS => json_encode(['empresaCnpj' => '14099269000181', 'tomadorCnpj' => '47715268000173', 'valorServico' => 497.00, 'discriminacao' => 'Assinatura mensal', 'referencia' => 'invoice_1234567'])]);
$nota = json_decode(curl_exec($ch));

Resposta — 200 OK

200 OK · autorizada
json
{ "id": "nfly_nota_clxxx", "numero": "000042851", "codigoVerif": "ABX-9FKL", "dataEmissao": "2026-03-07T14:32:00-03:00", "municipio": "Sao Paulo", "valorServico": 497.00, "valorIss": 9.94, "status": "AUTORIZADA", "referencia": "invoice_1234567", "linkPdf": "https://api.notafly.com.br/api/notas/nfly_nota_xxx/pdf" }

Consultar nota

GET/notas/:id🔑 API Key
Retorna dados completos de uma NFS-e pelo ID do Notafly.
GET/notas?referencia=invoice_1234567🔑 API Key
Busca notas pelo campo referencia. Ideal para rastrear sem armazenar o ID interno.
💡

Sempre use o campo referencia com o ID da sua transação. Você pode consultar a nota a qualquer momento sem depender do ID do Notafly.


Cancelar nota

DELETE/notas/:id🔑 API Key
Cancela uma NFS-e autorizada. Cancelamento transmitido automaticamente à Prefeitura.
⚠️

Em São Paulo o prazo de cancelamento é 7 dias corridos da emissão.


Download do PDF

GET/notas/:id/pdf
Retorna o PDF da NFS-e. Endpoint público — pode ser compartilhado diretamente com o tomador.

Gerenciar API Keys

Esses endpoints usam autenticação por JWT (sessão do dashboard).

GET/api-keys🔐 JWT
Lista todas as API Keys ativas. O valor completo nunca é retornado.
POST/api-keys🔐 JWT
Cria uma nova API Key. O valor completo é retornado uma única vez.
DELETE/api-keys/:id🔐 JWT
Revoga uma API Key imediatamente.

Guia: Hotmart

Em Ferramentas → Webhooks, cadastre sua URL e selecione PURCHASE_APPROVED.

node.js + express
app.post('/webhooks/hotmart', async (req, res) => {
  const { event, data } = req.body;
  if (event !== 'PURCHASE_APPROVED') return res.sendStatus(200);
  const { buyer, purchase } = data;
  await fetch('https://api.notafly.com.br/api/emit', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${process.env.NOTAFLY_API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ empresaCnpj: 'SEU_CNPJ', tomadorCpf: buyer.document.replace(/\D/g, ''), tomadorEmail: buyer.email, valorServico: purchase.price.value, discriminacao: purchase.product.name, referencia: purchase.transaction })
  });
  res.sendStatus(200);
});

Guia: Kiwify

Configure em Configurações → Webhooks com o evento order.approved.

node.js
app.post('/webhooks/kiwify', async (req, res) => {
  const { event, data } = req.body;
  if (event !== 'order.approved') return res.sendStatus(200);
  await fetch('https://api.notafly.com.br/api/emit', {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${process.env.NOTAFLY_API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({ empresaCnpj: 'SEU_CNPJ', tomadorCpf: data.Customer.cpf, tomadorEmail: data.Customer.email, valorServico: data.order_value / 100, discriminacao: data.Product.name, referencia: data.order_id })
  });
  res.sendStatus(200);
});

Guia: Stripe

Ideal para SaaS com assinaturas recorrentes.

💡

Salve o CNPJ/CPF nos metadados do Customer no Stripe (customer.metadata.cnpj) para automatizar completamente a integração.

node.js — stripe webhook
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), async (req, res) => {
  const event = stripe.webhooks.constructEvent(req.body, req.headers['stripe-signature'], process.env.STRIPE_WEBHOOK_SECRET);
  if (event.type === 'invoice.payment_succeeded') {
    const invoice = event.data.object;
    const customer = await stripe.customers.retrieve(invoice.customer);
    await fetch('https://api.notafly.com.br/api/emit', {
      method: 'POST',
      headers: { 'Authorization': `Bearer ${process.env.NOTAFLY_API_KEY}`, 'Content-Type': 'application/json' },
      body: JSON.stringify({ empresaCnpj: 'SEU_CNPJ', tomadorCnpj: customer.metadata.cnpj, tomadorEmail: customer.email, valorServico: invoice.amount_paid / 100, discriminacao: invoice.lines.data[0].description, referencia: invoice.id })
    });
  }
  res.sendStatus(200);
});

Guia: n8n / Zapier

Use o nó HTTP Request do n8n ou Webhooks by Zapier.

  1. Método: POST · URL: https://api.notafly.com.br/api/emit
  2. Authentication: Header Auth → Name: Authorization, Value: Bearer nfly_live_sk_xxx
  3. Body: JSON com campos mapeados do nó anterior
🔴

No n8n use expressões: {{ $json.customer_email }}, {{ $json.amount / 100 }} etc.


Códigos de erro

Todos os erros seguem: {"statusCode": 422, "error": "CÓDIGO", "message": "..."}

HTTPCódigoCausa e solução
401UNAUTHORIZEDAPI Key ausente, inválida ou revogada.
403NOTE_LIMIT_EXCEEDEDLimite mensal de notas atingido. Faça upgrade em Dashboard → Plano.
404COMPANY_NOT_FOUNDO empresaCnpj não está cadastrado no Notafly.
404NOTE_NOT_FOUNDID ou referência não encontrado.
422MUNICIPIO_NAO_SUPORTADOMunicípio da emissora ainda não suportado.
422PREFEITURA_REJECTEDNota rejeitada. Veja o campo detail para o código exato.
429RATE_LIMIT_EXCEEDED60 req/min excedidos. Aguarde o reset em X-RateLimit-Reset.
503PREFEITURA_OFFLINEPrefeitura indisponível. Nota enfileirada e retentada automaticamente.
🔄

Erros 503 são transitórios. O Notafly retenta com backoff exponencial.


Status da nota

StatusSignificado
AUTORIZADANota emitida e autorizada pela prefeitura.
PROCESSANDONa fila do worker. Será transmitida automaticamente.
AGENDADAAgendada para emissão em data/hora futura.
ERROFalha definitiva. Veja errorMessage.
CANCELADACancelamento transmitido com sucesso.

Changelog

v1.2 — Março 2026

  • Endpoint POST /api/emit público via API Key
  • Validação de município com retorno MUNICIPIO_NAO_SUPORTADO
  • Gerenciamento de API Keys via dashboard e API
  • Header X-RateLimit-Remaining em todas as respostas

v1.1 — Janeiro 2026

  • Suporte a multi-município (estrutura base NFS-e Nacional)
  • Campo referencia em todos os endpoints de consulta
  • Download de PDF via URL pública opaca

v1.0 — Novembro 2025

  • Lançamento — emissão NFS-e São Paulo via SOAP + mTLS
  • Agendamento com hora exata e recorrência
  • Upload de certificado A1 com criptografia AES-256-GCM
Voltar ao Notafly