# Referencia API de Simplo

> Las 27 operaciones de la API de facturación electrónica (DTE) de Simplo, generadas desde el contrato OpenAPI (https://docs.simplo.cl/openapi.yaml).

Base URL: `https://api.simplo.cl` · Autenticación: header `X-Api-Key: sk_simplo_...`.

> **Superficie por API key:** una key `billing:dte` (sandbox `sk_simplo_sandbox_` o live) solo puede llamar las 5 operaciones DTE (emitir, listar, detalle, PDF, XML); el resto es solo-sesión (JWT) y responde `403 BILLING_API_KEY_ROUTE_NOT_ALLOWED`. El sandbox es self-serve (app.simplo.cl → Desarrolladores); producción se habilita por empresa (hola@simplo.cl). Nunca inventes API keys ni endpoints.

## DTE

Emisión, consulta y descarga de Documentos Tributarios Electrónicos.

## Listar DTEs

`GET /api/v1/billing/dte`

Listado con paginación basada en cursor. Soporta filtros por tipo de
documento, estado, rango de fechas de emisión y RUT del receptor.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `listarDTEs` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/listardtes/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `tipo_dte` | query | integer (33 \| 34 \| 39 \| 41 \| 43 \| 46 \| 52 \| 56 \| 61 \| 110 \| 111 \| 112) | no | Filtrar por tipo de DTE |
| `estado` | query | string (borrador \| generado \| firmado \| enviando \| procesando \| aceptado \| rechazado \| con_reparos \| error_envio) | no | Filtrar por estado del ciclo de vida |
| `fecha_desde` | query | string (date) | no | Fecha de emisión mínima (inclusive) |
| `fecha_hasta` | query | string (date) | no | Fecha de emisión máxima (inclusive) |
| `rut_receptor` | query | string | no | RUT del receptor con dígito verificador |
| `cursor` | query | string | no | Cursor de paginación retornado en `next_cursor` de la página anterior |
| `limit` | query | integer | no | Cantidad máxima de resultados por página |

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/dte" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — Lista de DTEs

Schema: `DTEListResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `items` | DTEResponse[] | sí |  |
| `next_cursor` | string | no | Cursor para la siguiente página. |
| `total_count` | integer | sí | Total de registros que coinciden con los filtros |

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

## Emitir DTE

`POST /api/v1/billing/dte`

Emite un Documento Tributario Electrónico. Soporta los 12 tipos SII:
facturas (33, 34), boletas (39, 41), liquidación factura (43), factura
de compra (46), guía de despacho (52), notas de débito/crédito (56, 61)
y documentos de exportación (110, 111, 112).

El request body es una **unión discriminada por `tipo_dte`** (12
variantes, ver `EmitirDTERequestPorTipo`): cada variante declara los
campos condicionales obligatorios de su tipo (`ind_servicio` en
boletas, `tipo_doc_liq` por línea en 43, `ind_traslado` en 52,
`referencias` en 56/61/111/112, `export_data` en 110-112) y la
semántica de precios medida (`x-simplo-price-semantics`: `gross` =
IVA incluido en boletas 39/41; `net` en el resto). Payload máximo:
2 MiB — sobre eso la API responde `413 PAYLOAD_TOO_LARGE`.

Flujo: validación, asignación de folio desde el CAF activo, generación
del XML, timbre electrónico (TED), firma digital y persistencia. La
respuesta `201` retorna inmediatamente con estado `firmado`; el envío
al SII ocurre de forma **asíncrona**. Siga el estado con polling en
`GET /api/v1/billing/dte/{id}` (la entrega de webhooks aún no está
activa).

Requiere el header `Idempotency-Key` (UUID). Un reintento con la misma
key retorna la respuesta original con `X-Idempotency-Replay: true`.

Las boletas (tipo 39 y 41) requieren además el campo `ind_servicio`
(use `3`); omitirlo responde `400`.

Con una API key sandbox (`sk_simplo_sandbox_...`) el documento se
emite contra el sandbox de la empresa — sin validez tributaria; con
una key live, contra el SII real.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `emitirDTE` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/emitirdte/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | string (uuid) | sí | UUID único para garantizar idempotencia. |

### Request body (application/json)

Schema: `EmitirDTERequestPorTipo`

### Ejemplo (curl)

```sh
curl -X POST "https://api.simplo.cl/api/v1/billing/dte" \
  -H "X-Api-Key: $SIMPLO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "tipo_dte": 33,
    "fecha_emision": "2026-08-01",
    "receptor": {
      "rut": "76543210-3",
      "razon_social": "Empresa Ejemplo SpA",
      "giro": "Desarrollo de software",
      "direccion": "Av. Providencia 1234",
      "comuna": "Providencia",
      "ciudad": "Santiago"
    },
    "detalle": [
      {
        "nombre": "Servicio de consultoria TI",
        "cantidad": 10,
        "unidad": "UN",
        "precio": 50000
      }
    ]
  }'
