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

# API Overview

> A basic introduction to the YoFacturo API.

## Base URL

All API endpoints are relative to:

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

## Versioning

The current stable version is **v1**. All v1 endpoints are prefixed with `/api/v1/`.

There are no version negotiation headers — the version is part of the URL path.

## Request format

* Content type: `application/json`
* Encoding: UTF-8
* All timestamps must be in **ISO 8601** format (`YYYY-MM-DDTHH:MM:SSZ`)
* Dates (without time) must be `YYYY-MM-DD`

## Response format

All responses return JSON.

**Exception:** `GET /api/v1/batch_invoices/{id}/pdf` returns an `application/pdf` binary payload (the associated issued invoice PDF).

Most endpoints that return a single resource wrap the payload in a `data` key:

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

**Exception:** `POST /api/v1/auth/sessions` returns a flat JSON object at the root level — no `data` envelope:

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

List responses include a `meta` object with pagination info:

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

The `POST /api/v1/invoice_batches` endpoint may additionally include an `errors` key alongside `data` when some invoices in the batch fail validation (partial success):

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

The `errors` object is keyed by `external_invoice_id`.

## Pagination

List endpoints accept two query parameters:

| Parameter  | Type    | Default | Max   | Description             |
| ---------- | ------- | ------- | ----- | ----------------------- |
| `page`     | integer | `1`     | —     | Page number (1-indexed) |
| `per_page` | integer | `25`    | `100` | Results per page        |

## Idempotency

`POST /api/v1/invoice_batches` requires an **`Idempotency-Key`** header containing a valid UUID. Resubmitting the same key within the idempotency window returns the cached response without re-processing the batch.

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

## Rate limiting

Most protected endpoints enforce rate limits per organization. When exceeded, the API returns `429 Too Many Requests` with a `Retry-After` header indicating the number of seconds to wait.

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

<Note>
  `POST /api/v1/invoice_batches` is **excluded** from rate limiting — idempotency already prevents duplicate processing.
</Note>

## Error responses

All errors follow a consistent envelope:

```json theme={null}
{
  "error": {
    "code": "string",
    "message": "Human-readable description"
  }
}
```

### Error codes

| HTTP status | Code                      | Description                                                |
| ----------- | ------------------------- | ---------------------------------------------------------- |
| `400`       | `bad_request`             | Missing or blank required parameter                        |
| `401`       | `unauthorized`            | Missing, invalid, or expired authentication                |
| `404`       | `not_found`               | Resource not found within the current organization         |
| `422`       | `missing_idempotency_key` | `Idempotency-Key` header is absent                         |
| `422`       | `invalid_idempotency_key` | `Idempotency-Key` is not a valid UUID                      |
| `422`       | `validation_failed`       | Request body failed validation (see `message` for details) |
| `422`       | `unprocessable_content`   | Record could not be saved due to validation errors         |
| `429`       | `too_many_requests`       | Too many requests — check `Retry-After` header             |
