Skip to content

Repository files navigation

NFE.io SDK para Node.js (v5)

npm versionNode.js VersionTypeScriptLicense: MITskills.sh

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.

📋 Índice

✨ Recursos

  • 🎯 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

📦 Instalação

Requisitos:

  • Node.js >= 22.0.0
  • TypeScript >= 5.0 (se usar TypeScript)
npm install nfe-io

ou

yarn add nfe-io

ou

pnpm add nfe-io

🚀 Início Rápido

⚡ Setup Rápido para Testes

# 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 examples

📦 Instalação em Projeto Novo

npm install nfe-io

Uso Básico (ESM)

import{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}`);

Uso com CommonJS

const{ NfeClient }=require('nfe-io');constnfe=newNfeClient({apiKey: process.env.NFE_API_KEY,environment: 'production'});// Mesma API que ESM

🤖 Skill para Agentes de IA

Este 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-nodejs

Descubra no diretório: skills.sh

📚 Documentação

Recursos da API

O SDK fornece os seguintes recursos:

🧾 Notas Fiscais de Serviço (nfe.serviceInvoices)

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)

🏢 Empresas (nfe.companies)

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'});

👔 Pessoas Jurídicas (nfe.legalPeople)

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');

👤 Pessoas Físicas (nfe.naturalPeople)

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');

🔗 Webhooks (nfe.webhooks)

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);

📍 Endereços (nfe.addresses)

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 com dataApiKey, ou o SDK usará apiKey como fallback.

🚚 Notas de Transporte - CT-e (nfe.transportationInvoices)

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 com dataApiKey, ou o SDK usará apiKey como fallback.

Pré-requisitos:

  • Empresa deve estar cadastrada com certificado digital A1 válido
  • Webhook deve estar configurado para receber notificações de CT-e

📥 NF-e de Entrada - Distribuição (nfe.inboundProductInvoices)

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 com dataApiKey, ou o SDK usará apiKey como 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ódigoEvento
210210Ciência da Operação (padrão)
210220Confirmação da Operação
210240Operação não Realizada

📦 NF-e de Produto - Emissão (nfe.productInvoices)

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.

🏛️ Inscrições Estaduais (nfe.stateTaxes)

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. Configure dataApiKey para chave separada, ou o SDK usará apiKey como fallback.

🔍 Consulta de NF-e por Chave de Acesso (nfe.productInvoiceQuery)

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 com dataApiKey, ou o SDK usará apiKey como fallback.

🧾 Consulta de Cupom Fiscal Eletrônico - CFe-SAT (nfe.consumerInvoiceQuery)

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.

🏢 Consulta CNPJ / Pessoa Jurídica (nfe.legalEntityLookup)

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 com dataApiKey, ou o SDK usará apiKey como fallback.

👤 Consulta CPF / Pessoa Física (nfe.naturalPersonLookup)

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 com dataApiKey, ou o SDK usará apiKey como fallback.

🧮 Cálculo de Impostos (nfe.taxCalculation)

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. Configure dataApiKey para uma chave específica, ou o SDK usará apiKey como fallback.

📋 Códigos Auxiliares de Impostos (nfe.taxCodes)

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) e pageCount (padrão: 50).


Opções de Configuração

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}});

Variáveis de Ambiente

O SDK suporta as seguintes variáveis de ambiente:

VariávelDescrição
NFE_API_KEYChave API principal (fallback para apiKey)
NFE_DATA_API_KEYChave 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({});

Tratamento de Erros

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);}}

🔄 Migração da v2

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);}

📝 Exemplos

⚡ Exemplos Práticos Prontos para Uso

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.js

Exemplos disponíveis:

  1. 📊 Listar Notas Fiscais - Consulte notas existentes (comece por aqui!)
  2. 👥 Gerenciar Pessoas - CRUD de clientes (pessoas físicas/jurídicas)
  3. 🧾 Emitir Nota Fiscal - Fluxo completo: criar → enviar email → baixar PDF/XML
  4. 🔔 Configurar Webhooks - Receba notificações de eventos

Veja examples/README.md para documentação completa.


Fluxo Completo de Emissão de Nota Fiscal

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);

Configuração de Webhook

// 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');});

Criação de Notas Fiscais em Lote

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 };}

🏗️ Referência da API

Documentação completa da API disponível em:

🧪 Desenvolvimento & Testes

Executando Testes

# 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:ui

Testes de Integração

Os 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:integration

Veja 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.

Geração de Tipos OpenAPI

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:watch

Localizaçã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 → tsdown

Nota: 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.

Verificação de Tipos

npm run typecheck

Build

npm run build

🤝 Contribuindo

Contribuições são bem-vindas! Por favor, veja CONTRIBUTING.md para orientações.

📄 Licença

MIT © NFE.io

🆘 Suporte


Feito com ❤️ pela equipe NFE.io

About

SDK oficial da NFE.io para Node.js (TypeScript, zero dependências) para emitir NFS-e — nota fiscal de serviço eletrônica — e consultar CNPJ e CEP via API. Documentos fiscais do Brasil com async/await nativo.

Topics

Resources

Contributing

Stars

140 stars

Watchers

13 watching

Forks

Releases

Used by

Contributors

Languages