---
title: "Emisión de DTE"
description: "Aprende desde cero a emitir facturas, boletas, notas de crédito, guías de despacho y otros documentos tributarios electrónicos desde tu software con API Gateway V2."
type: "academy"
category: "course"
tags: [api-gateway-v2]
authors: [Anonymous]
date: "2026-11-05"
last_update: "2026-11-05"
time_minutes: 136
draft: false
unlisted: false
image: "https://www.apigateway.cl/img/content/academy/integracion-para-la-emision-de-dte/integracion.jpg"
url: "https://www.apigateway.cl/academy/emision-de-dte"
---

# Emisión de DTE




---

## Fundamentos de la facturación electrónica



---

### ¿Qué es la facturación electrónica?

Qué es un documento tributario electrónico, por qué existe y qué rol cumplen tu sistema, el SII y API Gateway.

# ¿Qué es la facturación electrónica?

Este curso parte de cero: no necesitas saber nada de facturación ni de impuestos. Al terminarlo vas a entender qué es un documento tributario, qué pide el SII y cómo emitirlo desde tu software con **API Gateway V2**.

## Un documento tributario, en palabras simples

Cada vez que una empresa vende algo en Chile tiene que dejar constancia de esa venta ante el **Servicio de Impuestos Internos (SII)**, que es la institución que cobra los impuestos. Esa constancia es un **documento tributario**: una factura, una boleta, una nota de crédito, una guía de despacho, etc.

Antes esos documentos se imprimían en talonarios de papel timbrados por el SII. Hoy son electrónicos, y por eso se llaman **Documentos Tributarios Electrónicos**, o **DTE**.

Un DTE tiene la misma validez legal que el documento en papel. La diferencia es que:

- No es un PDF: es un archivo **XML** con un formato definido por el SII.
- Va **firmado electrónicamente** por la empresa que lo emite, para probar quién lo hizo.
- Lleva un **timbre electrónico** que prueba que el SII autorizó su número (folio).
- Se **envía al SII** apenas se emite, para que el SII sepa de esa venta.

El PDF que ve el cliente es solo una **representación impresa** del XML. Lo que tiene validez tributaria es el XML.

&gt; [!INFO] ¿Por qué importa el IVA?
&gt;
&gt; La mayoría de las ventas en Chile pagan **IVA** (Impuesto al Valor Agregado), que es el 19% del precio neto. El documento tributario es la forma en que el SII sabe cuánto IVA cobró cada empresa y cuánto IVA pagó en sus compras. Por eso es tan importante que los montos del documento sean exactos.

## ¿Quién participa?

| Actor | Qué hace |
|-------|----------|
| **Emisor** | La empresa que vende y emite el documento. En tu integración es tu cliente (o tu propia empresa). |
| **Receptor** | Quien compra y recibe el documento: otra empresa o una persona. |
| **SII** | Autoriza los folios, recibe cada documento y valida que esté correcto. |
| **Tu software** | Junta los datos de la venta (quién compra, qué compra, cuánto cuesta) y llama a la API. |
| **API Gateway** | Arma el XML en el formato del SII, lo timbra, lo firma, lo envía al SII y genera el PDF. |

## ¿Qué resuelve API Gateway V2?

Armar un DTE &quot;a mano&quot; es difícil: el formato del SII tiene cientos de campos y reglas, el XML debe firmarse con criptografía y el envío al SII usa servicios web propios del SII. API Gateway V2 incluye la **biblioteca de LibreDTE** (el mismo núcleo de LibreDTE Edición Enterprise) y la expone como una API REST:

- Tú envías los datos del documento en **JSON**.
- La API calcula los totales e impuestos, timbra el documento con tu CAF y lo firma con tu certificado digital.
- La API envía el documento al SII, consulta el resultado y genera el PDF.

Tu sistema sigue siendo el dueño de los datos: decide qué emitir, guarda los XML y lleva el control de los folios.

## Lo que vas a aprender

1. **Fundamentos**: los conceptos, los tipos de documentos, los requisitos y el proceso completo.
2. **Preparación**: cómo funciona la API, tu primera llamada, el certificado digital y los folios (CAF).
3. **Emisión paso a paso**: desde los datos del documento hasta su PDF.
4. **Casos prácticos**: una factura de principio a fin, notas de crédito, guías de despacho, facturas exentas y boletas.
5. **Paso a producción**: errores frecuentes, buenas prácticas y la lista de verificación final.

