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

> **Beta privada:** la emisión de DTE y en general las operaciones de escritura vía API key están en beta privada; hoy las API keys operan en modo lectura. Para solicitar acceso escribe a 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) | 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).

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**. Use webhooks o polling en
`GET /api/v1/billing/dte/{id}` para seguir el estado.

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

> **Beta privada**: la emisión y las escrituras vía API key están en
> beta privada (solicitar acceso: hola@simplo.cl); las API keys hoy
> operan en modo lectura.

- 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: `EmitirDTERequest`

| 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). |
| `fecha_emision` | string (date) | no | Fecha de emisión tributaria del DTE en formato YYYY-MM-DD. |
| `receptor` | Receptor | sí |  |
| `detalle` | LineaDetalle[] | sí |  |
| `comisiones` | ComisionDTE[] | no | Comisiones de Liquidación Factura (tipo 43) |
| `impuestos_retenciones` | ImpuestoRetencion[] | no | Impuestos retenidos en Totales/ImptoReten. |
| `referencias` | Referencia[] | no | Requerido para notas de crédito (61), notas de débito (56), y exportación (111, 112) |
| `ind_traslado` | integer (1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9) | no | Tipo de traslado para Guía de Despacho (tipo 52): - 1: Operación constituye venta - 2: Venta por efectuar - 3: Consignación - 4: Entrega gratuita - 5: Traslado interno - 6: Otros traslados no venta - 7: Guía de devolución - 8: Traslado para exportación (no venta) - 9: Venta para exportación |
| `tipo_despacho` | integer (1 \| 2 \| 3) | no | Modo de despacho para Guía de Despacho (tipo 52): - 1: Despacho por cuenta del comprador - 2: Despacho por cuenta del emisor a instalaciones del comprador - 3: Despacho por cuenta del emisor a otras instalaciones |
| `ind_servicio` | integer (1 \| 2 \| 3 \| 4 \| 5 \| 6) | no | Indicador de servicio: - 1: Facturación de servicios periódicos domiciliarios - 2: Facturación de otros servicios periódicos - 3: Factura de servicio; en exportación, servicio calificado por Aduana - 4: Factura de exportación por servicios de hotelería - 5: Factura de exportación por transporte terrestre internacional - 6: Factura de exportación por servicios prestados y utilizados totalmente en el extranjero |
| `descuentos_globales` | DscRcgGlobal[] | no | Descuentos y recargos globales aplicados sobre el neto |
| `auto_send` | boolean | no | Cuando es `true` (default), el DTE se encola para envío individual al SII inmediatamente después de emitirse. |
| `export_data` | ExportData | no | Datos de exportación para tipos 110, 111, 112 |
| `metadata` | object | no | Metadata extensible definida por el integrador |

#### Receptor

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `rut` | string | sí | RUT del receptor con dígito verificador |
| `razon_social` | string | sí |  |
| `giro` | string | no |  |
| `direccion` | string | no |  |
| `comuna` | string | no |  |
| `ciudad` | string | no |  |

#### LineaDetalle

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `tipo_doc_liq` | string | no | Tipo de documento liquidado. |
| `ind_exe` | integer (1) | no | Marca una línea como exenta cuando el tipo de DTE lo requiere. |
| `cod_imp_adic` | integer | no | Código de impuesto adicional por línea. |
| `nombre` | string | sí | Nombre del item o servicio |
| `dsc_item` | string | no | Descripción adicional de la línea. |
| `cantidad` | number | no | Cantidad (soporta decimales para unidades fraccionarias). |
| `unidad` | string | no | Unidad de medida opcional del item, por ejemplo `UN`, `Kg` o `Lt` |
| `precio` | integer | no | Precio unitario en pesos chilenos. |
| `monto_item` | integer | no | Monto total de la línea. |
| `descuento_pct` | number | no | Descuento porcentual sobre la línea (0-100) |
| `recargo_pct` | number | no | Recargo porcentual sobre la línea (0-100) |

#### ComisionDTE

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `tipo_movim` | string (C \| O) | sí | `C` para cobro/comisión positiva, `O` para otros movimientos o rebajas. |
| `glosa` | string | sí |  |
| `tasa_comision` | number | no |  |
| `val_com_neto` | integer | sí |  |
| `val_com_exe` | integer | sí |  |
| `val_com_iva` | integer | no |  |

#### ImpuestoRetencion

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `tipo_imp` | integer | sí | Código SII del impuesto retenido. |
| `tasa_imp` | number | no | Tasa usada para calcular el monto retenido cuando `monto_imp` no viene informado. |
| `monto_imp` | integer | no | Monto retenido explícito. |

#### Referencia

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `tipo_doc_ref` | integer (33 \| 34 \| 39 \| 41 \| 43 \| 46 \| 52 \| 56 \| 61 \| 110 \| 111 \| 112) \| string | sí |  |
| `folio_ref` | integer | sí | Folio del documento referenciado |
| `fecha_ref` | string (date) | sí | Fecha del documento referenciado |
| `codigo_ref` | integer (1 \| 2 \| 3) | no | Código de referencia SII: - 1: Anula documento referenciado - 2: Corrige texto del documento referenciado - 3: Corrige montos del documento referenciado |
| `razon_ref` | string | sí | Razón de la referencia |

