@useinvio/nfse-sdk 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/CHANGELOG.md +176 -0
  2. package/README.en.md +146 -0
  3. package/README.md +77 -518
  4. package/dist/agent.d.ts +131 -0
  5. package/dist/agent.js +551 -0
  6. package/dist/agent.js.map +1 -0
  7. package/dist/certificate.d.ts +96 -0
  8. package/dist/certificate.js +218 -0
  9. package/dist/certificate.js.map +1 -0
  10. package/dist/certificateValidation.d.ts +11 -6
  11. package/dist/certificateValidation.js +23 -12
  12. package/dist/certificateValidation.js.map +1 -1
  13. package/dist/cli.d.ts +2 -0
  14. package/dist/cli.js +520 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/cliBin.d.ts +2 -0
  17. package/dist/cliBin.js +6 -0
  18. package/dist/cliBin.js.map +1 -0
  19. package/dist/cliExample.d.ts +6 -0
  20. package/dist/cliExample.js +29 -0
  21. package/dist/cliExample.js.map +1 -0
  22. package/dist/client.d.ts +51 -4
  23. package/dist/client.js +41 -10
  24. package/dist/client.js.map +1 -1
  25. package/dist/config.d.ts +3 -0
  26. package/dist/config.js +8 -0
  27. package/dist/config.js.map +1 -1
  28. package/dist/consultas.d.ts +34 -0
  29. package/dist/consultas.js +61 -0
  30. package/dist/consultas.js.map +1 -0
  31. package/dist/dpsJson.js +1 -41
  32. package/dist/dpsJson.js.map +1 -1
  33. package/dist/dpsJsonSchema.d.ts +17 -0
  34. package/dist/dpsJsonSchema.js +184 -0
  35. package/dist/dpsJsonSchema.js.map +1 -0
  36. package/dist/emissaoNota.d.ts +11 -6
  37. package/dist/emissaoNota.js +10 -6
  38. package/dist/emissaoNota.js.map +1 -1
  39. package/dist/eventoJson.d.ts +76 -0
  40. package/dist/eventoJson.js +128 -0
  41. package/dist/eventoJson.js.map +1 -0
  42. package/dist/eventosNfse.d.ts +38 -0
  43. package/dist/eventosNfse.js +73 -0
  44. package/dist/eventosNfse.js.map +1 -0
  45. package/dist/fiscalDomains.d.ts +22 -0
  46. package/dist/fiscalDomains.js +99 -0
  47. package/dist/fiscalDomains.js.map +1 -0
  48. package/dist/fiscalValidation.js +21 -53
  49. package/dist/fiscalValidation.js.map +1 -1
  50. package/dist/gzipB64.d.ts +5 -0
  51. package/dist/gzipB64.js +12 -0
  52. package/dist/gzipB64.js.map +1 -1
  53. package/dist/index.d.ts +22 -7
  54. package/dist/index.js +11 -4
  55. package/dist/index.js.map +1 -1
  56. package/dist/jsonSchemaCheck.d.ts +12 -0
  57. package/dist/jsonSchemaCheck.js +70 -0
  58. package/dist/jsonSchemaCheck.js.map +1 -0
  59. package/dist/loadPfx.d.ts +2 -0
  60. package/dist/loadPfx.js +2 -1
  61. package/dist/loadPfx.js.map +1 -1
  62. package/dist/mcpCli.d.ts +2 -0
  63. package/dist/mcpCli.js +7 -0
  64. package/dist/mcpCli.js.map +1 -0
  65. package/dist/mcpServer.d.ts +49 -0
  66. package/dist/mcpServer.js +159 -0
  67. package/dist/mcpServer.js.map +1 -0
  68. package/dist/nfseXml.d.ts +48 -0
  69. package/dist/nfseXml.js +86 -0
  70. package/dist/nfseXml.js.map +1 -0
  71. package/dist/rejeicoes.d.ts +50 -0
  72. package/dist/rejeicoes.js +62 -0
  73. package/dist/rejeicoes.js.map +1 -0
  74. package/dist/rejeicoesCatalog.d.ts +10 -0
  75. package/dist/rejeicoesCatalog.js +4449 -0
  76. package/dist/rejeicoesCatalog.js.map +1 -0
  77. package/dist/sefinClient.d.ts +107 -7
  78. package/dist/sefinClient.js +232 -22
  79. package/dist/sefinClient.js.map +1 -1
  80. package/dist/signXml.d.ts +3 -3
  81. package/dist/signXml.js +17 -7
  82. package/dist/signXml.js.map +1 -1
  83. package/dist/testing.d.ts +80 -0
  84. package/dist/testing.js +285 -0
  85. package/dist/testing.js.map +1 -0
  86. package/dist/xmlBuild.d.ts +11 -0
  87. package/dist/xmlBuild.js +44 -0
  88. package/dist/xmlBuild.js.map +1 -0
  89. package/dist/xmlInspection.d.ts +1 -1
  90. package/dist/xmlInspection.js +10 -9
  91. package/dist/xmlInspection.js.map +1 -1
  92. package/dist/xsdValidation.d.ts +24 -5
  93. package/dist/xsdValidation.js +97 -67
  94. package/dist/xsdValidation.js.map +1 -1
  95. package/docs/README.md +47 -0
  96. package/docs/REGRAS_NEGOCIO_EMISSAO.md +8 -8
  97. package/docs/conceitos/como-funciona.md +87 -0
  98. package/docs/guias/adn.md +51 -0
  99. package/docs/guias/agentes-ia.md +111 -0
  100. package/docs/guias/cancelar.md +70 -0
  101. package/docs/guias/certificado.md +88 -0
  102. package/docs/guias/cli.md +68 -0
  103. package/docs/guias/consultar.md +54 -0
  104. package/docs/guias/emitir.md +172 -0
  105. package/docs/guias/recuperar-emissao.md +33 -0
  106. package/docs/guias/rejeicoes.md +70 -0
  107. package/docs/guias/testes.md +79 -0
  108. package/docs/guias/timeouts.md +33 -0
  109. package/docs/referencia/ambientes.md +35 -0
  110. package/docs/referencia/api.md +137 -0
  111. package/docs/referencia/erros.md +55 -0
  112. package/docs/tutoriais/primeira-nfse.md +130 -0
  113. package/examples/README.md +3 -1
  114. package/examples/cancel-nfse.ts +29 -0
  115. package/examples/client-resource.ts +3 -5
  116. package/examples/emit-homologation.ts +3 -4
  117. package/examples/handle-errors.ts +3 -3
  118. package/examples/recover-emission.ts +29 -0
  119. package/llms.txt +97 -82
  120. package/package.json +31 -6