&gt; [!TIP] Antes de seguir
&gt;
&gt; Si todavía no tienes una conexión ni un token, revisa primero el curso [Primeros pasos](https://www.apigateway.cl/academy/primeros-pasos). Ahí se explica cómo crear la conexión, el token y cómo leer la documentación de la API.


    
---

### Conceptos clave

Glosario de los términos de facturación electrónica que se usan en todo el curso: RUT, folio, CAF, timbre, firma, sobre, Track ID y más.

# Conceptos clave

Estos son los términos que vas a encontrar en todo el curso y en la documentación del SII. Vuelve a esta página cada vez que una palabra no te suene.

## Identificación

| Término | Qué es | Ejemplo |
|---------|--------|---------|
| **RUT** | Rol Único Tributario: el número que identifica a una persona o empresa ante el SII. Termina en un **dígito verificador** (DV), que puede ser un número o la letra `K`. | `88888888-8` |
| **Razón social** | Nombre legal de la empresa. | `Mi Empresa SpA` |
| **Giro** | Descripción de la actividad del negocio. | `Venta de software` |
| **Actividad económica (Acteco)** | Código numérico del SII para la actividad del emisor. Lo encuentras en la situación tributaria de la empresa en el SII, o con `GET /api/v2/sii/contribuyentes/situacion_tributaria/tercero/{rut}`, en `actividades[].codigo`. | `620100` |

&gt; [!WARNING] Formato del RUT
&gt;
&gt; En la API el RUT siempre va **sin puntos y con guion**: `88888888-8`. El dígito verificador se valida: un RUT con el DV incorrecto se rechaza con un error `422`.

## El documento

| Término | Qué es |
|---------|--------|
| **DTE** | Documento Tributario Electrónico: la factura, boleta, nota, guía, etc., en formato XML. Las boletas también son DTE; cuando un paso de la emisión es distinto para ellas, el curso separa &quot;facturas, notas y guías&quot; de &quot;boletas&quot;. |
| **Tipo de documento** | Código numérico del SII que indica qué documento es: `33` factura, `61` nota de crédito, `52` guía de despacho, etc. Lo verás en el campo `TipoDTE`. |
| **Folio** | El número correlativo del documento (la factura N° 1, N° 2, ...). No lo inventas: el SII te autoriza rangos de folios. |
| **Neto, IVA y total** | El **neto** es el precio sin IVA. El **IVA** es el 19% del neto. El **total** es neto + IVA (más otros impuestos si aplican). |
| **Afecto / exento** | Una venta **afecta** paga IVA. Una venta **exenta** no lo paga (por ejemplo, algunos servicios de educación o salud). |
| **Referencia** | Vínculo de un documento con otro. Por ejemplo, una nota de crédito debe indicar a qué factura corrige. |

## La autorización del SII

| Término | Qué es |
|---------|--------|
| **Emisor autorizado** | Empresa que el SII habilitó para emitir DTE con un software propio o de mercado (como API Gateway). |
| **Resolución** | Número y fecha de la resolución del SII que autoriza al emisor. Va dentro de cada envío. Ver [Resolución de autorización](https://www.apigateway.cl/academy/emision-de-dte/fundamentos/resolucion-de-autorizacion). |
| **CAF** | Código de Autorización de Folios: archivo XML que entrega el SII con un rango de folios autorizados para un tipo de documento. Sin CAF no hay folios y sin folios no se puede emitir. |
| **Timbre electrónico (TED)** | Bloque de datos dentro del XML, firmado con la llave del CAF. Prueba que el folio fue autorizado por el SII. En el PDF se dibuja como un código de barras. |

## La firma y el envío

| Término | Qué es |
|---------|--------|
| **Certificado digital (firma electrónica)** | Archivo (normalmente `.p12` o `.pfx`) con el que una **persona** firma documentos. Lo emite una entidad certificadora autorizada. |
| **Firma del documento** | Firma criptográfica del XML hecha con el certificado digital. Prueba quién emitió el documento y que no se modificó. |
| **Sobre** | XML que &quot;envuelve&quot; uno o más DTE para enviarlos al SII: un `EnvioBOLETA` para las boletas y un `EnvioDTE` para los demás documentos. Tiene una **carátula** con quién envía, a quién y con qué resolución. |
| **Track ID** | Número que entrega el SII al recibir un sobre. Con él consultas después si el SII aceptó o rechazó los documentos. |
| **Reparos** | Observaciones del SII sobre un documento que igual acepta. Un documento **aceptado con reparos** es válido; los reparos se corrigen en los documentos siguientes. |
| **Correo de intercambio** | Correo electrónico que cada empresa registra en el SII para recibir el XML de los documentos que otras empresas le emiten. |

## Los ambientes del SII

El SII tiene dos ambientes completamente separados:

| Ambiente | Para qué sirve | Validez tributaria |
|----------|----------------|--------------------|
| **Certificación** (pruebas) | Probar tu integración sin consecuencias. Tiene sus propios CAF y su propia resolución. | Ninguna |
| **Producción** | Emitir documentos reales. | Total |

Un CAF de certificación **no sirve** en producción, ni al revés. En la API eliges el ambiente en cada llamada que habla con el SII.

&gt; [!WARNING] El ambiente por defecto es producción
&gt;
&gt; Si no indicas el ambiente, las operaciones que hablan con el SII usan **producción**. Mientras desarrollas, indica siempre el ambiente de certificación. En cada paso del curso te mostramos cómo.

## Un mapa rápido

![Mapa rápido: los datos de la venta, el CAF y el certificado digital forman el DTE, que va al SII dentro de un sobre y se puede imprimir como PDF](https://www.apigateway.cl/img/content/academy/emision-de-dte/mapa-rapido.svg)

En las siguientes lecciones vemos cada pieza de este mapa con calma.


    
---

### Tipos de documentos

Qué documento emitir en cada situación: facturas, boletas, notas de crédito y débito, guías de despacho, facturas de compra y documentos de exportación.

# Tipos de documentos

No todas las ventas se documentan igual. El SII define un **tipo de documento** para cada situación, y cada uno tiene un código numérico que vas a usar en el campo `TipoDTE`.

Para elegir el documento correcto hazte dos preguntas:

1. **¿A quién le vendo?** A otra empresa (que quiere recuperar el IVA) o a un consumidor final.
2. **¿La venta paga IVA?** Afecta (sí paga) o exenta (no paga).

## Documentos de venta

| Código | Documento | Cuándo se usa | Precio en el detalle |
|--------|-----------|---------------|----------------------|
| **33** | Factura electrónica | Venta afecta a otra empresa. | **Neto** (sin IVA) |
| **34** | Factura exenta electrónica | Venta exenta a otra empresa. | Sin IVA |
| **39** | Boleta electrónica | Venta afecta a un consumidor final. | **Bruto** (IVA incluido) |
| **41** | Boleta exenta electrónica | Venta exenta a un consumidor final. | Sin IVA |

**Ejemplo**: una tienda de computadores que vende un notebook a una empresa emite una **factura (33)**; si se lo vende a una persona, emite una **boleta (39)**.

&gt; [!WARNING] Neto en facturas, bruto en boletas
&gt;
&gt; En una factura afecta, el precio unitario de cada producto es el **neto** y la API le suma el 19% de IVA. En una boleta afecta, el precio unitario es el precio **final, con IVA incluido**. Confundir esto es el error más común: un producto de $10.000 con IVA incluido se informa como $10.000 en la boleta, pero como $8.403 en la factura.

## Notas de crédito y débito

Un DTE emitido **no se puede modificar ni borrar**. Si tiene un error, o si después de la venta cambia algo, se emite una nota que lo corrige:

| Código | Documento | Efecto | Ejemplos |
|--------|-----------|--------|----------|
| **61** | Nota de crédito electrónica | **Disminuye** o anula lo cobrado | Anular una factura, devolución de productos, descuento posterior, corregir un dato del receptor |
| **56** | Nota de débito electrónica | **Aumenta** lo cobrado | Cobrar intereses, una diferencia de precio, o anular una nota de crédito |

Toda nota debe llevar una **referencia** al documento que corrige (tipo, folio y fecha) y un **código de referencia**:

| `CodRef` | Significado |
|----------|-------------|
| `1` | Anula el documento de referencia |
| `2` | Corrige un texto del documento de referencia (por ejemplo, la dirección del receptor) |
| `3` | Corrige montos del documento de referencia |

Lo practicamos en el caso [Nota de crédito](https://www.apigateway.cl/academy/emision-de-dte/casos-practicos/nota-de-credito).

## Traslado y compras

| Código | Documento | Cuándo se usa |
|--------|-----------|---------------|
| **52** | Guía de despacho electrónica | Acompaña el **traslado de mercadería**: ventas que se facturan después, traslados entre bodegas, devoluciones, etc. |
| **46** | Factura de compra electrónica | La emite el **comprador** cuando el vendedor no puede emitir factura (por ejemplo, algunos pequeños productores). El comprador retiene el IVA. |

La guía de despacho siempre indica el **motivo del traslado** en el campo `IndTraslado`:

| `IndTraslado` | Motivo |
|---------------|--------|
| `1` | Operación constituye venta |
| `2` | Ventas por efectuar |
| `3` | Consignaciones |
| `4` | Entrega gratuita |
| `5` | Traslados internos |
| `6` | Otros traslados no venta |
| `7` | Guía de devolución |
| `8` | Traslado para exportación (no venta) |
| `9` | Venta para exportación |

Lo practicamos en el caso [Guía de despacho](https://www.apigateway.cl/academy/emision-de-dte/casos-practicos/guia-de-despacho).

## Exportación

| Código | Documento |
|--------|-----------|
| **110** | Factura de exportación electrónica |
| **111** | Nota de débito de exportación electrónica |
| **112** | Nota de crédito de exportación electrónica |

Las exportaciones no pagan IVA, se expresan normalmente en moneda extranjera y requieren datos aduaneros adicionales. Son un caso avanzado: empieza por los documentos nacionales.

## ¿Qué puedes emitir con API Gateway V2?

Todos los documentos de esta página. Para cada uno, la API construye el XML, lo timbra, lo firma, lo valida, arma el sobre y genera el PDF:

- Facturas: afecta (`33`) y exenta (`34`).
- Boletas: afecta (`39`) y exenta (`41`).
- Factura de compra (`46`).
- Guía de despacho (`52`).
- Notas de crédito (`61`) y de débito (`56`).
- Documentos de exportación (`110`, `111` y `112`).

&gt; [!NOTE] Las boletas usan su propio sobre
&gt;
&gt; Las boletas van en un sobre distinto y el SII las recibe por un servicio distinto al de las facturas. Revisa el caso [Boleta de principio a fin](https://www.apigateway.cl/academy/emision-de-dte/casos-practicos/boletas) para ver sus diferencias.

&gt; [!TIP] Ejemplos listos para usar
&gt;
&gt; La API incluye más de 50 ejemplos de documentos (facturas con descuentos, guías con distintos motivos de traslado, notas que anulan o corrigen, etc.). En [Tu primera llamada](https://www.apigateway.cl/academy/emision-de-dte/preparacion/tu-primera-llamada) aprendes a listarlos y obtenerlos.


    
---

### Requisitos para emitir

Lo que necesita la empresa emisora y lo que necesita tu integración antes de emitir el primer documento.

# Requisitos para emitir

Antes de emitir hay requisitos de **la empresa que emite** (ante el SII) y requisitos de **tu integración** (ante API Gateway). Revisa ambos: la mayoría de los problemas de una integración nueva vienen de un requisito que falta.

## Requisitos de la empresa emisora

| Requisito | Qué es | Cómo se obtiene |
|-----------|--------|-----------------|
| **Inicio de actividades** | La empresa está registrada en el SII con una actividad económica. | Trámite en el SII. Normalmente ya existe. |
| **Autorización para emitir con software propio o de mercado** | El SII habilitó a la empresa para emitir DTE fuera del sistema gratuito del SII. Se obtiene con el **proceso de certificación de DTE**. | Lo gestiona el proveedor del software. Puedes solicitarlo en [certificación de DTE de LibreDTE](https://www.libredte.cl/certificacion-dte). |
| **Certificado digital** | Firma electrónica de una **persona** autorizada ante el SII para firmar los documentos de la empresa. | Se compra a una entidad certificadora autorizada. Se descarga como `.p12` o `.pfx` con una contraseña. |
| **CAF** | Rango de folios autorizados por el SII para cada tipo de documento. | Se solicitan al SII, en su sitio web o con la API (ver [Folios y CAF](https://www.apigateway.cl/academy/emision-de-dte/preparacion/folios-y-caf)). |
| **Resolución** | Número y fecha de la autorización del emisor. | La entrega el SII al terminar la certificación. Lo vemos en [Resolución de autorización](https://www.apigateway.cl/academy/emision-de-dte/fundamentos/resolucion-de-autorizacion). |

&gt; [!INFO] ¿Cómo sé si una empresa ya está autorizada?
&gt;
&gt; En el [listado de empresas autorizadas del SII](https://palena.sii.cl/cvc/dte/ee_empresas_dte.html) puedes buscar por RUT. También puedes consultarlo con la API en el recurso `GET /api/v2/sii/dte/contribuyentes/autorizado/{rut}` (revisa la [documentación de la API](https://www.apigateway.cl/docs/api)).

### El proceso de certificación del SII

Es un trámite que demuestra ante el SII que el software emite documentos correctos. Se hace **una sola vez por empresa**, en el ambiente de certificación del SII, e incluye:

1. Postular la empresa a la certificación en el sitio del SII.
2. Emitir los documentos de un **set de pruebas** que entrega el SII.
3. Generar los libros y muestras impresas solicitados.
4. Declarar el cumplimiento de requisitos.

Al terminar, el SII autoriza a la empresa a emitir en producción. Mientras tanto, puedes desarrollar y probar tu integración en el ambiente de certificación.

&gt; [!TIP] No partas el desarrollo esperando la certificación
&gt;
&gt; Puedes aprender y probar la construcción de documentos, el timbre, la firma y el PDF **sin CAF reales**, usando un CAF de prueba que genera la propia API. Lo explicamos en [Folios y CAF](https://www.apigateway.cl/academy/emision-de-dte/preparacion/folios-y-caf).

## Requisitos de tu integración

| Requisito | Detalle |
|-----------|---------|
| **Conexión y token de API Gateway** | Toda llamada lleva la cabecera `Authorization: Token &lt;token&gt;`. Revisa [Tu primera petición](https://www.apigateway.cl/academy/primeros-pasos/punto-de-partida/primera-peticion). |
| **Créditos** | Cada operación consume créditos. El costo de cada una aparece en la [documentación de la API](https://www.apigateway.cl/docs/api) y en [Precios](https://www.apigateway.cl/pricing). |
| **Productos activos** | La conexión debe tener activos los productos que incluyen las operaciones que usarás. Revísalo en [Gestionar conexión](https://app.apigateway.cl/connections/manage). |
| **Un lugar seguro para el certificado** | El certificado y su llave privada se envían en cada operación que firma. Guárdalos como secretos de tu servidor, nunca en el código. |
| **Una base de datos** | Para guardar los folios disponibles, cada XML emitido, su Track ID y su estado. API Gateway **no almacena** tus documentos. |

&gt; [!WARNING] API Gateway no guarda tus documentos
&gt;
&gt; API Gateway es una pasarela: genera y envía, pero no almacena los XML. Es tu sistema el que debe guardarlos. La ley exige conservar los documentos tributarios por al menos **6 años**.

## Lista de verificación

Antes de seguir, confirma que tienes:

1. Una conexión en API Gateway, con su token y créditos.
2. El certificado digital (`.p12` o `.pfx`) y su contraseña.
3. El RUT, la razón social, el giro, la actividad económica y la dirección del emisor.
4. Si vas a enviar al SII: la empresa en proceso de certificación (o ya autorizada), su resolución y un CAF del ambiente que usarás.


    
---

### Resolución de autorización

Qué es la resolución que autoriza a una empresa a emitir DTE, cómo saber si la tiene, cómo interpretarla y dónde se usa en la API.

# Resolución de autorización

Para emitir DTE con un software como API Gateway, la empresa necesita una **resolución de autorización** del SII. Es el acto formal con que el SII la habilita para emitir documentos electrónicos con un **software de mercado**, es decir, fuera del sistema gratuito del SII.

Sin esta resolución, los documentos que envíes en producción no tendrán validez.

## Qué datos tiene

La resolución tiene dos datos que vas a usar en tu integración:

| Dato | Ejemplo | Para qué se usa |
|------|---------|-----------------|
| **Número de resolución** | `80` | Va en la carátula de cada sobre que envías (`NroResol`). |
| **Fecha de resolución** | `2026-01-15` | Va en la carátula junto al número (`FchResol`). |

Además, el SII registra **qué tipos de documento** tiene autorizados la empresa y desde qué fecha. Una empresa puede estar autorizada para facturas y no para guías de despacho, por ejemplo.

## ¿Cómo sé si una empresa tiene la resolución?

### En el sitio del SII

En el [listado de empresas autorizadas del SII](https://palena.sii.cl/cvc/dte/ee_empresas_dte.html) puedes buscar la empresa por su RUT. Si aparece, verás su número y fecha de resolución y la lista de documentos que tiene autorizados.

### Con la API

```bash
curl https://app.apigateway.cl/api/v2/sii/dte/contribuyentes/autorizado/88888888-8 \
  -H &quot;Authorization: Token $API_TOKEN&quot;
```

Respuesta (resumida):

```json
{
    &quot;data&quot;: {
        &quot;rut&quot;: &quot;88888888-8&quot;,
        &quot;razon_social&quot;: &quot;Mi Empresa SpA&quot;,
        &quot;autorizado&quot;: true,
        &quot;resolucion&quot;: {
            &quot;numero&quot;: 80,
            &quot;fecha&quot;: &quot;2026-01-15&quot;
        },
        &quot;software&quot;: &quot;mercado&quot;,
        &quot;documentos&quot;: [
            { &quot;codigo&quot;: 33, &quot;descripcion&quot;: &quot;FACTURA ELECTRONICA&quot;, &quot;autorizado&quot;: &quot;2026-01-15&quot;, &quot;desautorizado&quot;: null },
            { &quot;codigo&quot;: 61, &quot;descripcion&quot;: &quot;NOTA CREDITO ELECTRONICA&quot;, &quot;autorizado&quot;: &quot;2026-01-15&quot;, &quot;desautorizado&quot;: null }
        ]
    }
}
```

| Campo | Qué indica |
|-------|------------|
| `autorizado` | Si la empresa está autorizada a emitir DTE. |
| `resolucion` | El número y la fecha de la resolución. |
| `software` | Con qué sistema está autorizada: `mercado` (software de mercado) o `mipyme` (sistema gratuito del SII). |
| `documentos` | Cada tipo de documento autorizado, con su fecha de autorización y, si dejó de estarlo, su fecha de desautorización. |

Agrega `?certificacion=1` a la URL para consultar el ambiente de certificación.

## Cómo interpretar el resultado

| Situación | Qué significa | ¿Puede emitir con API Gateway? |
|-----------|---------------|--------------------------------|
| No aparece o `autorizado: false` | La empresa no emite documentos electrónicos. | Primero debe **certificarse**. |
| `software: mipyme` | Emite con el sistema gratuito del SII (Portal MIPYME). | Primero debe **certificarse** con un software de mercado. |
| `software: mercado` | Está autorizada para emitir con un software de mercado. | Sí, con los documentos que tenga autorizados. |

&gt; [!INFO] No hay un solo número de resolución
&gt;
&gt; Muchas empresas que emiten con software de mercado tienen la resolución número `80`, pero existen otros números según la fecha y el tipo de autorización. Usa siempre el número y la fecha que tiene registrados la empresa, nunca uno de ejemplo.

### El caso especial de las boletas

Las boletas electrónicas tienen una regla propia. En la lista de documentos autorizados, fíjate en el código **890**, &quot;Sistema SII de emisión de boletas electrónicas&quot;:

**Si el código 890 aparece sin fecha de desautorización**, la empresa emite boletas con el sistema del SII y **debe certificarse** para emitirlas con un software de mercado:

![Boleta que requiere certificación](https://www.apigateway.cl/img/content/academy/integracion-para-la-emision-de-dte/boleta-requiere-certificacion.png)

**Si el código 890 tiene fecha de desautorización**, la empresa dejó el sistema del SII y **no necesita certificarse** para las boletas:

![Boleta que no requiere certificación](https://www.apigateway.cl/img/content/academy/integracion-para-la-emision-de-dte/boleta-no-requiere-certificacion.png)

**Si el código 890 no aparece** y las boletas (`39` y `41`) están autorizadas, tampoco necesita certificarse para las boletas:

![Boleta sin código 890](https://www.apigateway.cl/img/content/academy/integracion-para-la-emision-de-dte/boleta-sin-codigo-890.png)

## La resolución en cada ambiente

El SII tiene dos ambientes (ver [Conceptos clave](https://www.apigateway.cl/academy/emision-de-dte/fundamentos/conceptos-clave)), y cada uno usa su propia resolución:

| Ambiente | Número de resolución | Fecha de resolución |
|----------|----------------------|---------------------|
| **Certificación** | Siempre `0` | La fecha de autorización que muestra el SII en el ambiente de certificación. |
| **Producción** | El número de la resolución real (por ejemplo `80`) | La fecha de esa resolución. |

&gt; [!WARNING] No mezcles las resoluciones
&gt;
&gt; Si envías a producción con la resolución de certificación (número `0`), o al revés, el SII rechaza el envío. Guarda las dos en la configuración de cada empresa y elige según el ambiente.

## Dónde se usa en la API

La resolución no va dentro del XML del DTE, así que debes indicarla en las dos operaciones que la necesitan, en `emisor.autorizacion_dte`:

| Operación | Para qué la usa |
|-----------|-----------------|
| [Armar el sobre](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-3-armar-el-sobre) (`dispatcher/create`) | La escribe en la carátula del sobre (`FchResol` y `NroResol`). Es obligatoria: sin ella no se puede crear el sobre. |
| [Generar el PDF](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-6-generar-el-pdf) (`renderer/render`) | La imprime al pie del timbre, como &quot;Resolución 80 del 2026&quot;. Si no la indicas, el PDF sale sin esa línea. |

En ambas operaciones va igual. En **certificación**, con número `0` y la fecha de autorización en ese ambiente:

```json
&quot;emisor&quot;: {
    &quot;rut&quot;: &quot;88888888-8&quot;,
    &quot;razon_social&quot;: &quot;Mi Empresa SpA&quot;,
    &quot;autorizacion_dte&quot;: {
        &quot;fecha_resolucion&quot;: &quot;2025-11-20&quot;,
        &quot;numero_resolucion&quot;: 0
    }
}
```

En **producción**, con la resolución real; en el ejemplo, la número `80` del `2026-01-15`:

```json
&quot;autorizacion_dte&quot;: {
    &quot;fecha_resolucion&quot;: &quot;2026-01-15&quot;,
    &quot;numero_resolucion&quot;: 80
}
```

## ¿Cómo obtener la autorización?

La autorización se obtiene con el **proceso de certificación** del SII (ver [Requisitos para emitir](https://www.apigateway.cl/academy/emision-de-dte/fundamentos/requisitos-para-emitir)). Si necesitas ayuda con el proceso, puedes solicitar el [servicio de certificación de LibreDTE](https://www.libredte.cl/certificacion-dte#cotizar), donde un equipo experto lo hace por ti.

&gt; [!TIP] Puedes avanzar mientras tanto
&gt;
&gt; La certificación toma tiempo, pero no bloquea tu desarrollo. Puedes construir, timbrar, firmar y generar el PDF con un CAF de prueba, y hacer los envíos en el ambiente de certificación.


    
---

### El proceso de emisión

Las seis etapas para emitir un DTE y el recurso de API Gateway V2 que se usa en cada una.

# El proceso de emisión

Emitir un DTE no es una sola llamada: es una secuencia de pasos, y cada paso usa el resultado del anterior. **Tu sistema dirige el proceso**: en cada paso llama a una operación de API Gateway, recibe el resultado y lo guarda antes de seguir con el siguiente. Este es el mapa completo que seguiremos en el módulo [Emisión paso a paso](https://www.apigateway.cl/academy/emision-de-dte/emision). Si prefieres ver todos los pasos juntos en código, revisa [Factura de principio a fin](https://www.apigateway.cl/academy/emision-de-dte/casos-practicos/factura-de-principio-a-fin) y [Boleta de principio a fin](https://www.apigateway.cl/academy/emision-de-dte/casos-practicos/boletas).

![El proceso de emisión en seis pasos: tu sistema ejecuta cada paso llamando a una operación de API Gateway y guarda lo que recibe; API Gateway se comunica con el SII](https://www.apigateway.cl/img/content/academy/emision-de-dte/proceso-de-emision.svg)

## Las etapas y sus recursos

Todas las URL parten en `https://app.apigateway.cl`. Todos los DTE siguen los mismos pasos, incluidas las boletas; solo cambian las operaciones del envío y de la consulta del estado, porque el SII recibe las boletas por un servicio propio.

| Paso | ¿Es obligatorio? | Qué ocurre | Recurso |
|------|------------------|------------|---------|
| **1. Construir** | Obligatorio | Tu sistema arma un JSON con el emisor, el receptor, los productos y el folio. La API completa los datos que faltan, calcula los totales, timbra con el CAF y firma con el certificado. Entrega el XML del DTE. | `POST /api/v2/libredte/billing/document/builder/build` |
| **2. Validar** | Opcional | Revisa que el XML cumpla el esquema del SII y que sus datos sean coherentes, antes de enviarlo. Recomendado mientras desarrollas. | `POST /api/v2/libredte/billing/document/validator/validateSchema` |
| **3. Sobre** | Obligatorio | Envuelve uno o más documentos en un sobre firmado, con la resolución del emisor: un `EnvioBOLETA` para las boletas o un `EnvioDTE` para los demás documentos. | `POST /api/v2/libredte/billing/document/dispatcher/create` |
| **4. Enviar** | Obligatorio | Sube el sobre al SII. El SII responde con un **Track ID**. | Facturas, notas y guías: `POST /api/v2/libredte/billing/integration/sii_dte/sendXmlDocument`&lt;br&gt;Boletas: `POST /api/v2/libredte/billing/integration/sii_boleta/sendXmlDocument` |
| **5. Estado** | Obligatorio | Con el Track ID, consulta si el SII aceptó o rechazó cada documento. | Facturas, notas y guías: `POST /api/v2/libredte/billing/integration/sii_dte/checkXmlDocumentSentStatus`&lt;br&gt;Boletas: `POST /api/v2/libredte/billing/integration/sii_boleta/checkXmlDocumentSentStatus` |
| **6. PDF** | Opcional | Genera la representación impresa (con el timbre como código de barras). Es el documento que normalmente se entrega al cliente. | `POST /api/v2/libredte/billing/document/renderer/render` |

Y para obtener los folios, antes de todo:

| Qué | Recurso |
|-----|---------|
| Solicitar folios (CAF) al SII | `POST /api/v2/sii/dte/caf/solicitar/{emisor}/{dte}/{cantidad}` |
| Revisar un CAF | `POST /api/v2/libredte/billing/identifier/caf_loader/load` |

## Lo que hace cada parte

| Responsabilidad | Quién la tiene |
|-----------------|----------------|
| Decidir qué documento emitir y con qué datos | Tu sistema |
| Asignar el folio y no repetirlo nunca | Tu sistema |
| Calcular IVA y totales | API Gateway |
| Timbrar y firmar | API Gateway |
| Enviar al SII y consultar el estado | API Gateway, cuando tu sistema lo llama |
| Guardar el XML, el Track ID y el estado | Tu sistema |
| Generar el PDF | API Gateway |
| Entregar el documento al receptor: el PDF y, si es una empresa que emite documentos electrónicos, el XML a su correo de intercambio | Tu sistema |
| Reintentar si algo falla | Tu sistema |

&gt; [!INFO] ¿Por qué tantos pasos y no uno solo?
&gt;
&gt; Porque en la práctica cada paso puede fallar por razones distintas, y tu sistema necesita saber en cuál quedó cada documento. Si el SII está caído, por ejemplo, el documento ya está construido y firmado: solo falta reintentar el envío. Si lo tuvieras todo en una sola llamada, no sabrías qué repetir.

## Los estados de un documento en tu sistema

Te recomendamos guardar un estado por documento, así sabes siempre qué falta:

![Estados de un documento: construido, enviado (con Track ID), y luego aceptado, aceptado con reparos o rechazado; si falla el envío queda en error de envío y se reintenta](https://www.apigateway.cl/img/content/academy/emision-de-dte/estados-del-documento.svg)

Un documento **rechazado** no tiene validez: el SII lo considera no emitido. Hay que corregir los datos y emitirlo de nuevo, con el mismo folio. Lo vemos en detalle en [Consultar el estado](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-5-consultar-el-estado).


    
---

## Preparación de la integración



---

### Cómo funciona la API de LibreDTE

La forma de las URL, del cuerpo y de las respuestas de los recursos /api/v2/libredte/, la regla del base64 y los errores.

# Cómo funciona la API de LibreDTE

La emisión de documentos en API Gateway V2 se hace con los recursos que empiezan con `/api/v2/libredte/`. Todos siguen las mismas reglas, así que si entiendes esta lección vas a poder usar cualquiera de ellos.

## La URL

Cada recurso es una **operación** de la biblioteca de LibreDTE, identificada por cuatro partes:

```
POST https://app.apigateway.cl/api/v2/libredte/{paquete}/{componente}/{worker}/{operación}
```

Por ejemplo, la operación que construye un documento es:

```
POST https://app.apigateway.cl/api/v2/libredte/billing/document/builder/build
                                               ──┬──── ───┬──── ───┬─── ──┬──
                                              paquete componente worker operación
```

| Parte | Significado | Valores que usarás en este curso |
|-------|-------------|----------------------------------|
| `paquete` | Área de la biblioteca | `billing` (facturación), `system` (certificado) |
| `componente` | Tema dentro del área | `document`, `identifier` (folios), `integration` (SII), ... |
| `worker` | Quién hace el trabajo | `builder`, `validator`, `dispatcher`, `renderer`, `sii_dte`, ... |
| `operación` | Qué se hace | `build`, `validateSchema`, `create`, `render`, ... |

La operación se escribe en camelCase, igual que el método de la biblioteca: `validateSchema`, `sendXmlDocument`. El paquete, el componente y el worker se escriben tal como los nombra la biblioteca, por ejemplo `sii_dte`.

Todas las operaciones usan el método **POST**.

## El cuerpo de la solicitud

El cuerpo siempre es un objeto JSON con un único atributo, `parameters`, que contiene los parámetros de la operación con el nombre que declara la documentación:

```json
{
    &quot;parameters&quot;: {
        &quot;nombre_del_parametro&quot;: &quot;valor&quot;
    }
}
```

Por ejemplo, la operación que construye un documento recibe un único parámetro llamado `bag` (la &quot;bolsa&quot; con los datos del documento):

```json
{
    &quot;parameters&quot;: {
        &quot;bag&quot;: {
            &quot;parsedData&quot;: { &quot;...&quot;: &quot;datos del documento&quot; },
            &quot;caf&quot;: &quot;...&quot;,
            &quot;certificate&quot;: { &quot;...&quot;: &quot;certificado digital&quot; }
        }
    }
}
```

## Las cabeceras

```http
Authorization: Token &lt;tu_token&gt;
Content-Type: application/json
```

El token es el de tu conexión de API Gateway. A diferencia de las consultas al SII de otros cursos, aquí **no** hay bloque `auth` con RUT y clave: lo que se necesita para hablar con el SII (el certificado digital) va dentro de los parámetros de cada operación.

## La regla del base64

Los datos que no son JSON viajan codificados en **base64**: los XML (del DTE, del sobre, del CAF), los archivos `.p12` y los PDF. Esto evita problemas de caracteres especiales, porque los XML del SII usan la codificación ISO-8859-1 y no UTF-8.

| Dato | Cómo se envía | Cómo vuelve |
|------|---------------|-------------|
| Datos del documento | JSON | JSON |
| XML de un DTE, de un sobre o de un CAF | base64 | base64 |
| Certificado `.p12`/`.pfx` | base64 (con su contraseña aparte) | (no vuelve) |
| Certificado en formato PEM | texto PEM, **sin** base64 | (no vuelve) |
| PDF | (no se envía) | base64 |

Ejemplos para codificar y decodificar en la terminal:

```bash
# Codificar un archivo en base64, en una sola línea
base64 -i caf.xml | tr -d &#039;\n&#039;

# Decodificar el base64 de una respuesta a un archivo
echo &quot;PD94bWwgdmVyc2lvbj0i...&quot; | base64 -d &gt; dte.xml
```

## La respuesta

Si la operación funciona, la respuesta es un JSON con el resultado dentro de `data`:

```json
{
    &quot;data&quot;: {
        &quot;...&quot;: &quot;resultado de la operación&quot;
    }
}
```

Algunas operaciones no entregan nada (por ejemplo, una validación que no encontró problemas). En ese caso la respuesta es `{&quot;data&quot;: null}` con código `200`.

## Los errores

Si algo falla, la respuesta trae el código HTTP y un mensaje en `detail`:

```json
{
    &quot;code&quot;: 422,
    &quot;detail&quot;: &quot;El folio 500 del documento 88888888-8_T033F000000500 no está disponible en el rango del CAF CAF33D1H100.&quot;
}
```

| Código | Qué significa | Qué hacer |
|--------|---------------|-----------|
| `400` | Falta un parámetro o no tiene el tipo esperado. | Revisa los nombres dentro de `parameters`. |
| `401` | Token inválido o ausente. | Revisa la cabecera `Authorization`. |
| `402` | Problema de créditos o de pago de la conexión. | Revisa tu conexión (ver [Manejo de errores](https://www.apigateway.cl/academy/primeros-pasos/punto-de-partida/manejo-de-errores)). |
| `404` | La operación no existe. | Revisa la URL: las cuatro partes deben coincidir con la documentación. |
| `422` | La operación se ejecutó, pero **los datos fueron rechazados**: un RUT inválido, un folio fuera del CAF, un XML mal formado, una firma inválida, etc. | Lee `detail`: explica exactamente qué dato corregir. |
| `500` | Error inesperado. | Reintenta y, si persiste, [abre un ticket](https://www.apigateway.cl/help) con la hora y la operación. |
| `503` | El servicio de LibreDTE no está disponible en ese momento. | Reintenta más tarde. |

&gt; [!TIP] El 422 es tu amigo
&gt;
&gt; Casi todos los errores de una integración nueva son `422`, y el mensaje de `detail` dice qué está mal. Muéstralo en tus logs completo: te ahorrará mucho tiempo.

## Dónde ver cada operación

La [documentación de la API](https://www.apigateway.cl/docs/api) tiene una ficha por operación, agrupadas como **API LibreDTE - billing.document**, **API LibreDTE - billing.identifier**, etc. Cada ficha indica:

- Los parámetros y un ejemplo del cuerpo.
- Qué entrega y por qué puede rechazar los datos.
- El costo en créditos.


    
---

### Tu primera llamada

Una primera llamada sin riesgo: listar y obtener los ejemplos de documentos que incluye la API.

# Tu primera llamada

Antes de construir documentos, haz una llamada sencilla que no necesita certificado ni folios: pedir los **ejemplos de documentos** que trae la biblioteca. Te sirve para confirmar que el token funciona y, además, te entrega documentos de ejemplo listos para adaptar.

## Listar los ejemplos

```bash
curl -X POST https://app.apigateway.cl/api/v2/libredte/billing/document/examples/list \
  -H &quot;Authorization: Token $API_TOKEN&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d &#039;{&quot;parameters&quot;: {}}&#039;
```

Esta operación no tiene parámetros, por eso `parameters` va vacío. La respuesta es la lista de ejemplos disponibles:

```json
{
    &quot;data&quot;: [
        {
            &quot;id&quot;: &quot;033_factura_afecta/033_001_simple&quot;,
            &quot;category&quot;: &quot;033_factura_afecta&quot;,
            &quot;case&quot;: &quot;033_001_simple&quot;
        },
        {
            &quot;id&quot;: &quot;052_guia_despacho/052_001_constituye_venta&quot;,
            &quot;category&quot;: &quot;052_guia_despacho&quot;,
            &quot;case&quot;: &quot;052_001_constituye_venta&quot;
        }
    ]
}
```

La categoría empieza con el código del tipo de documento: `033` factura, `052` guía de despacho, `061` nota de crédito, etc.

## Obtener un ejemplo

```bash
curl -X POST https://app.apigateway.cl/api/v2/libredte/billing/document/examples/get \
  -H &quot;Authorization: Token $API_TOKEN&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d &#039;{&quot;parameters&quot;: {&quot;id&quot;: &quot;033_factura_afecta/033_001_simple&quot;}}&#039;
```

Respuesta:

```json
{
    &quot;data&quot;: {
        &quot;id&quot;: &quot;033_factura_afecta/033_001_simple&quot;,
        &quot;example&quot;: {
            &quot;Encabezado&quot;: {
                &quot;IdDoc&quot;: {
                    &quot;TipoDTE&quot;: 33,
                    &quot;Folio&quot;: 1
                },
                &quot;Emisor&quot;: {
                    &quot;RUTEmisor&quot;: &quot;88888888-8&quot;,
                    &quot;RznSoc&quot;: &quot;Mi Empresa SpA&quot;,
                    &quot;GiroEmis&quot;: &quot;Venta de software&quot;,
                    &quot;Acteco&quot;: 620200,
                    &quot;DirOrigen&quot;: &quot;Av. Siempre Viva 742&quot;,
                    &quot;CmnaOrigen&quot;: &quot;Providencia&quot;
                },
                &quot;Receptor&quot;: {
                    &quot;RUTRecep&quot;: &quot;60803000-K&quot;,
                    &quot;RznSocRecep&quot;: &quot;Servicio de Impuestos Internos&quot;,
                    &quot;GiroRecep&quot;: &quot;Gobierno&quot;,
                    &quot;DirRecep&quot;: &quot;Santiago&quot;,
                    &quot;CmnaRecep&quot;: &quot;Santiago&quot;
                }
            },
            &quot;Detalle&quot;: [
                {
                    &quot;NmbItem&quot;: &quot;Conectores RJ45&quot;,
                    &quot;QtyItem&quot;: 450,
                    &quot;PrcItem&quot;: 70
                }
            ]
        },
        &quot;expected&quot;: {
            &quot;Encabezado&quot;: {
                &quot;Totales&quot;: {
                    &quot;MntNeto&quot;: 31500,
                    &quot;IVA&quot;: 5985,
                    &quot;MntTotal&quot;: 37485
                }
            }
        }
    }
}
```

&gt; [!NOTE] Datos de ejemplo
&gt;
&gt; Los ejemplos de la API traen los datos de un emisor de demostración. En este extracto los reemplazamos por datos ficticios. Cuando emitas, usa siempre los datos de tu empresa.

- `example` son los datos del documento, tal como los enviarás para construirlo.
- `expected` son los totales que debería calcular la API. Fíjate que el ejemplo **no trae totales**: la API los calcula (450 × $70 = $31.500 neto, más 19% de IVA = $5.985).

&gt; [!TIP] Usa los ejemplos como plantilla
&gt;
&gt; Cuando tengas que emitir un caso nuevo (una factura con descuento, una guía de devolución, una nota que corrige montos), busca primero si existe un ejemplo parecido. Es la forma más rápida de saber qué campos lleva.

## Qué revisar si falla

| Respuesta | Causa probable |
|-----------|----------------|
| `401` | El token está mal escrito o falta la palabra `Token` antes del token. |
| `402` | La conexión no tiene créditos o tiene un problema de pago. |
| `404` | Hay un error en la URL. |
| `200` con `data` | ¡Todo bien! Sigue con la siguiente lección. |

## En Python

La API es HTTP y JSON, así que funciona con cualquier lenguaje. En Python, con `requests`:

```python
import os
import requests

API_URL = &#039;https://app.apigateway.cl/api/v2/libredte&#039;
HEADERS = {
    &#039;Authorization&#039;: f&#039;Token {os.environ[&quot;API_TOKEN&quot;]}&#039;,
    &#039;Content-Type&#039;: &#039;application/json&#039;,
}

def libredte(operacion: str, parameters: dict) -&gt; dict | list | None:
    &quot;&quot;&quot;Ejecuta una operación de LibreDTE y entrega el contenido de `data`.&quot;&quot;&quot;
    response = requests.post(
        f&#039;{API_URL}/{operacion}&#039;,
        json={&#039;parameters&#039;: parameters},
        headers=HEADERS,
        timeout=120,
    )
    if response.status_code != 200:
        try:
            detalle = response.json().get(&#039;detail&#039;, response.text)
        except ValueError:  # La respuesta de error no viene en JSON.
            detalle = response.text
        raise RuntimeError(f&#039;{operacion}: HTTP {response.status_code}: {detalle}&#039;)
    return response.json()[&#039;data&#039;]

ejemplos = libredte(&#039;billing/document/examples/list&#039;, {})
print(len(ejemplos), &#039;ejemplos disponibles&#039;)
```

Usaremos esta función `libredte()` en el resto del curso.


    
---

### El certificado digital

Qué es el certificado digital, en qué formatos enviarlo a la API, cómo verificarlo y cómo protegerlo.

# El certificado digital

El **certificado digital** (o firma electrónica) es lo que permite firmar los documentos. Pertenece a una **persona**, no a la empresa: es la persona que el SII autorizó para firmar los documentos de la empresa emisora.

Se usa en tres momentos:

1. Para **firmar el DTE** al construirlo.
2. Para **firmar el sobre** que se envía al SII.
3. Para **autenticarse en el SII** al enviar y al consultar el estado.

&gt; [!INFO] El RUT de la firma no es el de la empresa
&gt;
&gt; El certificado tiene el RUT de la persona (por ejemplo `11222333-9`), no el de la empresa (`88888888-8`). En el sobre aparece como `RutEnvia`: quien envía el documento en nombre de la empresa. Esa persona debe estar autorizada en el SII para la empresa emisora.

## Formatos que acepta la API

En las operaciones de LibreDTE el certificado va en un objeto `certificate`, en **una** de estas dos formas. En todos los ejemplos del curso usamos PEM, porque es el mismo formato que usan los recursos de consulta al SII.

### Opción 1: certificado y llave privada en PEM (la que usamos en este curso)

```json
&quot;certificate&quot;: {
    &quot;certificate&quot;: &quot;-----BEGIN CERTIFICATE-----\nMIIEcTCCA1mgAwIBAgIBRTAN...\n-----END CERTIFICATE-----\n&quot;,
    &quot;privateKey&quot;: &quot;-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0B...\n-----END PRIVATE KEY-----\n&quot;
}
```

- `certificate`: el certificado público en formato PEM (texto, **sin** base64).
- `privateKey`: la llave privada en formato PEM (texto, **sin** base64).

Normalmente el certificado se entrega como archivo `.p12` o `.pfx`. Para obtener los PEM a partir de ese archivo, cárgalo con la operación `system/certificate/loader/load`: envía el archivo en base64 y su contraseña, como en la [opción 2](#opción-2-archivo-p12--pfx-en-base64):

```bash
curl -X POST https://app.apigateway.cl/api/v2/libredte/system/certificate/loader/load \
  -H &quot;Authorization: Token $API_TOKEN&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d &#039;{
    &quot;parameters&quot;: {
        &quot;certificate&quot;: {
            &quot;data&quot;: &quot;MIIKkQIBAzCCClcGCSqGSIb3DQEHAaCCCkgEggpEMIIKQDCCBPcGCSqG...&quot;,
            &quot;password&quot;: &quot;contraseña_del_archivo&quot;
        }
    }
}&#039;
```

La respuesta trae el certificado en `cert` y la llave privada en `pkey`, los dos en PEM:

```json
{
    &quot;data&quot;: {
        &quot;id&quot;: &quot;11222333-9&quot;,
        &quot;name&quot;: &quot;Daniel Bot&quot;,
        &quot;cert&quot;: &quot;-----BEGIN CERTIFICATE-----\nMIIEcTCCA1mgAwIBAgIBRTAN...\n-----END CERTIFICATE-----\n&quot;,
        &quot;pkey&quot;: &quot;-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0B...\n-----END PRIVATE KEY-----\n&quot;,
        &quot;...&quot;: &quot;...&quot;
    }
}
```

Guarda `cert` como `cert.pem` y `pkey` como `key.pem`. Haz esta conversión una sola vez y guarda los PEM como secretos: no la repitas en cada emisión.

&gt; [!TIP] Los saltos de línea
&gt;
&gt; En JSON, los saltos de línea de un PEM se escriben como `\n`. Si armas el JSON con un lenguaje de programación (leyendo el archivo y serializándolo), esto ocurre solo. Si lo pegas a mano, revisa que no quede todo en una línea sin `\n`.

### Opción 2: archivo `.p12` / `.pfx` en base64

```json
&quot;certificate&quot;: {
    &quot;data&quot;: &quot;MIIKkQIBAzCCClcGCSqGSIb3DQEHAaCCCkgEggpEMIIKQDCCBPcGCSqG...&quot;,
    &quot;password&quot;: &quot;contraseña_del_archivo&quot;
}
```

- `data`: el archivo `.p12` o `.pfx` completo, codificado en base64 en una sola línea.
- `password`: la contraseña del archivo.

```bash
base64 -i firma.p12 | tr -d &#039;\n&#039;
```

&gt; [!WARNING] No es el mismo formato que en las consultas al SII
&gt;
&gt; Los recursos de consulta al SII (por ejemplo, los de folios en `/api/v2/sii/dte/caf/...`) reciben el certificado en el bloque `auth.cert` con los campos `cert-data` y `pkey-data` (o `file-data` y `file-pass`). Los recursos de LibreDTE (`/api/v2/libredte/...`) lo reciben en `certificate` con `certificate` y `privateKey` (o `data` y `password`). Son el mismo certificado, con distinto nombre de campos.

| Recurso | Campo | PEM | `.p12` en base64 |
|---------|-------|-----|------------------|
| `/api/v2/libredte/...` | `certificate` | `certificate` + `privateKey` | `data` + `password` |
| `/api/v2/sii/...` | `auth.cert` | `cert-data` + `pkey-data` | `file-data` + `file-pass` |

## Verificar el certificado

Antes de usarlo para firmar, puedes comprobar que la API lo lee bien y cuándo vence:

```bash
curl -X POST https://app.apigateway.cl/api/v2/libredte/system/certificate/loader/load \
  -H &quot;Authorization: Token $API_TOKEN&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d &#039;{
    &quot;parameters&quot;: {
        &quot;certificate&quot;: {
            &quot;certificate&quot;: &quot;-----BEGIN CERTIFICATE-----\nMIIG...\n-----END CERTIFICATE-----&quot;,
            &quot;privateKey&quot;: &quot;-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----&quot;
        }
    }
}&#039;
```

La respuesta trae, entre otros datos:

```json
{
    &quot;data&quot;: {
        &quot;id&quot;: &quot;11222333-9&quot;,
        &quot;name&quot;: &quot;Daniel Bot&quot;,
        &quot;email&quot;: &quot;daniel.bot@example.com&quot;,
        &quot;from&quot;: &quot;2026-10-29T11:38:23&quot;,
        &quot;to&quot;: &quot;2027-10-29T11:38:23&quot;,
        &quot;expirationDays&quot;: 364,
        &quot;isActive&quot;: true,
        &quot;issuer&quot;: &quot;Derafu Test Certificate Authority&quot;
    }
}
```

| Campo | Qué revisar |
|-------|-------------|
| `id` | El RUT de la persona dueña del certificado. |
| `to` / `expirationDays` | Cuándo vence. Un certificado vencido no puede firmar. |
| `isActive` | Debe ser `true`. |

Si falta un dato, la API responde con un error como:

```json
{
    &quot;code&quot;: 422,
    &quot;detail&quot;: &quot;Se requieren los datos del certificado (data y password) o sus llaves (certificate y privateKey).&quot;
}
```

## Seguridad

El certificado permite firmar documentos tributarios **a nombre de la empresa**. Trátalo como una contraseña:

- Guárdalo cifrado o en un almacén de secretos (variables de entorno del servidor, un vault, el gestor de secretos de tu nube).
- Nunca lo subas a un repositorio ni lo envíes desde el navegador o una app móvil: las llamadas a la API deben salir de **tu servidor**.
- No guardes en tus logs las solicitudes ni las respuestas completas: incluyen el certificado.
- Controla su vencimiento y renuévalo antes de que expire.

## Un certificado de prueba

Mientras sigues el curso puedes construir documentos con un certificado de prueba: la API firmará el XML igual. Lo que no podrás hacer sin un certificado real autorizado es **enviar al SII**, porque el SII rechazará la autenticación.

La API genera uno con esta operación:

```bash
curl -X POST https://app.apigateway.cl/api/v2/libredte/billing/trading_parties/mandatario_manager/createFakeCertificate \
  -H &quot;Authorization: Token $API_TOKEN&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d &#039;{
    &quot;parameters&quot;: {
        &quot;mandatario&quot;: {
            &quot;run&quot;: &quot;11222333-9&quot;,
            &quot;nombre&quot;: &quot;Daniel Bot&quot;,
            &quot;email&quot;: &quot;daniel.bot@example.com&quot;
        }
    }
}&#039;
```

La respuesta (resumida) trae el certificado y su llave privada en PEM, válidos por un año:

```json
{
    &quot;data&quot;: {
        &quot;id&quot;: &quot;11222333-9&quot;,
        &quot;name&quot;: &quot;Daniel Bot&quot;,
        &quot;email&quot;: &quot;daniel.bot@example.com&quot;,
        &quot;from&quot;: &quot;2026-11-04T14:07:03&quot;,
        &quot;to&quot;: &quot;2027-11-04T14:07:03&quot;,
        &quot;issuer&quot;: &quot;Derafu Test Certificate Authority&quot;,
        &quot;cert&quot;: &quot;-----BEGIN CERTIFICATE-----\nMIIE...\n-----END CERTIFICATE-----\n&quot;,
        &quot;pkey&quot;: &quot;-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----\n&quot;,
        &quot;...&quot;: &quot;...&quot;
    }
}
```

Guarda `cert` como `cert.pem` y `pkey` como `key.pem`, y úsalos como cualquier certificado en PEM: `&quot;certificate&quot;: {&quot;certificate&quot;: &lt;cert&gt;, &quot;privateKey&quot;: &lt;pkey&gt;}`.


    
---

### Folios y CAF

Qué es un CAF, cómo solicitarlo al SII con la API o en el sitio del SII, cómo revisarlo, cómo controlar los folios en tu sistema y cómo practicar con un CAF de prueba.

# Folios y CAF

Cada documento tiene un **folio** (su número). No puedes usar cualquier número: el SII te autoriza **rangos de folios** por tipo de documento, y esa autorización llega en un archivo llamado **CAF** (Código de Autorización de Folios).

Por ejemplo, un CAF puede decir: &quot;la empresa `88888888-8` puede emitir facturas (`33`) con los folios del `1` al `100`&quot;.

## Qué contiene un CAF

Es un XML firmado por el SII:

```xml
&lt;AUTORIZACION&gt;
  &lt;CAF version=&quot;1.0&quot;&gt;
    &lt;DA&gt;
      &lt;RE&gt;88888888-8&lt;/RE&gt;          &lt;!-- RUT del emisor --&gt;
      &lt;RS&gt;Mi Empresa SpA&lt;/RS&gt;      &lt;!-- Razón social --&gt;
      &lt;TD&gt;33&lt;/TD&gt;                  &lt;!-- Tipo de documento --&gt;
      &lt;RNG&gt;&lt;D&gt;1&lt;/D&gt;&lt;H&gt;100&lt;/H&gt;&lt;/RNG&gt;&lt;!-- Rango: desde el 1 hasta el 100 --&gt;
      &lt;FA&gt;2026-10-29&lt;/FA&gt;          &lt;!-- Fecha de autorización --&gt;
      &lt;RSAPK&gt;...&lt;/RSAPK&gt;           &lt;!-- Llave pública --&gt;
      &lt;IDK&gt;100&lt;/IDK&gt;
    &lt;/DA&gt;
    &lt;FRMA algoritmo=&quot;SHA1withRSA&quot;&gt;...&lt;/FRMA&gt;   &lt;!-- Firma del SII --&gt;
  &lt;/CAF&gt;
  &lt;RSASK&gt;...&lt;/RSASK&gt;               &lt;!-- Llave privada para timbrar --&gt;
  &lt;RSAPUBK&gt;...&lt;/RSAPUBK&gt;
&lt;/AUTORIZACION&gt;
```

La llave privada del CAF (`RSASK`) es la que se usa para **timbrar** cada documento. Por eso el CAF también es un dato sensible: guárdalo con el mismo cuidado que el certificado.

&gt; [!INFO] Reglas de los folios
&gt;
&gt; - Un CAF sirve para **un solo tipo de documento** y **un solo emisor**.
&gt; - Un CAF de **certificación** no sirve en **producción**, y al revés.
&gt; - Cada folio se usa **una sola vez**. La excepción es un documento **rechazado** por el SII: se considera no emitido, y su folio se vuelve a usar al emitirlo corregido.
&gt; - Los CAF de facturas, notas de crédito y notas de débito **vencen a los 6 meses** de autorizados: revisa la fecha de vencimiento al cargarlo. Los de boletas, facturas exentas, guías de despacho y documentos de exportación no vencen.

## Obtener el CAF

Los CAF se solicitan al SII con el certificado digital de una persona autorizada por la empresa. Puedes hacerlo de dos formas, y ambas sirven para **cualquier** CAF, incluido el primero de cada tipo de documento:

| Forma | Cuándo conviene |
|-------|-----------------|
| **Con la API** | Para automatizar: tu sistema pide folios cuando se están acabando. |
| **En el sitio del SII** | Para una solicitud puntual, a mano: [ambiente de certificación](https://www.sii.cl/factura_electronica/factura_mercado/menu_certificacion.html) o [ambiente de producción](https://palena.sii.cl/dte/menu.html). |

### Solicitar un CAF con la API

```bash
curl -X POST &quot;https://app.apigateway.cl/api/v2/sii/dte/caf/solicitar/88888888-8/33/100?certificacion=1&quot; \
  -H &quot;Authorization: Token $API_TOKEN&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d &#039;{
    &quot;auth&quot;: {
        &quot;cert&quot;: {
            &quot;cert-data&quot;: &quot;-----BEGIN CERTIFICATE-----\nMIIG...\n-----END CERTIFICATE-----&quot;,
            &quot;pkey-data&quot;: &quot;-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----&quot;
        }
    }
}&#039;
```

| Parte | Significado |
|-------|-------------|
| `88888888-8` | RUT del emisor |
| `33` | Tipo de documento |
| `100` | Cantidad de folios |
| `certificacion=1` | Ambiente de certificación. Usa `0` (o no lo indiques) para producción. |

La respuesta **no es JSON**: es directamente el XML del CAF, en codificación ISO-8859-1. Guárdalo tal cual como archivo.

&gt; [!WARNING] El SII decide la cantidad
&gt;
&gt; El SII puede autorizar menos folios de los que pides, según el historial de emisión de la empresa. Revisa siempre el rango real del CAF que recibiste.

### Otros recursos de folios

Todos son `POST`, usan el bloque `auth.cert` y el parámetro `certificacion` igual que la solicitud, y sus URL parten en `/api/v2/sii/dte/caf/`:

| Para qué sirve | Recurso |
|----------------|---------|
| Volver a descargar un CAF ya autorizado, por ejemplo si lo perdiste | `xml/{emisor}/{dte}/{desde}/{hasta}/{fecha}` |
| Ver el historial de CAF solicitados | `solicitudes/{emisor}/{dte}` |
| Ver el estado de un folio en el SII | `estado/{emisor}/{dte}/{folio}` |
| Ver qué folios de un rango están recibidos, anulados o pendientes | `estados/{emisor}/{dte}/{desde}/{hasta}/{estado}` |
| Anular folios que nunca vas a usar | `anular/{emisor}/{dte}/{desde}/{hasta}` |

El detalle de cada uno está en la [documentación de la API](https://www.apigateway.cl/docs/api), en **API DTE - Código de Asignación de Folios (CAF)**.

## Revisar un CAF

Antes de guardar un CAF en tu sistema, cárgalo con la API para leer sus datos. El XML va en base64:

```bash
curl -X POST https://app.apigateway.cl/api/v2/libredte/billing/identifier/caf_loader/load \
  -H &quot;Authorization: Token $API_TOKEN&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d &#039;{&quot;parameters&quot;: {&quot;xml&quot;: &quot;PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iSVNPLTg4NTktMSI/Pgo8QVVU...&quot;}}&#039;
```

Respuesta (resumida):

```json
{
    &quot;data&quot;: {
        &quot;id&quot;: &quot;CAF33D1H100&quot;,
        &quot;emisor&quot;: {
            &quot;rut&quot;: &quot;88888888-8&quot;,
            &quot;razon_social&quot;: &quot;Mi Empresa SpA&quot;
        },
        &quot;tipoDocumento&quot;: 33,
        &quot;folioDesde&quot;: 1,
        &quot;folioHasta&quot;: 100,
        &quot;cantidadFolios&quot;: 100,
        &quot;fechaAutorizacion&quot;: &quot;2026-10-29&quot;,
        &quot;fechaVencimiento&quot;: &quot;2027-04-27&quot;,
        &quot;vigente&quot;: true,
        &quot;vence&quot;: true
    }
}
```

Guarda en tu base de datos al menos: el emisor, el tipo de documento, `folioDesde`, `folioHasta`, `fechaVencimiento`, el ambiente y el XML del CAF.

## Controlar los folios en tu sistema

La API **no** lleva la cuenta de qué folios usaste: eso es responsabilidad de tu sistema. Una forma simple de hacerlo:

**Tabla de CAF**: un registro por cada CAF recibido.

| emisor | tipo | desde | hasta | vence | ambiente |
|--------|------|-------|-------|-------|----------|
| 88888888-8 | 33 | 1 | 100 | 2027-04-27 | certificación |

**Tabla de folios usados**: un registro por cada folio que asignas.

| emisor | tipo | folio | estado |
|--------|------|-------|--------|
| 88888888-8 | 33 | 1 | aceptado |
| 88888888-8 | 33 | 2 | enviado |

Para emitir:

1. Busca un CAF vigente del emisor, tipo de documento y ambiente.
2. Toma el siguiente folio libre de ese CAF y **resérvalo** en tu base de datos dentro de una transacción, para que dos emisiones simultáneas nunca usen el mismo folio.
3. Construye el documento con ese folio y ese CAF.
4. Cuando queden pocos folios (por ejemplo, el 20%), solicita un nuevo CAF.

&gt; [!WARNING] El folio debe estar dentro del CAF
&gt;
&gt; Si el folio no está en el rango del CAF, la API responde con un `422`:
&gt; `El folio 500 del documento 88888888-8_T033F000000500 no está disponible en el rango del CAF CAF33D1H100.`

## Practicar con un CAF de prueba

Mientras aprendes, no necesitas un CAF real. La API puede generar un **CAF ficticio** para cualquier emisor:

```bash
curl -X POST https://app.apigateway.cl/api/v2/libredte/billing/identifier/caf_faker/create \
  -H &quot;Authorization: Token $API_TOKEN&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d &#039;{
    &quot;parameters&quot;: {
        &quot;emisor&quot;: {&quot;rut&quot;: &quot;88888888-8&quot;, &quot;razon_social&quot;: &quot;Mi Empresa SpA&quot;},
        &quot;codigoDocumento&quot;: 33,
        &quot;folioDesde&quot;: 1,
        &quot;folioHasta&quot;: 100
    }
}&#039;
```

La respuesta tiene el mismo formato que `caf_loader/load` y además el XML del CAF en base64 en el campo `xml`. Ese valor es el que usarás como `caf` al construir documentos.

&gt; [!WARNING] Un CAF de prueba nunca va al SII
&gt;
&gt; Con un CAF ficticio puedes construir, timbrar, firmar, validar y generar el PDF, pero el SII **rechazará** cualquier documento timbrado con él. Úsalo solo para aprender y para tus pruebas automáticas.


    
---

## Emisión paso a paso



---

### Paso 1: Construir el DTE (obligatorio)

Cómo armar los datos del documento y transformarlos en un DTE timbrado y firmado con la operación builder/build, y qué guardar de la respuesta.

# Paso 1: Construir el DTE (obligatorio)

Todo empieza con los datos de la venta. Tu sistema los arma en JSON y la operación **`builder/build`** los transforma en el XML oficial del documento. Es la misma operación para todos los documentos: facturas, notas, guías y boletas. En una sola llamada la API:

1. **Normaliza** los datos: completa campos por defecto, numera las líneas y calcula los totales.
2. **Timbra** el documento con la llave del CAF (genera el timbre electrónico, TED).
3. **Firma** el XML con tu certificado digital.

## Los datos del documento

El JSON sigue **la misma estructura y los mismos nombres de campos que el XML oficial del SII**. Por eso los nombres están en español abreviado (`RznSoc`, `NmbItem`, `PrcItem`): son los del SII.

```json
{
    &quot;Encabezado&quot;: {
        &quot;IdDoc&quot;:    { &quot;...&quot;: &quot;qué documento es&quot; },
        &quot;Emisor&quot;:   { &quot;...&quot;: &quot;quién vende&quot; },
        &quot;Receptor&quot;: { &quot;...&quot;: &quot;quién compra&quot; },
        &quot;Totales&quot;:  { &quot;...&quot;: &quot;montos: no los envíes, los calcula la API&quot; }
    },
    &quot;Detalle&quot;:      [ { &quot;...&quot;: &quot;un objeto por producto o servicio&quot; } ],
    &quot;DscRcgGlobal&quot;: [ { &quot;...&quot;: &quot;descuentos o recargos globales (opcional)&quot; } ],
    &quot;Referencia&quot;:   [ { &quot;...&quot;: &quot;documentos relacionados (opcional)&quot; } ]
}
```

No envíes los totales: la API los calcula. Antes de construir, reserva en tu sistema el folio que vas a usar, para que nunca se repita.

El SII define muchos más campos: formas de pago, descuentos, referencias, datos de transporte, impuestos adicionales y otros. La descripción de cada uno, su largo máximo y en qué documentos es obligatorio están en la documentación oficial del SII:

**Documentos tributarios electrónicos (no boletas):**

- [Descripción del formato de DTE](https://www.sii.cl/factura_electronica/factura_mercado/formato_dte_202602.pdf)
- [Diagrama del XML de DTE](https://www.sii.cl/factura_electronica/factura_mercado/diagrama_dte.zip)

**Boletas:**

- [Descripción del formato de boletas](https://www.sii.cl/factura_electronica/factura_mercado/boletas_elec_0720_3.pdf)
- [Diagrama del XML de boletas](https://www.sii.cl/factura_electronica/factura_mercado/diag_boleta_0920.zip)

Para ver cómo se usan, revisa los ejemplos de la API con la operación `examples/get` (ver [Tu primera llamada](https://www.apigateway.cl/academy/emision-de-dte/preparacion/tu-primera-llamada)) y los [casos prácticos](https://www.apigateway.cl/academy/emision-de-dte/casos-practicos).

## La solicitud

```
POST https://app.apigateway.cl/api/v2/libredte/billing/document/builder/build
```

La llamada es la misma para todos los documentos, incluidas las boletas; cambian los datos del documento (`parsedData`) y el CAF.

La &quot;bolsa&quot; (`bag`) agrupa todo lo que se necesita para construir el documento:

| Campo | Qué es |
|-------|--------|
| `parsedData` | Los datos del documento, en JSON (ver [Los datos del documento](#los-datos-del-documento)). |
| `caf` | El XML del CAF en base64. Debe ser del mismo tipo de documento: de facturas para una factura, de boletas para una boleta. |
| `certificate` | El certificado digital (ver [El certificado digital](https://www.apigateway.cl/academy/emision-de-dte/preparacion/certificado-digital)). |

**La fecha de emisión** va en `IdDoc.FchEmis` (`AAAA-MM-DD`). Si no la envías, la API usa la fecha del día. Guárdala junto al documento: la necesitarás para corregirlo con una nota de crédito (`FchRef`) y para verificarlo en el SII. También la encuentras en la respuesta, en `data.document.Encabezado.IdDoc.FchEmis`.

Estos son los ejemplos de cada caso:

### 1.1. Facturas, notas y guías

```json
{
    &quot;parameters&quot;: {
        &quot;bag&quot;: {
            &quot;parsedData&quot;: {
                &quot;Encabezado&quot;: {
                    &quot;IdDoc&quot;: { &quot;TipoDTE&quot;: 33, &quot;Folio&quot;: 1, &quot;FmaPago&quot;: 1 },
                    &quot;Emisor&quot;: {
                        &quot;RUTEmisor&quot;: &quot;88888888-8&quot;,
                        &quot;RznSoc&quot;: &quot;Mi Empresa SpA&quot;,
                        &quot;GiroEmis&quot;: &quot;Venta de software&quot;,
                        &quot;Acteco&quot;: 620100,
                        &quot;DirOrigen&quot;: &quot;Av. Siempre Viva 742&quot;,
                        &quot;CmnaOrigen&quot;: &quot;Providencia&quot;
                    },
                    &quot;Receptor&quot;: {
                        &quot;RUTRecep&quot;: &quot;77777777-7&quot;,
                        &quot;RznSocRecep&quot;: &quot;Cliente Ejemplo Ltda.&quot;,
                        &quot;GiroRecep&quot;: &quot;Comercio&quot;,
                        &quot;DirRecep&quot;: &quot;Calle Falsa 123&quot;,
                        &quot;CmnaRecep&quot;: &quot;Santiago&quot;
                    }
                },
                &quot;Detalle&quot;: [
                    { &quot;NmbItem&quot;: &quot;Servicio de desarrollo&quot;, &quot;QtyItem&quot;: 1, &quot;PrcItem&quot;: 100000 }
                ]
            },
            &quot;caf&quot;: &quot;PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iSVNPLTg4NTktMSI/Pgo8QVVU...&quot;,
            &quot;certificate&quot;: {
                &quot;certificate&quot;: &quot;-----BEGIN CERTIFICATE-----\nMIIG...\n-----END CERTIFICATE-----&quot;,
                &quot;privateKey&quot;: &quot;-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----&quot;
            }
        }
    }
}
```

El precio (`PrcItem`) va **neto**. No hay totales: la API calcula neto $100.000, IVA $19.000 y total $119.000.

### 1.2. Boletas

```json
{
    &quot;parameters&quot;: {
        &quot;bag&quot;: {
            &quot;parsedData&quot;: {
                &quot;Encabezado&quot;: {
                    &quot;IdDoc&quot;: { &quot;TipoDTE&quot;: 39, &quot;Folio&quot;: 1 },
                    &quot;Emisor&quot;: {
                        &quot;RUTEmisor&quot;: &quot;88888888-8&quot;,
                        &quot;RznSoc&quot;: &quot;Mi Empresa SpA&quot;,
                        &quot;GiroEmis&quot;: &quot;Venta de artículos de computación&quot;,
                        &quot;DirOrigen&quot;: &quot;Av. Siempre Viva 742&quot;,
                        &quot;CmnaOrigen&quot;: &quot;Providencia&quot;
                    },
                    &quot;Receptor&quot;: {
                        &quot;RUTRecep&quot;: &quot;66666666-6&quot;,
                        &quot;RznSocRecep&quot;: &quot;Cliente final&quot;,
                        &quot;DirRecep&quot;: &quot;Santiago&quot;,
                        &quot;CmnaRecep&quot;: &quot;Santiago&quot;
                    }
                },
                &quot;Detalle&quot;: [
                    { &quot;NmbItem&quot;: &quot;Mouse inalámbrico&quot;, &quot;QtyItem&quot;: 2, &quot;PrcItem&quot;: 11900 }
                ]
            },
            &quot;caf&quot;: &quot;PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iSVNPLTg4NTktMSI/Pgo8QVVU...&quot;,
            &quot;certificate&quot;: {
                &quot;certificate&quot;: &quot;-----BEGIN CERTIFICATE-----\nMIIG...\n-----END CERTIFICATE-----&quot;,
                &quot;privateKey&quot;: &quot;-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----&quot;
            }
        }
    }
}
```

La API calcula un total de $23.800, del que $20.000 es neto y $3.800 es IVA. Lo que cambia respecto de una factura:

| Dato | En una boleta |
|------|---------------|
| `TipoDTE` | `39`, o `41` si es una boleta exenta. |
| `PrcItem` | **Con IVA incluido.** |
| Receptor | Opcional. Si el cliente no da su RUT, usa `66666666-6`. |
| `FmaPago`, `Acteco`, `GiroRecep` | No se usan. |
| `RznSoc`, `GiroEmis` | Se envían igual que en una factura. En el XML de la boleta la API los escribe como `RznSocEmisor` y `GiroEmisor`, los nombres que usa el SII. |
| `caf` | Un CAF de boletas (`39`, o `41` para la exenta). |

En una **boleta exenta** (`41`), marca cada ítem con `IndExe: 1`: la API calcula `MntExe` con el total, sin IVA.

## Qué se obtiene según lo que envíes

| Envías | Obtienes | Sirve para |
|--------|----------|------------|
| Solo `parsedData` | Un **borrador**, sin timbre ni firma | Previsualizar los totales o el PDF de una cotización |
| `parsedData` + `caf` | Un documento **timbrado**, sin firma | (Poco uso práctico) |
| `parsedData` + `caf` + `certificate` | Un documento **timbrado y firmado** | **Emitir**: es lo que se envía al SII |

Para emitir, envía siempre los tres.

## La respuesta

Esta es la respuesta para la factura del ejemplo, construida con un CAF del ambiente de certificación. Se muestran los campos que usarás; la tabla de abajo describe todos. Los valores largos (XML en base64, llaves y certificados) están acortados con `...`:

```json
{
    &quot;data&quot;: {
        &quot;document_id&quot;: &quot;88888888-8_T033F000000001&quot;,
        &quot;document_xml&quot;: &quot;PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0i...&quot;,
        &quot;document&quot;: {
            &quot;Encabezado&quot;: {
                &quot;IdDoc&quot;: {
                    &quot;TipoDTE&quot;: 33,
                    &quot;Folio&quot;: 1,
                    &quot;FchEmis&quot;: &quot;2026-10-29&quot;,
                    &quot;TpoTranVenta&quot;: 1,
                    &quot;FmaPago&quot;: 1
                },
                &quot;Emisor&quot;: {
                    &quot;RUTEmisor&quot;: &quot;88888888-8&quot;,
                    &quot;RznSoc&quot;: &quot;Mi Empresa SpA&quot;,
                    &quot;GiroEmis&quot;: &quot;Venta de software&quot;,
                    &quot;Acteco&quot;: 620100,
                    &quot;DirOrigen&quot;: &quot;Av. Siempre Viva 742&quot;,
                    &quot;CmnaOrigen&quot;: &quot;Providencia&quot;
                },
                &quot;Receptor&quot;: {
                    &quot;RUTRecep&quot;: &quot;77777777-7&quot;,
                    &quot;RznSocRecep&quot;: &quot;Cliente Ejemplo Ltda.&quot;,
                    &quot;GiroRecep&quot;: &quot;Comercio&quot;,
                    &quot;DirRecep&quot;: &quot;Calle Falsa 123&quot;,
                    &quot;CmnaRecep&quot;: &quot;Santiago&quot;
                },
                &quot;Totales&quot;: {
                    &quot;MntNeto&quot;: 100000,
                    &quot;TasaIVA&quot;: 19,
                    &quot;IVA&quot;: 19000,
                    &quot;MntTotal&quot;: 119000
                }
            },
            &quot;Detalle&quot;: [
                {
                    &quot;NroLinDet&quot;: 1,
                    &quot;NmbItem&quot;: &quot;Servicio de desarrollo&quot;,
                    &quot;QtyItem&quot;: 1,
                    &quot;PrcItem&quot;: 100000,
                    &quot;MontoItem&quot;: 100000
                }
            ]
        },
        &quot;document_normalized&quot;: {
            &quot;Encabezado&quot;: {
                &quot;Totales&quot;: {
                    &quot;MntNeto&quot;: 100000,
                    &quot;MntExe&quot;: null,
                    &quot;TasaIVA&quot;: 19,
                    &quot;IVA&quot;: 19000,
                    &quot;ImptoReten&quot;: null,
                    &quot;CredEC&quot;: null,
                    &quot;MntTotal&quot;: 119000,
                    &quot;TpoMoneda&quot;: null
                }
            },
            &quot;...&quot;: &quot;todos los campos del formato&quot;
        },
        &quot;document_type&quot;: {
            &quot;codigo&quot;: 33,
            &quot;nombre&quot;: &quot;Factura electrónica&quot;,
            &quot;...&quot;: &quot;...&quot;
        },
        &quot;certificate&quot;: {
            &quot;id&quot;: &quot;11222333-9&quot;,
            &quot;name&quot;: &quot;Daniel Bot&quot;,
            &quot;...&quot;: &quot;...&quot;,
            &quot;pkey&quot;: &quot;-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----&quot;
        },
        &quot;caf&quot;: {
            &quot;id&quot;: &quot;CAF33D1H100&quot;,
            &quot;...&quot;: &quot;...&quot;,
            &quot;privateKey&quot;: &quot;-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----&quot;
        },
        &quot;...&quot;: &quot;document_parsed, document_stamp, timbre, document_auth, document_extra, emisor, receptor y options&quot;
    }
}
```

| Campo | Qué es | ¿Guardarlo? |
|-------|--------|-------------|
| `document_xml` | **El XML del DTE timbrado y firmado, en base64.** Es el documento con validez tributaria. | Sí, siempre |
| `document_id` | Identificador del documento: emisor, tipo y folio. | Sí |
| `document` | Los datos del documento tal como quedaron en el XML, solo con los campos que tienen valor. | Opcional |
| `document_normalized` | Los mismos datos con todos los campos del formato; los que no se usan vienen en `null`. Incluye los totales calculados. | Opcional |
| `document_parsed` | Los datos tal como los enviaste en `parsedData`. | No |
| `document_type` | Datos del tipo de documento: nombre, si es cedible, si es exento, etc. | No |
| `document_stamp` | El timbre electrónico (TED) en XML, en base64. Ya está dentro de `document_xml`. | No |
| `timbre` | El mismo timbre electrónico, en formato JSON. | No |
| `document_auth` | La resolución del emisor, si la indicaste. | No |
| `document_extra` | Datos adicionales del documento, si los hay. | No |
| `emisor`, `receptor` | Los datos del emisor y del receptor que usó la API. | No |
| `certificate` | Los datos del certificado usado, **incluida su llave privada** (`pkey`). | **No** |
| `caf` | Los datos del CAF usado, **incluida su llave privada** (`privateKey`). | **No** |
| `options` | Las opciones que usó cada etapa de la construcción. | No |

&gt; [!WARNING] Guarda solo lo necesario
&gt;
&gt; La respuesta incluye los datos del certificado y del CAF que se usaron, con sus llaves. No guardes la respuesta completa en tu base de datos ni en tus logs: guarda el `document_xml`, el `document_id` y, si los necesitas, los totales.

Decodificado, `document_xml` se ve así (resumido):

```xml
&lt;?xml version=&quot;1.0&quot; encoding=&quot;ISO-8859-1&quot;?&gt;
&lt;DTE xmlns=&quot;http://www.sii.cl/SiiDte&quot; version=&quot;1.0&quot;&gt;
  &lt;Documento ID=&quot;LibreDTE_88888888-8_T033F000000000001&quot;&gt;
    &lt;Encabezado&gt;
      &lt;IdDoc&gt;&lt;TipoDTE&gt;33&lt;/TipoDTE&gt;&lt;Folio&gt;1&lt;/Folio&gt;&lt;FchEmis&gt;2026-10-29&lt;/FchEmis&gt;&lt;/IdDoc&gt;
      &lt;Emisor&gt;...&lt;/Emisor&gt;
      &lt;Receptor&gt;...&lt;/Receptor&gt;
      &lt;Totales&gt;&lt;MntNeto&gt;100000&lt;/MntNeto&gt;&lt;TasaIVA&gt;19&lt;/TasaIVA&gt;&lt;IVA&gt;19000&lt;/IVA&gt;&lt;MntTotal&gt;119000&lt;/MntTotal&gt;&lt;/Totales&gt;
    &lt;/Encabezado&gt;
    &lt;Detalle&gt;...&lt;/Detalle&gt;
    &lt;TED version=&quot;1.0&quot;&gt;...&lt;/TED&gt;            &lt;!-- timbre electrónico --&gt;
    &lt;TmstFirma&gt;2026-10-29T16:57:50&lt;/TmstFirma&gt;
  &lt;/Documento&gt;
  &lt;Signature xmlns=&quot;http://www.w3.org/2000/09/xmldsig#&quot;&gt;...&lt;/Signature&gt;  &lt;!-- firma --&gt;
&lt;/DTE&gt;
```

En una **boleta**, la respuesta tiene los mismos campos. `document_type` trae el código `39` (&quot;Boleta electrónica&quot;) y el encabezado del XML usa los nombres de las boletas:

```xml
&lt;IdDoc&gt;&lt;TipoDTE&gt;39&lt;/TipoDTE&gt;&lt;Folio&gt;1&lt;/Folio&gt;&lt;FchEmis&gt;2026-11-04&lt;/FchEmis&gt;&lt;IndServicio&gt;3&lt;/IndServicio&gt;&lt;/IdDoc&gt;
&lt;Emisor&gt;&lt;RUTEmisor&gt;88888888-8&lt;/RUTEmisor&gt;&lt;RznSocEmisor&gt;Mi Empresa SpA&lt;/RznSocEmisor&gt;&lt;GiroEmisor&gt;...&lt;/GiroEmisor&gt;...&lt;/Emisor&gt;
&lt;Totales&gt;&lt;MntNeto&gt;20000&lt;/MntNeto&gt;&lt;IVA&gt;3800&lt;/IVA&gt;&lt;MntTotal&gt;23800&lt;/MntTotal&gt;&lt;/Totales&gt;
```

`IndServicio` indica el tipo de venta; si no lo envías, la API pone `3` (venta de bienes y servicios).

&gt; [!INFO] El XML no se modifica
&gt;
&gt; Una vez firmado, el XML no se puede tocar: cualquier cambio, aunque sea un espacio, invalida la firma. Guarda el base64 tal como llega, o decodifícalo a bytes sin convertir la codificación (es ISO-8859-1, no UTF-8).

## Errores frecuentes en este paso

| Mensaje (`detail`) | Causa | Solución |
|--------------------|-------|----------|
| `El XPath &quot;//Encabezado/IdDoc/Folio&quot; ... es obligatorio: no coincidió con ningún nodo.` | Falta `IdDoc.Folio`. | Asigna el folio desde tu control de folios. |
| `El folio N del documento ... no está disponible en el rango del CAF ...` | El folio no está dentro del CAF enviado. | Usa un folio del rango, o el CAF que corresponde a ese folio. |
| `El CAF ... fue autorizado al emisor ..., pero el documento ... es del emisor ...` | El CAF es de otra empresa. | Usa un CAF solicitado por la empresa que emite el documento. |
| `El CAF ... es del tipo de documento ..., pero el documento ... es del tipo ...` | El CAF es de otro tipo de documento, por ejemplo uno de facturas (`33`) para una boleta (`39`). | Usa el CAF del mismo tipo que el documento. |
| `The verification digit of the RUT ... is incorrect.` | Un RUT tiene mal el dígito verificador. | Valida los RUT en tu sistema antes de emitir. |
| `Falta incluir documento de referencia.` | Es una nota de crédito o débito sin `Referencia`. | Agrega la referencia al documento que corrige. |
| `No se encontró un deserializador capaz de construir una instancia de ...CafInterface ... requiere datos codificados en base64 válido.` | El `caf` no viene en base64 válido. | Codifica el XML del CAF en base64, en una línea. |
| `Se requieren los datos del certificado ...` | El certificado viene incompleto. | Envía `certificate` + `privateKey` (PEM), o `data` + `password` (`.p12`). |

&gt; [!WARNING] Un CAF por emisor y por tipo de documento
&gt;
&gt; El CAF debe ser del **mismo emisor** y del **mismo tipo de documento**: una boleta (`39`) se timbra con un CAF de boletas, no con uno de facturas. Si no coinciden, la API rechaza la construcción con uno de los dos errores de la tabla.


    
---

### Paso 2: Validar antes de enviar (opcional)

Cómo revisar el esquema, los datos y la firma de un DTE antes de enviarlo al SII.

# Paso 2: Validar antes de enviar (opcional)

Este paso es opcional, pero muy recomendable mientras desarrollas: detecta en segundos los errores que el SII te diría recién al procesar el envío. Hay tres validaciones, y las tres reciben el mismo dato: el XML que construiste en el paso 1.

Las validaciones son **las mismas para todos los documentos, incluidas las boletas**: la API reconoce el tipo de documento y, si es una boleta, la revisa con el esquema de boletas del SII.

| Operación | Qué revisa |
|-----------|------------|
| `billing/document/validator/validateSchema` | Que el XML cumpla el **esquema oficial del SII** (campos, tipos de datos, largos, orden). |
| `billing/document/validator/validate` | Que los **datos** del documento sean coherentes (por ejemplo, que una nota tenga referencia). |
| `billing/document/validator/validateSignature` | Que la **firma** del XML sea válida. |

## Qué dato usar del paso 1

De la respuesta de [`builder/build`](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-1-construir-el-dte#la-respuesta) solo necesitas el campo **`document_xml`**:

```json
{
    &quot;data&quot;: {
        &quot;document_id&quot;: &quot;88888888-8_T033F000000001&quot;,
        &quot;document_xml&quot;: &quot;PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iSVNPLTg4NTktMSI/Pgo8RFRF...&quot;,
        &quot;...&quot;: &quot;los demás campos de la respuesta&quot;
    }
}
```

Copia ese valor **tal cual**, en base64 y sin decodificarlo, en el parámetro `source` de cada validación:

```json
{
    &quot;parameters&quot;: {
        &quot;source&quot;: &quot;&lt;el document_xml del paso 1&gt;&quot;
    }
}
```

&gt; [!WARNING] Valida el mismo XML que vas a enviar
&gt;
&gt; No vuelvas a construir el documento para validarlo: cada construcción genera un XML con otra firma. Valida el `document_xml` que guardaste, que es el mismo que usarás en el [paso 3](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-3-armar-el-sobre).

## Validar el esquema

```bash
curl -X POST https://app.apigateway.cl/api/v2/libredte/billing/document/validator/validateSchema \
  -H &quot;Authorization: Token $API_TOKEN&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d &#039;{&quot;parameters&quot;: {&quot;source&quot;: &quot;PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iSVNPLTg4NTktMSI/Pgo8RFRF...&quot;}}&#039;
```

Si el XML es válido, la respuesta es `200` con el documento leído como JSON dentro de `data`. Si no lo es, es un `422` con el motivo en `detail`.

## Validar los datos

```bash
curl -X POST https://app.apigateway.cl/api/v2/libredte/billing/document/validator/validate \
  -H &quot;Authorization: Token $API_TOKEN&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d &#039;{&quot;parameters&quot;: {&quot;source&quot;: &quot;PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iSVNPLTg4NTktMSI/Pgo8RFRF...&quot;}}&#039;
```

Si no hay problemas, la respuesta es `{&quot;data&quot;: null}` con código `200`.

## Validar la firma

```bash
curl -X POST https://app.apigateway.cl/api/v2/libredte/billing/document/validator/validateSignature \
  -H &quot;Authorization: Token $API_TOKEN&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d &#039;{&quot;parameters&quot;: {&quot;source&quot;: &quot;PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iSVNPLTg4NTktMSI/Pgo8RFRF...&quot;}}&#039;
```

La respuesta siempre es `200`, y el resultado está en `data.valid`. Si la firma es válida, `valid` es `true` y `signature` trae los datos de la firma, incluido quién firmó (`signer`):

```json
{
    &quot;data&quot;: {
        &quot;valid&quot;: true,
        &quot;error&quot;: null,
        &quot;signature&quot;: {
            &quot;reference&quot;: &quot;LibreDTE_88888888-8_T033F000000000001&quot;,
            &quot;digestValue&quot;: &quot;YMnSHe2YViJQh/GdUuLB66wOM3M=&quot;,
            &quot;signer&quot;: {
                &quot;id&quot;: &quot;11222333-9&quot;,
                &quot;name&quot;: &quot;Daniel Bot&quot;,
                &quot;to&quot;: &quot;2027-10-29T11:38:23&quot;,
                &quot;isActive&quot;: true,
                &quot;...&quot;: &quot;...&quot;
            },
            &quot;...&quot;: &quot;...&quot;
        }
    }
}
```

Si no es válida, `valid` es `false` y el motivo está en `error.message`. Por ejemplo, si el XML se modificó después de firmarlo:

```json
{
    &quot;data&quot;: {
        &quot;valid&quot;: false,
        &quot;error&quot;: {
            &quot;message&quot;: &quot;The DigestValue that comes in the XML \&quot;76PnCAaCZb2XiWjKywMj4K3Qvko=\&quot; for the reference \&quot;LibreDTE_88888888-8_T033F000000000001\&quot; does not match the calculated value when validating \&quot;KRgsXYrcUs+tmoE7Tg9UiOgWiSQ=\&quot;. The data of the reference could have been manipulated after being signed.&quot;,
            &quot;code&quot;: 0,
            &quot;errors&quot;: []
        },
        &quot;signature&quot;: { &quot;...&quot;: &quot;...&quot; }
    }
}
```

Revisa siempre `valid`: el código `200` solo indica que la validación se hizo, no que la firma sea válida.

Para no romper la firma, guarda y envía el `document_xml` tal como lo entrega la API.

## ¿Cuándo validar?

| Etapa | Recomendación |
|-------|---------------|
| Desarrollo y pruebas | Valida el esquema de **todos** los documentos. |
| Producción | Valida al menos el esquema. Cuesta pocos créditos y te evita rechazos del SII. |

&gt; [!TIP] El sobre también se valida
&gt;
&gt; En el siguiente paso armarás el sobre. Para el sobre existen las mismas validaciones: `billing/document/dispatcher/validate`, `billing/document/dispatcher/validateSchema` y `billing/document/dispatcher/validateSignature`. Esta última responde una lista, con un resultado por cada firma del sobre: la de cada documento y la del sobre.

&gt; [!INFO] La validación no reemplaza al SII
&gt;
&gt; Estas validaciones revisan el formato y los datos. Hay reglas que solo el SII puede verificar, como que el folio esté autorizado o que el certificado esté autorizado para la empresa. La respuesta final siempre la da el SII en el [paso 5](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-5-consultar-el-estado).


    
---

### Paso 3: Armar el sobre (obligatorio)

Qué es el sobre (EnvioBOLETA para las boletas y EnvioDTE para los demás documentos), cómo crearlo con dispatcher/create y cómo dirigirlo al SII.

# Paso 3: Armar el sobre (obligatorio)

El SII no recibe documentos sueltos: recibe un **sobre** que contiene uno o más documentos. Las facturas, notas y guías van en un sobre `EnvioDTE` y las boletas en un sobre `EnvioBOLETA`. Los dos se crean con la misma operación, `dispatcher/create`, que elige el tipo según el documento (ver [Un sobre por tipo de documento](#un-sobre-por-tipo-de-documento)).

El sobre tiene una **carátula** con:

| Dato de la carátula | Qué es | De dónde sale |
|---------------------|--------|---------------|
| `RutEmisor` | RUT de la empresa emisora | `emisor.rut` |
| `RutEnvia` | RUT de la persona que envía | El certificado digital |
| `RutReceptor` | A quién va dirigido el sobre | `receptor.rut` (ver abajo) |
| `FchResol` y `NroResol` | Resolución de autorización del emisor | `emisor.autorizacion_dte` |
| `SubTotDTE` | Cuántos documentos de cada tipo lleva | Se calcula solo |

El sobre también se **firma** con el certificado digital.

## Crear el sobre para el SII

```
POST https://app.apigateway.cl/api/v2/libredte/billing/document/dispatcher/create
```

```json
{
    &quot;parameters&quot;: {
        &quot;bag&quot;: {
            &quot;xmlDocument&quot;: &quot;PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iSVNPLTg4NTktMSI/Pgo8RFRF...&quot;,
            &quot;certificate&quot;: {
                &quot;certificate&quot;: &quot;-----BEGIN CERTIFICATE-----\nMIIG...\n-----END CERTIFICATE-----&quot;,
                &quot;privateKey&quot;: &quot;-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----&quot;
            },
            &quot;emisor&quot;: {
                &quot;rut&quot;: &quot;88888888-8&quot;,
                &quot;razon_social&quot;: &quot;Mi Empresa SpA&quot;,
                &quot;autorizacion_dte&quot;: {
                    &quot;fecha_resolucion&quot;: &quot;2025-11-20&quot;,
                    &quot;numero_resolucion&quot;: 0
                }
            },
            &quot;receptor&quot;: {
                &quot;rut&quot;: &quot;60803000-K&quot;
            }
        }
    }
}
```

| Campo | Qué es |
|-------|--------|
| `xmlDocument` | El `document_xml` del [paso 1](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-1-construir-el-dte), en base64. |
| `certificate` | El certificado con que se firma el sobre. |
| `emisor.autorizacion_dte` | La resolución del emisor: en **certificación**, número `0` y la fecha que muestra el SII en ese ambiente; en **producción**, el número y la fecha de la resolución real. |
| `receptor.rut` | A quién va dirigido el sobre. Para el SII usa `60803000-K`, el RUT del SII. |

## ¿Dónde obtengo la fecha y el número de resolución?

Son datos del emisor que entrega el SII, y cada ambiente tiene los suyos. Puedes obtenerlos de dos formas:

**Con la API**, consultando el estado de autorización del emisor:

```bash
# Producción
curl https://app.apigateway.cl/api/v2/sii/dte/contribuyentes/autorizado/88888888-8 \
  -H &quot;Authorization: Token $API_TOKEN&quot;

# Certificación
curl &quot;https://app.apigateway.cl/api/v2/sii/dte/contribuyentes/autorizado/88888888-8?certificacion=1&quot; \
  -H &quot;Authorization: Token $API_TOKEN&quot;
```

La resolución viene en `data.resolucion`. Esta es la respuesta en certificación:

```json
{
    &quot;data&quot;: {
        &quot;rut&quot;: &quot;88888888-8&quot;,
        &quot;autorizado&quot;: true,
        &quot;resolucion&quot;: {
            &quot;numero&quot;: 0,
            &quot;fecha&quot;: &quot;2025-11-20&quot;
        }
    }
}
```

Usa `resolucion.fecha` como `fecha_resolucion` y `resolucion.numero` como `numero_resolucion`. En certificación el número siempre es `0`.

**En el sitio del SII**, buscando al emisor por su RUT en el listado de empresas autorizadas: [certificación](https://maullin.sii.cl/cvc/dte/ee_empresas_dte.html) o [producción](https://palena.sii.cl/cvc/dte/ee_empresas_dte.html).

&gt; [!TIP] Consúltala una vez y guárdala
&gt;
&gt; La resolución no cambia de un envío a otro. Consúltala una vez por emisor y ambiente, y guárdala en la configuración de la empresa. Más detalles en [Resolución de autorización](https://www.apigateway.cl/academy/emision-de-dte/fundamentos/resolucion-de-autorizacion).

## La respuesta

Esta es la respuesta para el sobre del ejemplo. Los valores largos están acortados con `...`, y de `documents` se muestran solo los campos propios del sobre: el resto es igual a la [respuesta de `builder/build`](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-1-construir-el-dte#la-respuesta).

```json
{
    &quot;data&quot;: {
        &quot;tag&quot;: &quot;EnvioDTE&quot;,
        &quot;xml&quot;: &quot;PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0i...&quot;,
        &quot;documents&quot;: [
            {
                &quot;document_id&quot;: &quot;88888888-8_T033F000000001&quot;,
                &quot;document_xml&quot;: &quot;PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iSVNPLTg4NTktMSI/Pgo8RFRF...&quot;,
                &quot;document_auth&quot;: {
                    &quot;FchResol&quot;: &quot;2025-11-20&quot;,
                    &quot;NroResol&quot;: 0
                },
                &quot;...&quot;: &quot;los demás campos de builder/build (ver el paso 1)&quot;
            }
        ],
        &quot;caratula&quot;: {
            &quot;@attributes&quot;: {
                &quot;version&quot;: &quot;1.0&quot;
            },
            &quot;RutEmisor&quot;: &quot;88888888-8&quot;,
            &quot;RutEnvia&quot;: &quot;11222333-9&quot;,
            &quot;RutReceptor&quot;: &quot;60803000-K&quot;,
            &quot;FchResol&quot;: &quot;2025-11-20&quot;,
            &quot;NroResol&quot;: 0,
            &quot;TmstFirmaEnv&quot;: &quot;2026-10-30T09:23:51&quot;,
            &quot;SubTotDTE&quot;: [
                {
                    &quot;TpoDTE&quot;: 33,
                    &quot;NroDTE&quot;: 1
                }
            ]
        }
    }
}
```

| Campo | Qué es | ¿Guardarlo? |
|-------|--------|-------------|
| `xml` | **El sobre firmado, en base64.** Es lo que enviarás al SII en el [paso 4](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-4-enviar-al-sii). | Sí, siempre |
| `tag` | El tipo de sobre: `EnvioDTE`, o `EnvioBOLETA` si son boletas. | No |
| `caratula` | La carátula del sobre: emisor, quién envía (`RutEnvia`, el RUT del certificado), a quién va dirigido, la resolución, la fecha de firma y cuántos documentos de cada tipo lleva (`SubTotDTE`). | Opcional |
| `documents` | Los documentos que van dentro del sobre, con los mismos campos que entrega [`builder/build`](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-1-construir-el-dte#la-respuesta). `document_auth` trae la resolución que indicaste. | No |

&gt; [!WARNING] Guarda solo lo necesario
&gt;
&gt; Cada documento de `documents` incluye los datos del certificado, con su llave privada (`certificate.pkey`). No guardes la respuesta completa en tu base de datos ni en tus logs: guarda el `xml` del sobre.

## Varios documentos en un sobre

Si emites muchos documentos a la vez, puedes enviarlos en un solo sobre con `dispatcher/createMany`. Recibe una lista de bolsas en el parámetro `bags`, todas del **mismo emisor**:

```json
{
    &quot;parameters&quot;: {
        &quot;bags&quot;: [
            {
                &quot;xmlDocument&quot;: &quot;...DTE 1 en base64...&quot;,
                &quot;certificate&quot;: { &quot;certificate&quot;: &quot;...&quot;, &quot;privateKey&quot;: &quot;...&quot; },
                &quot;emisor&quot;: { &quot;rut&quot;: &quot;88888888-8&quot;, &quot;razon_social&quot;: &quot;Mi Empresa SpA&quot;, &quot;autorizacion_dte&quot;: { &quot;fecha_resolucion&quot;: &quot;2025-11-20&quot;, &quot;numero_resolucion&quot;: 0 } },
                &quot;receptor&quot;: { &quot;rut&quot;: &quot;60803000-K&quot; }
            },
            {
                &quot;xmlDocument&quot;: &quot;...DTE 2 en base64...&quot;
            }
        ]
    }
}
```

El certificado, el emisor y el receptor del sobre se toman de la primera bolsa.

&gt; [!TIP] ¿Uno por sobre o varios?
&gt;
&gt; Para empezar, usa **un documento por sobre**: es más simple saber qué documento tiene cada Track ID, y si el SII rechaza uno no afecta a los demás. Agrupa documentos en un sobre solo cuando el volumen lo justifique.

## Un sobre por tipo de documento

La llamada es la misma para todos los documentos: envía en `xmlDocument` el `document_xml` del documento, sea una factura o una boleta. La API elige el tipo de sobre y lo informa en `tag`:

| Documento en `xmlDocument` | `tag` de la respuesta | `caratula.SubTotDTE` | Se envía con (paso 4) |
|----------------------------|-----------------------|----------------------|-----------------------|
| Factura, nota o guía | `EnvioDTE` | `[{ &quot;TpoDTE&quot;: 33, &quot;NroDTE&quot;: 1 }]` | `sii_dte/sendXmlDocument` |
| Boleta | `EnvioBOLETA` | `[{ &quot;TpoDTE&quot;: 39, &quot;NroDTE&quot;: 1 }]` | `sii_boleta/sendXmlDocument` |

El resto de la respuesta tiene los mismos campos en los dos casos.

Un sobre lleva solo boletas o solo los demás DTE, nunca ambos. Si intentas juntarlos (por ejemplo, con `createMany`, ver [Varios documentos en un sobre](#varios-documentos-en-un-sobre)), la API responde:

```
El tipo de documento Factura electrónica no se puede agregar a un sobre de tipo ENVIO_BOLETA.
```


    
---

### Paso 4: Enviar al SII (obligatorio)

Cómo enviar el sobre al SII: las facturas, notas y guías con sii_dte/sendXmlDocument y las boletas con sii_boleta/sendXmlDocument, cómo elegir el ambiente y qué hacer con el Track ID.

# Paso 4: Enviar al SII (obligatorio)

Con el sobre firmado, lo envías al SII. El SII lo recibe, le asigna un **Track ID** y lo procesa en segundo plano. El resultado (aceptado o rechazado) se consulta después, en el [paso 5](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-5-consultar-el-estado).

## Qué operación usar

El SII recibe las boletas por un servicio distinto al de los demás documentos, así que hay una operación para cada tipo de sobre:

| Sobre del paso 3 (`tag`) | Documentos | Operación |
|--------------------------|------------|-----------|
| `EnvioDTE` | Facturas, notas de crédito y débito, guías de despacho y demás DTE | `billing/integration/sii_dte/sendXmlDocument` |
| `EnvioBOLETA` | Boletas (`39` y `41`) | `billing/integration/sii_boleta/sendXmlDocument` |

Las dos reciben los mismos parámetros y entregan un Track ID.

## 4.1. Facturas, notas y guías

### La solicitud

```
POST https://app.apigateway.cl/api/v2/libredte/billing/integration/sii_dte/sendXmlDocument
```

```json
{
    &quot;parameters&quot;: {
        &quot;request&quot;: {
            &quot;certificate&quot;: {
                &quot;certificate&quot;: &quot;-----BEGIN CERTIFICATE-----\nMIIG...\n-----END CERTIFICATE-----&quot;,
                &quot;privateKey&quot;: &quot;-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----&quot;
            },
            &quot;options&quot;: {
                &quot;environment&quot;: 1
            }
        },
        &quot;doc&quot;: &quot;PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iSVNPLTg4NTktMSI/Pgo8RW52aW9EVEU...&quot;,
        &quot;company&quot;: &quot;88888888-8&quot;
    }
}
```

| Parámetro | Qué es |
|-----------|--------|
| `request.certificate` | El certificado con que la API se autentica en el SII. |
| `request.options.environment` | El ambiente del SII: `1` certificación, `0` producción. |
| `doc` | El sobre `EnvioDTE` del [paso 3](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-3-armar-el-sobre) (su campo `xml`), en base64. |
| `company` | El RUT de la empresa emisora. |
| `retries` | (Opcional) Cuántas veces reintentar si el SII no responde. Máximo `10`. |

### La respuesta

```json
{
    &quot;data&quot;: {
        &quot;track_id&quot;: 4753411374
    }
}
```

El **Track ID** es el comprobante de que el SII recibió el sobre. **Guárdalo inmediatamente** junto al documento: sin él no puedes consultar el resultado.

## 4.2. Boletas

### La solicitud

```
POST https://app.apigateway.cl/api/v2/libredte/billing/integration/sii_boleta/sendXmlDocument
```

Los parámetros son **los mismos de 4.1** (`request`, `doc`, `company` y `retries`). La diferencia está en `doc`: va el sobre `EnvioBOLETA` del [paso 3](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-3-armar-el-sobre#un-sobre-por-tipo-de-documento).

### La respuesta

```json
{
    &quot;data&quot;: {
        &quot;track_id&quot;: 33790541,
        &quot;status&quot;: &quot;REC&quot;,
        &quot;received_at&quot;: &quot;2026-11-04T12:18:29-03:00&quot;,
        &quot;rut_sender&quot;: &quot;11222333-9&quot;,
        &quot;rut_company&quot;: &quot;88888888-8&quot;,
        &quot;retry_after&quot;: 5,
        &quot;location&quot;: &quot;https://apicert.sii.cl/recursos/v1/boleta.electronica.envio/88888888-8-33790541&quot;,
        &quot;rate_limit&quot;: {
            &quot;limit&quot;: 10,
            &quot;remaining&quot;: 10,
            &quot;reset&quot;: 1
        },
        &quot;file&quot;: &quot;libredte_boleta.xml&quot;
    }
}
```

| Campo | Qué es |
|-------|--------|
| `track_id` | El número de seguimiento del envío. **Guárdalo inmediatamente**: con él consultas el estado. |
| `status` | El estado del envío al recibirlo: `REC`, recibido. |
| `received_at` | Fecha y hora en que el SII recibió el sobre. |
| `rut_sender` | El RUT de quien envía: la persona del certificado. |
| `rut_company` | El RUT de la empresa emisora. |
| `retry_after` | Los segundos que el SII pide esperar **antes de consultar el estado** del envío. Es parte normal de la respuesta, no un error. Puede venir en `null`. |
| `rate_limit` | El límite de solicitudes que informa el servicio de boletas del SII: cuántas permite (`limit`), cuántas quedan (`remaining`) y en cuántos segundos se reinicia la cuenta (`reset`). Puede venir en `null`. |
| `location` | La ruta del SII para consultar el resultado del envío. No necesitas guardarla: el estado se consulta con el Track ID. |
| `file` | El nombre con que la API subió el archivo al SII. |

## Para los dos envíos

&gt; [!WARNING] Indica siempre el ambiente
&gt;
&gt; Si no envías `options.environment`, el documento se envía a **producción**. Durante el desarrollo usa siempre `&quot;environment&quot;: 1`, y asegúrate de que el CAF y la resolución sean del mismo ambiente al que envías.

&gt; [!INFO] Recibido no es aceptado
&gt;
&gt; Que el SII entregue un Track ID solo significa que **recibió** el sobre. Todavía puede rechazarlo por un error en los datos, en la firma o en la carátula. Para saber el resultado tienes que consultar el estado.

## Errores frecuentes en este paso

| Situación | Causa probable | Qué hacer |
|-----------|----------------|-----------|
| `No fue posible obtener el token para autenticar en el SII al usuario ...` | El SII no aceptó el certificado: no es válido, está vencido, es autofirmado, o la persona no está registrada en el SII para la empresa. | Revisa el certificado y que esa persona sea usuario autorizado de la empresa en el SII. |
| Error al enviar el XML | El SII no respondió o rechazó el archivo al recibirlo. | Revisa el mensaje de `detail` y reintenta más tarde si es un problema del SII. |
| RUT inválido | `company` mal escrito. | Usa el RUT sin puntos y con guion. |
| `El XML es un EnvioBOLETA y no se puede enviar con el worker de DTE, las boletas se envían con el worker de boletas.` | Enviaste un sobre de boletas con `sii_dte`. | Envía los sobres `EnvioBOLETA` con `sii_boleta/sendXmlDocument`. Revisa el `tag` del sobre antes de elegir la operación. |
| Boletas: `rate_limit.remaining` en `0` | Usaste todas las solicitudes que permite el servicio de boletas del SII. | Espera los segundos de `rate_limit.reset` antes de volver a llamar. |

## Si el SII no está disponible

El SII a veces está lento o fuera de servicio. Como el documento ya está construido y firmado, no lo pierdes:

1. Guarda el documento con estado &quot;error de envío&quot;.
2. Reintenta el envío más tarde (por ejemplo, cada 15 o 30 minutos) con un proceso automático.
3. Si los reintentos fallan por mucho tiempo, avisa a un responsable.

&gt; [!WARNING] Nunca construyas de nuevo un documento solo porque falló el envío
&gt;
&gt; Si construyes de nuevo, obtienes otro XML con otra firma para el mismo folio. Reintenta el envío del **mismo sobre** que ya tenías.


    
---

### Paso 5: Consultar el estado (obligatorio)

Cómo saber si el SII aceptó, aceptó con reparos o rechazó el envío de facturas, notas, guías o boletas, cómo interpretar los estados y cómo obtener el detalle de un rechazo.

# Paso 5: Consultar el estado (obligatorio)

El SII procesa los envíos en segundo plano. Con el **Track ID** del paso anterior consultas en qué va el procesamiento y, al final, si los documentos fueron aceptados o rechazados.

## Qué operación usar

Se consulta con el mismo servicio con que enviaste:

| Enviaste con | Consulta con |
|--------------|--------------|
| `sii_dte/sendXmlDocument` (sobre `EnvioDTE`) | `billing/integration/sii_dte/checkXmlDocumentSentStatus` |
| `sii_boleta/sendXmlDocument` (sobre `EnvioBOLETA`) | `billing/integration/sii_boleta/checkXmlDocumentSentStatus` |

Las dos reciben los mismos parámetros. Usa el mismo ambiente (`environment`) que usaste al enviar.

## 5.1. Facturas, notas y guías

### La solicitud

```
POST https://app.apigateway.cl/api/v2/libredte/billing/integration/sii_dte/checkXmlDocumentSentStatus
```

```json
{
    &quot;parameters&quot;: {
        &quot;request&quot;: {
            &quot;certificate&quot;: {
                &quot;certificate&quot;: &quot;-----BEGIN CERTIFICATE-----\nMIIG...\n-----END CERTIFICATE-----&quot;,
                &quot;privateKey&quot;: &quot;-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----&quot;
            },
            &quot;options&quot;: {
                &quot;environment&quot;: 1
            }
        },
        &quot;trackId&quot;: 4753411374,
        &quot;company&quot;: &quot;88888888-8&quot;
    }
}
```

### La respuesta

```json
{
    &quot;data&quot;: {
        &quot;query_number&quot;: 532120,
        &quot;query_datetime&quot;: &quot;2026-10-30T09:31:02&quot;,
        &quot;track_id&quot;: 4753411374,
        &quot;company&quot;: &quot;88888888-8&quot;,
        &quot;status&quot;: &quot;EPR&quot;,
        &quot;error&quot;: false,
        &quot;description&quot;: &quot;Envío Procesado&quot;,
        &quot;resume&quot;: {
            &quot;reported&quot;: 1,
            &quot;accepted&quot;: 1,
            &quot;rejected&quot;: 0,
            &quot;repairs&quot;: 0
        },
        &quot;documents&quot;: {
            &quot;33&quot;: {
                &quot;type&quot;: 33,
                &quot;reported&quot;: 1,
                &quot;accepted&quot;: 1,
                &quot;rejected&quot;: 0,
                &quot;repairs&quot;: 0
            }
        }
    }
}
```

| Campo | Qué es |
|-------|--------|
| `status` | Código del estado del envío (ver tabla). |
| `error` | `true` si el envío fue rechazado o hubo un error en la consulta. |
| `description` | Glosa del estado que entrega el SII. |
| `resume` | Cuántos documentos se informaron, aceptaron, rechazaron o tienen reparos. |
| `documents` | El mismo resumen, por tipo de documento. |
| `query_number`, `query_datetime` | El número y la fecha de la consulta en el SII. |

### Los estados del envío

| `status` | Significado | ¿Es final? | Qué hacer |
|----------|-------------|------------|-----------|
| `SOK` | Esquema validado | No | Consulta de nuevo más tarde |
| `CRT` | Carátula OK | No | Consulta de nuevo más tarde |
| `FOK` | Firma del envío validada | No | Consulta de nuevo más tarde |
| `PDR` | Envío en proceso | No | Consulta de nuevo más tarde |
| `EPR` | **Envío procesado** | Sí | Revisa `resume` (ver abajo) |
| `RSC` | Rechazado por error en el esquema | Sí | Corrige el XML y emite de nuevo, con el mismo folio |
| `RFR` | Rechazado por error en la firma | Sí | Revisa el certificado y emite de nuevo, con el mismo folio |
| `RCT` | Rechazado por error en la carátula | Sí | Revisa el emisor, la resolución y el ambiente del sobre |

Cuando el estado es `EPR`, el resultado de cada documento está en `resume`:

| Resultado | Cómo se ve | Significado |
|-----------|------------|-------------|
| **Aceptado** | `accepted` = `reported` | El documento es válido. |
| **Aceptado con reparos** | `repairs` &gt; 0 | El documento es válido, pero tiene observaciones menores. Revísalas para corregir los siguientes documentos. |
| **Rechazado** | `rejected` &gt; 0 | El documento **no es válido**. Hay que corregirlo y emitirlo de nuevo, con el mismo folio. |

&gt; [!INFO] Los códigos negativos
&gt;
&gt; Si `status` es un número negativo (por ejemplo `-11`) o un código como `001`, es un error de la **consulta** (no del documento): el Track ID no existe, el usuario no está autorizado o la sesión del SII expiró. Revisa `description` y que el RUT de `company` sea el mismo con que enviaste.

### ¿Por qué fue rechazado?

El estado indica **que** un documento fue rechazado, pero no siempre **por qué**. Para obtener el detalle, pide al SII que te envíe el resultado por correo:

```
POST https://app.apigateway.cl/api/v2/libredte/billing/integration/sii_dte/requestXmlDocumentSentStatusByEmail
```

```json
{
    &quot;parameters&quot;: {
        &quot;request&quot;: {
            &quot;certificate&quot;: { &quot;certificate&quot;: &quot;-----BEGIN CERTIFICATE-----\nMIIG...\n-----END CERTIFICATE-----&quot;, &quot;privateKey&quot;: &quot;-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----&quot; },
            &quot;options&quot;: { &quot;environment&quot;: 1 }
        },
        &quot;trackId&quot;: 4753411374,
        &quot;company&quot;: &quot;88888888-8&quot;
    }
}
```

La respuesta confirma que el SII recibió la solicitud:

```json
{
    &quot;data&quot;: {
        &quot;company&quot;: &quot;88888888-8&quot;,
        &quot;track_id&quot;: 4753411374,
        &quot;status&quot;: &quot;0&quot;,
        &quot;description&quot;: &quot;Requerimiento recibido OK.&quot;
    }
}
```

El SII envía el detalle de los rechazos al **correo configurado en el SII** para la empresa (no se puede elegir otro desde la API).

## 5.2. Boletas

### La solicitud

```
POST https://app.apigateway.cl/api/v2/libredte/billing/integration/sii_boleta/checkXmlDocumentSentStatus
```

Los parámetros son **los mismos de 5.1** (`request`, `trackId` y `company`), con el Track ID que entregó `sii_boleta/sendXmlDocument`.

### La respuesta

Mientras el SII procesa el envío, el estado no es final y todavía no hay resultados:

```json
{
    &quot;data&quot;: {
        &quot;track_id&quot;: 33790541,
        &quot;company&quot;: &quot;88888888-8&quot;,
        &quot;status&quot;: &quot;SOK&quot;,
        &quot;error&quot;: false,
        &quot;description&quot;: &quot;Schema validado&quot;,
        &quot;resume&quot;: {
            &quot;reported&quot;: 0,
            &quot;accepted&quot;: 0,
            &quot;rejected&quot;: 0,
            &quot;repairs&quot;: 0
        },
        &quot;documents&quot;: [],
        &quot;received_at&quot;: &quot;2026-11-04T12:18:29-03:00&quot;,
        &quot;sender&quot;: &quot;11222333-9&quot;,
        &quot;retry_after&quot;: null,
        &quot;location&quot;: null,
        &quot;rate_limit&quot;: null,
        &quot;details&quot;: []
    }
}
```

Cuando el estado es final, `resume` y `documents` traen los resultados, igual que en 5.1. Si el SII rechazó algo, `error` es `true` y `details` explica el motivo. En este ejemplo el SII rechazó el envío completo por un error de schema: el giro del emisor superaba el largo máximo.

```json
{
    &quot;data&quot;: {
        &quot;track_id&quot;: 33790541,
        &quot;company&quot;: &quot;88888888-8&quot;,
        &quot;status&quot;: &quot;RSC&quot;,
        &quot;error&quot;: true,
        &quot;description&quot;: &quot;Rechazado por schema&quot;,
        &quot;resume&quot;: {
            &quot;reported&quot;: 0,
            &quot;accepted&quot;: 0,
            &quot;rejected&quot;: 0,
            &quot;repairs&quot;: 0
        },
        &quot;documents&quot;: [],
        &quot;received_at&quot;: &quot;2026-11-04T12:18:29-03:00&quot;,
        &quot;sender&quot;: &quot;11222333-9&quot;,
        &quot;retry_after&quot;: null,
        &quot;location&quot;: null,
        &quot;rate_limit&quot;: null,
        &quot;details&quot;: [
            {
                &quot;type&quot;: null,
                &quot;folio&quot;: null,
                &quot;status&quot;: &quot;RCH&quot;,
                &quot;description&quot;: &quot;DTE Rechazado&quot;,
                &quot;errors&quot;: [
                    {
                        &quot;section&quot;: &quot;ENV&quot;,
                        &quot;line&quot;: 0,
                        &quot;level&quot;: 3,
                        &quot;code&quot;: 0,
                        &quot;description&quot;: &quot;Error en Schema&quot;,
                        &quot;detail&quot;: &quot;[0] LSX-00222: \&quot;VENTA AL POR MENOR DE COMPUTADORES, EQUIPO PERIFERICO, PROGR&quot;
                    }
                ]
            }
        ]
    }
}
```

| Campo | Qué es |
|-------|--------|
| `status` | Código del estado del envío (ver tabla). |
| `error` | `true` si el envío o alguna boleta fue rechazada. |
| `description` | Explicación del estado. |
| `resume` | Cuántas boletas se informaron, aceptaron, rechazaron o tienen reparos. |
| `documents` | El mismo resumen, por tipo de documento (`39` o `41`). Mientras no hay resultados, viene vacío (`[]`). |
| `details` | **Una entrada por cada problema**: una boleta rechazada o con reparos, o el envío completo si el rechazo es de todo el sobre. Si no hay problemas, viene vacío. |
| `received_at`, `sender` | Cuándo recibió el SII el sobre y quién lo envió. |
| `retry_after`, `rate_limit` | La espera que pide el SII y el límite de solicitudes del servicio de boletas (ver [paso 4](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-4-enviar-al-sii#42-boletas)). Pueden venir en `null`. |

### Los estados del envío de boletas

| `status` | Significado | ¿Es final? | Qué hacer |
|----------|-------------|------------|-----------|
| `REC` | Envío recibido | No | Consulta de nuevo más tarde |
| `SOK` | Schema validado | No | Consulta de nuevo más tarde |
| `CRT` | Carátula OK | No | Consulta de nuevo más tarde |
| `FOK` | Firma del envío validada | No | Consulta de nuevo más tarde |
| `PRD` | Envío en proceso | No | Consulta de nuevo más tarde |
| `EPR` | **Envío procesado** | Sí | Revisa `resume` y `details` |
| `RPR` | Aceptado con reparos | Sí | Revisa `details` para corregir las siguientes boletas |
| `RCH` | Rechazado por errores en la información | Sí | Revisa `details`, corrige y emite de nuevo, con el mismo folio |
| `RCO` | Rechazado por consistencia | Sí | Revisa `details`, corrige y emite de nuevo, con el mismo folio |
| `RSC` | Rechazado por schema | Sí | Corrige el XML y emite de nuevo, con el mismo folio |
| `RFR` | Rechazado por error en la firma | Sí | Revisa el certificado y emite de nuevo, con el mismo folio |
| `RCT` | Rechazado por error en la carátula | Sí | Revisa el emisor, la resolución y el ambiente del sobre |
| `RPT` | Envío repetido rechazado | Sí | Ese sobre ya se había enviado: consulta el estado con el Track ID del primer envío |
| `VOF` | No se encontró el archivo XML | Sí | Envía de nuevo el mismo sobre |

En los estados de rechazo, `error` es `true`.

### ¿Por qué fue rechazada una boleta?

A diferencia de las facturas, notas y guías, el detalle viene **en la misma respuesta**, en `details`. Cada entrada tiene:

| Campo | Qué es |
|-------|--------|
| `type` y `folio` | Qué boleta es. Vienen en `null` cuando el rechazo es de todo el envío, como en el ejemplo. |
| `status` | `DOK` aceptada, `RLV` aceptada con reparos leves, `RPR` aceptada con reparos, `RCH` rechazada. |
| `description` | Explicación del estado. |
| `errors` | Los problemas encontrados. `section` es la parte del documento (`ENV` envío, `CRT` carátula, `HED` encabezado, `DET` detalle, `REF` referencias, `TED` timbre, `CAF` folios, `DTE` documento); `level` es la gravedad (`1` reparo leve, `2` reparo, `3` rechazo); `description` y `detail` explican el problema. |

## Qué hacer con el folio según el resultado

La regla es la misma para facturas, notas, guías y boletas, y vale tanto si el SII rechaza el envío completo como si rechaza solo un documento dentro de un envío procesado:

| Resultado | ¿Es válido? | El folio | Qué hacer |
|-----------|-------------|----------|-----------|
| **Aceptado** | Sí | Queda usado. | Guarda el estado. |
| **Aceptado con reparos** | Sí | Queda usado: **no se puede volver a usar**. | Revisa los reparos para no repetirlos en los documentos siguientes. |
| **Rechazado** | No: el SII lo considera no emitido. | Queda libre: **se puede volver a usar**. | Corrige los datos y emite el documento de nuevo **con el mismo folio**: constrúyelo otra vez (paso 1), arma un sobre nuevo (paso 3) y envíalo (paso 4). |

&gt; [!WARNING] Un rechazo no es un envío fallido
&gt;
&gt; Si el envío **falló** (el SII no respondió y no tienes Track ID), el documento no se construye de nuevo: reintenta el envío del mismo sobre. Solo cuando el SII **rechazó** el documento lo construyes otra vez, corregido y con el mismo folio.

## Cada cuánto consultar

El SII suele procesar un envío en pocos minutos, pero puede demorar más en horas de alta carga. Una estrategia razonable:

1. Espera unos 30 segundos después del envío antes de la primera consulta.
2. Si el estado no es final, vuelve a consultar con esperas cada vez más largas (1, 2, 5, 10 minutos...).
3. Si después de varias horas sigue sin estado final, márcalo para revisión.

Un estado es final cuando ya no va a cambiar. Cualquier otro código significa que el SII sigue procesando, o que la consulta misma falló (por ejemplo, un código negativo): en los dos casos se vuelve a consultar más tarde. Esta función sirve para facturas y boletas; solo cambia el worker. Usa la función `libredte()` de [Tu primera llamada](https://www.apigateway.cl/academy/emision-de-dte/preparacion/tu-primera-llamada#en-python):

```python
import time

ESTADOS_FINALES = {&#039;EPR&#039;, &#039;LOK&#039;, &#039;RPR&#039;, &#039;RLV&#039;, &#039;RCH&#039;, &#039;RCO&#039;, &#039;RFR&#039;, &#039;RSC&#039;, &#039;RCT&#039;, &#039;RPT&#039;, &#039;VOF&#039;}


def esperar_estado(worker: str, request_sii: dict, track_id: int, company: str,
                   espera_inicial: int = 30) -&gt; dict | None:
    &quot;&quot;&quot;Consulta el estado hasta que sea final.

    worker: &#039;sii_dte&#039; (facturas, notas y guías) o &#039;sii_boleta&#039; (boletas).
    espera_inicial: en boletas, usa max(30, retry_after or 0) de la respuesta del envío.
    Entrega el estado final, o None si se acabaron las esperas sin estado final.
    &quot;&quot;&quot;
    for espera in [espera_inicial, 60, 120, 300, 600, 1800, 3600, 7200]:   # segundos
        time.sleep(espera)
        try:
            estado = libredte(f&#039;billing/integration/{worker}/checkXmlDocumentSentStatus&#039;, {
                &#039;request&#039;: request_sii,
                &#039;trackId&#039;: track_id,
                &#039;company&#039;: company,
            })
        except RuntimeError:
            continue   # La consulta falló (por ejemplo, el SII no respondió): se reintenta.
        if estado[&#039;status&#039;] in ESTADOS_FINALES:
            return estado
    return None   # Sin estado final: márcalo para revisión.
```

Por ejemplo, para una factura: `esperar_estado(&#039;sii_dte&#039;, {&#039;certificate&#039;: CERTIFICADO, &#039;options&#039;: {&#039;environment&#039;: 1}}, track_id, &#039;88888888-8&#039;)`.

&gt; [!TIP] Consulta desde un proceso en segundo plano
&gt;
&gt; No hagas esperar al usuario mientras el SII procesa. Emite, envía, guarda el Track ID y deja que un proceso programado (cron, cola de tareas) consulte los estados pendientes.

## Verificar un documento puntual

Cuando un documento ya fue aceptado, puedes verificar que exista en el SII y que sus datos coincidan.

### Facturas, notas y guías

Usa el recurso de **Documentos Emitidos**, con el tipo, el folio, la fecha, el monto y el receptor:

```bash
curl -X POST &quot;https://app.apigateway.cl/api/v2/sii/dte/emitidos/verificar?certificacion=1&quot; \
  -H &quot;Authorization: Token $API_TOKEN&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d &#039;{
    &quot;auth&quot;: {
        &quot;cert&quot;: {
            &quot;cert-data&quot;: &quot;-----BEGIN CERTIFICATE-----\nMIIG...\n-----END CERTIFICATE-----&quot;,
            &quot;pkey-data&quot;: &quot;-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----&quot;
        }
    },
    &quot;dte&quot;: {
        &quot;emisor&quot;: &quot;88888888-8&quot;,
        &quot;dte&quot;: 33,
        &quot;folio&quot;: 1,
        &quot;fecha&quot;: &quot;2026-10-29&quot;,
        &quot;total&quot;: 119000,
        &quot;receptor&quot;: &quot;77777777-7&quot;
    }
}&#039;
```

La respuesta:

```json
{
    &quot;data&quot;: {
        &quot;status&quot;: &quot;DOK&quot;,
        &quot;detalle&quot;: &quot;Documento recibido por el SII. Datos coinciden con los registrados.&quot;,
        &quot;track_id&quot;: 4753411374,
        &quot;razon_social&quot;: &quot;MI EMPRESA SPA&quot;
    }
}
```

| `status` | Significado |
|----------|-------------|
| `DOK` | Documento recibido por el SII. Los datos coinciden. |
| `DNK` | Documento recibido por el SII, pero los datos **no** coinciden. |
| `FAU` | El SII no ha recibido un documento con ese folio. |
| `FNA` | El folio no está autorizado por el SII. |

`track_id` es el del envío en que llegó el documento (`0` si el SII no lo informa) y `razon_social` es la del emisor según el SII (`null` si no viene).

### Boletas

Usa `sii_boleta/validateDocument`. El SII exige todos los datos: el tipo, el folio, la fecha, el total y el receptor.

```
POST https://app.apigateway.cl/api/v2/libredte/billing/integration/sii_boleta/validateDocument
```

```json
{
    &quot;parameters&quot;: {
        &quot;request&quot;: {
            &quot;certificate&quot;: {
                &quot;certificate&quot;: &quot;-----BEGIN CERTIFICATE-----\nMIIG...\n-----END CERTIFICATE-----&quot;,
                &quot;privateKey&quot;: &quot;-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----&quot;
            },
            &quot;options&quot;: {
                &quot;environment&quot;: 1
            }
        },
        &quot;company&quot;: &quot;88888888-8&quot;,
        &quot;document&quot;: 39,
        &quot;number&quot;: 1,
        &quot;date&quot;: &quot;2026-11-04&quot;,
        &quot;total&quot;: 23800,
        &quot;recipient&quot;: &quot;66666666-6&quot;
    }
}
```

| Parámetro | Qué es |
|-----------|--------|
| `company` | El RUT del emisor. |
| `document` | El tipo de boleta: `39` o `41`. |
| `number` | El folio. |
| `date` | La fecha de emisión (`AAAA-MM-DD`). |
| `total` | El total de la boleta. |
| `recipient` | El RUT del receptor (`66666666-6` si no se identificó). |

La respuesta:

```json
{
    &quot;data&quot;: {
        &quot;status&quot;: &quot;DOK&quot;,
        &quot;description&quot;: &quot;Documento Recibido por el SII. Datos Coinciden con los Registrados&quot;,
        &quot;rate_limit&quot;: null
    }
}
```

Los códigos que puede traer `status`:

| `status` | Significado |
|----------|-------------|
| `DOK` | Boleta recibida por el SII. Los datos coinciden. |
| `DNK` | Boleta recibida por el SII, pero los datos **no** coinciden. |
| `FAU` | El SII no ha recibido una boleta con ese folio. |
| `FNA` | El folio no está autorizado por el SII. |
| `FAN` | La boleta fue anulada. |
| `EMP` | La empresa no está autorizada a emitir documentos electrónicos. |
| `ANC`, `MMC`, `TMC` | Una nota de crédito anula la boleta, modifica sus montos o modifica su texto. |
| `AND`, `MMD`, `TMD` | Una nota de débito anula la boleta, modifica sus montos o modifica su texto. |

&gt; [!NOTE] Otra forma de consultar el estado de facturas, notas y guías
&gt;
&gt; El recurso `POST /api/v2/sii/dte/emitidos/estado_envio/{emisor}/{trackId}` también entrega el estado de un envío `EnvioDTE`, con el certificado en `auth.cert`. Revisa la [documentación de la API](https://www.apigateway.cl/docs/api) en **API DTE - Documentos Emitidos**.


    
---

### Paso 6: Generar el PDF (opcional)

Cómo generar la representación impresa del DTE con renderer/render: copias tributaria y cedible, formatos y diseños disponibles.

# Paso 6: Generar el PDF (opcional)

El cliente no lee XML: necesita un documento para ver, imprimir o archivar. La operación **`renderer/render`** genera la **representación impresa** del documento, con el timbre electrónico dibujado como código de barras (el que el SII llama PDF417). Es la misma operación para todos los documentos, incluidas las boletas.

&gt; [!NOTE] ¿Por qué es opcional?
&gt;
&gt; El documento con validez legal es el XML, no el PDF, y la API no exige generarlo. Pero el cliente necesita un documento que pueda ver o imprimir, así que en la práctica casi todas las integraciones lo generan.

## La solicitud

```
POST https://app.apigateway.cl/api/v2/libredte/billing/document/renderer/render
```

```json
{
    &quot;parameters&quot;: {
        &quot;bag&quot;: {
            &quot;xmlDocument&quot;: &quot;PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iSVNPLTg4NTktMSI/Pgo8RFRF...&quot;,
            &quot;emisor&quot;: {
                &quot;rut&quot;: &quot;88888888-8&quot;,
                &quot;razon_social&quot;: &quot;Mi Empresa SpA&quot;,
                &quot;autorizacion_dte&quot;: {
                    &quot;fecha_resolucion&quot;: &quot;2025-11-20&quot;,
                    &quot;numero_resolucion&quot;: 0
                }
            },
            &quot;options&quot;: {
                &quot;renderer&quot;: {
                    &quot;format&quot;: &quot;pdf&quot;
                }
            }
        }
    }
}
```

| Campo | Qué es |
|-------|--------|
| `xmlDocument` | El `document_xml` del [paso 1](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-1-construir-el-dte). El PDF se genera desde el XML, así que siempre muestra exactamente lo que se envió al SII. |
| `emisor.autorizacion_dte` | La [resolución del emisor](https://www.apigateway.cl/academy/emision-de-dte/fundamentos/resolucion-de-autorizacion), la misma del sobre. Se imprime al pie del timbre como &quot;Resolución 0 del 2025&quot;. |

&gt; [!WARNING] No olvides la resolución
&gt;
&gt; El XML del DTE no incluye la resolución, así que la API no puede deducirla. Si no envías `emisor.autorizacion_dte`, el PDF se genera igual, pero **sin** la línea de la resolución, que debe aparecer en la representación impresa.

## La respuesta

```json
{
    &quot;data&quot;: {
        &quot;renderings&quot;: [
            {
                &quot;label&quot;: &quot;tributaria&quot;,
                &quot;mimeType&quot;: &quot;application/pdf&quot;,
                &quot;filename&quot;: &quot;LibreDTE_88888888-8_T033F000000000001_tributaria.pdf&quot;,
                &quot;copies&quot;: 1,
                &quot;copyNumber&quot;: 1,
                &quot;content&quot;: &quot;JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlIC9QYWdlCi9QYXJlbnQg...&quot;
            }
        ]
    }
}
```

`content` es el archivo en base64. Para guardarlo:

```python
import base64

resultado = libredte(&#039;billing/document/renderer/render&#039;, {
    &#039;bag&#039;: {
        &#039;xmlDocument&#039;: document_xml,  # El document_xml del paso 1.
        &#039;emisor&#039;: EMISOR,  # rut, razon_social y autorizacion_dte, como en el sobre.
        &#039;options&#039;: {&#039;renderer&#039;: {&#039;format&#039;: &#039;pdf&#039;}},
    },
})
for archivo in resultado[&#039;renderings&#039;]:
    with open(archivo[&#039;filename&#039;], &#039;wb&#039;) as f:
        f.write(base64.b64decode(archivo[&#039;content&#039;]))
```

## Copia tributaria y copia cedible

| Copia | Para qué |
|-------|----------|
| **Tributaria** | La copia normal del documento. Es la que se genera por defecto. |
| **Cedible** | Una copia con la leyenda &quot;CEDIBLE&quot; y el acuse de recibo, que el cliente firma al recibir la mercadería. Se usa para **ceder** la factura (factoring). |

Las **boletas** solo tienen copia tributaria: no se ceden.

Pide las copias que necesites, y cuántas de cada una, con `renderings`:

```json
&quot;options&quot;: {
    &quot;renderer&quot;: {
        &quot;format&quot;: &quot;pdf&quot;,
        &quot;renderings&quot;: {
            &quot;tributaria&quot;: 1,
            &quot;cedible&quot;: 1
        }
    }
}
```

La respuesta trae un elemento en `renderings` por cada copia, con su propio `label` y `filename`.

&gt; [!INFO] La copia cedible no aplica a todos los documentos
&gt;
&gt; Si pides una copia cedible de un documento que no la admite (por ejemplo, una nota de crédito o una boleta), esa copia simplemente no aparece en la respuesta. No es un error.

## Diseños y formatos

| Opción | Valores | Por defecto |
|--------|---------|-------------|
| `format` | `pdf` o `html` | `pdf` |
| `strategy` | `template.estandar`, `template.general`, `template.servicios_basicos` | `template.estandar` |

```json
&quot;options&quot;: {
    &quot;renderer&quot;: {
        &quot;strategy&quot;: &quot;template.general&quot;,
        &quot;format&quot;: &quot;pdf&quot;
    }
}
```

- **`template.estandar`**: el diseño de LibreDTE, para uso general.
- **`template.general`**: otro diseño para documentos de empresa.
- **`template.servicios_basicos`**: pensado para empresas de servicios básicos.
- **`html`**: entrega el documento en HTML, útil para mostrarlo dentro de tu sistema.

&gt; [!TIP] Muestra al cliente los datos que quieras que vea
&gt;
&gt; El PDF muestra lo que está en el XML. Si quieres que aparezcan el teléfono y el correo del emisor, el correo del cliente o un código de producto, inclúyelos en los datos del [paso 1](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-1-construir-el-dte).

&gt; [!NOTE] Impresoras térmicas
&gt;
&gt; Para puntos de venta con impresora térmica existe además una estrategia que genera comandos ESC/POS. Si la necesitas, revisa la ficha de la operación en la [documentación de la API](https://www.apigateway.cl/docs/api) o [abre un ticket](https://www.apigateway.cl/help).

## Entregar el documento al receptor

Cuando el SII acepta el documento, entrégalo al receptor. **Esto lo hace tu sistema**:

| Receptor | Qué le entregas |
|----------|-----------------|
| Una persona, o una empresa que no emite documentos electrónicos | El PDF. |
| Una empresa que emite documentos electrónicos | El PDF y **el XML** del documento, en un sobre dirigido a ella, enviado a su **correo de intercambio** (el que la empresa registró en el SII). |

Enviarle el XML a una empresa receptora es una obligación del emisor: con ese XML la empresa registra la compra y puede aceptar o reclamar el documento. Las boletas se entregan siempre como PDF (o impresas), porque el receptor es un consumidor final.

## ¿Se puede generar el PDF antes de enviar al SII?

Sí. El PDF solo necesita el XML, así que puedes generarlo apenas construyes el documento, por ejemplo para una vista previa. Para entregarlo al cliente, lo recomendable es esperar a que el SII lo acepte: si el SII lo rechaza, ese documento no tiene validez y el cliente tendría un documento que no sirve.


    
---

## Casos prácticos



---

### Factura de principio a fin

Un programa completo en Python que construye, valida, envía al SII, consulta el estado y genera el PDF de una factura electrónica.

# Factura de principio a fin

En este caso juntamos los seis pasos en un solo programa. Emite una factura afecta (`33`) en el **ambiente de certificación** del SII.

## Lo que necesitas

| Archivo o dato | Dónde se explica |
|----------------|------------------|
| Token de API Gateway | [Primeros pasos](https://www.apigateway.cl/academy/primeros-pasos) |
| Certificado digital en PEM: `cert.pem` y `key.pem` | [El certificado digital](https://www.apigateway.cl/academy/emision-de-dte/preparacion/certificado-digital) |
| CAF de facturas (`33`) del ambiente de certificación | [Folios y CAF](https://www.apigateway.cl/academy/emision-de-dte/preparacion/folios-y-caf) |
| Fecha de la resolución en certificación | [Resolución de autorización](https://www.apigateway.cl/academy/emision-de-dte/fundamentos/resolucion-de-autorizacion) |

&gt; [!TIP] ¿Aún no tienes CAF de certificación?
&gt;
&gt; Puedes probar los pasos 1, 2, 3 y 6 con un CAF y un certificado de prueba. Te explicamos cómo en [Probar sin el SII](#probar-sin-el-sii).

## El programa

Instala `requests` (`pip install requests`) y define la variable de entorno `API_TOKEN`. Deja en la misma carpeta los archivos `cert.pem`, `key.pem` y `caf_33.xml`.

```python
&quot;&quot;&quot;Emite una factura electrónica en el ambiente de certificación del SII.&quot;&quot;&quot;
import base64
import os
import time

import requests

API_URL = &#039;https://app.apigateway.cl/api/v2/libredte&#039;
HEADERS = {
    &#039;Authorization&#039;: f&#039;Token {os.environ[&quot;API_TOKEN&quot;]}&#039;,
    &#039;Content-Type&#039;: &#039;application/json&#039;,
}

AMBIENTE = 1  # 1: certificación, 0: producción.
SII_RUT = &#039;60803000-K&#039;

# Estados del envío que ya no cambian (ver el paso 5). Los demás significan
# que el SII sigue procesando, o que la consulta falló y hay que repetirla.
ESTADOS_FINALES = {&#039;EPR&#039;, &#039;LOK&#039;, &#039;RPR&#039;, &#039;RLV&#039;, &#039;RCH&#039;, &#039;RCO&#039;, &#039;RFR&#039;, &#039;RSC&#039;, &#039;RCT&#039;, &#039;RPT&#039;, &#039;VOF&#039;}
ESTADOS_ACEPTADOS = {&#039;EPR&#039;, &#039;LOK&#039;, &#039;RPR&#039;, &#039;RLV&#039;}


def libredte(operacion: str, parameters: dict) -&gt; dict | list | None:
    &quot;&quot;&quot;Ejecuta una operación de LibreDTE y entrega el contenido de `data`.&quot;&quot;&quot;
    response = requests.post(
        f&#039;{API_URL}/{operacion}&#039;,
        json={&#039;parameters&#039;: parameters},
        headers=HEADERS,
        timeout=120,
    )
    if response.status_code != 200:
        try:
            detalle = response.json().get(&#039;detail&#039;, response.text)
        except ValueError:  # La respuesta de error no viene en JSON.
            detalle = response.text
        raise RuntimeError(f&#039;{operacion}: HTTP {response.status_code}: {detalle}&#039;)
    return response.json()[&#039;data&#039;]


def leer_texto(ruta: str) -&gt; str:
    &quot;&quot;&quot;Lee un archivo de texto, como el certificado o la llave en PEM.&quot;&quot;&quot;
    with open(ruta, encoding=&#039;ascii&#039;) as archivo:
        return archivo.read()


def leer_base64(ruta: str) -&gt; str:
    &quot;&quot;&quot;Lee un archivo y lo entrega codificado en base64.&quot;&quot;&quot;
    with open(ruta, &#039;rb&#039;) as archivo:
        return base64.b64encode(archivo.read()).decode()


def guardar_base64(ruta: str, contenido: str) -&gt; None:
    &quot;&quot;&quot;Decodifica un base64 y lo guarda como archivo, sin tocar sus bytes.&quot;&quot;&quot;
    with open(ruta, &#039;wb&#039;) as archivo:
        archivo.write(base64.b64decode(contenido))


# Datos que normalmente vienen de tu base de datos.
CERTIFICADO = {
    &#039;certificate&#039;: leer_texto(&#039;cert.pem&#039;),
    &#039;privateKey&#039;: leer_texto(&#039;key.pem&#039;),
}
CAF = leer_base64(&#039;caf_33.xml&#039;)
EMISOR = {
    &#039;rut&#039;: &#039;88888888-8&#039;,
    &#039;razon_social&#039;: &#039;Mi Empresa SpA&#039;,
    &#039;autorizacion_dte&#039;: {
        &#039;fecha_resolucion&#039;: &#039;2025-11-20&#039;,  # Fecha de autorización en certificación.
        &#039;numero_resolucion&#039;: 0,            # En certificación siempre es 0.
    },
}
FOLIO = 1  # El siguiente folio libre del CAF, según tu control de folios.

# Paso 1: construir el DTE. Primero, los datos del documento.
datos = {
    &#039;Encabezado&#039;: {
        &#039;IdDoc&#039;: {&#039;TipoDTE&#039;: 33, &#039;Folio&#039;: FOLIO, &#039;FmaPago&#039;: 1},
        &#039;Emisor&#039;: {
            &#039;RUTEmisor&#039;: EMISOR[&#039;rut&#039;],
            &#039;RznSoc&#039;: EMISOR[&#039;razon_social&#039;],
            &#039;GiroEmis&#039;: &#039;Venta de software&#039;,
            &#039;Acteco&#039;: 620100,
            &#039;DirOrigen&#039;: &#039;Av. Siempre Viva 742&#039;,
            &#039;CmnaOrigen&#039;: &#039;Providencia&#039;,
        },
        &#039;Receptor&#039;: {
            &#039;RUTRecep&#039;: &#039;77777777-7&#039;,
            &#039;RznSocRecep&#039;: &#039;Cliente Ejemplo Ltda.&#039;,
            &#039;GiroRecep&#039;: &#039;Comercio&#039;,
            &#039;DirRecep&#039;: &#039;Calle Falsa 123&#039;,
            &#039;CmnaRecep&#039;: &#039;Santiago&#039;,
        },
    },
    &#039;Detalle&#039;: [
        {&#039;NmbItem&#039;: &#039;Servicio de desarrollo&#039;, &#039;QtyItem&#039;: 1, &#039;PrcItem&#039;: 100000},
        {&#039;NmbItem&#039;: &#039;Soporte técnico (horas)&#039;, &#039;QtyItem&#039;: 3, &#039;PrcItem&#039;: 25000},
    ],
}

# Con los datos, el CAF y el certificado se obtiene el DTE timbrado y firmado.
dte = libredte(&#039;billing/document/builder/build&#039;, {
    &#039;bag&#039;: {&#039;parsedData&#039;: datos, &#039;caf&#039;: CAF, &#039;certificate&#039;: CERTIFICADO},
})
xml_dte = dte[&#039;document_xml&#039;]
guardar_base64(f&#039;dte_33_{FOLIO}.xml&#039;, xml_dte)
totales = dte[&#039;document_normalized&#039;][&#039;Encabezado&#039;][&#039;Totales&#039;]
print(&#039;Documento construido:&#039;, dte[&#039;document_id&#039;], &#039;total&#039;, totales[&#039;MntTotal&#039;])

# Paso 2: validar el esquema antes de enviar.
libredte(&#039;billing/document/validator/validateSchema&#039;, {&#039;source&#039;: xml_dte})

# Paso 3: armar el sobre dirigido al SII.
sobre = libredte(&#039;billing/document/dispatcher/create&#039;, {
    &#039;bag&#039;: {
        &#039;xmlDocument&#039;: xml_dte,
        &#039;certificate&#039;: CERTIFICADO,
        &#039;emisor&#039;: EMISOR,
        &#039;receptor&#039;: {&#039;rut&#039;: SII_RUT},
    },
})
guardar_base64(f&#039;sobre_sii_33_{FOLIO}.xml&#039;, sobre[&#039;xml&#039;])

# Paso 4: enviar al SII.
request_sii = {&#039;certificate&#039;: CERTIFICADO, &#039;options&#039;: {&#039;environment&#039;: AMBIENTE}}
envio = libredte(&#039;billing/integration/sii_dte/sendXmlDocument&#039;, {
    &#039;request&#039;: request_sii,
    &#039;doc&#039;: sobre[&#039;xml&#039;],
    &#039;company&#039;: EMISOR[&#039;rut&#039;],
})
track_id = envio[&#039;track_id&#039;]
print(&#039;Enviado al SII, Track ID:&#039;, track_id)  # ¡Guárdalo en tu base de datos!

# Paso 5: consultar el estado hasta tener un resultado final.
estado = None
for espera in [30, 60, 120, 300, 600]:
    time.sleep(espera)
    try:
        estado = libredte(&#039;billing/integration/sii_dte/checkXmlDocumentSentStatus&#039;, {
            &#039;request&#039;: request_sii,
            &#039;trackId&#039;: track_id,
            &#039;company&#039;: EMISOR[&#039;rut&#039;],
        })
    except RuntimeError as error:
        # La consulta falló (por ejemplo, el SII no respondió): se reintenta.
        print(&#039;Falló la consulta, se reintenta:&#039;, error)
        continue
    print(&#039;Estado:&#039;, estado[&#039;status&#039;], estado[&#039;description&#039;])
    if estado[&#039;status&#039;] in ESTADOS_FINALES:
        break

resumen = estado[&#039;resume&#039;] if estado else {}
if not estado or estado[&#039;status&#039;] not in ESTADOS_FINALES:
    print(&#039;Sin estado final todavía. Vuelve a consultar más tarde con el Track ID&#039;, track_id)
elif estado[&#039;status&#039;] == &#039;RPT&#039;:
    print(&#039;El SII ya había recibido este sobre: consulta el estado con el Track ID del primer envío.&#039;)
elif estado[&#039;status&#039;] == &#039;VOF&#039;:
    print(&#039;El SII no encontró el archivo: envía de nuevo el mismo sobre (no lo construyas de nuevo).&#039;)
elif estado[&#039;status&#039;] in ESTADOS_ACEPTADOS and resumen.get(&#039;rejected&#039;, 0) == 0:
    resultado = &#039;aceptado con reparos&#039; if resumen.get(&#039;repairs&#039;) else &#039;aceptado&#039;
    print(&#039;Resultado:&#039;, resultado)

    # Paso 6: generar el PDF.
    pdf = libredte(&#039;billing/document/renderer/render&#039;, {
        &#039;bag&#039;: {
            &#039;xmlDocument&#039;: xml_dte,
            &#039;emisor&#039;: EMISOR,  # Con la resolución, que se imprime en el PDF.
            &#039;options&#039;: {&#039;renderer&#039;: {&#039;format&#039;: &#039;pdf&#039;, &#039;renderings&#039;: {&#039;tributaria&#039;: 1, &#039;cedible&#039;: 1}}},
        },
    })
    for archivo in pdf[&#039;renderings&#039;]:
        guardar_base64(archivo[&#039;filename&#039;], archivo[&#039;content&#039;])
        print(&#039;PDF generado:&#039;, archivo[&#039;filename&#039;])
else:
    # Para saber el motivo, pide el detalle por correo (ver el paso 5).
    print(&#039;El documento fue rechazado:&#039;, estado[&#039;status&#039;], estado[&#039;description&#039;])
```

## Probar sin el SII

Si todavía no tienes un CAF y un certificado reales del ambiente de certificación, puedes probar los pasos 1, 2, 3 y 6 con datos de prueba. Los pasos 4 y 5 no funcionan con ellos: el SII rechaza la autenticación y el programa se detiene en el envío.

1. **El certificado:** genera uno de prueba (ver [Un certificado de prueba](https://www.apigateway.cl/academy/emision-de-dte/preparacion/certificado-digital#un-certificado-de-prueba)) y guarda `cert` como `cert.pem` y `pkey` como `key.pem`.
2. **El CAF:** genera uno de prueba y guárdalo como `caf_33.xml`. Ejecuta esto una vez, con las funciones `libredte()` y `guardar_base64()` del programa. El CAF viene en base64 en el campo `xml`, y `guardar_base64()` lo decodifica al guardarlo:

```python
caf = libredte(&#039;billing/identifier/caf_faker/create&#039;, {
    &#039;emisor&#039;: {&#039;rut&#039;: &#039;88888888-8&#039;, &#039;razon_social&#039;: &#039;Mi Empresa SpA&#039;},
    &#039;codigoDocumento&#039;: 33,
    &#039;folioDesde&#039;: 1,
    &#039;folioHasta&#039;: 100,
})
guardar_base64(&#039;caf_33.xml&#039;, caf[&#039;xml&#039;])
```

3. **El programa:** borra todo lo que sigue a `# Paso 4: enviar al SII.` y pon en su lugar solo el paso 6, sin la condición de que el SII haya aceptado:

```python
# Paso 6: generar el PDF, sin pasar por el SII.
pdf = libredte(&#039;billing/document/renderer/render&#039;, {
    &#039;bag&#039;: {
        &#039;xmlDocument&#039;: xml_dte,
        &#039;emisor&#039;: EMISOR,
        &#039;options&#039;: {&#039;renderer&#039;: {&#039;format&#039;: &#039;pdf&#039;, &#039;renderings&#039;: {&#039;tributaria&#039;: 1, &#039;cedible&#039;: 1}}},
    },
})
for archivo in pdf[&#039;renderings&#039;]:
    guardar_base64(archivo[&#039;filename&#039;], archivo[&#039;content&#039;])
    print(&#039;PDF generado:&#039;, archivo[&#039;filename&#039;])
```

El documento que obtienes no tiene validez tributaria: el CAF es ficticio. Sirve para revisar los datos, los totales y el PDF.

## Qué hace, en orden

| Paso | Llamada | Qué guarda |
|------|---------|------------|
| 1 | `builder/build` | `dte_33_1.xml`: el documento timbrado y firmado |
| 2 | `validator/validateSchema` | (nada; falla si el XML no es válido) |
| 3 | `dispatcher/create` con `receptor` del SII | `sobre_sii_33_1.xml` |
| 4 | `sii_dte/sendXmlDocument` | El Track ID |
| 5 | `sii_dte/checkXmlDocumentSentStatus` | El estado final |
| 6 | `renderer/render` | Los PDF tributario y cedible |

## Para llevarlo a tu sistema

Este programa hace todo seguido para que lo entiendas de una vez. En un sistema real conviene separarlo:

1. **Al emitir** (cuando el usuario confirma la venta): reservar el folio, construir, validar, armar el sobre, enviar y guardar el Track ID. Responder al usuario.
2. **En segundo plano** (un proceso programado): consultar el estado de los envíos pendientes y actualizar cada documento.
3. **Cuando el documento es aceptado**: generar el PDF y entregarlo al cliente. Si el cliente es una empresa que emite documentos electrónicos, enviarle además el XML a su correo de intercambio (ver [Entregar el documento al receptor](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-6-generar-el-pdf#entregar-el-documento-al-receptor)).

Así ningún usuario espera al SII, y si algo falla en un paso, sabes exactamente desde dónde continuar.

&gt; [!NOTE] El mismo flujo en otros lenguajes
&gt;
&gt; Son solo solicitudes HTTP con JSON. Puedes traducir este programa a PHP, JavaScript, Java, C# o cualquier otro lenguaje usando su cliente HTTP habitual. Si usas un asistente de IA, cópiale esta página (ver [Cómo usar esta documentación](https://www.apigateway.cl/docs/como-usar-esta-documentacion)).


    
---

### Nota de crédito

Cómo anular una factura, corregir un texto o corregir un monto con una nota de crédito, y cuándo usar una nota de débito.

# Nota de crédito

Un documento aceptado por el SII **no se puede modificar ni eliminar**. Si tiene un error, o si cambió algo después de la venta, se corrige emitiendo una **nota de crédito** (`61`) que hace referencia al documento original.

El flujo de emisión es exactamente el mismo de una factura (construir, sobre, enviar, estado, PDF). Lo único que cambia son los datos: el `TipoDTE` es `61`, necesitas un **CAF de notas de crédito** y el documento lleva una **referencia**.

## Caso 1: anular una factura completa

Emitiste la factura folio `1` del `2026-10-29` (la del programa [Factura de principio a fin](https://www.apigateway.cl/academy/emision-de-dte/casos-practicos/factura-de-principio-a-fin), con dos ítems) y la venta se canceló. La nota de crédito repite los ítems de la factura y la anula:

```json
{
    &quot;Encabezado&quot;: {
        &quot;IdDoc&quot;: { &quot;TipoDTE&quot;: 61, &quot;Folio&quot;: 1 },
        &quot;Emisor&quot;: {
            &quot;RUTEmisor&quot;: &quot;88888888-8&quot;,
            &quot;RznSoc&quot;: &quot;Mi Empresa SpA&quot;,
            &quot;GiroEmis&quot;: &quot;Venta de software&quot;,
            &quot;Acteco&quot;: 620100,
            &quot;DirOrigen&quot;: &quot;Av. Siempre Viva 742&quot;,
            &quot;CmnaOrigen&quot;: &quot;Providencia&quot;
        },
        &quot;Receptor&quot;: {
            &quot;RUTRecep&quot;: &quot;77777777-7&quot;,
            &quot;RznSocRecep&quot;: &quot;Cliente Ejemplo Ltda.&quot;,
            &quot;GiroRecep&quot;: &quot;Comercio&quot;,
            &quot;DirRecep&quot;: &quot;Calle Falsa 123&quot;,
            &quot;CmnaRecep&quot;: &quot;Santiago&quot;
        }
    },
    &quot;Detalle&quot;: [
        { &quot;NmbItem&quot;: &quot;Servicio de desarrollo&quot;, &quot;QtyItem&quot;: 1, &quot;PrcItem&quot;: 100000 },
        { &quot;NmbItem&quot;: &quot;Soporte técnico (horas)&quot;, &quot;QtyItem&quot;: 3, &quot;PrcItem&quot;: 25000 }
    ],
    &quot;Referencia&quot;: [
        {
            &quot;TpoDocRef&quot;: 33,
            &quot;FolioRef&quot;: 1,
            &quot;FchRef&quot;: &quot;2026-10-29&quot;,
            &quot;CodRef&quot;: 1,
            &quot;RazonRef&quot;: &quot;Anula factura&quot;
        }
    ]
}
```

Los totales de la nota (neto $175.000, IVA $33.250, total $208.250) quedan iguales a los de la factura: así el SII descuenta la venta completa.

&gt; [!TIP] El folio es de la nota, no de la factura
&gt;
&gt; `IdDoc.Folio` es el folio de la **nota de crédito** (de su propio CAF). El folio de la factura que anulas va en `Referencia.FolioRef`, y su fecha de emisión (`FchEmis`) en `Referencia.FchRef`.

## Caso 2: corregir un texto

La factura salió con un error en un dato que no afecta los montos, por ejemplo el giro del receptor. La nota lleva `CodRef: 2` y un ítem que describe la corrección, **sin precio**: `&quot;PrcItem&quot;: false` le indica a la API que el ítem no lleva precio.

```json
&quot;Detalle&quot;: [
    { &quot;NmbItem&quot;: &quot;Corrige giro del receptor&quot;, &quot;QtyItem&quot;: 1, &quot;PrcItem&quot;: false }
],
&quot;Referencia&quot;: [
    {
        &quot;TpoDocRef&quot;: 33,
        &quot;FolioRef&quot;: 1,
        &quot;FchRef&quot;: &quot;2026-10-29&quot;,
        &quot;CodRef&quot;: 2,
        &quot;RazonRef&quot;: &quot;DONDE DICE Comercio DEBE DECIR Comercio al por mayor&quot;
    }
]
```

Los totales de esta nota quedan en `0`: no cambia ningún monto.

## Caso 3: corregir un monto

Cobraste de más: los 3 servicios de soporte eran a $20.000 y no a $25.000. La nota de crédito lleva solo la **diferencia** ($5.000 × 3) y `CodRef: 3`:

```json
&quot;Detalle&quot;: [
    { &quot;NmbItem&quot;: &quot;Soporte técnico (horas) - diferencia de precio&quot;, &quot;QtyItem&quot;: 3, &quot;PrcItem&quot;: 5000 }
],
&quot;Referencia&quot;: [
    {
        &quot;TpoDocRef&quot;: 33,
        &quot;FolioRef&quot;: 1,
        &quot;FchRef&quot;: &quot;2026-10-29&quot;,
        &quot;CodRef&quot;: 3,
        &quot;RazonRef&quot;: &quot;Corrige precio del soporte técnico&quot;
    }
]
```

Totales de la nota: neto $15.000, IVA $2.850, total $17.850.

## ¿Y la nota de débito?

La **nota de débito** (`56`) funciona igual, pero **aumenta** el monto: por ejemplo, si cobraste de menos, o para cobrar intereses. También se usa para **anular una nota de crédito** emitida por error:

```json
&quot;Referencia&quot;: [
    {
        &quot;TpoDocRef&quot;: 61,
        &quot;FolioRef&quot;: 1,
        &quot;FchRef&quot;: &quot;2026-10-29&quot;,
        &quot;CodRef&quot;: 1,
        &quot;RazonRef&quot;: &quot;Anula nota de crédito&quot;
    }
]
```

## Errores frecuentes

| Mensaje o situación | Causa |
|---------------------|-------|
| `Falta incluir documento de referencia.` | La nota no tiene `Referencia`. |
| El SII rechaza la nota | La factura referenciada no existe, tiene otra fecha, o es de otro receptor. Revisa `TpoDocRef`, `FolioRef` y `FchRef`. |
| `El CAF ... es del tipo de documento 33, pero el documento ... es del tipo 61.` | Usaste el CAF de facturas (`33`) en vez del de notas de crédito (`61`). |

&gt; [!INFO] ¿Se puede revertir una anulación?
&gt;
&gt; Sí. Una vez anulada con una nota de crédito, la factura ya no tiene efecto. Si después necesitas &quot;revivirla&quot;, se emite una nota de débito que anula esa nota de crédito, como en el ejemplo anterior.


    
---

### Guía de despacho

Cómo emitir una guía de despacho: tipo de despacho, motivo del traslado, datos del transporte y su relación con la factura.

# Guía de despacho

La **guía de despacho** (`52`) acompaña a la mercadería mientras se traslada. Es obligatoria cuando los productos salen de tu bodega, aunque todavía no se hayan facturado (o aunque no sea una venta, como un traslado entre sucursales).

## Lo que la hace distinta

| Campo | Dónde | Qué indica |
|-------|-------|------------|
| `IndTraslado` | `IdDoc` | **Obligatorio.** El motivo del traslado (venta, traslado interno, devolución, etc.). |
| `TipoDespacho` | `IdDoc` | Quién despacha: `1` el receptor, `2` el emisor a las instalaciones del cliente, `3` el emisor a otras instalaciones. |
| `Transporte` | `Encabezado` | Patente del vehículo, RUT del transportista, chofer y dirección de destino. |

Los motivos de `IndTraslado` son:

| Código | Motivo | Ejemplo |
|--------|--------|---------|
| `1` | Operación constituye venta | Despachas hoy y facturas después |
| `2` | Ventas por efectuar | Mercadería que se venderá más adelante |
| `3` | Consignaciones | Productos que otra tienda venderá por ti |
| `4` | Entrega gratuita | Muestras o donaciones |
| `5` | Traslados internos | De la bodega central a una sucursal |
| `6` | Otros traslados no venta | Envío a reparación |
| `7` | Guía de devolución | El cliente te devuelve productos |
| `8` | Traslado para exportación (no venta) | |
| `9` | Venta para exportación | |

## Ejemplo: despacho de una venta

```json
{
    &quot;Encabezado&quot;: {
        &quot;IdDoc&quot;: {
            &quot;TipoDTE&quot;: 52,
            &quot;Folio&quot;: 1,
            &quot;TipoDespacho&quot;: 2,
            &quot;IndTraslado&quot;: 1
        },
        &quot;Emisor&quot;: {
            &quot;RUTEmisor&quot;: &quot;88888888-8&quot;,
            &quot;RznSoc&quot;: &quot;Mi Empresa SpA&quot;,
            &quot;GiroEmis&quot;: &quot;Venta de equipos computacionales&quot;,
            &quot;Acteco&quot;: 465100,
            &quot;DirOrigen&quot;: &quot;Av. Siempre Viva 742&quot;,
            &quot;CmnaOrigen&quot;: &quot;Providencia&quot;
        },
        &quot;Receptor&quot;: {
            &quot;RUTRecep&quot;: &quot;77777777-7&quot;,
            &quot;RznSocRecep&quot;: &quot;Cliente Ejemplo Ltda.&quot;,
            &quot;GiroRecep&quot;: &quot;Comercio&quot;,
            &quot;DirRecep&quot;: &quot;Calle Falsa 123&quot;,
            &quot;CmnaRecep&quot;: &quot;Santiago&quot;
        },
        &quot;Transporte&quot;: {
            &quot;Patente&quot;: &quot;ABCD12&quot;,
            &quot;RUTTrans&quot;: &quot;88888888-8&quot;,
            &quot;Chofer&quot;: {
                &quot;RUTChofer&quot;: &quot;11222333-9&quot;,
                &quot;NombreChofer&quot;: &quot;Pedro Pérez&quot;
            },
            &quot;DirDest&quot;: &quot;Calle Falsa 123&quot;,
            &quot;CmnaDest&quot;: &quot;Santiago&quot;
        }
    },
    &quot;Detalle&quot;: [
        { &quot;NmbItem&quot;: &quot;Notebook 14 pulgadas&quot;, &quot;QtyItem&quot;: 5, &quot;PrcItem&quot;: 450000 }
    ]
}
```

Como `IndTraslado` es `1` (constituye venta), la guía lleva precios y la API calcula sus totales con IVA, igual que una factura.

&gt; [!INFO] Traslados que no son venta
&gt;
&gt; Si el traslado no es una venta (por ejemplo `5`, traslado interno), no necesitas valorizar la mercadería: puedes enviar los ítems solo con nombre y cantidad.

## Facturar una o varias guías

Cuando la guía es por una venta (`IndTraslado: 1`), después tienes que emitir la **factura**. La factura hace referencia a la guía (o a varias guías, en una factura a fin de mes):

```json
&quot;Referencia&quot;: [
    {
        &quot;TpoDocRef&quot;: 52,
        &quot;FolioRef&quot;: 1,
        &quot;FchRef&quot;: &quot;2026-10-29&quot;,
        &quot;RazonRef&quot;: &quot;Factura guía de despacho&quot;
    }
]
```

En las referencias de una factura no se usa `CodRef`: ese campo es solo para las notas de crédito y débito.

&gt; [!TIP] Ejemplos de guías
&gt;
&gt; La API incluye ejemplos para cada motivo de traslado: `052_guia_despacho/052_001_constituye_venta`, `052_002_traslado_interno`, `052_003_guia_devolucion`, `052_004_venta_por_efectuar`, `052_005_entrega_gratuita` y otros. Obtenlos con `billing/document/examples/get`.


    
---

### Factura exenta e ítems exentos

Cómo emitir una factura exenta de IVA y cómo incluir ítems exentos dentro de una factura afecta.

# Factura exenta e ítems exentos

Algunas ventas no pagan IVA (por ejemplo, ciertos servicios de educación, de salud o algunos arriendos). Para documentarlas hay dos caminos:

| Situación | Documento |
|-----------|-----------|
| **Toda** la venta es exenta | Factura exenta (`34`) |
| Una parte es afecta y otra exenta | Factura afecta (`33`) con algunos ítems marcados como exentos |

## Factura exenta (34)

Se arma igual que una factura, con `TipoDTE: 34` y los ítems marcados con `IndExe: 1`:

```json
{
    &quot;Encabezado&quot;: {
        &quot;IdDoc&quot;: { &quot;TipoDTE&quot;: 34, &quot;Folio&quot;: 1 },
        &quot;Emisor&quot;: {
            &quot;RUTEmisor&quot;: &quot;88888888-8&quot;,
            &quot;RznSoc&quot;: &quot;Mi Empresa SpA&quot;,
            &quot;GiroEmis&quot;: &quot;Capacitación&quot;,
            &quot;Acteco&quot;: 855000,
            &quot;DirOrigen&quot;: &quot;Av. Siempre Viva 742&quot;,
            &quot;CmnaOrigen&quot;: &quot;Providencia&quot;
        },
        &quot;Receptor&quot;: {
            &quot;RUTRecep&quot;: &quot;77777777-7&quot;,
            &quot;RznSocRecep&quot;: &quot;Cliente Ejemplo Ltda.&quot;,
            &quot;GiroRecep&quot;: &quot;Comercio&quot;,
            &quot;DirRecep&quot;: &quot;Calle Falsa 123&quot;,
            &quot;CmnaRecep&quot;: &quot;Santiago&quot;
        }
    },
    &quot;Detalle&quot;: [
        { &quot;IndExe&quot;: 1, &quot;NmbItem&quot;: &quot;Curso de capacitación&quot;, &quot;QtyItem&quot;: 5, &quot;PrcItem&quot;: 25000 }
    ]
}
```

La API calcula el total como monto exento: `MntExe` $125.000 y `MntTotal` $125.000, sin IVA.

## Ítems exentos dentro de una factura afecta

En una factura `33` puedes mezclar ítems afectos y exentos. Marca solo los exentos con `IndExe: 1`:

```json
&quot;Detalle&quot;: [
    { &quot;NmbItem&quot;: &quot;Licencia de software&quot;, &quot;QtyItem&quot;: 1, &quot;PrcItem&quot;: 100000 },
    { &quot;IndExe&quot;: 1, &quot;NmbItem&quot;: &quot;Capacitación en el uso del software&quot;, &quot;QtyItem&quot;: 1, &quot;PrcItem&quot;: 50000 }
]
```

La API calcula el IVA solo sobre la parte afecta: neto $100.000, IVA $19.000, exento $50.000 y total $169.000.

&gt; [!WARNING] Lo exento lo define la ley, no tu sistema
&gt;
&gt; Que una venta sea exenta depende de la ley y de la actividad del emisor. Si tienes dudas sobre qué ventas de tu cliente son exentas, consúltalo con su contador antes de configurar tu sistema.

&gt; [!NOTE] Recuerda el CAF
&gt;
&gt; La factura exenta (`34`) usa su propio CAF, distinto del de las facturas afectas (`33`).


    
---

### Boleta de principio a fin

Qué tienen de distinto las boletas y un programa completo en Python que construye, valida, envía al SII, consulta el estado y genera el PDF de una boleta electrónica.

# Boleta de principio a fin

La **boleta electrónica** (`39`) y la **boleta exenta** (`41`) son los documentos para ventas a **consumidores finales**. Siguen los mismos seis pasos que una factura, pero con dos diferencias importantes: algunos datos del documento cambian, y **el envío al SII y la consulta del estado usan otras operaciones**, porque el SII recibe las boletas por un servicio propio.

## Qué cambia respecto de una factura

| Aspecto | Factura (`33`) | Boleta (`39`) |
|---------|----------------|---------------|
| Precio en el detalle (`PrcItem`) | Neto, sin IVA | **Con IVA incluido** |
| Receptor | Datos completos de la empresa | Opcionales. Si el cliente no da su RUT, se usa `66666666-6`. |
| `GiroRecep`, `Acteco`, `FmaPago` | Se envían | No se usan |
| CAF | De facturas (`33`) | De boletas (`39`, o `41` para la exenta) |
| Sobre (paso 3) | `EnvioDTE` | `EnvioBOLETA` (la API lo crea sola) |
| Enviar al SII (paso 4) | `sii_dte/sendXmlDocument` | **`sii_boleta/sendXmlDocument`** |
| Consultar el estado (paso 5) | `sii_dte/checkXmlDocumentSentStatus` | **`sii_boleta/checkXmlDocumentSentStatus`** |
| Verificar un documento | `/api/v2/sii/dte/emitidos/verificar` | **`sii_boleta/validateDocument`** |
| Copia cedible del PDF | Sí | No |

El resto es igual: `builder/build`, las validaciones, `dispatcher/create` y `renderer/render` reciben los mismos parámetros. En cada paso, esto es lo que corresponde a las boletas:

| Paso | Dónde está |
|------|----------------------|
| 1. Construir | [1.2. Boletas](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-1-construir-el-dte#12-boletas): los datos y el CAF |
| 2. Validar | [Las mismas validaciones](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-2-validar) |
| 3. Armar el sobre | [Un sobre por tipo de documento](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-3-armar-el-sobre#un-sobre-por-tipo-de-documento) |
| 4. Enviar al SII | [4.2. Boletas](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-4-enviar-al-sii#42-boletas) |
| 5. Consultar el estado | [5.2. Boletas](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-5-consultar-el-estado#52-boletas) |
| 6. Generar el PDF | [Copia tributaria](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-6-generar-el-pdf#copia-tributaria-y-copia-cedible) |

## Lo que necesitas

| Archivo o dato | Dónde se explica |
|----------------|------------------|
| Token de API Gateway | [Primeros pasos](https://www.apigateway.cl/academy/primeros-pasos) |
| Certificado digital en PEM: `cert.pem` y `key.pem` | [El certificado digital](https://www.apigateway.cl/academy/emision-de-dte/preparacion/certificado-digital) |
| CAF de boletas (`39`) del ambiente de certificación | [Folios y CAF](https://www.apigateway.cl/academy/emision-de-dte/preparacion/folios-y-caf) |
| Fecha de la resolución en certificación | [Resolución de autorización](https://www.apigateway.cl/academy/emision-de-dte/fundamentos/resolucion-de-autorizacion) |

&gt; [!TIP] ¿Aún no tienes CAF de certificación?
&gt;
&gt; Puedes probar los pasos 1, 2, 3 y 6 con un CAF y un certificado de prueba. Te explicamos cómo en [Probar sin el SII](#probar-sin-el-sii).

## El programa

Instala `requests` (`pip install requests`) y define la variable de entorno `API_TOKEN`. Deja en la misma carpeta los archivos `cert.pem`, `key.pem` y `caf_39.xml`.

```python
&quot;&quot;&quot;Emite una boleta electrónica en el ambiente de certificación del SII.&quot;&quot;&quot;
import base64
import os
import time

import requests

API_URL = &#039;https://app.apigateway.cl/api/v2/libredte&#039;
HEADERS = {
    &#039;Authorization&#039;: f&#039;Token {os.environ[&quot;API_TOKEN&quot;]}&#039;,
    &#039;Content-Type&#039;: &#039;application/json&#039;,
}

AMBIENTE = 1  # 1: certificación, 0: producción.
SII_RUT = &#039;60803000-K&#039;

# Estados del envío que ya no cambian (ver el paso 5). Los demás significan
# que el SII sigue procesando, o que la consulta falló y hay que repetirla.
ESTADOS_FINALES = {&#039;EPR&#039;, &#039;LOK&#039;, &#039;RPR&#039;, &#039;RLV&#039;, &#039;RCH&#039;, &#039;RCO&#039;, &#039;RFR&#039;, &#039;RSC&#039;, &#039;RCT&#039;, &#039;RPT&#039;, &#039;VOF&#039;}
ESTADOS_ACEPTADOS = {&#039;EPR&#039;, &#039;LOK&#039;, &#039;RPR&#039;, &#039;RLV&#039;}


def libredte(operacion: str, parameters: dict) -&gt; dict | list | None:
    &quot;&quot;&quot;Ejecuta una operación de LibreDTE y entrega el contenido de `data`.&quot;&quot;&quot;
    response = requests.post(
        f&#039;{API_URL}/{operacion}&#039;,
        json={&#039;parameters&#039;: parameters},
        headers=HEADERS,
        timeout=120,
    )
    if response.status_code != 200:
        try:
            detalle = response.json().get(&#039;detail&#039;, response.text)
        except ValueError:  # La respuesta de error no viene en JSON.
            detalle = response.text
        raise RuntimeError(f&#039;{operacion}: HTTP {response.status_code}: {detalle}&#039;)
    return response.json()[&#039;data&#039;]


def leer_texto(ruta: str) -&gt; str:
    &quot;&quot;&quot;Lee un archivo de texto, como el certificado o la llave en PEM.&quot;&quot;&quot;
    with open(ruta, encoding=&#039;ascii&#039;) as archivo:
        return archivo.read()


def leer_base64(ruta: str) -&gt; str:
    &quot;&quot;&quot;Lee un archivo y lo entrega codificado en base64.&quot;&quot;&quot;
    with open(ruta, &#039;rb&#039;) as archivo:
        return base64.b64encode(archivo.read()).decode()


def guardar_base64(ruta: str, contenido: str) -&gt; None:
    &quot;&quot;&quot;Decodifica un base64 y lo guarda como archivo, sin tocar sus bytes.&quot;&quot;&quot;
    with open(ruta, &#039;wb&#039;) as archivo:
        archivo.write(base64.b64decode(contenido))


# Datos que normalmente vienen de tu base de datos.
CERTIFICADO = {
    &#039;certificate&#039;: leer_texto(&#039;cert.pem&#039;),
    &#039;privateKey&#039;: leer_texto(&#039;key.pem&#039;),
}
CAF = leer_base64(&#039;caf_39.xml&#039;)
EMISOR = {
    &#039;rut&#039;: &#039;88888888-8&#039;,
    &#039;razon_social&#039;: &#039;Mi Empresa SpA&#039;,
    &#039;autorizacion_dte&#039;: {
        &#039;fecha_resolucion&#039;: &#039;2025-11-20&#039;,  # Fecha de autorización en certificación.
        &#039;numero_resolucion&#039;: 0,            # En certificación siempre es 0.
    },
}
FOLIO = 1  # El siguiente folio libre del CAF de boletas.

# Paso 1: construir la boleta. Los precios van con IVA incluido.
datos = {
    &#039;Encabezado&#039;: {
        &#039;IdDoc&#039;: {&#039;TipoDTE&#039;: 39, &#039;Folio&#039;: FOLIO},
        &#039;Emisor&#039;: {
            &#039;RUTEmisor&#039;: EMISOR[&#039;rut&#039;],
            &#039;RznSoc&#039;: EMISOR[&#039;razon_social&#039;],
            &#039;GiroEmis&#039;: &#039;Venta de artículos de computación&#039;,
            &#039;DirOrigen&#039;: &#039;Av. Siempre Viva 742&#039;,
            &#039;CmnaOrigen&#039;: &#039;Providencia&#039;,
        },
        &#039;Receptor&#039;: {
            &#039;RUTRecep&#039;: &#039;66666666-6&#039;,  # Cliente sin RUT.
            &#039;RznSocRecep&#039;: &#039;Cliente final&#039;,
            &#039;DirRecep&#039;: &#039;Santiago&#039;,
            &#039;CmnaRecep&#039;: &#039;Santiago&#039;,
        },
    },
    &#039;Detalle&#039;: [
        {&#039;NmbItem&#039;: &#039;Mouse inalámbrico&#039;, &#039;QtyItem&#039;: 2, &#039;PrcItem&#039;: 11900},
    ],
}

boleta = libredte(&#039;billing/document/builder/build&#039;, {
    &#039;bag&#039;: {&#039;parsedData&#039;: datos, &#039;caf&#039;: CAF, &#039;certificate&#039;: CERTIFICADO},
})
xml_boleta = boleta[&#039;document_xml&#039;]
guardar_base64(f&#039;boleta_39_{FOLIO}.xml&#039;, xml_boleta)
totales = boleta[&#039;document_normalized&#039;][&#039;Encabezado&#039;][&#039;Totales&#039;]
print(&#039;Boleta construida:&#039;, boleta[&#039;document_id&#039;], &#039;total&#039;, totales[&#039;MntTotal&#039;])

# Paso 2: validar el esquema antes de enviar.
libredte(&#039;billing/document/validator/validateSchema&#039;, {&#039;source&#039;: xml_boleta})

# Paso 3: armar el sobre dirigido al SII. La API crea un EnvioBOLETA.
sobre = libredte(&#039;billing/document/dispatcher/create&#039;, {
    &#039;bag&#039;: {
        &#039;xmlDocument&#039;: xml_boleta,
        &#039;certificate&#039;: CERTIFICADO,
        &#039;emisor&#039;: EMISOR,
        &#039;receptor&#039;: {&#039;rut&#039;: SII_RUT},
    },
})
print(&#039;Sobre:&#039;, sobre[&#039;tag&#039;])  # EnvioBOLETA
guardar_base64(f&#039;sobre_sii_39_{FOLIO}.xml&#039;, sobre[&#039;xml&#039;])

# Paso 4: enviar al SII con el servicio de boletas.
request_sii = {&#039;certificate&#039;: CERTIFICADO, &#039;options&#039;: {&#039;environment&#039;: AMBIENTE}}
envio = libredte(&#039;billing/integration/sii_boleta/sendXmlDocument&#039;, {
    &#039;request&#039;: request_sii,
    &#039;doc&#039;: sobre[&#039;xml&#039;],
    &#039;company&#039;: EMISOR[&#039;rut&#039;],
})
track_id = envio[&#039;track_id&#039;]
print(&#039;Enviado al SII, Track ID:&#039;, track_id)  # ¡Guárdalo en tu base de datos!

# Paso 5: consultar el estado hasta tener un resultado final. La primera
# espera respeta los segundos que pidió el SII al recibir el envío.
estado = None
esperas = [max(30, envio[&#039;retry_after&#039;] or 0), 60, 120, 300, 600]
for espera in esperas:
    time.sleep(espera)
    try:
        estado = libredte(&#039;billing/integration/sii_boleta/checkXmlDocumentSentStatus&#039;, {
            &#039;request&#039;: request_sii,
            &#039;trackId&#039;: track_id,
            &#039;company&#039;: EMISOR[&#039;rut&#039;],
        })
    except RuntimeError as error:
        # La consulta falló (por ejemplo, el SII no respondió): se reintenta.
        print(&#039;Falló la consulta, se reintenta:&#039;, error)
        continue
    print(&#039;Estado:&#039;, estado[&#039;status&#039;], estado[&#039;description&#039;])
    if estado[&#039;status&#039;] in ESTADOS_FINALES:
        break

resumen = estado[&#039;resume&#039;] if estado else {}
if not estado or estado[&#039;status&#039;] not in ESTADOS_FINALES:
    print(&#039;Sin estado final todavía. Vuelve a consultar más tarde con el Track ID&#039;, track_id)
elif estado[&#039;status&#039;] == &#039;RPT&#039;:
    print(&#039;El SII ya había recibido este sobre: consulta el estado con el Track ID del primer envío.&#039;)
elif estado[&#039;status&#039;] == &#039;VOF&#039;:
    print(&#039;El SII no encontró el archivo: envía de nuevo el mismo sobre (no lo construyas de nuevo).&#039;)
elif estado[&#039;status&#039;] in ESTADOS_ACEPTADOS and resumen.get(&#039;rejected&#039;, 0) == 0:
    resultado = &#039;aceptada con reparos&#039; if resumen.get(&#039;repairs&#039;) else &#039;aceptada&#039;
    print(&#039;Resultado:&#039;, resultado)

    # Paso 6: generar el PDF (las boletas solo tienen copia tributaria).
    pdf = libredte(&#039;billing/document/renderer/render&#039;, {
        &#039;bag&#039;: {
            &#039;xmlDocument&#039;: xml_boleta,
            &#039;emisor&#039;: EMISOR,  # Con la resolución, que se imprime en el PDF.
            &#039;options&#039;: {&#039;renderer&#039;: {&#039;format&#039;: &#039;pdf&#039;}},
        },
    })
    for archivo in pdf[&#039;renderings&#039;]:
        guardar_base64(archivo[&#039;filename&#039;], archivo[&#039;content&#039;])
        print(&#039;PDF generado:&#039;, archivo[&#039;filename&#039;])
else:
    print(&#039;La boleta fue rechazada:&#039;, estado[&#039;status&#039;], estado[&#039;description&#039;])
    for detalle in estado[&#039;details&#039;]:
        print(&#039;Folio&#039;, detalle[&#039;folio&#039;], detalle[&#039;status&#039;], detalle[&#039;description&#039;])
```

## Probar sin el SII

Si todavía no tienes un CAF y un certificado reales del ambiente de certificación, puedes probar los pasos 1, 2, 3 y 6 con datos de prueba. Los pasos 4 y 5 no funcionan con ellos: el SII rechaza la autenticación y el programa se detiene en el envío.

1. **El certificado:** genera uno de prueba (ver [Un certificado de prueba](https://www.apigateway.cl/academy/emision-de-dte/preparacion/certificado-digital#un-certificado-de-prueba)) y guarda `cert` como `cert.pem` y `pkey` como `key.pem`.
2. **El CAF:** genera uno de prueba y guárdalo como `caf_39.xml`. Ejecuta esto una vez, con las funciones `libredte()` y `guardar_base64()` del programa. El CAF viene en base64 en el campo `xml`, y `guardar_base64()` lo decodifica al guardarlo:

```python
caf = libredte(&#039;billing/identifier/caf_faker/create&#039;, {
    &#039;emisor&#039;: {&#039;rut&#039;: &#039;88888888-8&#039;, &#039;razon_social&#039;: &#039;Mi Empresa SpA&#039;},
    &#039;codigoDocumento&#039;: 39,
    &#039;folioDesde&#039;: 1,
    &#039;folioHasta&#039;: 100,
})
guardar_base64(&#039;caf_39.xml&#039;, caf[&#039;xml&#039;])
```

3. **El programa:** borra todo lo que sigue a `# Paso 4: enviar al SII con el servicio de boletas.` y pon en su lugar solo el paso 6, sin la condición de que el SII haya aceptado:

```python
# Paso 6: generar el PDF, sin pasar por el SII.
pdf = libredte(&#039;billing/document/renderer/render&#039;, {
    &#039;bag&#039;: {
        &#039;xmlDocument&#039;: xml_boleta,
        &#039;emisor&#039;: EMISOR,
        &#039;options&#039;: {&#039;renderer&#039;: {&#039;format&#039;: &#039;pdf&#039;}},
    },
})
for archivo in pdf[&#039;renderings&#039;]:
    guardar_base64(archivo[&#039;filename&#039;], archivo[&#039;content&#039;])
    print(&#039;PDF generado:&#039;, archivo[&#039;filename&#039;])
```

La boleta que obtienes no tiene validez tributaria: el CAF es ficticio. Sirve para revisar los datos, los totales y el PDF.

## Qué hace, en orden

| Paso | Llamada | Qué guarda |
|------|---------|------------|
| 1 | `builder/build` | `boleta_39_1.xml`: la boleta timbrada y firmada |
| 2 | `validator/validateSchema` | (nada; falla si el XML no es válido) |
| 3 | `dispatcher/create` con `receptor` del SII | `sobre_sii_39_1.xml`, un `EnvioBOLETA` |
| 4 | `sii_boleta/sendXmlDocument` | El Track ID |
| 5 | `sii_boleta/checkXmlDocumentSentStatus` | El estado final |
| 6 | `renderer/render` | El PDF (copia tributaria) |

Para llevarlo a tu sistema, sepáralo igual que la factura: emitir y enviar en línea, consultar el estado en segundo plano y generar el PDF cuando la boleta es aceptada (ver [Factura de principio a fin](https://www.apigateway.cl/academy/emision-de-dte/casos-practicos/factura-de-principio-a-fin#para-llevarlo-a-tu-sistema)).

## Boleta exenta

La boleta exenta (`41`) se construye igual, con su propio CAF (`41`). Marca cada ítem como exento con **`IndExe: 1`**:

```json
{
    &quot;Encabezado&quot;: {
        &quot;IdDoc&quot;: { &quot;TipoDTE&quot;: 41, &quot;Folio&quot;: 1 },
        &quot;Emisor&quot;: {
            &quot;RUTEmisor&quot;: &quot;88888888-8&quot;,
            &quot;RznSoc&quot;: &quot;Mi Empresa SpA&quot;,
            &quot;GiroEmis&quot;: &quot;Venta de libros&quot;,
            &quot;DirOrigen&quot;: &quot;Av. Siempre Viva 742&quot;,
            &quot;CmnaOrigen&quot;: &quot;Providencia&quot;
        },
        &quot;Receptor&quot;: {
            &quot;RUTRecep&quot;: &quot;66666666-6&quot;,
            &quot;RznSocRecep&quot;: &quot;Cliente final&quot;,
            &quot;DirRecep&quot;: &quot;Santiago&quot;,
            &quot;CmnaRecep&quot;: &quot;Santiago&quot;
        }
    },
    &quot;Detalle&quot;: [
        { &quot;IndExe&quot;: 1, &quot;NmbItem&quot;: &quot;Libro&quot;, &quot;QtyItem&quot;: 1, &quot;PrcItem&quot;: 15000 }
    ]
}
```

La API calcula `MntExe` $15.000 y `MntTotal` $15.000, sin IVA. El sobre, el envío y la consulta del estado son los mismos de la boleta afecta.

## Reglas al agrupar boletas

- Un sobre `EnvioBOLETA` lleva solo boletas (`39` y `41`). Las facturas, notas y guías van en un `EnvioDTE` aparte, que se envía con `sii_dte`.
- Puedes enviar muchas boletas en un sobre con `dispatcher/createMany` (ver [Varios documentos en un sobre](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-3-armar-el-sobre#varios-documentos-en-un-sobre)). Si el SII rechaza alguna, el detalle de la consulta del estado indica su folio.

## Nota de crédito de una boleta

Una boleta se anula o corrige con una nota de crédito (`61`), con referencia `TpoDocRef: 39`. La nota de crédito **no es una boleta**: va en un sobre `EnvioDTE` y se envía con `sii_dte`, como una factura (ver [Nota de crédito](https://www.apigateway.cl/academy/emision-de-dte/casos-practicos/nota-de-credito)).


    
---

## Paso a producción



---

### Errores frecuentes

Los errores más comunes al integrar la emisión de DTE, ordenados por etapa, con su causa y su solución.

# Errores frecuentes

Esta es una guía de diagnóstico. Busca el síntoma que ves y la etapa en que ocurre.

## Errores de la API (antes de llegar al SII)

| Síntoma | Causa | Solución |
|---------|-------|----------|
| `401` | Token ausente o mal escrito. | Usa la cabecera `Authorization: Token &lt;token&gt;`, con la palabra `Token` y un espacio. |
| `402` | La conexión no tiene créditos o tiene un problema de pago. | Revisa tu conexión en [app.apigateway.cl](https://app.apigateway.cl). |
| `404` | La URL de la operación no existe. | Revisa las cuatro partes de la URL y que el método sea `POST`. |
| `400` | Falta un parámetro o tiene otro nombre. | Todos los parámetros van dentro de `parameters`, con el nombre exacto de la documentación (`bag`, `source`, `request`, `doc`, `company`, `trackId`). |
| `422` con `No se encontró un deserializador capaz de construir una instancia de ... requiere datos codificados en base64 válido.` | Un XML (del DTE, del sobre o del CAF) o un `.p12` no viene en base64. | Codifica en base64, en una sola línea, sin saltos. |
| `422` con `Se requieren los datos del certificado ...` | Certificado incompleto. | Envía `certificate` + `privateKey` (PEM), o `data` + `password` (`.p12`). |
| `503` | El servicio de LibreDTE no está disponible en ese momento. | Reintenta en unos minutos. |

## Errores al construir el documento o el sobre

| Mensaje (`detail`) | Causa | Solución |
|--------------------|-------|----------|
| `El XPath &quot;//Encabezado/IdDoc/Folio&quot; ... es obligatorio: no coincidió con ningún nodo.` | Falta `IdDoc.Folio`. | Asigna el folio desde tu control de folios. |
| `El folio N ... no está disponible en el rango del CAF ...` | El folio no está en el CAF enviado. | Revisa el rango del CAF y que sea el CAF del tipo de documento correcto. |
| `El CAF ... fue autorizado al emisor ..., pero el documento ... es del emisor ...` | El CAF es de otra empresa: su RUT no coincide con `RUTEmisor`. | Usa un CAF solicitado por la misma empresa que emite el documento. |
| `El CAF ... es del tipo de documento ..., pero el documento ... es del tipo ...` | El CAF es de otro tipo de documento. | Usa el CAF del mismo tipo que el documento: de facturas para una factura, de boletas para una boleta. |
| `The verification digit of the RUT ... is incorrect.` | RUT con dígito verificador incorrecto. | Valida los RUT al registrarlos en tu sistema. |
| `Falta incluir documento de referencia.` | Nota de crédito o débito sin `Referencia`. | Agrega la referencia al documento que corrige. |
| `La carátula del sobre no está definida.` | Al armar el sobre falta `emisor.autorizacion_dte` (la resolución) o el certificado. | Envía la resolución del emisor y el certificado en `dispatcher/create`. |
| Totales distintos a los esperados | En una factura enviaste precios con IVA, o en una boleta precios sin IVA. | Factura: `PrcItem` neto. Boleta: `PrcItem` con IVA. |

## Rechazos del SII

| Estado | Causa común | Solución |
|--------|-------------|----------|
| `RSC` Rechazado por error en el esquema | Un campo supera su largo máximo, tiene un formato inválido o falta. | Valida con `validator/validateSchema` antes de enviar. Revisa los largos máximos (por ejemplo, `GiroRecep` 40 caracteres). |
| `RFR` Rechazado por error en la firma | El XML se modificó después de firmarlo (por ejemplo, al cambiar su codificación). | Guarda y envía el base64 tal como lo entregó la API. No conviertas el XML a UTF-8. |
| `RCT` Rechazado por error en la carátula | La resolución (número o fecha) no corresponde, o no corresponde al ambiente. | En certificación usa número `0` y la fecha de certificación; en producción, la resolución real. |
| `EPR` con facturas, notas o guías rechazadas | Un dato del documento no es válido para el SII: folio no autorizado, CAF de otro ambiente, receptor inexistente, referencia a un documento que no existe. | Pide el detalle con `requestXmlDocumentSentStatusByEmail` (ver [Consultar el estado](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-5-consultar-el-estado)). |
| `EPR` con reparos | El documento es válido, pero tiene observaciones menores. | Revisa las observaciones para corregir los documentos siguientes. |

## Errores con boletas

| Síntoma | Causa | Solución |
|---------|-------|----------|
| `El tipo de documento Factura electrónica no se puede agregar a un sobre de tipo ENVIO_BOLETA.` | Juntaste una boleta y otro DTE en el mismo sobre. | Arma un sobre para las boletas y otro para los demás documentos. |
| `El XML es un EnvioBOLETA y no se puede enviar con el worker de DTE, las boletas se envían con el worker de boletas.` | Enviaste un sobre de boletas con `sii_dte`: el SII recibe las boletas por otro servicio. | Las boletas se envían con `sii_boleta/sendXmlDocument` y su estado se consulta con `sii_boleta/checkXmlDocumentSentStatus`. |
| `rate_limit.remaining` en `0` | Usaste todas las solicitudes que permite el servicio de boletas del SII. | Espera los segundos de `rate_limit.reset` antes de la siguiente llamada. |
| Totales distintos a los esperados | Enviaste precios sin IVA. | En una boleta, `PrcItem` va con IVA incluido. |
| Boleta exenta con `MntExe` en `0` | Los ítems de la boleta `41` no tienen `IndExe`. | Marca cada ítem con `IndExe: 1`. |
| `RPT` Envío repetido rechazado | Enviaste de nuevo un sobre que el SII ya había recibido. | Consulta el estado con el Track ID del primer envío. |
| `details` con boletas rechazadas | Un dato de esas boletas no es válido para el SII. | Revisa `section`, `description` y `detail` de cada error (ver [Consultar el estado de boletas](https://www.apigateway.cl/academy/emision-de-dte/emision/paso-5-consultar-el-estado#52-boletas)). |

## Errores de autenticación en el SII

| Síntoma | Causa | Solución |
|---------|-------|----------|
| Falla la autenticación al enviar o consultar | Certificado vencido, revocado o autofirmado. | Usa un certificado vigente, emitido por una entidad autorizada. |
| Falla la autenticación con un certificado válido | La persona del certificado no está autorizada en el SII para la empresa. | En el SII, la empresa debe registrar a esa persona como usuario autorizado para DTE. |
| El documento se envió a producción por error | No se indicó `options.environment`. | Indica siempre el ambiente. El valor por defecto es producción. |

## Errores de diseño que aparecen más tarde

Estos errores no dan un mensaje inmediato, pero causan problemas en producción:

| Problema | Consecuencia | Prevención |
|----------|--------------|------------|
| Dos emisiones usan el mismo folio | El SII rechaza la segunda, o hay dos documentos distintos con el mismo número. | Reserva el folio con una transacción en tu base de datos. |
| No se guardó el Track ID | No puedes saber si el documento fue aceptado. | Guárdalo apenas lo recibes. |
| Se construyó de nuevo un documento ya enviado | Hay dos XML distintos para el mismo folio. | Si falla el envío, reintenta el **mismo** sobre. Solo se construye de nuevo cuando el SII lo rechazó. |
| Se volvió a emitir un documento rechazado con otro folio | El folio del documento rechazado queda sin usar en el CAF. | Emite el documento corregido con el mismo folio. |
| No se guardó el XML | Pierdes el respaldo legal del documento. | Guarda cada XML emitido por al menos 6 años. |
| Se agotaron los folios | No se puede emitir. | Solicita un nuevo CAF antes de que se agote el actual. |

&gt; [!TIP] ¿No encuentras tu error?
&gt;
&gt; Revisa la [solución de problemas](https://www.apigateway.cl/docs/solucion-de-problemas) de la documentación. Si el problema sigue, [abre un ticket](https://www.apigateway.cl/help) indicando la operación, la hora de la llamada y el mensaje de `detail` (sin enviar tu certificado ni tu token).


    
---

### Buenas prácticas

Cómo diseñar tu integración para que sea segura, confiable y fácil de mantener, y la lista de verificación antes de emitir en producción.

# Buenas prácticas

## Guarda lo que necesitas, y nada más

Por cada documento emitido, guarda en tu base de datos:

| Dato | Por qué |
|------|---------|
| Emisor, tipo de documento y folio | Identifican el documento de forma única. |
| Ambiente (certificación o producción) | Para no mezclar documentos de prueba con documentos reales. |
| El XML del DTE (`document_xml`) | Es el documento con validez legal. |
| El XML del sobre enviado al SII | Para reintentar el envío o responder ante el SII. |
| Track ID y fecha de envío | Para consultar el estado. |
| Estado y fecha de la última consulta | Para saber qué falta. |
| Fecha de emisión (`FchEmis`) | Para referenciar el documento en una nota de crédito o débito (`FchRef`) y para verificarlo en el SII. |
| Totales (neto, IVA, exento, total) | Para tus reportes, sin tener que leer el XML. |

No guardes las respuestas completas de la API: incluyen datos del certificado y del CAF que no necesitas.

## Controla los folios con cuidado

- **Reserva** cada folio dentro de una transacción antes de construir el documento.
- **Nunca reutilices** el folio de un documento aceptado, aunque tenga reparos. El de un documento **rechazado** sí: emítelo corregido con el mismo folio.
- **Monitorea** los folios disponibles y solicita un CAF nuevo cuando queden cerca del 20%.
- **Revisa el vencimiento** de los CAF: un CAF vencido no sirve, aunque le queden folios.
- Si tienes folios que nunca usarás (por ejemplo, de un CAF que vence), **anúlalos** con el recurso `caf/anular`.

## Separa la emisión del seguimiento

Cuando el usuario confirma la venta, divide el trabajo en tres etapas:

| Etapa | Cuándo se ejecuta | Qué hace |
|-------|-------------------|----------|
| **1. Emisión** | En línea, al confirmar la venta | Reserva el folio, construye el DTE, arma el sobre, lo envía y guarda el Track ID. |
| **2. Seguimiento** | En segundo plano | Consulta los estados pendientes y los actualiza. |
| **3. Entrega** | Cuando el documento es aceptado | Genera el PDF y lo entrega al cliente. Si el receptor es una empresa que emite documentos electrónicos, le envía además el XML a su correo de intercambio. |

Así ningún usuario espera al SII, y cada parte se puede reintentar por separado.

## Diseña para los fallos

- Usa **tiempos de espera** generosos (60 a 120 segundos): el SII a veces responde lento.
- **Reintenta** los envíos y las consultas con esperas crecientes, no en un ciclo inmediato.
- Haz que cada paso sea **repetible** sin efectos duplicados: si vuelves a enviar un sobre que ya tiene Track ID, primero consulta su estado.
- Registra en tus logs la operación, el código HTTP y el `detail` de cada error.

## Protege los secretos

| Secreto | Recomendación |
|---------|---------------|
| Token de API Gateway | En variables de entorno o un almacén de secretos. Regenéralo si sospechas que se filtró. |
| Certificado digital y su contraseña | Cifrado, en un almacén de secretos. Nunca en el código ni en el navegador. |
| CAF | Contiene la llave para timbrar. Guárdalo con el mismo cuidado que el certificado. |

Todas las llamadas a la API deben salir de **tu servidor**, nunca desde una app web o móvil del usuario.

## Valida los datos en tu sistema

Muchos rechazos se evitan validando al registrar los datos, mucho antes de emitir:

- RUT con dígito verificador correcto.
- Largos máximos (razón social 100, giro del receptor 40, dirección 70, comuna 20, nombre del ítem 80).
- Precios y cantidades mayores que cero.
- Para facturas: giro, dirección y comuna del receptor.

## Mantén separados los ambientes

- Usa configuraciones distintas para certificación y producción (CAF, resolución y ambiente).
- Marca los documentos de certificación en tu base de datos para que nunca aparezcan en reportes reales.
- Antes de cambiar a producción, revisa la [lista de verificación](#lista-de-verificación-para-producción).

## Respalda

La ley exige conservar los documentos tributarios por al menos **6 años**. Incluye los XML en tus respaldos y prueba de vez en cuando que puedes recuperarlos. API Gateway no guarda una copia por ti.

## Lista de verificación para producción

Antes de emitir el primer documento con validez tributaria, revisa cada punto.

### La empresa emisora

- La empresa terminó la certificación y el SII la autorizó a emitir con software de mercado.
- Tienes el **número y la fecha de la resolución** de producción.
- La persona del certificado digital está autorizada en el SII para la empresa.
- El certificado digital está vigente y sabes cuándo vence.
- Tienes **CAF de producción** para cada tipo de documento que vas a emitir.

### Tu configuración

- `options.environment` es `0` en todas las llamadas al SII de producción.
- La resolución del sobre (`autorizacion_dte`) es la de producción, no la de certificación.
- Los CAF de producción están cargados y separados de los de certificación.
- La conexión tiene créditos y los productos necesarios activos.
- Las boletas se envían y se consultan con `sii_boleta`; las facturas, notas y guías, con `sii_dte`.

### Tu sistema

- Aplica las prácticas de esta página: folios reservados con una transacción, lo que se guarda de cada documento, seguimiento en segundo plano, reintentos con esperas crecientes, secretos protegidos, ambientes separados y respaldos.
- Hay una alerta cuando quedan pocos folios o el certificado está por vencer.

### Entrega y correcciones

- El PDF se genera y se entrega al cliente.
- A los receptores que son empresas que emiten documentos electrónicos, tu sistema les envía el XML a su correo de intercambio.
- Sabes cómo emitir una nota de crédito para corregir un documento.

### La primera emisión real

1. Emite **un solo documento** de bajo monto y con datos que conozcas bien.
2. Consulta su estado hasta que sea aceptado.
3. Revisa el PDF y verifica el documento: las facturas, notas y guías con `sii/dte/emitidos/verificar`, y las boletas con `sii_boleta/validateDocument`.
4. Si todo está bien, habilita la emisión para el resto.

&gt; [!WARNING] En producción no hay vuelta atrás
&gt;
&gt; Un documento aceptado en producción tiene validez tributaria: no se borra, solo se corrige con notas de crédito o débito. Haz tus pruebas en certificación.

&gt; [!TIP] ¿Terminaste el curso?
&gt;
&gt; Pon a prueba lo que aprendiste con la [autoevaluación](https://www.apigateway.cl/academy/emision-de-dte/ponte-a-prueba/autoevaluacion).


    
---

## ¡Ponte a prueba!



---

### Autoevaluación




## Test de Emisión de DTE con API Gateway V2

Autoevaluación sobre los conceptos de facturación electrónica y el proceso de emisión de DTE con API Gateway V2.

### 1. ¿Qué es lo que tiene validez tributaria en un documento tributario electrónico?

- [ ] El PDF que recibe el cliente
- [x] El XML timbrado y firmado
- [ ] El Track ID que entrega el SII

> El DTE es el XML timbrado con el CAF y firmado con el certificado digital. El PDF es solo su representación impresa.

### 2. ¿Qué es un CAF?

- [ ] El certificado digital de la persona que firma
- [x] El archivo del SII que autoriza un rango de folios para un tipo de documento
- [ ] El sobre con que se envían los documentos al SII

> El CAF (Código de Autorización de Folios) es un XML firmado por el SII con el rango de folios autorizados para un emisor y un tipo de documento.

### 3. Vendes un producto a una empresa y la venta paga IVA. ¿Qué documento emites?

- [ ] Boleta electrónica (39)
- [x] Factura electrónica (33)
- [ ] Guía de despacho (52)

> A otra empresa, con una venta afecta, se le emite una factura electrónica (33).

### 4. En una factura afecta (33), ¿cómo va el precio unitario (PrcItem) de cada ítem?

- [x] Neto, sin IVA: la API calcula el IVA
- [ ] Con IVA incluido
- [ ] Da lo mismo, la API lo detecta

> En facturas el PrcItem es neto y la API le suma el 19% de IVA. En boletas, en cambio, el PrcItem va con IVA incluido.

### 5. ¿Cómo va el cuerpo de una solicitud a los recursos /api/v2/libredte/?

- [ ] Con los datos en la raíz del JSON
- [x] Con los parámetros de la operación dentro del atributo parameters
- [ ] Con los datos en la URL como query string

> Todas las operaciones de LibreDTE reciben un JSON con el atributo parameters, que contiene los parámetros con el nombre que indica la documentación.

### 6. ¿Cómo se envían los XML (del DTE, del sobre o del CAF) a la API?

- [ ] Como texto XML dentro del JSON
- [x] Codificados en base64
- [ ] Como un archivo adjunto multipart

> Los datos que no son JSON, como los XML y los archivos .p12, viajan en base64 para que lleguen intactos, sin problemas de codificación.

### 7. ¿Qué se necesita en la bolsa (bag) de builder/build para obtener un documento listo para enviar al SII?

- [ ] Solo los datos del documento (parsedData)
- [ ] Los datos y el CAF
- [x] Los datos, el CAF y el certificado digital

> Con solo los datos se obtiene un borrador. Con el CAF se timbra y con el certificado se firma: los tres son necesarios para emitir.

### 8. Al enviar al SII con sii_dte/sendXmlDocument, ¿qué pasa si no indicas options.environment?

- [ ] Se envía al ambiente de certificación
- [ ] La API responde con un error
- [x] Se envía al ambiente de producción

> El ambiente por defecto es producción. Durante el desarrollo indica siempre environment: 1 (certificación).

### 9. El SII respondió con un Track ID. ¿Qué significa?

- [ ] Que el documento fue aceptado
- [x] Que el SII recibió el sobre, pero todavía hay que consultar si lo acepta
- [ ] Que el documento fue rechazado

> El Track ID confirma la recepción. El resultado (aceptado, con reparos o rechazado) se obtiene consultando el estado con checkXmlDocumentSentStatus.

### 10. Al consultar el estado, el SII responde status EPR. ¿Qué debes revisar?

- [ ] Nada: EPR significa que todos los documentos fueron aceptados
- [x] El resumen (resume): cuántos documentos se aceptaron, tienen reparos o fueron rechazados
- [ ] Que el envío sigue en proceso y debes esperar

> EPR significa envío procesado. El resultado de cada documento está en resume: accepted, repairs y rejected.

### 11. ¿Quién es responsable de no repetir nunca un folio?

- [ ] El SII
- [ ] API Gateway
- [x] Tu sistema

> La API no lleva la cuenta de los folios usados. Tu sistema debe reservar cada folio, idealmente con una transacción en su base de datos.

### 12. Emitiste una factura con un error en el monto y el SII ya la aceptó. ¿Qué haces?

- [ ] La construyes de nuevo con el mismo folio y la reenvías
- [x] Emites una nota de crédito con referencia a la factura y CodRef 3
- [ ] La eliminas en el SII

> Un documento aceptado no se modifica ni se elimina. Se corrige con una nota de crédito (o débito) que lo referencia; CodRef 3 corrige montos.

### 13. ¿A qué RUT va dirigido el sobre que se envía al SII?

- [x] Al RUT del SII, 60803000-K
- [ ] Al RUT del receptor del documento
- [ ] Al RUT de la persona del certificado

> El sobre para el SII se dirige al RUT del SII (receptor.rut 60803000-K).

### 14. ¿Por cuánto tiempo, como mínimo, debes guardar los XML de los documentos emitidos?

- [ ] 1 año
- [x] 6 años
- [ ] No es necesario, API Gateway los guarda

> La ley exige conservar los documentos tributarios al menos 6 años. API Gateway no almacena tus documentos.

### 15. Tienes un sobre EnvioBOLETA con boletas. ¿Con qué operación lo envías al SII?

- [ ] billing/integration/sii_dte/sendXmlDocument, la misma de las facturas
- [x] billing/integration/sii_boleta/sendXmlDocument
- [ ] No se envían: el SII las recibe en el Registro de Compras y Ventas

> El SII recibe las boletas por un servicio propio. Se envían con sii_boleta/sendXmlDocument y su estado se consulta con sii_boleta/checkXmlDocumentSentStatus.

### 16. En una boleta afecta (39), ¿qué precio va en PrcItem?

- [ ] El precio neto, sin IVA
- [x] El precio final, con IVA incluido
- [ ] El IVA del ítem

> En las boletas el precio va con IVA incluido. La API calcula el neto y el IVA a partir del total.


    

---

Última actualización el 05/11/2026
#api-gateway-v2