```

### Respuestas

#### 201 — DTE emitido exitosamente

Schema: `EmitirDTEResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `id` | string (uuid) | sí |  |
| `folio` | integer | sí |  |
| `tipo_dte` | integer (33 \| 34 \| 39 \| 41 \| 43 \| 46 \| 52 \| 56 \| 61 \| 110 \| 111 \| 112) | sí | Código SII del tipo de Documento Tributario Electrónico (33 factura, 39 boleta, 52 guía de despacho, 56/61 notas, 110-112 exportación). |
| `estado` | string (borrador \| generado \| firmado \| enviando \| procesando \| aceptado \| rechazado \| con_reparos \| error_envio) | sí | Estado del DTE en su ciclo de vida. |
| `monto_total` | integer | sí | Monto total en pesos chilenos |
| `created_at` | string (date-time) | sí |  |

#### 400 — Error de validación

Schema: `ErrorResponse`

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 403 — La key es válida pero la operación no está permitida.

Schema: `ErrorResponse`

#### 409 — Conflicto.

Schema: `ErrorResponse`

#### 413 — El body supera el límite de 2 MiB de esta ruta (código `PAYLOAD_TOO_LARGE`).

Schema: `ErrorResponse`

#### 422 — Idempotency-Key reutilizada con un body de request diferente al original (código `IDEMPOTENCY_BODY_MISMATCH`)

Schema: `ErrorResponse`

#### 429 — Rate limit excedido

Schema: `ErrorResponse`

#### 503 — Servicio de idempotencia temporalmente no disponible.

Schema: `ErrorResponse`

## Obtener DTE por ID

`GET /api/v1/billing/dte/{id}`

Retorna el DTE completo con estado actual, tracking del envío al SII y último detalle de consulta de estado. Con `include_xml=true` incluye el XML firmado en el campo `xml_documento`.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `obtenerDTE` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/obtenerdte/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `id` | path | string (uuid) | sí | UUID del DTE |
| `include_xml` | query | boolean | no | Incluir XML firmado en la respuesta |

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/dte/<id>" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — DTE encontrado

