Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
node_modules/
bower_components/
jspm_packages/
openspec/

# ----------------------------------------------------------------------------
# Build Outputs
Expand Down
78 changes: 72 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,18 +360,84 @@ const filtrado = await nfe.addresses.search({
});
```

> **Nota:** A API de Endereços usa um host separado (`address.api.nfe.io`). Você pode configurar uma chave API específica com `addressApiKey`, ou o SDK usará `apiKey` como fallback.
> **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:

```typescript
// Ativar busca automática de CT-e para uma empresa
const settings = await nfe.transportationInvoices.enable('empresa-id');
console.log('Status:', settings.status);
console.log('Iniciando do NSU:', settings.startFromNsu);

// Ativar a partir de um NSU específico
const settings = await nfe.transportationInvoices.enable('empresa-id', {
startFromNsu: 12345
});

// Ativar a partir de uma data específica
const settings = await nfe.transportationInvoices.enable('empresa-id', {
startFromDate: '2024-01-01T00:00:00Z'
});

// Verificar configurações atuais
const config = await nfe.transportationInvoices.getSettings('empresa-id');
console.log('Busca ativa:', config.status);

// Desativar busca automática
await nfe.transportationInvoices.disable('empresa-id');

// Consultar CT-e por chave de acesso (44 dígitos)
const cte = await nfe.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-e
const xml = await nfe.transportationInvoices.downloadXml(
'empresa-id',
'35240112345678000190570010000001231234567890'
);
fs.writeFileSync('cte.xml', xml);

// Consultar evento do CT-e
const evento = await nfe.transportationInvoices.getEvent(
'empresa-id',
'35240112345678000190570010000001231234567890',
'chave-evento'
);

// Baixar XML do evento
const eventoXml = await nfe.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

---

### Opções de Configuração

```typescript
const nfe = new NfeClient({
// Chave API principal do NFE.io (opcional se usar apenas Addresses com addressApiKey)
// Chave API principal do NFE.io (operações com documentos fiscais)
apiKey: 'sua-chave-api',

// Opcional: Chave API específica para consulta de endereços
// Opcional: Chave API para serviços de consulta (Endereços, CT-e, CNPJ, CPF)
// Se não fornecida, usa apiKey como fallback
addressApiKey: 'sua-chave-address-api',
dataApiKey: 'sua-chave-data-api',

// Opcional: Ambiente (padrão: 'production')
environment: 'production', // ou 'sandbox'
Expand Down Expand Up @@ -399,12 +465,12 @@ O SDK suporta as seguintes variáveis de ambiente:
| Variável | Descrição |
|----------|-----------|
| `NFE_API_KEY` | Chave API principal (fallback para `apiKey`) |
| `NFE_ADDRESS_API_KEY` | Chave API para endereços (fallback para `addressApiKey`) |
| `NFE_DATA_API_KEY` | Chave API para serviços de consulta (fallback para `dataApiKey`) |

```bash
# Configurar via ambiente
export NFE_API_KEY="sua-chave-api"
export NFE_ADDRESS_API_KEY="sua-chave-address"
export NFE_DATA_API_KEY="sua-chave-data"

