---
title: "Casos prácticos"
description: ""
type: "academy"
category: "module"
tags: []
authors: [Anonymous]
date: "2026-11-05"
last_update: "2026-11-05"
time_minutes: 25
draft: false
unlisted: false
url: "https://www.apigateway.cl/academy/emision-de-dte/casos-practicos"
---

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


    

---
Última actualización el 05/11/2026