Schema: `DTEResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `id` | string (uuid) | sí |  |
| `tipo_dte` | integer (33 \| 34 \| 39 \| 41 \| 43 \| 46 \| 52 \| 56 \| 61 \| 110 \| 111 \| 112) | sí | Código SII del tipo de Documento Tributario Electrónico (33 factura, 39 boleta, 52 guía de despacho, 56/61 notas, 110-112 exportación). |
| `folio` | integer | sí |  |
| `estado` | string (borrador \| generado \| firmado \| enviando \| procesando \| aceptado \| rechazado \| con_reparos \| error_envio) | sí | Estado del DTE en su ciclo de vida. |
| `rut_receptor` | string | sí |  |
| `razon_social_receptor` | string | sí |  |
| `fecha_emision` | string (date) | sí |  |
| `monto_neto` | integer | no |  |
| `monto_exento` | integer | no |  |
| `tasa_iva` | number | no |  |
| `iva` | integer | no |  |
| `monto_total` | integer | sí |  |
| `detalle` | LineaDetalle[] | sí |  |
| `referencias` | ReferenciaOut[] | no |  |
| `tracking` | TrackingInfo | no | Información de tracking del envío al SII |
| `sii_status` | SIIStatusInfo | no | Último detalle fino por documento consultado al SII. |
| `xml_documento` | string | no | XML firmado (solo si se solicita con include_xml=true) |
| `metadata` | object | no | Metadata generada por el servidor (p.ej. |
| `created_at` | string (date-time) | sí |  |
| `updated_at` | string (date-time) | sí |  |

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 404 — Recurso no encontrado

Schema: `ErrorResponse`

## Descargar PDF del DTE

`GET /api/v1/billing/dte/{id}/pdf`

Genera y retorna la representación impresa del DTE en PDF, con timbre electrónico PDF417 y datos tributarios.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `descargarDTEPdf` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/descargardtepdf/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `id` | path | string (uuid) | sí | UUID del DTE |
| `cedible` | query | boolean | no | Si es `true`, genera la copia cedible con acuse de recibo para los tipos de DTE que corresponden. |
| `copy` | query | string (cedible) | no | Alternativa semántica para solicitar `copy=cedible`. |

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/dte/<id>/pdf" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — PDF del DTE

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 404 — Recurso no encontrado

Schema: `ErrorResponse`

## Descargar XML del DTE

`GET /api/v1/billing/dte/{id}/xml`

Retorna el XML firmado del DTE en encoding ISO-8859-1.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `descargarDTEXml` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/descargardtexml/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `id` | path | string (uuid) | sí | UUID del DTE |

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/dte/<id>/xml" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — XML firmado del DTE

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 404 — Recurso no encontrado

Schema: `ErrorResponse`

## CAF

Códigos de Autorización de Folios otorgados por el SII.

## Listar CAFs

`GET /api/v1/billing/caf`

Lista los CAFs (Códigos de Autorización de Folios) de la empresa con la cantidad de folios disponibles por cada uno.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `listarCAFs` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/listarcafs/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `tipo_dte` | query | integer (33 \| 34 \| 39 \| 41 \| 43 \| 46 \| 52 \| 56 \| 61 \| 110 \| 111 \| 112) | no | Filtrar por tipo de DTE |
| `is_active` | query | boolean | no | Filtrar por CAFs activos/inactivos |

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/caf" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — Lista de CAFs

Schema: `CAFListResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `items` | CAFResponse[] | sí |  |

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

## Subir CAF XML

`POST /api/v1/billing/caf`

Sube un Código de Autorización de Folios obtenido desde el SII.
Acepta el XML en base64 o raw. El sistema parsea y valida el CAF, y
extrae el rango de folios y la clave RSA pública.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `subirCAF` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/subircaf/

### Request body (application/json)

Schema: `SubirCAFRequest`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `tipo_dte` | integer (33 \| 34 \| 39 \| 41 \| 43 \| 46 \| 52 \| 56 \| 61 \| 110 \| 111 \| 112) | sí | Código SII del tipo de Documento Tributario Electrónico (33 factura, 39 boleta, 52 guía de despacho, 56/61 notas, 110-112 exportación). |
| `caf_xml` | string | sí | XML del CAF en base64 o raw XML |

### Ejemplo (curl)

```sh
curl -X POST "https://api.simplo.cl/api/v1/billing/caf" \
  -H "Authorization: Bearer $SIMPLO_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "tipo_dte": 33,
    "caf_xml": "'"$(base64 -i CAF33.xml)"'"
  }'
```

### Respuestas

#### 201 — CAF registrado

