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

# Crear facturas y seguir el DTE

> Flujo de facturación comercial, emisión directa al SII, estados y recuperación segura en Raúl

## Qué recurso usar

Raúl separa la **factura comercial** del **documento tributario electrónico (DTE)**. La factura conserva el cobro, las líneas, el cliente y sus eventos. El DTE conserva el folio, el XML, el TrackID y el veredicto del SII. Ambos estados se consultan por separado.

Consulta el [mapa de endpoints de facturas](/invoices-endpoints) para elegir el identificador y la ruta correctos, incluidos los alias de compatibilidad.

| Necesidad | Ruta de entrada | Resultado |
| - | - | - |
| Crear y cobrar una factura comercial | `POST /api/v1/billing/invoices` | Factura en `DRAFT`; después se publica con `POST /{id}/publish` |
| Emitir un documento tributario desde una fuente existente, sin cambiar la factura comercial | `POST /api/v1/dte/documents` | DTE asociado a `invoice_id` o `factura_id` |
| Emitir una guía de despacho independiente | `POST /api/v1/dte/documents` | DTE tipo `GUIA_DESPACHO_52` con `client_id`, `lines` y `dispatch_guide` |

La emisión sigue **directo al SII**. Raúl no envía documentos por Wasabil. En estas rutas de backoffice se requiere una [sesión Better Auth](/authentication) con token Bearer, rol `admin` y acceso al módulo Finanzas.

## 1. Crear un borrador comercial

`POST /api/v1/billing/invoices` recibe los datos comerciales y devuelve `201` con la factura en `DRAFT`. `type`, `receiver_name`, `issue_date` y `due_date` son obligatorios. Puedes completar `line_items` antes de publicar; para publicar se exige al menos una línea y un total mayor que cero.

```bash theme={null}
curl -X POST "https://api.raul.ugps.io/api/v1/billing/invoices" \
  -H "Authorization: Bearer TU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "MANUAL",
    "dte_type": "FACTURA",
    "client_id": "11111111-1111-4111-8111-111111111111",
    "receiver_name": "Cliente Ejemplo SpA",
    "receiver_rut": "76123456-0",
    "issue_date": "2026-09-23",
    "due_date": "2026-10-23",
    "line_items": [
      {
        "description": "Servicio mensual",
        "quantity": 2,
        "unit_price": 10000,
        "discount_pct": 25
      }
    ]
  }'
```

El UUID es ilustrativo: usa un `client_id` real de tu organización. `unit_price` está expresado en pesos chilenos enteros; `discount_pct` es el porcentaje de descuento de la línea. La respuesta incluye `id`, `status`, montos y líneas. Guarda el `id` para consultar el borrador. Si el cliente exige OC o HES, agrega la referencia antes de publicar.

<Note>
  La API comercial no acepta una `idempotency_key` del cliente como la API de Wasabil. Un segundo `POST` de creación puede crear otra factura. Si pierdes la respuesta, busca primero la factura en `GET /api/v1/billing/invoices` antes de crear otra.
</Note>

## 2. Publicar y emitir

Cuando el borrador esté completo, llama a `POST /api/v1/billing/invoices/{id}/publish`. Raúl valida receptor, líneas, total y referencias OC/HES requeridas; guarda `PUBLISHED` e **intenta emitir el DTE automáticamente**. No llames a `emit-dte` después de cada `publish` exitoso.

```bash theme={null}
curl -X POST "https://api.raul.ugps.io/api/v1/billing/invoices/ID_DE_FACTURA/publish" \
  -H "Authorization: Bearer TU_TOKEN"
```

Una respuesta `200` puede contener `PUBLISHED` si falló la emisión automática. La respuesta no significa que el SII aceptó el documento. Consulta `GET /api/v1/billing/invoices/{id}` y revisa `status`, `dte_document_id` y `dte_documents[].local_status`. Si necesitas el detalle tributario, usa `GET /api/v1/dte/documents/{dteId}`: allí `localStatus`, `folio` y `siiTrackId` aparecen en **camelCase**. En la factura comercial los campos usan **snake\_case**.

## 3. Interpretar los estados