#### DscRcgGlobal

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `nro_lin_dr` | integer | no | Número de línea del descuento/recargo |
| `tpo_mov` | string (D \| R) | sí | D = descuento, R = recargo |
| `tpo_valor` | string (% \| $) | sí | % = porcentaje, $ = monto fijo |
| `valor_dr` | number | sí | Valor del descuento/recargo. |
| `glosa_dr` | string | no | Glosa descriptiva |
| `ind_exe_dr` | integer (1 \| 2) | no | 1 = descuento/recargo global no afecto; 2 = no facturable. |

#### ExportData

Datos de exportación para tipos 110, 111, 112

| Campo | Tipo | Requerido | Descripción |
| --- | --- | --- | --- |
| `tpo_moneda` | string | sí | Código de moneda según tabla Aduanas (e.g., "DOLAR USA", "EURO") |
| `tpo_cambio` | number | no | Tipo de cambio fijado por el Banco Central para OtraMoneda cuando se informa |
| `mnt_export` | number | no | Monto auxiliar de compatibilidad para OtraMoneda |
| `nacionalidad` | string | no | Código o nombre de país para Receptor/Extranjero/Nacionalidad |
| `num_id` | string | no | Número de identificación del receptor extranjero/turista para Exportaciones/Extranjero/NumId |
| `tipo_doc_id` | integer | no | No usar en tipos 110, 111, 112; el XSD de Exportaciones no permite TipoDocID dentro de Receptor/Extranjero |
| `forma_pago_exp` | integer | no | Código Aduana de forma de pago de exportación |
| `modalidad_venta` | integer | no | Código Aduana de modalidad de venta |
| `clausula_venta` | string | no | Cláusula Aduana, acepta código numérico o etiqueta conocida como CIF, CFR, FOB |
| `total_clausula` | number | no | Total de la cláusula de venta |
| `via_transporte` | integer | no | Código Aduana de vía de transporte |
| `puerto_embarque` | string | no | Código o nombre de puerto de embarque |
| `puerto_desembarque` | string | no | Código o nombre de puerto de desembarque |
| `tara` | integer | no | Tara |
| `unidad_tara` | integer | no | Código Aduana de unidad de medida de tara |
| `peso_bruto` | number | no | Peso bruto |
| `unidad_peso_bruto` | integer | no | Código Aduana de unidad de peso bruto |
| `peso_neto` | number | no | Peso neto |
| `unidad_peso_neto` | integer | no | Código Aduana de unidad de peso neto |
| `tipo_bulto` | string | no | Tipo de bulto, acepta código numérico o etiqueta conocida |
| `total_bultos` | integer | no | Total de bultos |
| `marcas` | string | no | Marcas informadas dentro de TipoBultos cuando la operación lo exige |
| `mnt_flete` | number | no | Monto de flete en moneda de venta |
| `mnt_seguro` | number | no | Monto de seguro en moneda de venta |
| `pais_recep` | string | no | Código o nombre de país receptor según tabla Aduanas |
| `pais_dest` | string | no | Código o nombre de país destino según tabla Aduanas |

### 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-K",
      "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) | 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`

#### 409 — Conflicto.

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) | 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` | Referencia[] | 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 |  |
| `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.

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

> **Beta privada**: las escrituras vía API key están en beta privada
> (solicitar acceso: hola@simplo.cl); las API keys hoy operan en modo
> lectura.

- 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 "X-Api-Key: $SIMPLO_API_KEY" \
  -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.

- 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 credencial actual (JWT o API key).

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

> **Beta privada**: las escrituras vía API key están en beta privada
> (solicitar acceso: hola@simplo.cl); las API keys hoy operan en modo
> lectura.

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

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

> **Beta privada**: las escrituras vía API key están en beta privada
> (solicitar acceso: hola@simplo.cl); las API keys hoy operan en modo
> lectura.

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

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

> **Beta privada**: las escrituras vía API key están en beta privada
> (solicitar acceso: hola@simplo.cl); las API keys hoy operan en modo
> lectura.

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

> **Beta privada**: las escrituras vía API key están en beta privada
> (solicitar acceso: hola@simplo.cl); las API keys hoy operan en modo
> lectura.

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

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

> **Beta privada**: las escrituras vía API key están en beta privada
> (solicitar acceso: hola@simplo.cl); las API keys hoy operan en modo
> lectura.

- 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-K",
    "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.

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

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

> **Beta privada**: las escrituras vía API key están en beta privada
> (solicitar acceso: hola@simplo.cl); las API keys hoy operan en modo
> lectura.

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

> **Beta privada**: las escrituras vía API key están en beta privada
> (solicitar acceso: hola@simplo.cl); las API keys hoy operan en modo
> lectura.

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

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

> **Beta privada**: las escrituras vía API key están en beta privada
> (solicitar acceso: hola@simplo.cl); las API keys hoy operan en modo
> lectura.

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

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

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

> **Beta privada**: las escrituras vía API key están en beta privada
> (solicitar acceso: hola@simplo.cl); las API keys hoy operan en modo
> lectura.

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

> **Beta privada**: las escrituras vía API key están en beta privada
> (solicitar acceso: hola@simplo.cl); las API keys hoy operan en modo
> lectura.

- 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`