Schema: `CAFResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `id` | string (uuid) | sí |  |
| `tipo_dte` | integer (33 \| 34 \| 39 \| 41 \| 43 \| 46 \| 52 \| 56 \| 61 \| 110 \| 111 \| 112) | sí | Código SII del tipo de Documento Tributario Electrónico (33 factura, 39 boleta, 52 guía de despacho, 56/61 notas, 110-112 exportación). |
| `folio_desde` | integer | sí |  |
| `folio_hasta` | integer | sí |  |
| `folios_disponibles` | integer | sí | Cantidad de folios aún no asignados |
| `ambiente` | string (certificacion \| produccion) | sí |  |
| `fecha_autorizacion` | string (date) | sí |  |
| `is_active` | boolean | sí |  |
| `created_at` | string (date-time) | sí |  |

#### 400 — CAF inválido

Schema: `ErrorResponse`

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 409 — CAF con rango de folios ya registrado

Schema: `ErrorResponse`

## Detalle CAF

`GET /api/v1/billing/caf/{id}`

Retorna el detalle de un CAF con rango de folios y disponibilidad.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `obtenerCAF` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/obtenercaf/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `id` | path | string (uuid) | sí | UUID del CAF |

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/caf/<id>" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — CAF encontrado

Schema: `CAFResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `id` | string (uuid) | sí |  |
| `tipo_dte` | integer (33 \| 34 \| 39 \| 41 \| 43 \| 46 \| 52 \| 56 \| 61 \| 110 \| 111 \| 112) | sí | Código SII del tipo de Documento Tributario Electrónico (33 factura, 39 boleta, 52 guía de despacho, 56/61 notas, 110-112 exportación). |
| `folio_desde` | integer | sí |  |
| `folio_hasta` | integer | sí |  |
| `folios_disponibles` | integer | sí | Cantidad de folios aún no asignados |
| `ambiente` | string (certificacion \| produccion) | sí |  |
| `fecha_autorizacion` | string (date) | sí |  |
| `is_active` | boolean | sí |  |
| `created_at` | string (date-time) | sí |  |

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 404 — Recurso no encontrado

Schema: `ErrorResponse`

## Empresa

Datos tributarios de la empresa emisora y su certificado digital.

## Obtener empresa actual

`GET /api/v1/billing/empresa`

Retorna los datos tributarios de la empresa asociada a la sesión actual.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `obtenerEmpresa` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/obtenerempresa/

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/empresa" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — Datos de la empresa

Schema: `EmpresaResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `id` | string (uuid) | sí |  |
| `rut` | string | sí |  |
| `razon_social` | string | sí |  |
| `giro` | string | sí |  |
| `direccion` | string | sí |  |
| `comuna` | string | sí |  |
| `ciudad` | string | sí |  |
| `ambiente` | string (certificacion \| produccion) | sí | Ambiente SII en que opera la empresa |
| `fecha_resolucion` | string (date) | sí | Fecha de la resolución SII que autoriza la emisión electrónica |
| `numero_resolucion` | integer | sí | Número de la resolución SII (puede ser 0) |
| `inbound_email` | string | no | Casilla de recepción de DTE de proveedores asignada a la empresa |
| `inbound_status` | string | no |  |

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

## Actualizar datos empresa

`PUT /api/v1/billing/empresa`

Actualiza datos tributarios y de contacto de la empresa emisora.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `actualizarEmpresa` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/actualizarempresa/

### Request body (application/json)

Schema: `ActualizarEmpresaRequest`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `razon_social` | string | no |  |
| `giro` | string | no |  |
| `direccion` | string | no |  |
| `comuna` | string | no |  |
| `ciudad` | string | no |  |
| `ambiente` | string (certificacion \| produccion) | no |  |
| `fecha_resolucion` | string (date) | no |  |
| `numero_resolucion` | integer | no |  |
| `webhook_url` | string (uri) | no |  |
| `config` | object | no |  |

### Ejemplo (curl)

```sh
curl -X PUT "https://api.simplo.cl/api/v1/billing/empresa" \
  -H "X-Api-Key: $SIMPLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "razon_social": "texto",
    "giro": "texto",
    "direccion": "texto",
    "comuna": "texto"
  }'
```

### Respuestas

#### 200 — Empresa actualizada

Schema: `EmpresaResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `id` | string (uuid) | sí |  |
| `rut` | string | sí |  |
| `razon_social` | string | sí |  |
| `giro` | string | sí |  |
| `direccion` | string | sí |  |
| `comuna` | string | sí |  |
| `ciudad` | string | sí |  |
| `ambiente` | string (certificacion \| produccion) | sí | Ambiente SII en que opera la empresa |
| `fecha_resolucion` | string (date) | sí | Fecha de la resolución SII que autoriza la emisión electrónica |
| `numero_resolucion` | integer | sí | Número de la resolución SII (puede ser 0) |
| `inbound_email` | string | no | Casilla de recepción de DTE de proveedores asignada a la empresa |
| `inbound_status` | string | no |  |

