Primeiros passos
Este guia cobre a instalação, a criação do cliente e a emissão da sua primeira nota fiscal de serviço (NFS-e), do envio até o PDF.
1. Instale o pacote
pip install nfe-io
# ou
uv add nfe-io
Python 3.10 ou superior. O SDK não tem dependências de runtime: usa só a biblioteca padrão. O
pacote se chama nfe-io no PyPI e é importado como nfeio.
2. Configure as chaves
A NFE.io usa duas chaves, cada uma para um grupo de APIs:
| Parâmetro | Variável de ambiente | Usada em |
|---|---|---|
api_key | NFE_API_KEY | NFS-e, empresas, certificados, webhooks |
data_api_key | NFE_DATA_API_KEY | consultas de CNPJ, CPF e CEP |
export NFE_API_KEY="sua-chave"
export NFE_DATA_API_KEY="sua-chave-de-dados"
O SDK nunca usa uma chave no lugar da outra. Se você tem uma chave só, use o mesmo valor nas duas. Detalhes em Configuração.
3. Crie um cliente
from nfeio import NfeClient
client = NfeClient() # lê NFE_API_KEY e NFE_DATA_API_KEY
Também dá para passar as chaves direto: NfeClient(api_key="...", data_api_key="..."). O argumento
explícito vence a variável de ambiente. O cliente é thread-safe: crie um por configuração e
reutilize.
4. Emita uma NFS-e
from decimal import Decimal
from nfeio import NfeClient, ServiceInvoice
from nfeio.types import ServiceInvoiceCreateParams
client = NfeClient()
company_id = "ID_DA_EMPRESA"
params: ServiceInvoiceCreateParams = {
"cityServiceCode": "10677",
"description": "Consultoria em tecnologia",
"servicesAmount": Decimal("150.00"),
"borrower": {
"type": "NaturalPerson",
"name": "Maria Silva",
"federalTaxNumber": "52998224725",
"email": "[email protected]",
},
}
invoice: ServiceInvoice = client.service_invoices.create_and_wait(
company_id, params, external_id="pedido-1001"
)
print(invoice.id, invoice.flow_status) # ... Issued
print(invoice["number"]) # qualquer campo do JSON, pelo nome original
print(repr(invoice.services_amount)) # Decimal(...), sem erro de arredondamento
Três coisas para notar:
- O corpo usa as chaves da API (camelCase), exatamente como na referência da NFS-e: copie um exemplo da documentação e ele funciona. Os argumentos dos métodos seguem o padrão Python (snake_case).
external_idé a sua chave de deduplicação. Use sempre, com um valor que identifique a venda no seu sistema. É ele que permite reconciliar uma emissão com resultado incerto sem duplicar a nota (veja Tratamento de erros).create_and_waitespera a prefeitura. A emissão é assíncrona: a API responde202e a nota passa por estados intermediários atéIssued. O método consulta a nota até um estado final (120 s por padrão). Os detalhes estão em Síncrono, assíncrono e polling.
Não existe host de homologação nem chave de teste. O ambiente (produção ou teste) é configurado na empresa, na inscrição municipal. Para testar, use uma empresa com ambiente de testes.
5. Baixe o PDF e o XML
from pathlib import Path
from nfeio import NfeClient
client = NfeClient()
company_id = "ID_DA_EMPRESA"
invoice_id = "ID_DA_NOTA"
pdf: bytes = client.service_invoices.download_pdf(company_id, invoice_id)
Path("nota.pdf").write_bytes(pdf)
xml: bytes = client.service_invoices.download_xml(company_id, invoice_id)
Path("nota.xml").write_bytes(xml)
Mais em Downloads.
6. Leia a resposta
Toda resposta é um NfeObject, um Mapping imutável sobre o JSON recebido:
obj["campo"]dá acesso a qualquer campo, inclusive os que o SDK ainda não conhece. Objetos aninhados também sãoNfeObject:invoice["borrower"]["address"]["city"]["code"].- Algumas propriedades tipadas corrigem ou tipam o que vem no fio: ids, status, datas
(
datetimecom fuso), valores (Decimal) e documentos (CNPJ/CPF comostrcom zeros à esquerda). Exemplos:invoice.flow_status,invoice.services_amount,invoice.issued_on,invoice.borrower.federal_tax_number. obj.to_dict()devolve uma cópia em dicionários comuns, serializável comjson.dumps.obj.last_response.request_idtraz ox-request-idda resposta. Informe esse valor ao suporte.
No acesso por chave, valores aparecem como vieram no JSON (float). Nas propriedades tipadas, como
Decimal. Nas requisições, int, float e Decimal são aceitos, e Decimal("100.10") é enviado
sem perda como 100.10.
Próximos passos
- Configuração: timeouts, retry, TLS e opções por chamada.
- Tratamento de erros: a regra de nunca reenviar uma emissão às cegas.
- Webhooks: receba a conclusão da nota por push, sem polling.
- Notas de serviço: todos os métodos de
service_invoices.