| Estado | Recurso | Significado | Acción |
| - | - | - | - |
| `DRAFT` | Factura | Borrador editable | Completar datos y publicar |
| `PUBLISHED` | Factura | Publicación guardada; la emisión automática puede haber fallado | Revisar los DTE asociados antes de reintentar |
| `DTE_SENT` | Factura | Emisión enviada con TrackID | Esperar el veredicto del SII |
| `SII_ACCEPTED` / `SII_REJECTED` | Factura | Veredicto ya reflejado en el ciclo comercial | Continuar o corregir según el resultado |
| `LOCAL_VALIDATED` | DTE | Validado localmente; no hay confirmación de envío | Consultar el error antes de retomar |
| `SII_UPLOAD_UNCERTAIN` | DTE | Se inició el upload, pero Raúl no pudo confirmar si el SII lo recibió | Conciliar el folio con el SII; no reemitir ni liberar el folio |
| `SII_PENDING` | DTE | Existe TrackID y falta el veredicto | Sincronizar el estado del DTE |
| `SII_ACCEPTED` / `SII_REJECTED` | DTE | Veredicto del SII | Conservar la trazabilidad; corregir mediante el flujo tributario correspondiente |

Puedes encontrar documentos inciertos con `GET /api/v1/dte/documents?status=SII_UPLOAD_UNCERTAIN` o filtrar `POST /api/v1/dte/documents/query` con `{"status":"SII_UPLOAD_UNCERTAIN"}`. El listado responde en camelCase. El estado incierto exige revisión operativa: todavía no existe una operación pública que concilie automáticamente un upload sin TrackID.

El resumen `GET /api/v1/dte/documents/by-invoice/{invoiceId}/status` devuelve `sii.status: "uncertain"`, `sii.errorCode: "upload_uncertain"`, `sii.folio` y el ID del DTE. También puedes buscar los registros locales por tipo y folio con `GET /api/v1/dte/documents/by-folio/{tipo}/{folio}`; la existencia local por sí sola no confirma recepción por el SII.

Para un DTE `SII_PENDING` con TrackID, usa `POST /api/v1/dte/documents/{dteId}/sync` y vuelve a consultar el documento. El seguimiento puede requerir más de una consulta; **TrackID no equivale a aceptación**.

## Errores y reintentos

| Caso | Qué hacer |
| - | - |
| `400` por datos o referencias incompletas | Corrige el borrador y vuelve a publicar |
| `401` / `403` | Revisa sesión, rol y acceso a Finanzas |
| `409` por un DTE existente o envío sin resolver | Consulta la factura y sus DTE; conserva el folio |
| Timeout o `5xx` en `publish` | Consulta la factura antes de repetir; puede haberse guardado la publicación o iniciado el upload |
| `PUBLISHED` sin DTE enviado | Revisa el error y, si comprobaste que no hay upload incierto, retoma con `POST /api/v1/billing/invoices/{id}/emit-dte` |
| `SII_UPLOAD_UNCERTAIN` | Concilia con el SII usando RUT emisor, tipo, folio y fecha; escala si no hay evidencia concluyente |

La ruta `emit-dte` se conserva para recuperación y está marcada como deprecada en la referencia API; propaga el error de emisión. El reintento interno utiliza una clave estable asociada a la factura y el tipo de DTE, pero **la creación de facturas no ofrece idempotencia HTTP controlada por el consumidor**. Nunca asumas que repetir un `POST` sin consultar el estado es seguro.

## Alcance del contrato actual

La factura comercial permite `FACTURA` o `BOLETA` en `dte_type`. El DTE directo soporta `FACTURA_33`, `BOLETA_39` y `GUIA_DESPACHO_52`. Los precios de las líneas de factura se reciben en CLP enteros; `unit_price_uf` existe como dato opcional de línea. Esta API no expone en estas rutas los campos `payment_method`, `currency`, `issue` ni una `idempotency_key` enviados por el cliente como en Wasabil. El envío de correo, el pago y el PDF tienen sus propias rutas y estados.

Consulta la [referencia OpenAPI](https://api.raul.ugps.io/api/openapi.json) para los campos y respuestas completos y [Errores y reintentos](/error-handling) para las demás operaciones con efectos externos.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.