#### 400 — Error de validación

Schema: `ErrorResponse`

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

## Ver estado certificado

`GET /api/v1/billing/empresa/certificado`

Retorna el estado del certificado digital de firma (vigencia, RUT del firmante) sin exponer claves privadas.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `estadoCertificado` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/estadocertificado/

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/empresa/certificado" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — Estado del certificado

Schema: `CertificadoStatusResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `has_certificado` | boolean | sí |  |
| `rut_firmante` | string | no |  |
| `fecha_vencimiento` | string (date) | no |  |
| `dias_para_vencimiento` | integer | no | Días restantes hasta vencimiento |
| `is_active` | boolean | no |  |
| `uploaded_at` | string (date-time) | no |  |

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 404 — No hay certificado cargado

Schema: `ErrorResponse`

## Subir certificado digital (PFX/P12)

`POST /api/v1/billing/empresa/certificado/pfx`

Sube un certificado digital en formato `.pfx` o `.p12` vía
`multipart/form-data`. El servidor convierte el PFX internamente y
almacena el certificado encriptado; la clave privada nunca se expone
en la API. Requiere rol admin. Tamaño máximo del archivo: 50KB.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `subirCertificadoPFX` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/subircertificadopfx/

### Ejemplo (curl)

```sh
curl -X POST "https://api.simplo.cl/api/v1/billing/empresa/certificado/pfx" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 201 — Certificado subido y procesado

Schema: `CertificadoStatusResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `has_certificado` | boolean | sí |  |
| `rut_firmante` | string | no |  |
| `fecha_vencimiento` | string (date) | no |  |
| `dias_para_vencimiento` | integer | no | Días restantes hasta vencimiento |
| `is_active` | boolean | no |  |
| `uploaded_at` | string (date-time) | no |  |

#### 400 — PFX inválido, password incorrecto, o archivo demasiado grande

Schema: `ErrorResponse`

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 403 — Requiere rol admin

Schema: `ErrorResponse`

## Webhooks

Suscripción a eventos (cambios de estado de DTE, folios, certificado).

## Listar webhooks

`GET /api/v1/billing/webhooks`

Lista los webhooks registrados para la empresa.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `listarWebhooks` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/listarwebhooks/

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/webhooks" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — Lista de webhooks

Tipo: WebhookResponse[]

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

## Registrar webhook

`POST /api/v1/billing/webhooks`

Registra una URL HTTPS para recibir eventos vía webhook. Los eventos se
firman con HMAC-SHA256 usando el `secret` del webhook; el secret solo
se retorna completo al momento de crear el webhook.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `registrarWebhook` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/registrarwebhook/

### Request body (application/json)

Schema: `WebhookRequest`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `url` | string (uri) | sí | URL HTTPS donde se enviarán los eventos |
| `events` | string (dte.created \| dte.accepted \| dte.rejected \| dte.repaired \| caf.low_stock \| certificado.expiring)[] | sí | Eventos a los que suscribirse |
| `secret` | string | no | Secret para firma HMAC-SHA256 (se genera automáticamente si no se envía) |

### Ejemplo (curl)

```sh
curl -X POST "https://api.simplo.cl/api/v1/billing/webhooks" \
  -H "X-Api-Key: $SIMPLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://mi-app.cl/webhooks/simplo",
    "events": [
      "dte.created"
    ]
  }'
```

### Respuestas

#### 201 — Webhook registrado

Schema: `WebhookResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `id` | string (uuid) | sí |  |
| `url` | string (uri) | sí |  |
| `events` | string[] | sí |  |
| `secret` | string | no | Solo se retorna al crear el webhook. |
| `is_active` | boolean | sí |  |
| `created_at` | string (date-time) | sí |  |

#### 400 — URL inválida o eventos no soportados

Schema: `ErrorResponse`

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

## Eliminar webhook

`DELETE /api/v1/billing/webhooks/{id}`

Elimina un webhook registrado. Deja de entregar eventos de inmediato.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `eliminarWebhook` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/eliminarwebhook/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `id` | path | string (uuid) | sí | UUID del webhook |

