SDK Oficial NFE.io para Node.js 22+ - SDK TypeScript moderno para emissão de notas fiscais de serviço eletrônicas (NFS-e).
✨ Versão 5 - TypeScript nativo, zero dependências em runtime e API moderna async/await. Inclui emissão RTC (Reforma Tributária), NFC-e, inscrições municipais, certificados, notificações e webhooks de conta. Veja a migração v4 → v5.
- Recursos
- Instalação
- Início Rápido
- Skill para Agentes de IA
- Documentação
- Migração da v2
- Exemplos
- Referência da API
- Contribuindo
- Licença
- 🎯 TypeScript Moderno - Segurança de tipos completa com TypeScript 5.3+
- 🚀 Zero Dependências - Usa API fetch nativa do Node.js (Node 22+)
- ⚡ Async/Await - API limpa baseada em promises
- 🔄 Retry Automático - Lógica de retry com exponential backoff integrada
- 📦 ESM & CommonJS - Funciona com ambos os sistemas de módulos
- 🧪 Bem Testado - Mais de 80 testes com 88% de cobertura
- 📖 JSDoc Completo - Documentação completa da API
- 🛡️ Tratamento de Erros - Classes de erro tipadas para melhor tratamento
Requisitos:
- Node.js >= 22.0.0
- TypeScript >= 5.0 (se usar TypeScript)
npm install nfe-ioou
yarn add nfe-ioou
pnpm add nfe-io# 1. Clone e instale
git clone https://github.com/nfe/client-nodejs.git
cd client-nodejs
npm install
# 2. Configure suas credenciais (interativo)
npm run examples:setup
# 3. Teste a conexão
npm run examples:test
# 4. Execute os exemplos
npm run examplesnpm install nfe-ioimport{NfeClient}from'nfe-io';// Inicializar o clienteconstnfe=newNfeClient({apiKey: 'sua-chave-api',environment: 'production'// ou 'development'});// Criar uma empresaconstempresa=awaitnfe.companies.create({federalTaxNumber: '12345678000190',name: 'Minha Empresa Ltda',email: 'empresa@exemplo.com.br',taxRegime: 1,// Simples Nacionaladdress: {country: 'BRA',postalCode: '01310-100',street: 'Av. Paulista',number: '1578',city: {code: '3550308',name: 'São Paulo'},state: 'SP'}});// Emitir uma nota fiscal de serviçoconstnotaFiscal=awaitnfe.serviceInvoices.create(empresa.id,{cityServiceCode: '01234',description: 'Serviços de desenvolvimento web',servicesAmount: 1000.00,borrower: {type: 'LegalEntity',federalTaxNumber: 12345678000190,name: 'Empresa Cliente',email: 'cliente@exemplo.com.br',address: {country: 'BRA',postalCode: '01310-100',street: 'Av. Paulista',number: '1000',city: {code: '3550308',name: 'São Paulo'},state: 'SP'}}});console.log(`Nota fiscal criada: ${notaFiscal.number}`);const{ NfeClient }=require('nfe-io');constnfe=newNfeClient({apiKey: process.env.NFE_API_KEY,environment: 'production'});// Mesma API que ESMEste repositório embarca uma skill que ensina agentes de código (Claude Code, Cursor, etc.) a usar o SDK corretamente. Instale com:
npx skills add nfe/client-nodejsO SDK fornece os seguintes recursos:
Gerenciar NFS-e (Nota Fiscal de Serviço Eletrônica):
// ⭐ RECOMENDADO: Criar e aguardar conclusão (lida com processamento assíncrono)constnotaFiscal=awaitnfe.serviceInvoices.createAndWait(empresaId,{borrower: {federalTaxNumber: 12345678901,name: 'João da Silva',email: 'joao@example.com',},cityServiceCode: '10677',description: 'Serviços de consultoria',servicesAmount: 1500.00,},{pollingInterval: 2000,// Verificar a cada 2 segundosmaxWaitTime: 60000,// Aguardar até 60 segundos});console.log(`✅ Nota fiscal emitida: ${notaFiscal.number}`);// Criar nota fiscal manualmente (retorna 201 imediato ou 202 async)constresult=awaitnfe.serviceInvoices.create(empresaId,dadosNota);// Verificar se é síncrono (201) ou assíncrono (202)if('id'inresult){// Síncrono - nota emitida imediatamenteconsole.log('Nota emitida:',result.number);}else{// Assíncrono - requer pollingconsole.log('Processando:',result.flowStatus);// Use createAndWait() ou pollUntilComplete() em vez disso}// Listar notas fiscais com filtrosconstnotas=awaitnfe.serviceInvoices.list(empresaId,{pageCount: 50,pageIndex: 1,// paginação é 1-based (primeira página = 1)searchPeriod: {startDate: '2024-01-01',endDate: '2024-01-31',},});// Buscar nota fiscal específicaconstnota=awaitnfe.serviceInvoices.retrieve(empresaId,notaFiscalId);// Verificar status de processamentoconststatus=awaitnfe.serviceInvoices.getStatus(empresaId,notaFiscalId);console.log(`Status: ${status.status}, Completo: ${status.isComplete}`);// Cancelar nota fiscalconstnotaCancelada=awaitnfe.serviceInvoices.cancel(empresaId,notaFiscalId);// Enviar nota fiscal por emailawaitnfe.serviceInvoices.sendEmail(empresaId,notaFiscalId,{emails: ['cliente@example.com','financeiro@example.com'],});// Baixar PDF (single ou bulk)constpdfBuffer=awaitnfe.serviceInvoices.downloadPdf(empresaId,notaFiscalId);fs.writeFileSync('nota.pdf',pdfBuffer);// Baixar todas as notas como ZIPconstzipBuffer=awaitnfe.serviceInvoices.downloadPdf(empresaId);fs.writeFileSync('todas-notas.zip',zipBuffer);// Baixar XMLconstxmlBuffer=awaitnfe.serviceInvoices.downloadXml(empresaId,notaFiscalId);fs.writeFileSync('nota.xml',xmlBuffer);// Criar múltiplas notas em lote (batch)constnotasData=[/* ... array de dados de notas ... */];constnotas=awaitnfe.serviceInvoices.createBatch(empresaId,notasData,{waitForComplete: true,// Aguardar todas completaremmaxConcurrent: 5,// Processar 5 por vez});console.log(`✅ ${notas.length} notas fiscais criadas em lote`);Recursos Avançados:
- ⏱️ Polling Automático:
createAndWait()lida automaticamente com processamento assíncrono - 📦 Criação em Lote:
createBatch()cria múltiplas notas com controle de concorrência - 📥 Downloads Bulk: Baixe todas as notas como ZIP (PDF ou XML)
- 🔍 Verificação de Status:
getStatus()verifica se nota completou processamento - 🎯 Discriminated Unions: TypeScript detecta automaticamente tipo de resposta (201 vs 202)
Gerenciar empresas na sua conta:
// Criar empresa (a API exige name, federalTaxNumber, taxRegime e address)constempresa=awaitnfe.companies.create({name: 'Nome da Empresa',federalTaxNumber: 12345678000190,taxRegime: 'SimplesNacional',address: {state: 'SP',city: {code: '3550308',name: 'São Paulo'},district: 'Centro',street: 'Rua Exemplo',number: '100',postalCode: '01001000',country: 'BRA',},});// Listar empresas — v2, cursor-based (recomendado; a API v1 está sendo descontinuada)constpagina=awaitnfe.companies.listV2({limit: 50});// próxima página: listV2({ limit: 50, startingAfter: <id do último item> })// Listar todas as empresas (varredura completa com paginação automática)constempresas=awaitnfe.companies.listAll();// Buscar empresa específicaconstempresa=awaitnfe.companies.retrieve(empresaId);// Atualizar empresa — ATENÇÃO: é PUT (substituição total), não update parcial.// Envie o objeto completo (read-modify-write); campos omitidos são zerados.constatual=awaitnfe.companies.retrieve(empresaId);constatualizada=awaitnfe.companies.update(empresaId,{
...atual,tradeName: 'Novo Nome Fantasia',});// Upload de certificado digitalawaitnfe.companies.uploadCertificate(empresaId,{file: certificadoBuffer,password: 'senha-certificado'});Gerenciar pessoas jurídicas (empresas/negócios):
// Criar pessoa jurídicaconstpessoa=awaitnfe.legalPeople.create(empresaId,{federalTaxNumber: '12345678000190',name: 'Nome da Empresa',email: 'empresa@exemplo.com.br',address: {/* ... */}});// Listar todas as pessoas jurídicasconstpessoas=awaitnfe.legalPeople.list(empresaId);// Buscar por CNPJconstpessoa=awaitnfe.legalPeople.findByTaxNumber(empresaId,'12345678000190');Gerenciar pessoas físicas (indivíduos):
// Criar pessoa físicaconstpessoa=awaitnfe.naturalPeople.create(empresaId,{federalTaxNumber: 12345678901,name: 'João da Silva',email: 'joao@exemplo.com.br',address: {/* ... */}});// Buscar por CPFconstpessoa=awaitnfe.naturalPeople.findByTaxNumber(empresaId,'12345678901');Gerenciar configurações de webhook. Webhooks são gerenciados por conta
(/v2/webhooks) — os métodos por empresa estão deprecated (a rota retorna 404):
// Criar webhook — a URI precisa responder 2xx já na criação (ping de verificação)constwebhook=awaitnfe.webhooks.createAccountWebhook({uri: 'https://meuapp.com.br/webhooks/nfe',contentType: 'json',secret: 'um-segredo-de-32-a-64-caracteres-aqui',filters: ['service_invoice.issued_successfully','service_invoice.cancelled_successfully']});// Listar webhooks da contaconstwebhooks=awaitnfe.webhooks.listAccountWebhooks();// Atualizar webhookawaitnfe.webhooks.updateAccountWebhook(webhookId,{filters: ['service_invoice.issued_successfully']});// Validar assinatura do webhookconstehValido=nfe.webhooks.validateSignature(payload,assinatura,segredo);Consultar endereços brasileiros por CEP ou termo de busca:
// Buscar endereço por CEPconstendereco=awaitnfe.addresses.lookupByPostalCode('01310-100');console.log(endereco.street);// 'Avenida Paulista'console.log(endereco.city.name);// 'São Paulo'console.log(endereco.state);// 'SP'// Buscar por termo (nome de rua, bairro, etc.)constresultado=awaitnfe.addresses.lookupByTerm('Paulista');for(constendofresultado.addresses){console.log(`${end.postalCode}: ${end.street}, ${end.city.name}`);}// Buscar com filtro ODataconstfiltrado=awaitnfe.addresses.search({filter: "city.name eq 'São Paulo'"});Nota: A API de Endereços usa um host separado (
address.api.nfe.io). Você pode configurar uma chave API específica comdataApiKey, ou o SDK usaráapiKeycomo fallback.
Consultar CT-e (Conhecimento de Transporte Eletrônico) via Distribuição DFe:
// Ativar busca automática de CT-e para uma empresaconstsettings=awaitnfe.transportationInvoices.enable('empresa-id');console.log('Status:',settings.status);console.log('Iniciando do NSU:',settings.startFromNsu);// Ativar a partir de um NSU específicoconstsettings=awaitnfe.transportationInvoices.enable('empresa-id',{startFromNsu: 12345});// Ativar a partir de uma data específicaconstsettings=awaitnfe.transportationInvoices.enable('empresa-id',{startFromDate: '2024-01-01T00:00:00Z'});// Verificar configurações atuaisconstconfig=awaitnfe.transportationInvoices.getSettings('empresa-id');console.log('Busca ativa:',config.status);// Desativar busca automáticaawaitnfe.transportationInvoices.disable('empresa-id');// Consultar CT-e por chave de acesso (44 dígitos)constcte=awaitnfe.transportationInvoices.retrieve('empresa-id','35240112345678000190570010000001231234567890');console.log('Remetente:',cte.nameSender);console.log('Valor:',cte.totalInvoiceAmount);console.log('Emissão:',cte.issuedOn);// Baixar XML do CT-econstxml=awaitnfe.transportationInvoices.downloadXml('empresa-id','35240112345678000190570010000001231234567890');fs.writeFileSync('cte.xml',xml);// Consultar evento do CT-econstevento=awaitnfe.transportationInvoices.getEvent('empresa-id','35240112345678000190570010000001231234567890','chave-evento');// Baixar XML do eventoconsteventoXml=awaitnfe.transportationInvoices.downloadEventXml('empresa-id','35240112345678000190570010000001231234567890','chave-evento');Nota: A API de CT-e usa um host separado (
api.nfse.io). Você pode configurar uma chave API específica comdataApiKey, ou o SDK usaráapiKeycomo fallback.
Pré-requisitos:
- Empresa deve estar cadastrada com certificado digital A1 válido
- Webhook deve estar configurado para receber notificações de CT-e
Consultar NF-e (Nota Fiscal Eletrônica de Produto) recebidas via Distribuição NF-e:
// Ativar busca automática de NF-e para uma empresaconstsettings=awaitnfe.inboundProductInvoices.enableAutoFetch('empresa-id',{environmentSEFAZ: 'Production',webhookVersion: '2',});console.log('Status:',settings.status);// Ativar a partir de um NSU específicoconstsettings=awaitnfe.inboundProductInvoices.enableAutoFetch('empresa-id',{startFromNsu: '999999',environmentSEFAZ: 'Production',});// Verificar configurações atuaisconstconfig=awaitnfe.inboundProductInvoices.getSettings('empresa-id');console.log('Busca ativa:',config.status);// Desativar busca automáticaawaitnfe.inboundProductInvoices.disableAutoFetch('empresa-id');// Consultar NF-e por chave de acesso - formato webhook v2 (recomendado)constnfe_doc=awaitnfe.inboundProductInvoices.getProductInvoiceDetails('empresa-id','35240112345678000190550010000001231234567890');console.log('Emissor:',nfe_doc.issuer?.name);console.log('Valor:',nfe_doc.totalInvoiceAmount);// Baixar XML da NF-econstxml=awaitnfe.inboundProductInvoices.getXml('empresa-id','35240112345678000190550010000001231234567890');fs.writeFileSync('nfe.xml',xml);// Baixar PDF (DANFE)constpdf=awaitnfe.inboundProductInvoices.getPdf('empresa-id','35240112345678000190550010000001231234567890');// Enviar manifestação (Ciência da Operação por padrão)awaitnfe.inboundProductInvoices.manifest('empresa-id','35240112345678000190550010000001231234567890');// Manifestar com evento específicoawaitnfe.inboundProductInvoices.manifest('empresa-id','35240112345678000190550010000001231234567890',210220// Confirmação da Operação);// Consultar evento da NF-econstevento=awaitnfe.inboundProductInvoices.getEventDetails('empresa-id','35240112345678000190550010000001231234567890','chave-evento');// Baixar XML do eventoconsteventoXml=awaitnfe.inboundProductInvoices.getEventXml('empresa-id','35240112345678000190550010000001231234567890','chave-evento');// Reprocessar webhookawaitnfe.inboundProductInvoices.reprocessWebhook('empresa-id','35240...');Nota: A API de NF-e Distribuição usa um host separado (
api.nfse.io). Você pode configurar uma chave API específica comdataApiKey, ou o SDK usaráapiKeycomo fallback.
Pré-requisitos:
- Empresa deve estar cadastrada com certificado digital A1 válido
- Webhook deve estar configurado para receber notificações de NF-e
Tipos de Manifestação:
| Código | Evento |
|---|---|
210210 | Ciência da Operação (padrão) |
210220 | Confirmação da Operação |
210240 | Operação não Realizada |
Ciclo completo de gestão de NF-e (Nota Fiscal Eletrônica de Produto) — emissão, listagem, consulta, cancelamento, carta de correção (CC-e), inutilização e download de arquivos (PDF/XML):
// Emitir NF-e (assíncrono — retorna 202)constresult=awaitnfe.productInvoices.create('empresa-id',{operationNature: 'Venda de mercadoria',operationType: 'Outgoing',buyer: {name: 'Empresa LTDA',federalTaxNumber: 12345678000190},items: [{code: 'PROD-001',description: 'Produto X',quantity: 1,unitAmount: 100}],payment: [{paymentDetail: [{method: 'Cash',amount: 100}]}],});// Listar NF-e (environment é obrigatório)constinvoices=awaitnfe.productInvoices.list('empresa-id',{environment: 'Production',limit: 10,});// Consultar NF-e por IDconstinvoice=awaitnfe.productInvoices.retrieve('empresa-id','invoice-id');// Cancelar NF-e (assíncrono)awaitnfe.productInvoices.cancel('empresa-id','invoice-id','Motivo do cancelamento');// Download de PDF e XMLconstpdf=awaitnfe.productInvoices.downloadPdf('empresa-id','invoice-id');constxml=awaitnfe.productInvoices.downloadXml('empresa-id','invoice-id');// Carta de correção (CC-e) — razão de 15 a 1.000 caracteresawaitnfe.productInvoices.sendCorrectionLetter('empresa-id','invoice-id','Correcao do endereco do destinatario conforme novo cadastro');// Inutilizar faixa de numeraçãoawaitnfe.productInvoices.disableRange('empresa-id',{environment: 'Production',serie: 1,state: 'SP',beginNumber: 100,lastNumber: 110,});Nota: Operações de emissão, cancelamento, CC-e e inutilização são assíncronas — retornam 202/204. Conclusão é notificada via webhooks.
CRUD de inscrições estaduais (IE) — configuração necessária para emissão de NF-e de produto:
// Listar inscrições estaduaisconsttaxes=awaitnfe.stateTaxes.list('empresa-id');// Criar inscrição estadualconsttax=awaitnfe.stateTaxes.create('empresa-id',{taxNumber: '123456789',serie: 1,number: 1,code: 'sP',environmentType: 'production',type: 'nFe',});// Consultar, atualizar e excluirconstretrieved=awaitnfe.stateTaxes.retrieve('empresa-id','state-tax-id');awaitnfe.stateTaxes.update('empresa-id','state-tax-id',{serie: 2});awaitnfe.stateTaxes.delete('empresa-id','state-tax-id');Nota: Usa o host
api.nfse.io. ConfiguredataApiKeypara chave separada, ou o SDK usaráapiKeycomo fallback.
Consultar NF-e (Nota Fiscal Eletrônica de Produto) diretamente na SEFAZ por chave de acesso. Recurso somente leitura sem necessidade de escopo de empresa:
// Consultar dados completos da NF-econstinvoice=awaitnfe.productInvoiceQuery.retrieve('35240112345678000190550010000001231234567890');console.log('Status:',invoice.currentStatus);console.log('Emissor:',invoice.issuer?.name);console.log('Valor:',invoice.totals?.icms?.invoiceAmount);// Baixar DANFE (PDF)constpdf=awaitnfe.productInvoiceQuery.downloadPdf('35240112345678000190550010000001231234567890');fs.writeFileSync('danfe.pdf',pdf);// Baixar XML da NF-econstxml=awaitnfe.productInvoiceQuery.downloadXml('35240112345678000190550010000001231234567890');fs.writeFileSync('nfe.xml',xml);// Listar eventos fiscais (cancelamentos, correções, manifestações)constresult=awaitnfe.productInvoiceQuery.listEvents('35240112345678000190550010000001231234567890');for(consteventofresult.events??[]){console.log(event.description,event.authorizedOn);}Nota: A API de Consulta NF-e usa um host separado (
nfe.api.nfe.io). Você pode configurar uma chave API específica comdataApiKey, ou o SDK usaráapiKeycomo fallback.
Consultar CFe-SAT (Cupom Fiscal Eletrônico) por chave de acesso. Recurso somente leitura sem necessidade de escopo de empresa:
// Consultar dados completos do cupom fiscalconstcoupon=awaitnfe.consumerInvoiceQuery.retrieve('35240112345678000190590000000012341234567890');console.log('Status:',coupon.currentStatus);// 'Authorized'console.log('Emissor:',coupon.issuer?.name);console.log('Valor:',coupon.totals?.couponAmount);// Baixar XML do CFeconstxml=awaitnfe.consumerInvoiceQuery.downloadXml('35240112345678000190590000000012341234567890');fs.writeFileSync('cfe.xml',xml);Nota: A API de Consulta CFe-SAT usa o mesmo host (
nfe.api.nfe.io) e chave de API que a consulta de NF-e.
Consultar dados cadastrais de empresas brasileiras (CNPJ) na Receita Federal e nas SEFAZs estaduais:
// Consulta básica por CNPJ (aceita com ou sem pontuação)constresult=awaitnfe.legalEntityLookup.getBasicInfo('12.345.678/0001-90');console.log('Razão Social:',result.legalEntity?.name);console.log('Nome Fantasia:',result.legalEntity?.tradeName);console.log('Status:',result.legalEntity?.status);// 'Active'console.log('Porte:',result.legalEntity?.size);// 'ME', 'EPP', etc.console.log('Cidade:',result.legalEntity?.address?.city?.name);// Consulta com opçõesconstresult=awaitnfe.legalEntityLookup.getBasicInfo('12345678000190',{updateAddress: false,// Não atualizar endereço via CorreiosupdateCityCode: true,// Atualizar código IBGE da cidade});// Consultar Inscrição Estadual (IE) por estadoconstieSP=awaitnfe.legalEntityLookup.getStateTaxInfo('SP','12345678000190');for(consttaxofieSP.legalEntity?.stateTaxes??[]){console.log(`IE: ${tax.taxNumber} - Status: ${tax.status}`);console.log(` NFe: ${tax.nfe?.status}, CTe: ${tax.cte?.status}`);}// Avaliar IE para emissão de nota fiscalconstinvoice=awaitnfe.legalEntityLookup.getStateTaxForInvoice('MG','12345678000190');for(consttaxofinvoice.legalEntity?.stateTaxes??[]){if(tax.status==='Abled'){console.log(`Pode emitir com IE: ${tax.taxNumber}`);}}// Obter melhor IE sugerida para emissãoconstsugestao=awaitnfe.legalEntityLookup.getSuggestedStateTaxForInvoice('SP','12345678000190');constmelhorIE=sugestao.legalEntity?.stateTaxes?.[0];console.log('IE recomendada:',melhorIE?.taxNumber);Nota: A API de Consulta CNPJ usa um host separado (
legalentity.api.nfe.io). Você pode configurar uma chave API específica comdataApiKey, ou o SDK usaráapiKeycomo fallback.
Consultar a situação cadastral de CPF (pessoa física) na Receita Federal:
// Consulta com CPF e data de nascimentoconstresult=awaitnfe.naturalPersonLookup.getStatus('123.456.789-01','1990-01-15');console.log('Nome:',result.name);// 'JOÃO DA SILVA'console.log('Status:',result.status);// 'Regular'// Também aceita Date objectconstresult=awaitnfe.naturalPersonLookup.getStatus('12345678901',newDate(1990,0,15));console.log('Situação Cadastral:',result.status);Nota: A API de Consulta CPF usa um host separado (
naturalperson.api.nfe.io). Você pode configurar uma chave API específica comdataApiKey, ou o SDK usaráapiKeycomo fallback.
Calcular todos os tributos aplicáveis (ICMS, ICMS-ST, PIS, COFINS, IPI, II) para operações com produtos usando o Motor de Cálculo de Tributos:
// Calcular impostos de uma operação de vendaconstresultado=awaitnfe.taxCalculation.calculate('tenant-id',{operationType: 'Outgoing',issuer: {state: 'SP',taxRegime: 'RealProfit'},recipient: {state: 'RJ'},items: [{id: 'item-1',operationCode: 121,origin: 'National',ncm: '61091000',quantity: 10,unitAmount: 100.00}]});for(constitemofresultado.items??[]){console.log(`Item ${item.id}: CFOP ${item.cfop}`);console.log(` ICMS: CST=${item.icms?.cst}, valor=${item.icms?.vICMS}`);console.log(` PIS: CST=${item.pis?.cst}, valor=${item.pis?.vPIS}`);console.log(` COFINS: CST=${item.cofins?.cst}, valor=${item.cofins?.vCOFINS}`);}Nota: A API de Cálculo de Impostos usa o host
api.nfse.io. ConfiguredataApiKeypara uma chave específica, ou o SDK usaráapiKeycomo fallback.
Consultar tabelas de referência necessárias para o cálculo de impostos:
// Listar códigos de operação (natureza de operação)constcodigos=awaitnfe.taxCodes.listOperationCodes({pageIndex: 1,pageCount: 20});for(constcodofcodigos.items??[]){console.log(`${cod.code} - ${cod.description}`);}// Listar finalidades de aquisiçãoconstfinalidades=awaitnfe.taxCodes.listAcquisitionPurposes();// Listar perfis fiscais do emissorconstperfisEmissor=awaitnfe.taxCodes.listIssuerTaxProfiles();// Listar perfis fiscais do destinatárioconstperfisDestinatario=awaitnfe.taxCodes.listRecipientTaxProfiles();Nota: Todas as listagens suportam paginação via
pageIndex(1-based) epageCount(padrão: 50).
constnfe=newNfeClient({// Chave API principal do NFE.io (operações com documentos fiscais)apiKey: 'sua-chave-api',// Opcional: Chave API para serviços de consulta (Endereços, CT-e, CNPJ, CPF)// Se não fornecida, usa apiKey como fallbackdataApiKey: 'sua-chave-data-api',// Opcional: Ambiente (padrão: 'production')environment: 'production',// ou 'sandbox'// Opcional: URL base customizada (sobrescreve environment)baseUrl: 'https://api-customizada.nfe.io/v1',// Opcional: Timeout de requisição em milissegundos (padrão: 30000)timeout: 60000,// Opcional: Configuração de retryretryConfig: {maxRetries: 3,baseDelay: 1000,maxDelay: 10000,backoffMultiplier: 2}});O SDK suporta as seguintes variáveis de ambiente:
| Variável | Descrição |
|---|---|
NFE_API_KEY | Chave API principal (fallback para apiKey) |
NFE_DATA_API_KEY | Chave API para serviços de consulta (fallback para dataApiKey) |
# Configurar via ambienteexport NFE_API_KEY="sua-chave-api"export NFE_DATA_API_KEY="sua-chave-data"# Usar SDK sem passar chaves no código
const nfe = new NfeClient({});O SDK fornece classes de erro tipadas:
import{NfeError,AuthenticationError,ValidationError,NotFoundError,RateLimitError}from'nfe-io';try{constnotaFiscal=awaitnfe.serviceInvoices.create(empresaId,dados);}catch(erro){if(erroinstanceofAuthenticationError){console.error('Chave API inválida:',erro.message);}elseif(erroinstanceofValidationError){console.error('Dados inválidos:',erro.details);}elseif(erroinstanceofNotFoundError){console.error('Recurso não encontrado:',erro.message);}elseif(erroinstanceofRateLimitError){console.error('Limite de requisições excedido, tente novamente em:',erro.retryAfter);}elseif(erroinstanceofNfeError){console.error('Erro da API:',erro.code,erro.message);}else{console.error('Erro inesperado:',erro);}}Veja MIGRATION.md para um guia completo de migração.
Principais Mudanças:
// v2 (callbacks + promises)varnfe=require('nfe-io')('chave-api');nfe.serviceInvoices.create('id-empresa',dados,function(err,notaFiscal){if(err)returnconsole.error(err);console.log(notaFiscal);});// v3 (async/await + TypeScript)import{NfeClient}from'nfe-io';constnfe=newNfeClient({apiKey: 'chave-api'});try{constnotaFiscal=awaitnfe.serviceInvoices.create('id-empresa',dados);console.log(notaFiscal);}catch(erro){console.error(erro);}O diretório examples/ contém exemplos completos que você pode executar com suas credenciais:
# Modo interativo com menu
npm run examples
# Ou diretamente
node examples/run-examples.jsExemplos disponíveis:
- 📊 Listar Notas Fiscais - Consulte notas existentes (comece por aqui!)
- 👥 Gerenciar Pessoas - CRUD de clientes (pessoas físicas/jurídicas)
- 🧾 Emitir Nota Fiscal - Fluxo completo: criar → enviar email → baixar PDF/XML
- 🔔 Configurar Webhooks - Receba notificações de eventos
Veja examples/README.md para documentação completa.
import{NfeClient}from'nfe-io';constnfe=newNfeClient({apiKey: process.env.NFE_API_KEY!,environment: 'production'});asyncfunctionemitirNotaFiscal(){// 1. Buscar ou criar empresaconstempresas=awaitnfe.companies.list();constempresa=empresas.data[0];// 2. Criar nota fiscal com polling automáticoconstnotaFiscal=awaitnfe.serviceInvoices.createAndWait(empresa.id,{cityServiceCode: '01234',description: 'Consultoria em TI',servicesAmount: 5000.00,borrower: {type: 'LegalEntity',federalTaxNumber: 12345678000190,name: 'Cliente Exemplo Ltda',email: 'contato@cliente.com.br',address: {country: 'BRA',postalCode: '01310-100',street: 'Av. Paulista',number: '1000',city: {code: '3550308',name: 'São Paulo'},state: 'SP'}}},{maxAttempts: 30,intervalMs: 2000});console.log(`✅ Nota fiscal emitida: ${notaFiscal.number}`);// 3. Enviar por emailawaitnfe.serviceInvoices.sendEmail(empresa.id,notaFiscal.id);console.log('📧 Email enviado');// 4. Baixar PDFconstpdf=awaitnfe.serviceInvoices.downloadPdf(empresa.id,notaFiscal.id);awaitfs.promises.writeFile(`nota-fiscal-${notaFiscal.number}.pdf`,pdf);console.log('💾 PDF salvo');}emitirNotaFiscal().catch(console.error);// Configurar webhook para receber eventos de notas fiscaisconstwebhook=awaitnfe.webhooks.create(empresaId,{url: 'https://meuapp.com.br/api/webhooks/nfe',events: ['invoice.issued','invoice.cancelled','invoice.error'],active: true});// No seu endpoint de webhook (capture o corpo cru: app.use(express.raw({ type: '*/*' })))app.post('/api/webhooks/nfe',(req,res)=>{constassinatura=req.headers['x-hub-signature'];// header correto (HMAC-SHA1), não 'x-nfe-signature'constehValido=nfe.webhooks.validateSignature(req.body,assinatura,process.env.WEBHOOK_SECRET);if(!ehValido){returnres.status(401).send('Assinatura inválida');}const{ event, data }=req.body;if(event==='invoice.issued'){console.log('Nota fiscal emitida:',data.id);}res.status(200).send('OK');});asyncfunctionemitirNotasEmLote(empresaId: string,notasFiscais: DadosNota[]){constresultados=awaitPromise.allSettled(notasFiscais.map(dados=>nfe.serviceInvoices.createAndWait(empresaId,dados)));constsucesso=resultados.filter(r=>r.status==='fulfilled');constfalha=resultados.filter(r=>r.status==='rejected');console.log(`✅ ${sucesso.length} notas fiscais emitidas`);console.log(`❌ ${falha.length} notas fiscais falharam`);return{ sucesso, falha };}Documentação completa da API disponível em:
# Executar todos os testes (unit + integration)
npm test# Executar apenas testes unitários
npm run test:unit
# Executar apenas testes de integração (requer chave API)
npm run test:integration
# Executar com cobertura
npm run test:coverage
# Executar com UI
npm run test:uiOs testes de integração validam contra a API real do NFE.io:
# Definir sua chave API de desenvolvimento/testeexport NFE_API_KEY="sua-chave-api-desenvolvimento"export NFE_TEST_ENVIRONMENT="development"export RUN_INTEGRATION_TESTS="true"# Executar testes de integração
npm run test:integrationVeja tests/integration/README.md para documentação detalhada.
Nota: Testes de integração fazem chamadas reais à API e podem gerar custos dependendo do seu plano.
O SDK gera tipos TypeScript automaticamente a partir de especificações OpenAPI. As specs são mantidas manualmente em openapi/spec/:
# Validar todas as specs OpenAPI
npm run validate:spec
# Gerar tipos TypeScript a partir das specs
npm run generate
# Modo watch - regenerar automaticamente ao modificar specs
npm run generate:watchLocalização das specs: openapi/spec/*.yaml
Tipos gerados: src/generated/*.ts
Configuração: openapi/generator-config.yaml
O processo de build valida automaticamente as specs e gera tipos antes da compilação:
npm run build
# → Executa: validate:spec → generate → typecheck → tsdownNota: Arquivos gerados não devem ser editados manualmente. Edite as specs OpenAPI e regenere.
Para orientações de migração, veja docs/MIGRATION-TO-GENERATED-TYPES.md.
npm run typechecknpm run buildContribuições são bem-vindas! Por favor, veja CONTRIBUTING.md para orientações.
MIT © NFE.io
- 📧 Email: suporte@nfe.io
- 📖 Documentação: https://nfe.io/docs/
- 🐛 Issues: https://github.com/nfe/client-nodejs/issues
Feito com ❤️ pela equipe NFE.io