# Usar SDK sem passar chaves no código
const nfe = new NfeClient({});
Expand Down
141 changes: 141 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Complete API reference for the NFE.io Node.js SDK v3.
- [Legal People](#legal-people)
- [Natural People](#natural-people)
- [Webhooks](#webhooks)
- [Transportation Invoices (CT-e)](#transportation-invoices-ct-e)
- [Types](#types)
- [Error Handling](#error-handling)
- [Advanced Usage](#advanced-usage)
Expand Down Expand Up @@ -1504,13 +1505,153 @@ const events = await nfe.webhooks.getAvailableEvents();
// ['invoice.issued', 'invoice.cancelled', ...]
```

---

### Transportation Invoices (CT-e)

**Resource:** `nfe.transportationInvoices`

Manage CT-e (Conhecimento de Transporte Eletrônico) documents via SEFAZ Distribuição DFe.

> **Note:** This resource uses a separate API host (`api.nfse.io`). You can configure a specific API key with `dataApiKey`, or the SDK will use `apiKey` as fallback.

**Prerequisites:**
- Company must be registered with a valid A1 digital certificate
- Webhook must be configured to receive CT-e notifications

#### `enable(companyId: string, options?: EnableTransportationInvoiceOptions): Promise<TransportationInvoiceInboundSettings>`

Enable automatic CT-e search for a company.

```typescript
// Enable with default settings
const settings = await nfe.transportationInvoices.enable('company-id');

// Enable starting from a specific NSU
const settings = await nfe.transportationInvoices.enable('company-id', {
startFromNsu: 12345
});

// Enable starting from a specific date
const settings = await nfe.transportationInvoices.enable('company-id', {
startFromDate: '2024-01-01T00:00:00Z'
});
```

**Options:**

| Property | Type | Description |
|----------|------|-------------|
| `startFromNsu` | `number` | Start searching from this NSU number |
| `startFromDate` | `string` | Start searching from this date (ISO 8601) |

#### `disable(companyId: string): Promise<TransportationInvoiceInboundSettings>`

Disable automatic CT-e search for a company.

```typescript
const settings = await nfe.transportationInvoices.disable('company-id');
console.log('Status:', settings.status); // 'Disabled'
```

#### `getSettings(companyId: string): Promise<TransportationInvoiceInboundSettings>`

Get current automatic CT-e search settings.

```typescript
const settings = await nfe.transportationInvoices.getSettings('company-id');
console.log('Status:', settings.status);
console.log('Start NSU:', settings.startFromNsu);
console.log('Created:', settings.createdOn);
```

**Response:**

| Property | Type | Description |
|----------|------|-------------|
| `status` | `string` | Current status ('Active', 'Disabled', etc.) |
| `startFromNsu` | `number` | Starting NSU number |
| `startFromDate` | `string` | Starting date (if configured) |
| `createdOn` | `string` | Creation timestamp |
| `modifiedOn` | `string` | Last modification timestamp |

#### `retrieve(companyId: string, accessKey: string): Promise<TransportationInvoiceMetadata>`

Retrieve CT-e metadata by its 44-digit access key.

```typescript
const cte = await nfe.transportationInvoices.retrieve(
'company-id',
'35240112345678000190570010000001231234567890'
);
console.log('Sender:', cte.nameSender);
console.log('CNPJ:', cte.federalTaxNumberSender);
console.log('Amount:', cte.totalInvoiceAmount);
console.log('Issued:', cte.issuedOn);
```

**Response:**

| Property | Type | Description |
|----------|------|-------------|
| `accessKey` | `string` | 44-digit access key |
| `type` | `string` | Document type |
| `status` | `string` | Document status |
| `nameSender` | `string` | Sender company name |
| `federalTaxNumberSender` | `string` | Sender CNPJ |
| `totalInvoiceAmount` | `number` | Total invoice amount |
| `issuedOn` | `string` | Issue date |
| `receivedOn` | `string` | Receipt date |

#### `downloadXml(companyId: string, accessKey: string): Promise<string>`

Download CT-e XML content.

```typescript
const xml = await nfe.transportationInvoices.downloadXml(
'company-id',
'35240112345678000190570010000001231234567890'
);
fs.writeFileSync('cte.xml', xml);
```

#### `getEvent(companyId: string, accessKey: string, eventKey: string): Promise<TransportationInvoiceMetadata>`

Retrieve CT-e event metadata.

```typescript
const event = await nfe.transportationInvoices.getEvent(
'company-id',
'35240112345678000190570010000001231234567890',
'event-key-123'
);
console.log('Event type:', event.type);
console.log('Event status:', event.status);
```

#### `downloadEventXml(companyId: string, accessKey: string, eventKey: string): Promise<string>`

Download CT-e event XML content.

```typescript
const eventXml = await nfe.transportationInvoices.downloadEventXml(
'company-id',
'35240112345678000190570010000001231234567890',
'event-key-123'
);
fs.writeFileSync('cte-event.xml', eventXml);
```

---

## Types

### Core Types

```typescript
interface NfeConfig {
apiKey?: string;
dataApiKey?: string; // API key for data/query services (Addresses, CT-e, CNPJ, CPF)
environment?: 'production' | 'development';
baseUrl?: string;
timeout?: number;
Expand Down
28 changes: 14 additions & 14 deletions examples/address-lookup.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Brazilian addresses (CEP/postal code lookups).
*
* Prerequisites:
* - Set NFE_ADDRESS_API_KEY or NFE_API_KEY environment variable
* - Set NFE_DATA_API_KEY or NFE_API_KEY environment variable
* - Or pass the API key directly in the configuration
*
* Run this example:
Expand All @@ -14,12 +14,12 @@

import { NfeClient } from '../dist/index.js';

// Configuration with separate address API key (optional)
// Configuration with separate data API key (optional)
const client = new NfeClient({
// You can use a separate API key for address lookups
// addressApiKey: process.env.NFE_ADDRESS_API_KEY,
// You can use a separate API key for data/query services (addresses, CT-e)
// dataApiKey: process.env.NFE_DATA_API_KEY,

// Or use the main API key (will be used as fallback for addresses)
// Or use the main API key (will be used as fallback for data services)
apiKey: process.env.NFE_API_KEY,

// Environment: 'production' or 'development'
Expand Down Expand Up @@ -103,21 +103,21 @@ async function searchWithFilter() {
}

/**
* Example 4: Using only addressApiKey (isolated usage)
* Example 4: Using only dataApiKey (isolated usage)
*/
async function isolatedAddressUsage() {
console.log('\n🔐 Example 4: Isolated Address API Usage');
console.log('\n🔐 Example 4: Isolated Data API Usage');
console.log('='.repeat(50));

// Create a client with ONLY addressApiKey
// This is useful when you only have access to the Address API
const addressOnlyClient = new NfeClient({
addressApiKey: process.env.NFE_ADDRESS_API_KEY || process.env.NFE_API_KEY,
// Create a client with ONLY dataApiKey
// This is useful when you only have access to data/query services
const dataOnlyClient = new NfeClient({
dataApiKey: process.env.NFE_DATA_API_KEY || process.env.NFE_API_KEY,
});

try {
// Addresses work
const result = await addressOnlyClient.addresses.lookupByPostalCode('20040-020');
const result = await dataOnlyClient.addresses.lookupByPostalCode('20040-020');
console.log('Rio de Janeiro CEP lookup succeeded!');
console.log(` ${result.street}, ${result.city?.name}/${result.state}`);
} catch (error) {
Expand Down Expand Up @@ -165,9 +165,9 @@ async function main() {
console.log('🏠 NFE.io Address Lookup Examples');
console.log('━'.repeat(50));

if (!process.env.NFE_API_KEY && !process.env.NFE_ADDRESS_API_KEY) {
if (!process.env.NFE_API_KEY && !process.env.NFE_DATA_API_KEY) {
console.error('\n❌ No API key found!');
console.error('Please set NFE_API_KEY or NFE_ADDRESS_API_KEY environment variable.');
console.error('Please set NFE_API_KEY or NFE_DATA_API_KEY environment variable.');
console.error('\nExample:');
console.error(' export NFE_API_KEY="your-api-key"');
console.error(' node examples/address-lookup.js');
Expand Down
4 changes: 4 additions & 0 deletions examples/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ ${companyId ? `NFE_COMPANY_ID=${companyId}` : '# NFE_COMPANY_ID=seu-company-id-a

# Timeout em ms (opcional)
# NFE_TIMEOUT=30000

# Chave de API para serviços de consulta (opcional)
# Se não definida, usa NFE_API_KEY como fallback
# NFE_DATA_API_KEY=sua-chave-data-aqui
`;

try {
Expand Down
Loading
Loading