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

# Información General

> Facturación electrónica en Bolivia, URL base, autenticación, formato de respuesta y paginación.

## Facturación Electrónica

Bolivia implementó la facturación electrónica a través del **SIAT** (Sistema Integrado de Administración Tributaria) del **SIN** (Servicio de Impuestos Nacionales). Toda factura emitida debe validarse en tiempo real por el SIAT antes de tener validez fiscal.

El proceso involucra:

* Firma digital con certificado emitido por el SIN
* Generación del **CUF** (Código Único de Facturación)
* Validación en línea contra el SIAT
* Generación de PDF y XML firmado

CUCU abstrae toda esta complejidad en una sola API REST:

<CardGroup cols={2}>
  <Card title="Emite facturas" icon="file-invoice">
    Un solo `POST /api/v1/invoices`. CUCU firma, valida con el SIAT, genera CUF, PDF, XML y envía el email al cliente.
  </Card>

  <Card title="15 tipos de documento" icon="file-lines">
    Compra-venta, exportación, zona franca, educación, salud, hoteles, aerolíneas y más. Mismo endpoint, distinto `invoiceType`.
  </Card>

  <Card title="Notas de crédito/débito" icon="file-circle-minus">
    Documentos de ajuste fiscal con cálculo automático de montos contra la factura original.
  </Card>

  <Card title="Contingencia offline" icon="triangle-exclamation">
    Cuando el SIAT no está disponible, CUCU emite con CUF offline y sincroniza al reconectarse.
  </Card>
</CardGroup>

***

## URL Base

CUCU opera en dos ambientes completamente aislados. Mismo formato de respuesta, mismas validaciones, misma lógica. La única diferencia es la conexión al SIAT.

<CardGroup cols={2}>
  <Card title="Sandbox" icon="flask">
    ```
    https://sandbox.cucu.bo
    ```

    SIAT Piloto — facturas de desarrollo, sin validez fiscal. **Incluido en tu plan.**
  </Card>

  <Card title="Producción" icon="rocket">
    ```
    https://api.cucu.bo
    ```

    SIAT Producción — facturas fiscalmente válidas ante el SIN.
  </Card>
</CardGroup>

| Característica          | Sandbox                     | Producción                     |
| ----------------------- | --------------------------- | ------------------------------ |
| **API Key**             | `sk_test_...`               | `sk_live_...`                  |
| **Ambiente SIAT**       | Piloto (ambiente 2)         | Producción (ambiente 1)        |
| **Validez fiscal**      | No — facturas de prueba     | Sí — reportadas al SIN         |
| **Certificado digital** | Demo (preconfigurado)       | Requerido (emitido por el SIN) |
| **PDF**                 | Con marca "SIN VALOR LEGAL" | Sin marca de agua              |

Cambiar de ambiente requiere solo dos variables: la **URL base** y la **API Key**. Todos los endpoints, request bodies y response formats son idénticos.

<Tip>
  Si tu integración funciona en sandbox, funciona en producción con solo cambiar la URL y la key.
</Tip>

***

## Autenticación

Todas las llamadas autenticadas requieren el header `X-API-Key`:

<CodeGroup>
  ```bash cURL theme={"system"}
  curl -X GET https://sandbox.cucu.bo/api/v1/invoices \
    -H "X-API-Key: YOUR_API_KEY"
  ```

  ```javascript JavaScript theme={"system"}
  const response = await fetch('https://sandbox.cucu.bo/api/v1/invoices', {
    headers: { 'X-API-Key': process.env.CUCU_API_KEY }
  });
  ```

  ```python Python theme={"system"}
  import requests
  response = requests.get(
      'https://sandbox.cucu.bo/api/v1/invoices',
      headers={'X-API-Key': os.environ['CUCU_API_KEY']}
  )
  ```

  ```go Go theme={"system"}
  req, _ := http.NewRequest("GET", "https://sandbox.cucu.bo/api/v1/invoices", nil)
  req.Header.Set("X-API-Key", os.Getenv("CUCU_API_KEY"))
  resp, _ := http.DefaultClient.Do(req)
  ```
</CodeGroup>

| Prefijo       | Ambiente               | Validez fiscal |
| ------------- | ---------------------- | -------------- |
| `sk_test_...` | Sandbox (SIAT Piloto)  | No             |
| `sk_live_...` | Producción (SIAT real) | Sí             |

<Warning>
  Las keys `sk_live_` nunca deben exponerse en código frontend, repos públicos ni apps móviles. Solo en tu backend, vía variables de entorno o secret manager.
</Warning>

| HTTP  | Código         | Causa                                   |
| ----- | -------------- | --------------------------------------- |
| `401` | `UNAUTHORIZED` | API Key ausente, inválida o revocada    |
| `403` | `FORBIDDEN`    | Key válida pero sin permisos al recurso |

***

## Formato de Respuesta

Todas las respuestas usan el wrapper estándar `ApiResponse`:

<Tabs>
  <Tab title="Respuesta exitosa">
    ```json theme={"system"}
    {
      "success": true,
      "message": "Operación exitosa",
      "data": { },
      "error": null,
      "timestamp": "2026-02-22T12:00:00"
    }
    ```
  </Tab>

  <Tab title="Respuesta con error">
    ```json theme={"system"}
    {
      "success": false,
      "message": null,
      "data": null,
      "error": {
        "code": "VALIDATION_ERROR",
        "details": "El campo 'nitCliente' es requerido"
      },
      "timestamp": "2026-02-22T12:00:00"
    }
    ```
  </Tab>
</Tabs>

| Campo       | Tipo    | Descripción                          |
| ----------- | ------- | ------------------------------------ |
| `success`   | boolean | `true` si la operación fue exitosa   |
| `message`   | string  | Mensaje descriptivo (puede ser null) |
| `data`      | object  | Datos del recurso o resultado        |
| `error`     | object  | Detalle del error (null si éxito)    |
| `timestamp` | string  | Fecha/hora ISO 8601                  |

***

## Paginación

Los endpoints de listado usan paginación basada en offset:

```bash theme={"system"}
GET /api/v1/invoices?page=0&size=20
```

| Parámetro | Tipo    | Default | Descripción                   |
| --------- | ------- | ------- | ----------------------------- |
| `page`    | integer | `0`     | Número de página (base 0)     |
| `size`    | integer | `20`    | Elementos por página (máx 50) |

```json theme={"system"}
{
  "success": true,
  "data": {
    "content": [ ],
    "page": 0,
    "size": 20,
    "totalElements": 150,
    "totalPages": 8,
    "first": true,
    "last": false
  }
}
```

| Campo            | Tipo    | Descripción                       |
| ---------------- | ------- | --------------------------------- |
| `content`        | array   | Elementos de la página actual     |
| `totalElements`  | integer | Total de elementos en el conjunto |
| `totalPages`     | integer | Total de páginas                  |
| `first` / `last` | boolean | Si es la primera o última página  |