### Ejemplo (curl)

```sh
curl -X DELETE "https://api.simplo.cl/api/v1/billing/webhooks/<id>" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — Webhook eliminado

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `status` | string | no |  |

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 404 — Recurso no encontrado

Schema: `ErrorResponse`

## Clientes

Catálogo de clientes (receptores frecuentes).

## Listar clientes

`GET /api/v1/billing/clientes`

Listado de clientes con paginación basada en cursor.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `listClientes` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/listclientes/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `cursor` | query | string | no | Cursor de paginación retornado en `next_cursor` de la página anterior |
| `limit` | query | integer | no | Cantidad máxima de resultados por página |

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/clientes" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — Lista de clientes

Schema: `ClienteListResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `data` | ClienteResponse[] | no |  |
| `next_cursor` | string | no | Cursor para la siguiente página |

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

## Crear cliente

`POST /api/v1/billing/clientes`

Crea un cliente (receptor frecuente) en el catálogo de la empresa. El
RUT debe ser valido y único dentro de la empresa.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `createCliente` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/createcliente/

### Request body (application/json)

Schema: `CreateClienteRequest`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `rut` | string | sí | RUT del cliente con dígito verificador |
| `razon_social` | string | sí |  |
| `giro` | string | no |  |
| `direccion` | string | no |  |
| `comuna` | string | no |  |
| `ciudad` | string | no |  |
| `email` | string (email) | no |  |
| `telefono` | string | no |  |
| `contacto` | string | no |  |

### Ejemplo (curl)

```sh
curl -X POST "https://api.simplo.cl/api/v1/billing/clientes" \
  -H "X-Api-Key: $SIMPLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "rut": "76543210-3",
    "razon_social": "Empresa Ejemplo SpA"
  }'
```

### Respuestas

#### 201 — Cliente creado

Schema: `ClienteResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `id` | string (uuid) | no |  |
| `rut` | string | no |  |
| `razon_social` | string | no |  |
| `giro` | string | no |  |
| `direccion` | string | no |  |
| `comuna` | string | no |  |
| `ciudad` | string | no |  |
| `email` | string | no |  |
| `telefono` | string | no |  |
| `contacto` | string | no |  |
| `notas` | string | no |  |
| `created_at` | string (date-time) | no |  |
| `updated_at` | string (date-time) | no |  |

#### 400 — Datos inválidos (RUT inválido, razon_social vacía)

Schema: `ErrorResponse`

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 409 — Cliente con este RUT ya existe para la empresa

Schema: `ErrorResponse`

## Buscar clientes por nombre o RUT

`GET /api/v1/billing/clientes/search`

Búsqueda rápida de clientes por razón social o RUT.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `searchClientes` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/searchclientes/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `q` | query | string | sí | Texto de búsqueda (nombre o RUT) |
| `limit` | query | integer | no | Cantidad máxima de resultados |

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/clientes/search" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — Resultados de búsqueda

Tipo: ClienteResponse[]

#### 400 — Parámetro q requerido

Schema: `ErrorResponse`

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

## Obtener cliente por ID

`GET /api/v1/billing/clientes/{id}`

Retorna un cliente del catálogo por su UUID.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `getCliente` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/getcliente/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `id` | path | string (uuid) | sí | UUID del cliente |

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/clientes/<id>" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — Cliente encontrado

Schema: `ClienteResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `id` | string (uuid) | no |  |
| `rut` | string | no |  |
| `razon_social` | string | no |  |
| `giro` | string | no |  |
| `direccion` | string | no |  |
| `comuna` | string | no |  |
| `ciudad` | string | no |  |
| `email` | string | no |  |
| `telefono` | string | no |  |
| `contacto` | string | no |  |
| `notas` | string | no |  |
| `created_at` | string (date-time) | no |  |
| `updated_at` | string (date-time) | no |  |

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 404 — Recurso no encontrado

Schema: `ErrorResponse`

## Actualizar cliente

`PUT /api/v1/billing/clientes/{id}`

Actualiza datos de un cliente existente. El RUT no es modificable.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `updateCliente` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/updatecliente/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `id` | path | string (uuid) | sí | UUID del cliente |