package/README.md CHANGED
@@ -1,52 +1,35 @@
1
1
  # @useinvio/nfse-sdk
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@useinvio/nfse-sdk.svg)](https://www.npmjs.com/package/@useinvio/nfse-sdk)
4
- [![npm access](https://img.shields.io/badge/npm-public-brightgreen.svg)](https://www.npmjs.com/package/@useinvio/nfse-sdk)
4
+ [![CI](https://github.com/useinvio/nfse-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/useinvio/nfse-sdk/actions/workflows/ci.yml)
5
5
  [![Node.js](https://img.shields.io/badge/node-%3E%3D20-339933.svg)](https://nodejs.org/)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
6
7
 
7
- [Website](https://sdk.useinvio.com/)
8
+ [Website](https://sdk.useinvio.com/) · [Playground](https://useinvio.github.io/nfse-sdk/) · [Documentação](./docs/README.md) · [English](./README.en.md)
8
9
 
9
- [English version](./ENGLISH.md)
10
+ <img width="959" height="296" alt="NFS-e SDK" src="https://github.com/user-attachments/assets/d6c45737-e7ca-4ea7-a06f-d93b7c16e4f0" />
10
11
 
11
- <img width="959" height="296" alt="image" src="https://github.com/user-attachments/assets/d6c45737-e7ca-4ea7-a06f-d93b7c16e4f0" />
12
+ **Emita, consulte e cancele NFS-e Nacional em TypeScript, sem escrever XML fiscal na mão.**
12
13
 
13
- ---
14
+ Você descreve a nota em JSON; o SDK monta a DPS, valida contra o XSD oficial,
15
+ assina com o certificado A1, compacta, envia por mTLS para a SEFIN e devolve a
16
+ resposta oficial em formato estruturado. Sem binários nativos e sem `xmllint`.
14
17
 
15
- SDK TypeScript para integração com a **NFS-e Nacional** (SEFIN).
18
+ ## O que ele faz
16
19
 
17
- Transforme JSON em DPS/NFS-e, assine com XMLDSIG, compacte em GZip/Base64 e transmita por mTLS sem escrever XML fiscal na mão.
18
-
19
- O SDK cuida da camada protocolar: certificado A1, montagem de DPS, validações estruturais, assinatura XML, compactação, envio, consulta e normalização de rejeições da SEFIN. A aplicação [...]
20
-
21
- **Para quem é:** ERPs, SaaS financeiros, plataformas de cobrança, contabilidades digitais e times Node.js/TypeScript que precisam integrar com a NFS-e Nacional.
22
-
23
- **O que ele não é:** um motor fiscal, consultor tributário ou substituto da validação contábil do seu produto.
24
-
25
- ---
26
-
27
- ## Índice
28
-
29
- - [Instalação](#instalação)
30
- - [Quick start](#quick-start)
31
- - [Por que usar](#por-que-usar)
32
- - [Escolhendo o ponto de entrada](#escolhendo-o-ponto-de-entrada)
33
- - [Cliente orientado a recursos](#cliente-orientado-a-recursos)
34
- - [Certificado A1](#certificado-a1)
35
- - [Emitir a partir de XML pronto](#emitir-a-partir-de-xml-pronto)
36
- - [Emitir a partir de JSON declarativo](#emitir-a-partir-de-json-declarativo)
37
- - [Inspecionar o XML antes de enviar](#inspecionar-o-xml-antes-de-enviar)
38
- - [Tratar rejeições da SEFIN](#tratar-rejeições-da-sefin)
39
- - [Consultar uma NFS-e emitida](#consultar-uma-nfs-e-emitida)
40
- - [Enviar evento](#enviar-evento-ex-cancelamento)
41
- - [Série e número da DPS](#série-e-número-da-dps)
42
- - [Ambientes](#ambientes)
43
- - [Referência da API](#referência-da-api)
44
- - [Desenvolvimento](#desenvolvimento)
45
- - [Publicação no npm](#publicação-no-npm)
46
- - [Divulgação e exemplos](#divulgação-e-exemplos)
47
- - [Assistente GPT](#assistente-gpt)
48
-
49
- ---
20
+ | Operação | Função | No `NfseClient` |
21
+ |---|---|---|
22
+ | Emitir a partir de JSON ou XML | `emitirNfse` | `invoices.create` |
23
+ | Validar sem enviar (JSON + XSD) | `validateDpsJsonRequest`, `buildDpsFromJson` | `invoices.buildDpsJson` |
24
+ | Consultar com resultado tipado | `obterNfse` | `invoices.retrieve` |
25
+ | Recuperar uma emissão após timeout | `recuperarNfsePorDps` | `invoices.recover` |
26
+ | Cancelar / cancelar por substituição | `cancelarNfse`, `cancelarNfsePorSubstituicao` | `invoices.cancel`, `invoices.cancelBySubstitution` |
27
+ | Baixar o DANFSe em PDF | `baixarDanfse` | `invoices.danfse` |
28
+ | Distribuição por NSU e parâmetros municipais (ADN) | `distribuirDfePorNsu`, `consultarAliquota`… | `distribution`, `municipalParameters` |
29
+ | Explicar rejeições com o texto oficial | `explicarRejeicao`, `explicarErros`, [uma página por código](./docs/rejeicoes/README.md) | – |
30
+ | Usar pelo terminal | `npx nfse init`, `doctor`, `validate`, `emit`, `explain` | – |
31
+ | Testar sem certificado nem rede | `@useinvio/nfse-sdk/testing` | – |
32
+ | Servidor MCP e ferramentas para agentes de IA | `npx -y @useinvio/nfse-mcp`, `@useinvio/nfse-sdk/agent` | – |
50
33
 
51
34
  ## Instalação
52
35
 
@@ -54,21 +37,23 @@ O SDK cuida da camada protocolar: certificado A1, montagem de DPS, validações
54
37
  npm install @useinvio/nfse-sdk
55
38
  ```
56
39
 
57
- > Node.js ≥ 20 é obrigatório.
58
-
59
- ---
40
+ Node.js 20 ou mais recente. Nada para instalar no sistema: a validação XSD roda
41
+ em WebAssembly.
60
42
 
61
- ## Quick start
43
+ ## Em 60 segundos
62
44
 
63
- O caminho mais comum: emitir uma nota a partir de JSON declarativo.
45
+ ```bash
46
+ NFSE_CERT_PATH=./certificado.pfx
47
+ NFSE_CERT_PASSWORD=sua-senha
48
+ ```
64
49
 
65
50
  ```ts
66
- import { emitirNfse, loadPfx, EmitirNotaError } from '@useinvio/nfse-sdk';
51
+ import { emitirNfse, EmitirNotaError, NfseCertificate } from '@useinvio/nfse-sdk';
67
52
 
68
- const pfx = loadPfx('./certificado.pfx', process.env.PFX_PASSWORD!);
53
+ const certificado = NfseCertificate.fromEnv(); // a chave privada nunca aparece em logs
69
54
 
70
55
  const nota = {
71
- ambiente: 'restrita' as const,
56
+ ambiente: 'restrita' as const, // produção restrita: o sandbox oficial
72
57
  prestador: {
73
58
  cnpj: '12345678000195',
74
59
  cLocEmi: '4106902',
@@ -87,505 +72,79 @@ const nota = {
87
72
  dhEmi: '2026-06-15T10:30:00-03:00',
88
73
  dCompet: '2026-06-01',
89
74
  valores: { vServ: '1500.00' },
90
- tributacaoMunicipal: {
91
- tribISSQN: '1',
92
- tpRetISSQN: '1',
93
- },
94
- tributacaoFederal: {
95
- piscofins: { CST: '07' },
96
- },
97
- totTrib: {
98
- pTotTribFed: '0.00',
99
- pTotTribEst: '0.00',
100
- pTotTribMun: '5.00',
101
- },
102
- },
103
- };
104
-
105
- try {
106
- const resultado = await emitirNfse(nota, pfx);
107
- console.log(resultado.chaveAcesso); // chave de 50 dígitos
108
- console.log(resultado.nfseXml); // XML autorizado pela SEFIN
109
- } catch (error) {
110
- if (error instanceof EmitirNotaError) {
111
- for (const rejeicao of error.erros) {
112
- console.error(rejeicao.Codigo, rejeicao.Descricao);
113
- }
114
- }
115
- }
116
- ```
117
-
118
- ---
119
-
120
- ## Por que usar
121
-
122
- - Entrada JSON tipada para construir DPS no layout nacional.
123
- - Assinatura XMLDSIG, GZip/Base64 e mTLS encapsulados em uma API Node.js.
124
- - Erros oficiais da SEFIN preservados em formato estruturado.
125
- - Builder separado para inspecionar ou salvar o XML antes de transmitir.
126
- - Cliente `NfseClient` para configurar certificado, ambiente e defaults uma vez.
127
- - Validação explícita de campos fiscais obrigatórios, sem defaults silenciosos.
128
-
129
- ---
130
-
131
- ## Escolhendo o ponto de entrada
132
-
133
- | Situação | O que usar |
134
- |---|---|
135
- | Quer uma API de cliente com `client.invoices.create(...)` | `new NfseClient(...)` |
136
- | Outro sistema já gera o XML da DPS | `emitirNfse(xmlString, pfx)` |
137
- | Você monta os dados e quer que a SDK construa o XML | `emitirNfse(notaJson, pfx)` |
138
- | Precisa inspecionar ou salvar o XML antes de enviar | `buildDpsFromJson(nota)` |
139
- | Fluxo customizado (assinar, compactar ou enviar separadamente) | funções de baixo nível |
140
-
141
- ---
142
-
143
- ## Cliente orientado a recursos
144
-
145
- Use `NfseClient` quando preferir configurar ambiente e certificado uma vez e
146
- emitir notas por recursos, como `client.invoices.create(...)`.
147
-
148
- O cliente usa os mesmos campos do JSON declarativo (`prestador`, `servico` e
149
- `emissao`). Os `defaults` seguem o mesmo formato e podem ser sobrescritos em
150
- cada chamada.
151
-
152
- ```ts
153
- import { NfseClient } from '@useinvio/nfse-sdk';
154
-
155
- const client = new NfseClient({
156
- environment: 'sandbox',
157
- certificate: {
158
- content: process.env.NFSE_CERTIFICATE!, // PFX em base64
159
- password: process.env.NFSE_CERTIFICATE_PASSWORD!,
160
- },
161
- defaults: {
162
- prestador: {
163
- cnpj: '12345678000195',
164
- cLocEmi: '4106902',
165
- serie: '1601',
166
- opSimpNac: '1',
167
- regEspTrib: '0',
168
- },
169
- servico: {
170
- cTribNac: '010201',
171
- xDescServ: 'Servico ficticio de desenvolvimento de software',
172
- cLocPrestacao: '4106902',
173
- },
174
- },
175
- });
176
-
177
- const invoice = await client.invoices.create({
178
- emissao: {
179
- nDPS: '1',
180
- valores: { vServ: '1000.00' },
181
- tomador: {
182
- CPF: '00000000000',
183
- xNome: 'Cliente Exemplo',
184
- end: {
185
- endNac: { cMun: '4106902', CEP: '80010000' },
186
- xLgr: 'Rua Exemplo', nro: '100', xBairro: 'Centro',
187
- },
188
- },
189
- tributacaoMunicipal: {
190
- tribISSQN: '1',
191
- tpRetISSQN: '1',
192
- },
193
- tributacaoFederal: {
194
- piscofins: { CST: '07' },
195
- },
196
- totTrib: {
197
- pTotTribFed: '0.00',
198
- pTotTribEst: '0.00',
199
- pTotTribMun: '5.00',
200
- },
201
- },
202
- });
203
-
204
- console.log(invoice.chaveAcesso);
205
- console.log(invoice.nfseXml);
206
- ```
207
-
208
- `environment: 'sandbox'` é alias de `restrita`, e `production` é alias de
209
- `producao`. O campo `certificate.content` aceita o conteúdo binário do PFX em
210
- `Buffer` ou o PFX codificado em base64, formato comum para variáveis de
211
- ambiente.
212
-
213
- Para inspecionar a DPS gerada sem assinar nem enviar:
214
-
215
- ```ts
216
- const dps = client.invoices.buildDpsJson({
217
- prestador: {
218
- serie: '1701',
219
- },
220
- emissao: {
221
- nDPS: '2',
222
- valores: { vServ: '2500.00' },
223
75
  tributacaoMunicipal: { tribISSQN: '1', tpRetISSQN: '1' },
224
- totTrib: { pTotTribFed: '0', pTotTribEst: '0', pTotTribMun: '5' },
225
- },
226
- });
227
- ```
228
-
229
- ---
230
-
231
-
232
- ### Validacao e compatibilidade
233
-
234
- `validateDpsJsonRequest(entrada)` retorna `valid`, `issues` (erros), `warnings` (avisos) e uma copia `normalizedPayload`. Campos opcionais devem ser omitidos ou `undefined`; strings vazias, `null` e tipos incorretos sao rejeitados. Consulte [o mapeamento JSON](JSON_MAPPING.md) para os limites de datas e valores.
235
-
236
- Divergencias entre `vServ` e a conversao cambial geram avisos, preservando o valor explicito. O mesmo vale para o valor estrangeiro do bloco de comercio exterior. Todos os valores monetarios sao arredondados para duas casas, inclusive `comExt.vServMoeda`; valores de servico que arredondam para zero sao rejeitados. Leia `warnings` antes da emissao quando quiser apresentar esses avisos ao usuario.
237
-
238
- `prepararNota` verifica a vigencia do certificado antes de assinar; `transmitirNotaPreparada` verifica novamente antes do envio. `assertCertificateValidity(pfx, now?)` expoe essa verificacao. A checagem de titularidade continua explicita via `assertCertificateForProvider(pfx, documento, now?)`; o SDK nao resolve representacao fiscal.
239
-
240
- O ambiente para JSON segue `options.ambiente` → `request.ambiente` → `restrita`, tanto no XML quanto no destino. XML externo usa `tpAmb` e rejeita uma opcao divergente. Notas preparadas tambem precisam ter o mesmo ambiente no XML assinado e no envio.
241
-
242
- `client.invoices.get(chaveAcesso, { ambiente: 'producao' })` permite consultar uma emissao feita com sobrescrita de ambiente. Sem opcao, usa `defaults.ambiente` ou o ambiente do construtor. O cliente nao memoriza o ambiente da ultima emissao.
243
-
244
- HTTP 2xx sem XML NFS-e bem formado e chave de 50 digitos consistente gera `EmitirNotaError` com codigo `INVALID_AUTHORIZATION_RESPONSE`, preservando corpo, status e DPS. Isso nao confirma rejeicao fiscal: concilie a emissao antes de reenviar. Nao ha retentativa automatica nem verificacao da assinatura da NFS-e recebida.
245
-
246
- Veja [as correcoes e mudancas de comportamento](docs/CORRECOES_EMISSAO.md) e os [payloads nacional e exterior testados](examples/payloads.ts). Os exemplos declaram cenarios ilustrativos; a aplicacao escolhe o enquadramento aplicavel.
247
-
248
- > **Migracao para 3.0.0:** esta versao tem breaking changes de validacao e resposta de autorizacao. Leia o guia curto em [CORRECOES_EMISSAO.md](docs/CORRECOES_EMISSAO.md) antes de atualizar.
249
-
250
- ## Certificado A1
251
-
252
- ### A partir de arquivo
253
-
254
- ```ts
255
- import { loadPfx } from '@useinvio/nfse-sdk';
256
-
257
- const pfx = loadPfx('./certificado.pfx', process.env.PFX_PASSWORD!);
258
- ```
259
-
260
- ### A partir de buffer (ex.: certificado descriptografado do banco)
261
-
262
- ```ts
263
- import { loadPfxFromBuffer } from '@useinvio/nfse-sdk';
264
-
265
- const pfx = loadPfxFromBuffer(pfxBuffer, password);
266
- ```
267
-
268
- O objeto `pfx` retornado contém chave privada e certificado em PEM, pronto para assinar e fazer mTLS.
269
-
270
- ---
271
-
272
- ## Emitir a partir de XML pronto
273
-
274
- Use quando outro sistema (ERP, sistema legado) já gera o XML da DPS no layout nacional.
275
-
276
- ```ts
277
- import { emitirNfse, loadPfx } from '@useinvio/nfse-sdk';
278
-
279
- const pfx = loadPfx('./certificado.pfx', process.env.PFX_PASSWORD!);
280
-
281
- const resultado = await emitirNfse(dpsXml, pfx, { ambiente: 'restrita' });
282
-
283
- console.log(resultado.chaveAcesso);
284
- console.log(resultado.nfseXml);
285
- ```
286
-
287
- > O XML precisa ter `Id` valido em `<infDPS>` e `tpAmb` consistente com o destino. `options.dpsId` apenas seleciona a referencia de assinatura; nao corrige um XML incompleto nem dispensa o XSD.
288
-
289
- ---
290
-
291
- ## Emitir a partir de JSON declarativo
292
-
293
- Use quando a aplicação mantém os perfis de prestador e serviço e quer que a SDK monte o XML.
294
-
295
- Para a referência completa de campos aceitos no JSON, consulte [JSON_MAPPING.md](./JSON_MAPPING.md).
296
- O builder valida formatos e combinações mínimas antes de gerar XML, mas não escolhe códigos fiscais por você. Campos como `tributacaoMunicipal` e `totTrib` precisam ser informados explicita[...]
297
-
298
- ```ts
299
- import { emitirNfse, loadPfx, type DpsJsonRequest } from '@useinvio/nfse-sdk';
300
-
301
- const nota: DpsJsonRequest = {
302
- ambiente: 'restrita',
303
- prestador: {
304
- cnpj: '12345678000195',
305
- cLocEmi: '4106902',
306
- serie: '1601',
307
- opSimpNac: '1',
308
- regEspTrib: '0',
309
- },
310
- servico: {
311
- cTribNac: '010201',
312
- xDescServ: 'Desenvolvimento de software',
313
- cLocPrestacao: '4106902',
314
- cNBS: '115022000',
315
- },
316
- emissao: {
317
- nDPS: '1',
318
- dhEmi: '2026-06-15T10:30:00-03:00',
319
- dCompet: '2026-06-01',
320
- valores: { vServ: '1500.00' },
321
- tributacaoMunicipal: {
322
- tribISSQN: '1',
323
- tpRetISSQN: '1',
324
- },
325
- tributacaoFederal: {
326
- piscofins: { CST: '07' },
327
- },
328
- totTrib: {
329
- pTotTribFed: '0.00',
330
- pTotTribEst: '0.00',
331
- pTotTribMun: '5.00',
332
- },
76
+ tributacaoFederal: { piscofins: { CST: '07' } },
77
+ totTrib: { pTotTribFed: '0.00', pTotTribEst: '0.00', pTotTribMun: '5.00' },
333
78
  },
334
79
  };
335
80
 
336
- const pfx = loadPfx('./certificado.pfx', process.env.PFX_PASSWORD!);
337
- const resultado = await emitirNfse(nota, pfx);
338
- ```
339
-
340
- > `pTotTribFed`, `pTotTribEst` e `pTotTribMun` são percentuais com duas casas decimais (ex.: `"5.00"`), diferentes das alíquotas com quatro casas (`pAliq`).
341
- > O shape simplificado legado de `tribNac` é rejeitado: IBS/CBS no layout nacional `v1.01` exige o bloco RTC `IBSCBS`, ainda não implementado nesta SDK.
342
-
343
- ---
344
-
345
- ## Inspecionar o XML antes de enviar
346
-
347
- Útil para comparar com um XML de referência, salvar snapshots ou depurar rejeições de schema.
348
-
349
- ```ts
350
- import { buildDpsFromJson } from '@useinvio/nfse-sdk';
351
-
352
- const { id, xml } = buildDpsFromJson(nota);
353
-
354
- console.log(id); // ex.: "DPS..."
355
- console.log(xml); // XML não assinado da DPS
356
- ```
357
-
358
- ---
359
-
360
- ## Tratar rejeições da SEFIN
361
-
362
- `emitirNfse` lança `EmitirNotaError` quando a SEFIN retorna HTTP fora de 2xx ou resposta sem XML autorizado.
363
-
364
- ```ts
365
- import { EmitirNotaError, emitirNfse } from '@useinvio/nfse-sdk';
366
-
367
81
  try {
368
- await emitirNfse(nota, pfx);
82
+ const { chaveAcesso, nfseXml } = await emitirNfse(nota, certificado);
83
+ console.log(chaveAcesso); // chave de 50 dígitos
369
84
  } catch (error) {
370
85
  if (!(error instanceof EmitirNotaError)) throw error;
371
-
372
- console.log('HTTP:', error.status);
373
- console.log('DPS ID:', error.dpsId);
374
-
375
- for (const rejeicao of error.erros) {
376
- console.log(rejeicao.Codigo); // código oficial SEFIN
377
- console.log(rejeicao.Descricao); // descrição da rejeição
378
- console.log(rejeicao.Complemento); // detalhe adicional (quando presente)
379
- }
380
- }
381
- ```
382
-
383
- ---
384
-
385
- ## Consultar uma NFS-e emitida
386
-
387
- ```ts
388
- import { consultarNfse } from '@useinvio/nfse-sdk';
389
-
390
- const resposta = await consultarNfse(chaveAcesso, pfx, 'restrita');
391
-
392
- if (resposta.status === 200) {
393
- console.log(resposta.body);
394
- } else {
395
- console.error('Falha na consulta:', resposta.status, resposta.body);
86
+ for (const rejeicao of error.erros) console.error(rejeicao.Codigo, rejeicao.Descricao);
396
87
  }
397
88
  ```
398
89
 
399
- ---
400
-
401
- ## Enviar evento (ex.: cancelamento)
402
-
403
- ```ts
404
- import { enviarEvento, gzipBase64, signEnveloped } from '@useinvio/nfse-sdk';
405
-
406
- const signedEventXml = signEnveloped(pedRegXml, pedRegId, 'infPedReg', pfx);
407
- const pedRegXmlGZipB64 = gzipBase64(signedEventXml);
408
-
409
- const resposta = await enviarEvento(pedRegXmlGZipB64, pfx, chaveAcesso, 'restrita');
410
- ```
411
-
412
- ---
413
-
414
- ## Série e número da DPS
90
+ Primeira vez? Siga o [tutorial](./docs/tutoriais/primeira-nfse.md): emitir,
91
+ consultar, baixar o PDF e cancelar na produção restrita, do zero. Ou experimente
92
+ sem certificado, pelo terminal:
415
93
 
416
- A SEFIN identifica uma DPS pela combinação de prestador, município, `serie` e `nDPS`.
417
-
418
- ```ts
419
- // série no perfil do prestador (padrão para todas as DPS)
420
- prestador: {
421
- serie: '1601',
422
- }
423
-
424
- // ou por emissão (sobrescreve prestador.serie apenas para esta DPS)
425
- emissao: {
426
- serie: '1601',
427
- nDPS: '4',
428
- }
429
- ```
430
-
431
- O padrão usual é manter uma `serie` fixa e incrementar `nDPS` em cada nova DPS:
432
-
433
- ```
434
- serie 1601, nDPS 1
435
- serie 1601, nDPS 2
436
- serie 1601, nDPS 3
437
- ```
438
-
439
- > O Emissor Web usa séries como `70000`. Para emissão via API, use uma série válida para API (ex.: `1601`) e controle o `nDPS` na sua aplicação.
440
-
441
- ---
442
-
443
- ## Ambientes
444
-
445
- | Chave | URL |
446
- |---|---|
447
- | `restrita` | `https://sefin.producaorestrita.nfse.gov.br/SefinNacional` |
448
- | `producao` | `https://sefin.nfse.gov.br/SefinNacional` |
449
-
450
- ```ts
451
- import { resolveSefinBaseUrl } from '@useinvio/nfse-sdk';
452
-
453
- const baseUrl = resolveSefinBaseUrl('restrita');
94
+ ```bash
95
+ npx nfse init && npx nfse emit nota.json --mock
454
96
  ```
455
97
 
456
- ---
457
-
458
- ## Observabilidade da SEFIN
459
-
460
- O SDK pode emitir métricas de latência das chamadas mTLS feitas contra a SEFIN quando `NFSE_SEFIN_LATENCY_METRICS=1` está configurada. Por padrão, percentis como `p50Ms`, `p95Ms` e `p99Ms` ficam desligados e precisam de `includePercentiles: true`. Essas métricas medem o round-trip externo da SEFIN, separado da latência total da sua API.
98
+ ## Documentação
461
99
 
462
- Leia o guia completo em [docs/METRICS.md](./docs/METRICS.md).
463
-
464
- ---
465
-
466
- ## Referência da API
467
-
468
- ### Funções principais
469
-
470
- | Função | Descrição |
100
+ | Guia | |
471
101
  |---|---|
472
- | `new NfseClient(options)` | Cria cliente com ambiente, certificado e defaults no mesmo formato do JSON declarativo. |
473
- | `emitirNfse(input, pfx, options?)` | Emite uma NFS-e a partir de XML ou JSON. Retorna `ResultadoEmissaoNota`. |
474
- | `consultarNfse(chaveAcesso, pfx, ambiente?)` | Consulta uma NFS-e pela chave de acesso. |
475
- | `enviarEvento(xmlGzipB64, pfx, chaveAcesso, ambiente?)` | Envia evento fiscal (cancelamento, etc.). |
476
- | `buildDpsFromJson(nota)` | Monta o XML da DPS sem assinar nem enviar. |
477
- | `setSefinRequestObserver(observer)` | Registra um hook para observar latência/status das chamadas à SEFIN. |
478
- | `createSefinLatencyTracker(options?)` | Agrega amostras recentes e pode calcular percentis quando `includePercentiles` estiver habilitado. |
102
+ | [Certificado A1](./docs/guias/certificado.md) | Variáveis de ambiente, cofres de segredo, vários emitentes. |
103
+ | [Emitir](./docs/guias/emitir.md) | JSON, `NfseClient`, XML pronto, série e número. |
104
+ | [Consultar e DANFSe](./docs/guias/consultar.md) | Resultado tipado e PDF. |
105
+ | [Recuperar após timeout](./docs/guias/recuperar-emissao.md) | Sem notas duplicadas quando a conexão cai. |
106
+ | [Cancelar](./docs/guias/cancelar.md) | e101101 e substituição (e105102). |
107
+ | [Erros e rejeições](./docs/guias/rejeicoes.md) | O que cada erro significa e o que fazer. |
108
+ | [Linha de comando](./docs/guias/cli.md) | `nfse doctor`, `emit`, `cancel`, `explain`. |
109
+ | [Testar sem certificado](./docs/guias/testes.md) | SEFIN simulada para o seu CI. |
110
+ | [Agentes de IA e MCP](./docs/guias/agentes-ia.md) | Servidor MCP, plugin do Claude Code, ferramentas para o seu agente. |
111
+ | [Referência da API](./docs/referencia/api.md) | Todas as funções. |
112
+ | [Mapeamento do JSON](./JSON_MAPPING.md) | Cada campo de `DpsJsonRequest`. |
479
113
 
480
- ### Certificado
114
+ Exemplos executáveis em [`examples/`](./examples).
481
115
 
482
- | Função | Descrição |
483
- |---|---|
484
- | `assertCertificateValidity(pfx, now?)` | Verifica vigencia do certificado; aplicada na preparacao e no envio. |
485
- | `assertCertificateForProvider(pfx, documento, now?)` | Verifica explicitamente vigencia e correspondencia do titular. |
486
- | `loadPfx(path, password)` | Carrega certificado A1 a partir de arquivo. |
487
- | `loadPfxFromBuffer(buffer, password)` | Carrega certificado A1 a partir de buffer. |
116
+ ## Com agentes de IA
488
117
 
489
- ### Funções de baixo nível
490
-
491
- | Função | Descrição |
492
- |---|---|
493
- | `signDps(xml, dpsId, pfx)` | Assina XML de DPS com XMLDSIG. |
494
- | `signEnveloped(xml, id, ref, pfx)` | Assina XML genérico (eventos). |
495
- | `verifyDps(xml, certPem)` | Verifica assinatura de uma DPS. |
496
- | `gzipBase64(xml)` | Compacta XML em GZip e codifica em Base64. |
497
- | `gunzipBase64(b64)` | Descompacta resposta GZip/Base64. |
498
- | `extrairErros(body)` | Normaliza erros oficiais de uma resposta da SEFIN. |
499
- | `resolveSefinBaseUrl(ambiente)` | Retorna a URL base do ambiente. |
500
-
501
- ### Tipos exportados
502
-
503
- ```ts
504
- import type {
505
- Ambiente,
506
- CreateInvoiceInput,
507
- GetInvoiceOptions,
508
- DpsJsonInput,
509
- DpsJsonRequest,
510
- EmitirNotaOptions,
511
- NfseClientDpsDefaults,
512
- NfseClientOptions,
513
- NotaInput,
514
- PfxMaterial,
515
- PrestadorProfile,
516
- ResultadoEmissaoNota,
517
- SefinErro,
518
- SefinResposta,
519
- ServicoProfile,
520
- } from '@useinvio/nfse-sdk';
521
- ```
522
-
523
- ### Constantes
524
-
525
- ```ts
526
- import { SEFIN_BASE_URL, TP_AMB, DEFAULT_AMBIENTE } from '@useinvio/nfse-sdk';
527
- ```
528
-
529
- ---
530
-
531
- ## Desenvolvimento
118
+ Emita uma NFS-e conversando com o Claude. Para experimentar sem certificado, o
119
+ modo de teste usa uma SEFIN simulada:
532
120
 
533
121
  ```bash
534
- npm install
535
- npm run typecheck # verifica tipos sem compilar
536
- npm run build # compila para dist/
537
- npm test # build + tipos + testes unitários
122
+ claude mcp add nfse --env NFSE_MCP_MOCK=1 --env NFSE_MCP_ALLOW_WRITE=1 -- npx -y @useinvio/nfse-mcp
538
123
  ```
539
124
 
540
- `npm test` também valida uma DPS gerada contra os XSD oficiais em `schemas/nfse/v1.01/Schemas/1.01`. Para compatibilidade com `xmllint`, o teste corrige em uma cópia temporária a âncora regex[...]
541
-
542
- ### Uso local em outro projeto
125
+ Ou instale o plugin do Claude Code, que inclui o servidor e uma skill com o fluxo:
543
126
 
544
- ```json
545
- {
546
- "dependencies": {
547
- "@useinvio/nfse-sdk": "file:../nfse-sdk"
548
- }
549
- }
127
+ ```text
128
+ /plugin install nfse-nacional --marketplace useinvio/nfse-sdk
550
129
  ```
551
130
 
552
- ---
553
-
554
- ## Publicação no npm
555
-
556
- Pacote publicado publicamente no npm como [`@useinvio/nfse-sdk`](https://www.npmjs.com/package/@useinvio/nfse-sdk).
557
-
558
- ```bash
559
- npm install
560
- npm run typecheck
561
- npm run build
562
- npm pack --dry-run # verifica o que será publicado
563
- npm publish
564
- ```
565
-
566
- O pacote usa `publishConfig.access = public`, necessário para publicar um pacote escopado público no npm.
567
-
568
- ---
569
-
570
- ## Divulgação e exemplos
571
-
572
- - Exemplos copiáveis ficam em [`examples/`](./examples).
573
- - Material de lançamento, mensagens para redes e prompt de landing page ficam em [`docs/launch.md`](./docs/launch.md).
574
-
575
- ---
131
+ Emitir e cancelar sempre passam por um resumo que você aprova antes do envio, e
132
+ o certificado nunca chega ao modelo. Veja o [guia de agentes e MCP](./docs/guias/agentes-ia.md).
133
+ Para assistentes de código, o pacote inclui [`llms.txt`](./llms.txt).
576
134
 
577
- ## Assistente GPT
135
+ ## O que fica com a sua aplicação
578
136
 
579
- Para criar um GPT que ajude outros devs a implementar e documentar esta SDK, use:
137
+ O SDK cuida do protocolo; ele não é um motor fiscal. Códigos de serviço, CST,
138
+ alíquotas, retenções, regime tributário e a numeração da DPS são decisões da
139
+ sua aplicação e de quem cuida da parte tributária. Campos fiscais obrigatórios
140
+ nunca recebem valores padrão silenciosos. O grupo IBS/CBS da reforma tributária
141
+ ainda não é suportado.
580
142
 
581
- - [`docs/gpt-assistant.md`](./docs/gpt-assistant.md): configuracao completa do GPT, instrucoes copiaveis, starters e testes de preview.
582
- - [`docs/gpt-knowledge.md`](./docs/gpt-knowledge.md): resumo compacto para subir como arquivo de Knowledge.
143
+ ## Contribuir
583
144
 
584
- ---
145
+ Issues e PRs são bem-vindos. Veja [CONTRIBUTING.md](./CONTRIBUTING.md) e o
146
+ [CHANGELOG](./CHANGELOG.md).
585
147
 
586
- ## Princípios de design
148
+ ## Licença
587
149
 
588
- - Sem dependência de banco de dados, config de aplicação ou estado de tenant.
589
- - Funções pequenas, testáveis e reutilizáveis.
590
- - Erros oficiais da SEFIN são preservados na íntegra, não engolidos.
591
- - O SDK transporta declarações fiscais; não valida se estão contabilmente corretas.
150
+ [MIT](./LICENSE) © Invio