# SDK y CLI

Frihet ofrece un SDK oficial de TypeScript y una CLI para gestionar tu negocio desde codigo o terminal. Ambos paquetes estan publicados en npm.

| Paquete       | npm                                                                                           | Uso                           |
| ------------- | --------------------------------------------------------------------------------------------- | ----------------------------- |
| `@frihet/sdk` | [![npm](https://img.shields.io/npm/v/@frihet/sdk)](https://www.npmjs.com/package/@frihet/sdk) | SDK para Node.js / TypeScript |
| `frihet`      | [![npm](https://img.shields.io/npm/v/frihet)](https://www.npmjs.com/package/frihet)           | CLI para terminal             |

---

## Instalacion

### SDK

```bash
npm install @frihet/sdk
```

### CLI

```bash
npm install -g frihet
```

---

## Autenticacion

Necesitas una API key. Generala en **Ajustes > Desarrolladores > API Keys** dentro de [app.frihet.io](https://app.frihet.io/settings/security?utm_source=frihet_io&utm_medium=docs&utm_campaign=docs_cta). Las claves comienzan con `fri_`.

### SDK

```typescript

const frihet = new Frihet({
  apiKey: 'fri_live_...',
});
```

Opciones adicionales:

| Opcion    | Tipo     | Por defecto                | Descripcion              |
| --------- | -------- | -------------------------- | ------------------------ |
| `apiKey`  | `string` | --                         | Tu API key (obligatorio) |
| `baseUrl` | `string` | `https://api.frihet.io/v1` | URL base de la API       |
| `timeout` | `number` | `30000`                    | Timeout en milisegundos  |

### CLI

```bash
frihet login
# Introduce tu API key interactivamente

# O directamente:
frihet login --key fri_live_...
```

La key se guarda en `~/.frihet/config.json` con permisos `0600`. Tambien puedes usar la variable de entorno `FRIHET_API_KEY`.

---

## SDK — Inicio rapido

### Listar facturas

```typescript

const frihet = new Frihet({ apiKey: 'fri_live_...' });

const page = await frihet.invoices.list({ limit: 10, status: 'paid' });
console.log(`${page.total} facturas pagadas`);

for (const inv of page.data) {
  console.log(`${inv.documentNumber} — ${inv.clientName} — ${inv.total}`);
}
```

### Crear una factura

```typescript
const invoice = await frihet.invoices.create({
  clientName: 'Acme S.L.',
  items: [
    { description: 'Consultoria', quantity: 10, unitPrice: 150 },
    { description: 'Desarrollo web', quantity: 1, unitPrice: 3000 },
  ],
  taxRate: 21,
  dueDate: '2026-04-15',
});

console.log(`Factura ${invoice.documentNumber} creada (${invoice.total} EUR)`);
```

### Buscar y actualizar

```typescript
// Busqueda por texto
const results = await frihet.clients.search('Acme');

// Actualizar un cliente
await frihet.clients.update(results.data[0].id, {
  email: 'nuevo@acme.com',
  fiscalZone: 'peninsula',
});
```

### Marcar factura como pagada y enviar por email

```typescript
await frihet.invoices.markPaid('inv_abc123');

await frihet.invoices.send('inv_abc123', {
  recipientEmail: 'cliente@acme.com',
  locale: 'es',
});
```

### Crear abono / factura rectificativa

```typescript
const creditNote = await frihet.invoices.createCreditNote('inv_abc123', {
  reason: 'error',
  reasonDescription: 'Correccion de importe',
  fullCredit: true,
});

console.log(`Abono ${creditNote.documentNumber} creado`);
```

CLI:

```bash
frihet invoices credit-note inv_abc123 --reason error --full
```

---

## CLI — Inicio rapido

### Ver estado del negocio

```bash
frihet status
# Revenue:   EUR 12.500,00
# Expenses:  EUR 3.200,00
# Net:       EUR 9.300,00

frihet status --month 2026-02
```

### Gestionar facturas

```bash
# Listar facturas
frihet invoices list --status paid --limit 5

# Buscar
frihet invoices list -q "Acme"

# Ver detalle
frihet invoices get inv_abc123

# Crear factura
frihet invoices create --client "Acme S.L." --item "Consultoria,10,150" --tax 21

# Marcar como pagada
frihet invoices paid inv_abc123

# Enviar por email
frihet invoices send inv_abc123 --to cliente@acme.com
```

### Gestionar gastos

```bash
# Listar gastos
frihet expenses list --from 2026-01-01 --to 2026-03-31

# Crear gasto
frihet expenses create --desc "Hosting mensual" --amount 49.99 --category software --vendor "Hetzner"
```

### Gestionar clientes

```bash
# Listar clientes
frihet clients list

# Buscar
frihet clients list -q "Acme"

# Crear cliente
frihet clients create --name "Acme S.L." --email info@acme.com --tax-id B12345678 --zone peninsula
```

---

## Recursos disponibles

El SDK expone los siguientes recursos como propiedades de la instancia `Frihet`:

| Recurso      | Propiedad             | Metodos                                                                                                               |
| ------------ | --------------------- | --------------------------------------------------------------------------------------------------------------------- |
| Facturas     | `frihet.invoices`     | `list`, `retrieve`, `create`, `update`, `del`, `search`, `markPaid`, `send`, `pdf`, `createBatch`, `createCreditNote` |
| Gastos       | `frihet.expenses`     | `list`, `retrieve`, `create`, `update`, `del`, `search`, `createBatch`                                                |
| Clientes     | `frihet.clients`      | `list`, `retrieve`, `create`, `update`, `del`, `search`                                                               |
| Proveedores  | `frihet.vendors`      | `list`, `retrieve`, `create`, `update`, `del`, `search`                                                               |
| Productos    | `frihet.products`     | `list`, `retrieve`, `create`, `update`, `del`, `search`                                                               |
| Presupuestos | `frihet.quotes`       | `list`, `retrieve`, `create`, `update`, `del`, `search`, `pdf`, `send`                                                |
| Webhooks     | `frihet.webhooks`     | `list`, `retrieve`, `create`, `update`, `del` + `verifySignature` (estatico)                                          |
| Inteligencia | `frihet.intelligence` | `context`, `summary`, `monthly`, `quarterly`                                                                          |

Todos los metodos `list` y `search` devuelven un objeto `Page<T>`:

```typescript
interface Page<T> {
  data: T[];
  total: number;
  limit: number;
  offset: number;
}
```

---

## Manejo de errores

El SDK lanza errores tipados para cada tipo de fallo:

```typescript
  AuthenticationError,
  NotFoundError,
  ValidationError,
  RateLimitError,
  TimeoutError,
} from '@frihet/sdk';

try {
  await frihet.invoices.retrieve('no-existe');
} catch (err) {
  if (err instanceof NotFoundError) {
    console.log('Factura no encontrada');
  } else if (err instanceof AuthenticationError) {
    console.log('API key invalida');
  } else if (err instanceof ValidationError) {
    console.log('Datos invalidos:', err.message, err.details);
  } else if (err instanceof RateLimitError) {
    console.log(`Rate limit. Reintentar en ${err.retryAfter}s`);
  } else if (err instanceof TimeoutError) {
    console.log('Timeout');
  }
}
```

| Clase                 | Codigo HTTP | Cuando                                  |
| --------------------- | ----------- | --------------------------------------- |
| `AuthenticationError` | 401         | API key invalida o ausente              |
| `NotFoundError`       | 404         | Recurso no encontrado                   |
| `ValidationError`     | 400 / 422   | Datos de entrada invalidos              |
| `RateLimitError`      | 429         | Limite de peticiones excedido           |
| `TimeoutError`        | --          | Sin respuesta en el timeout configurado |
| `APIError`            | Otros       | Error generico del servidor             |

### Reintentos automaticos

El SDK reintenta automaticamente las peticiones que reciben codigos 429 (rate limit) o 5xx (error de servidor), hasta 3 veces con backoff exponencial. No necesitas implementar logica de reintentos.

---

## Idempotencia

Para operaciones de creacion, puedes enviar un `idempotencyKey` para evitar duplicados en caso de reintentos:

```typescript
await frihet.invoices.create(
  { clientName: 'Acme S.L.', items: [{ description: 'Servicio', quantity: 1, unitPrice: 500 }] },
  { idempotencyKey: 'mi-clave-unica-123' },
);
```

---

## Verificar webhooks

El SDK incluye un metodo estatico para verificar la firma HMAC-SHA256 de los webhooks:

```typescript

const isValid = Webhooks.verifySignature(
  rawBody, // string o Buffer del body
  req.headers['x-frihet-signature'], // cabecera de firma
  'whsec_tu_secreto', // secreto del webhook
);
```

---

## Variables de entorno

| Variable         | Descripcion                                                            |
| ---------------- | ---------------------------------------------------------------------- |
| `FRIHET_API_KEY` | API key (alternativa a `frihet login` en CLI o al constructor del SDK) |
| `FRIHET_API_URL` | URL base personalizada                                                 |

---

## Mas informacion

- [API REST](/desarrolladores/api-rest) — referencia completa de endpoints
- [Webhooks](/desarrolladores/webhooks) — eventos y verificacion de firma
- [Repositorio en GitHub](https://github.com/Frihet-io/frihet-sdk) — codigo fuente, issues, contribuciones
- [npm @frihet/sdk](https://www.npmjs.com/package/@frihet/sdk) | [npm frihet](https://www.npmjs.com/package/frihet)