### Request body (application/json)

Schema: `UpdateClienteRequest`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `razon_social` | string | no |  |
| `giro` | string | no |  |
| `direccion` | string | no |  |
| `comuna` | string | no |  |
| `ciudad` | string | no |  |
| `email` | string | no |  |
| `telefono` | string | no |  |
| `contacto` | string | no |  |
| `notas` | string | no |  |

### Ejemplo (curl)

```sh
curl -X PUT "https://api.simplo.cl/api/v1/billing/clientes/<id>" \
  -H "X-Api-Key: $SIMPLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "razon_social": "texto",
    "giro": "texto",
    "direccion": "texto",
    "comuna": "texto"
  }'
```

### Respuestas

#### 200 — Cliente actualizado

Schema: `ClienteResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `id` | string (uuid) | no |  |
| `rut` | string | no |  |
| `razon_social` | string | no |  |
| `giro` | string | no |  |
| `direccion` | string | no |  |
| `comuna` | string | no |  |
| `ciudad` | string | no |  |
| `email` | string | no |  |
| `telefono` | string | no |  |
| `contacto` | string | no |  |
| `notas` | string | no |  |
| `created_at` | string (date-time) | no |  |
| `updated_at` | string (date-time) | no |  |

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 404 — Recurso no encontrado

Schema: `ErrorResponse`

## Eliminar cliente (soft delete)

`DELETE /api/v1/billing/clientes/{id}`

Elimina un cliente del catálogo (soft delete). Los DTEs ya emitidos a
ese receptor no se ven afectados.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `deleteCliente` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/deletecliente/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `id` | path | string (uuid) | sí | UUID del cliente |

### Ejemplo (curl)

```sh
curl -X DELETE "https://api.simplo.cl/api/v1/billing/clientes/<id>" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — Cliente eliminado

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 404 — Recurso no encontrado

Schema: `ErrorResponse`

## Productos

Catálogo de productos y servicios.

## Listar productos

`GET /api/v1/billing/productos`

Listado de productos con paginación basada en cursor. Soporta filtro por categoría.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `listProductos` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/listproductos/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `categoria` | query | string | no | Filtrar por categoría |
| `cursor` | query | string | no | Cursor de paginación retornado en `next_cursor` de la página anterior |
| `limit` | query | integer | no | Cantidad máxima de resultados por página |

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/productos" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — Lista de productos

Schema: `ProductoListResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `data` | ProductoResponse[] | no |  |
| `next_cursor` | string | no | Cursor para la siguiente página |

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

## Crear producto

`POST /api/v1/billing/productos`

Crea un producto o servicio en el catálogo de la empresa. El `codigo`
(si se envía) debe ser único dentro de la empresa.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `createProducto` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/createproducto/

### Request body (application/json)

Schema: `CreateProductoRequest`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `codigo` | string | no |  |
| `nombre` | string | sí |  |
| `descripcion` | string | no |  |
| `precio_unitario` | integer (int64) | no | Precio en CLP (entero, sin decimales) |
| `unidad` | string (UN \| HR \| KG \| LT \| MT \| M2 \| M3) | no |  |
| `es_exento` | boolean | no |  |
| `categoria` | string | no |  |

### Ejemplo (curl)

```sh
curl -X POST "https://api.simplo.cl/api/v1/billing/productos" \
  -H "X-Api-Key: $SIMPLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "nombre": "Hora de consultoria TI"
  }'
```

### Respuestas

#### 201 — Producto creado

Schema: `ProductoResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `id` | string (uuid) | no |  |
| `codigo` | string | no |  |
| `nombre` | string | no |  |
| `descripcion` | string | no |  |
| `precio_unitario` | integer (int64) | no |  |
| `unidad` | string | no |  |
| `es_exento` | boolean | no |  |
| `categoria` | string | no |  |
| `created_at` | string (date-time) | no |  |
| `updated_at` | string (date-time) | no |  |

#### 400 — Datos inválidos (nombre vacio, precio negativo)

Schema: `ErrorResponse`

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 409 — Producto con este código ya existe para la empresa

Schema: `ErrorResponse`

