> ## Documentation Index
> Fetch the complete documentation index at: https://docs.yofacturo.es/llms.txt
> Use this file to discover all available pages before exploring further.

# Descripción general de la API

> Una introducción básica a la API de YoFacturo.

## URL base

Todos los endpoints de la API son relativos a:

```
https://app.yofacturo.es
```

## Versiones

La versión estable actual es **v1**. Todos los endpoints v1 tienen el prefijo `/api/v1/`.

No existen cabeceras de negociación de versión — la versión forma parte de la ruta de la URL.

## Formato de solicitud

* Content type: `application/json`
* Codificación: UTF-8
* Todos los timestamps deben estar en formato **ISO 8601** (`YYYY-MM-DDTHH:MM:SSZ`)
* Las fechas (sin hora) deben ser `YYYY-MM-DD`

## Formato de respuesta

Todas las respuestas devuelven JSON.

**Excepción:** `GET /api/v1/batch_invoices/{id}/pdf` devuelve un payload binario `application/pdf` (el PDF de la factura emitida asociada).

La mayoría de endpoints que devuelven un único recurso envuelven el contenido en la clave `data`:

```json theme={null}
{
  "data": {
    "id": 123,
    "status": "received",
    ...
  }
}
```

**Excepción:** `POST /api/v1/auth/sessions` devuelve un objeto JSON plano a nivel raíz — sin envelope `data`:

```json theme={null}
{
  "session_token": "...",
  "expires_at": "2026-03-27T10:30:00Z"
}
```

Las respuestas de lista incluyen un objeto `meta` con información de paginación:

```json theme={null}
{
  "data": [...],
  "meta": {
    "current_page": 1,
    "total_pages": 4,
    "total_count": 87,
    "per_page": 25
  }
}
```

El endpoint `POST /api/v1/invoice_batches` puede incluir adicionalmente una clave `errors` junto a `data` cuando algunas facturas del lote fallan la validación (éxito parcial):

```json theme={null}
{
  "data": { ... },
  "errors": {
    "inv-bad-001": ["Issuer nif no puede estar en blanco"]
  }
}
```

El objeto `errors` está indexado por `external_invoice_id`.

## Paginación

Los endpoints de lista aceptan dos parámetros de consulta:

| Parámetro  | Tipo    | Por defecto | Máximo | Descripción               |
| ---------- | ------- | ----------- | ------ | ------------------------- |
| `page`     | integer | `1`         | —      | Número de página (base 1) |
| `per_page` | integer | `25`        | `100`  | Resultados por página     |

## Idempotencia

`POST /api/v1/invoice_batches` requiere la cabecera **`Idempotency-Key`** con un UUID válido. Reenviar la misma clave dentro de la ventana de idempotencia devuelve la respuesta cacheada sin reprocesar el lote.

```http theme={null}
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
```

## Rate limiting

La mayoría de endpoints protegidos aplican límites de tasa por organización. Cuando se supera el límite, la API devuelve `429 Too Many Requests` con la cabecera `Retry-After` indicando los segundos de espera.

```http theme={null}
HTTP/1.1 429 Too Many Requests
Retry-After: 30
```

<Note>
  `POST /api/v1/invoice_batches` está **excluido** del rate limiting — la idempotencia ya previene el procesamiento duplicado.
</Note>

## Respuestas de error

Todos los errores siguen un envelope consistente:

```json theme={null}
{
  "error": {
    "code": "string",
    "message": "Descripción legible"
  }
}
```

### Códigos de error

| Estado HTTP | Código                    | Descripción                                                   |
| ----------- | ------------------------- | ------------------------------------------------------------- |
| `400`       | `bad_request`             | Parámetro requerido ausente o vacío                           |
| `401`       | `unauthorized`            | Autenticación ausente, inválida o expirada                    |
| `404`       | `not_found`               | Recurso no encontrado en la organización actual               |
| `422`       | `missing_idempotency_key` | La cabecera `Idempotency-Key` está ausente                    |
| `422`       | `invalid_idempotency_key` | `Idempotency-Key` no es un UUID válido                        |
| `422`       | `validation_failed`       | El cuerpo de la solicitud falló la validación (ver `message`) |
| `422`       | `unprocessable_content`   | El registro no pudo guardarse por errores de validación       |
| `429`       | `too_many_requests`       | Demasiadas solicitudes — consulta la cabecera `Retry-After`   |
