Pular para o conteúdo
NFSeIA
Páginas da documentação

Prévia: a API abre junto com o painel.

Emitir a primeira nota

Em cinco minutos, no ambiente de teste: sem certificado digital e sem valor fiscal.

1. Pegue a chave de teste

Crie a conta e copie a chave nfs_test_... no painel. Deixe numa variável de ambiente:

Terminal
export NFSEIA_CHAVE="nfs_test_sua_chave"

Confira se ela funciona e veja os padrões da nota da sua empresa (código de serviço, descrição, impostos):

Terminal
curl https://api.nfseia.com.br/v1/empresa \
  -H "Authorization: Bearer $NFSEIA_CHAVE"

2. Emita

O mínimo é a referência do pedido, o tomador e o valor. O que você não mandar de serviço e impostos vem dos padrões da empresa. Se o tomador ainda não estiver salvo, mande também o nome.

Terminal
curl -X POST https://api.nfseia.com.br/v1/notas \
  -H "Authorization: Bearer $NFSEIA_CHAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7d4f8c2a-1b3e-4f6a-9c0d-2e5b8a1f3c7d" \
  -d '{
    "referencia_externa": "pedido-1042",
    "tomador": {
      "documento": "12345678000195",
      "nome": "Padaria Pão Quente Ltda",
      "email": "[email protected]"
    },
    "servico": { "descricao": "Manutenção do site, novembro de 2026" },
    "valores": { "valor_servico": "1500.00" }
  }'

Em Node (18 ou mais novo, sem biblioteca):

Node
import { randomUUID } from 'node:crypto';

const resposta = await fetch('https://api.nfseia.com.br/v1/notas', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.NFSEIA_CHAVE}`,
    'Content-Type': 'application/json',
    // Gere uma vez por tentativa e reutilize se precisar repetir a mesma chamada.
    'Idempotency-Key': randomUUID(),
  },
  body: JSON.stringify({
    referencia_externa: 'pedido-1042',
    tomador: {
      documento: '12345678000195',
      nome: 'Padaria Pão Quente Ltda',
      email: '[email protected]',
    },
    servico: { descricao: 'Manutenção do site, novembro de 2026' },
    valores: { valor_servico: '1500.00' },
  }),
  signal: AbortSignal.timeout(35_000),
});

const corpo = await resposta.json();
if (resposta.status === 201 || resposta.status === 200) {
  console.log(`Nota ${corpo.numero} ${corpo.status}`, corpo.links.pdf);
} else if (resposta.status === 202) {
  console.log('Nota pendente; o webhook avisa quando sair.', corpo.id);
} else {
  console.error(corpo.erro.mensagem, corpo.erro.como_resolver, corpo.erro.detalhes);
}

Em Python (com requests):

Python
import os
import uuid

import requests

resposta = requests.post(
    "https://api.nfseia.com.br/v1/notas",
    headers={
        "Authorization": f"Bearer {os.environ['NFSEIA_CHAVE']}",
        # Gere uma vez por tentativa e reutilize se precisar repetir a mesma chamada.
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "referencia_externa": "pedido-1042",
        "tomador": {
            "documento": "12345678000195",
            "nome": "Padaria Pão Quente Ltda",
            "email": "[email protected]",
        },
        "servico": {"descricao": "Manutenção do site, novembro de 2026"},
        "valores": {"valor_servico": "1500.00"},
    },
    timeout=35,
)

corpo = resposta.json()
if resposta.status_code in (200, 201):
    print(f"Nota {corpo['numero']} {corpo['status']}", corpo["links"]["pdf"])
elif resposta.status_code == 202:
    print("Nota pendente; o webhook avisa quando sair.", corpo["id"])
else:
    print(corpo["erro"]["mensagem"], corpo["erro"]["como_resolver"], corpo["erro"]["detalhes"])

3. Entenda a resposta

Status O que aconteceu O que fazer
201 Nota autorizada. Guarde id, numero e chave_acesso.
200 Já havia nota com essa referencia_externa. Trate como sucesso: é a mesma nota.
202 Nota pendente, com o motivo em pendencia.motivo (por exemplo, a SEFIN não respondeu a tempo). Espere o webhook nota.pendente_resolvida ou consulte depois. Não emita de novo com outra referência.
400 Dados recusados antes do envio. Corrija os campos de erro.detalhes.
422 A SEFIN recusou a nota de forma definitiva. Corrija conforme erro.detalhes e emita de novo com a mesma referência e uma Idempotency-Key nova.
429 ou 5xx Limite ou falha temporária. Repita com a mesma Idempotency-Key, depois do Retry-After.

Os códigos e o formato dos erros estão em Erros e limites.

4. Teste os caminhos difíceis

No ambiente de teste, um marcador na descrição do serviço força o resultado:

  • [simular:rejeitada]: a SEFIN simulada recusa a nota (422 nota_rejeitada).
  • [simular:pendente]: a nota fica pendente (202) e vira autorizada em cerca de 1 minuto, com os eventos nota.pendente_resolvida e nota.autorizada.

Exemplo: "descricao": "Manutenção do site [simular:pendente]".

5. Baixe o PDF e o XML

Terminal
curl https://api.nfseia.com.br/v1/notas/nota_01JC8Z4M3QK7T2V9X5B6N1R0PD/pdf \
  -H "Authorization: Bearer $NFSEIA_CHAVE" -o nota.pdf

O XML oficial fica em /xml, guardado por 5 anos. No teste, o PDF sai com a marca "sem valor fiscal".

6. Vá para a produção

  1. Envie o certificado digital A1 (e-CNPJ) da empresa pelo link de envio do painel. O arquivo vai direto para o cofre; nem o painel nem a API veem o certificado aberto.
  2. Libere a produção no painel e confirme pelo e-mail da empresa.
  3. Crie a chave nfs_live_... e troque no seu sistema. O código é o mesmo.

O teste grátis vale 5 notas reais ou 7 dias, o que vier primeiro. O ambiente de teste continua de graça depois.