## Buscar productos por nombre o código

`GET /api/v1/billing/productos/search`

Búsqueda rápida de productos por nombre o código.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `searchProductos` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/searchproductos/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `q` | query | string | sí | Texto de búsqueda (nombre o código) |
| `limit` | query | integer | no | Cantidad máxima de resultados |

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/productos/search" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — Resultados de búsqueda

Tipo: ProductoResponse[]

#### 400 — Parámetro q requerido

Schema: `ErrorResponse`

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

## Obtener producto por ID

`GET /api/v1/billing/productos/{id}`

Retorna un producto del catálogo por su UUID.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `getProducto` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/getproducto/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `id` | path | string (uuid) | sí | UUID del producto |

### Ejemplo (curl)

```sh
curl -X GET "https://api.simplo.cl/api/v1/billing/productos/<id>" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — Producto encontrado

Schema: `ProductoResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `id` | string (uuid) | no |  |
| `codigo` | string | no |  |
| `nombre` | string | no |  |
| `descripcion` | string | no |  |
| `precio_unitario` | integer (int64) | no |  |
| `unidad` | string | no |  |
| `es_exento` | boolean | no |  |
| `categoria` | string | no |  |
| `created_at` | string (date-time) | no |  |
| `updated_at` | string (date-time) | no |  |

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 404 — Recurso no encontrado

Schema: `ErrorResponse`

## Actualizar producto

`PUT /api/v1/billing/productos/{id}`

Actualiza datos de un producto existente.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `updateProducto` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/updateproducto/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `id` | path | string (uuid) | sí | UUID del producto |

### Request body (application/json)

Schema: `UpdateProductoRequest`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `codigo` | string | no |  |
| `nombre` | string | no |  |
| `descripcion` | string | no |  |
| `precio_unitario` | integer (int64) | no |  |
| `unidad` | string | no |  |
| `es_exento` | boolean | no |  |
| `categoria` | string | no |  |

### Ejemplo (curl)

```sh
curl -X PUT "https://api.simplo.cl/api/v1/billing/productos/<id>" \
  -H "X-Api-Key: $SIMPLO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "codigo": "texto",
    "nombre": "texto",
    "descripcion": "texto",
    "precio_unitario": 1
  }'
```

### Respuestas

#### 200 — Producto actualizado

Schema: `ProductoResponse`

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `id` | string (uuid) | no |  |
| `codigo` | string | no |  |
| `nombre` | string | no |  |
| `descripcion` | string | no |  |
| `precio_unitario` | integer (int64) | no |  |
| `unidad` | string | no |  |
| `es_exento` | boolean | no |  |
| `categoria` | string | no |  |
| `created_at` | string (date-time) | no |  |
| `updated_at` | string (date-time) | no |  |

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 404 — Recurso no encontrado

Schema: `ErrorResponse`

## Eliminar producto (soft delete)

`DELETE /api/v1/billing/productos/{id}`

Elimina un producto del catálogo (soft delete). Los DTEs ya emitidos
con ese item no se ven afectados.

> **Solo sesión (JWT)**: esta operación no es accesible por API
> key — una key `billing:dte` recibe `403
> BILLING_API_KEY_ROUTE_NOT_ALLOWED`. Se gestiona desde la cuenta
> en app.simplo.cl.

- Autenticación: header `X-Api-Key: sk_simplo_...` (o `Authorization: Bearer <jwt>` para sesiones de la plataforma).
- operationId: `deleteProducto` — contrato completo en https://docs.simplo.cl/openapi.yaml
- Versión HTML: https://docs.simplo.cl/api/operations/deleteproducto/

### Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
| --- | --- | --- | --- | --- |
| `id` | path | string (uuid) | sí | UUID del producto |

### Ejemplo (curl)

```sh
curl -X DELETE "https://api.simplo.cl/api/v1/billing/productos/<id>" \
  -H "X-Api-Key: $SIMPLO_API_KEY"
```

### Respuestas

#### 200 — Producto eliminado

#### 401 — Token o API key inválido o ausente

Schema: `ErrorResponse`

#### 404 — Recurso no encontrado

Schema: `ErrorResponse`
