Documentos Tributarios Electrónicos (DTE)
Un DTE es un documento tributario que se emite ante el SII de Chile. La API cubre nueve tipos, desde la factura afecta hasta la liquidación factura, con un mismo endpoint de emisión.
Esta guía es conceptual: explica el flujo, los modos y las restricciones que se descubren en runtime. El detalle exhaustivo de campos, tipos y esquemas de respuesta vive en la especificación OpenAPI — acá no se duplica.
Antes de emitir
Sección titulada «Antes de emitir»Tres cosas tienen que existir en tu tenant antes del primer POST:
| Requisito | Qué es | ¿Por API? |
|---|---|---|
| Emisor DTE | La empresa que emite, con su certificado digital vigente delegado a la plataforma. Su identificador es el emisorDteId que pide el endpoint de emisión | Sí, por tokenización SII |
| Folios CAF | Los rangos de folios que el SII autoriza por tipo de documento. Sin folios disponibles, la emisión falla | No |
dirOrigen | La dirección de origen configurada en el emisor. El SII la exige en el encabezado | No |
El alta de un emisor DTE sí se hace íntegramente por API: el camino es la tokenización SII,
donde el titular entrega su certificado en un wizard de Redcumbre y tú recibes el emisor de vuelta.
Está documentado en Emisores Tributarios y Emisores DTE. Los folios CAF y la
dirOrigen no se resuelven por API: si te faltan, escribe a tu contacto en REDCUMBRE.
Tipos soportados
Sección titulada «Tipos soportados»| Código | tipoDte | Documento |
|---|---|---|
| 33 | FACTURA_AFECTA | Factura Electrónica Afecta |
| 34 | FACTURA_EXENTA | Factura Electrónica Exenta |
| 39 | BOLETA_AFECTA | Boleta Electrónica Afecta |
| 41 | BOLETA_EXENTA | Boleta Electrónica Exenta |
| 43 | LIQUIDACION_FACTURA | Liquidación Factura |
| 46 | FACTURA_COMPRA | Factura de Compra (cambio de sujeto) |
| 52 | GUIA_DESPACHO | Guía de Despacho |
| 56 | NOTA_DEBITO | Nota de Débito |
| 61 | NOTA_CREDITO | Nota de Crédito |
El canal de emisión es del emisor, no del tipo de documento
Sección titulada «El canal de emisión es del emisor, no del tipo de documento»Es lo primero que conviene entender, porque de ahí cuelgan el límite de líneas, el modo de emisión y la forma exacta de la respuesta.
El canal es una propiedad del emisor DTE configurado en tu tenant. Una misma factura afecta se emite por un canal o por otro según cómo esté habilitado tu emisor: no lo decide el tipo de documento ni lo eliges en la petición. Te lo indica tu contacto en REDCUMBRE, junto con el resto de los prerequisitos.
| Canal | Cómo emite | Qué cambia para ti |
|---|---|---|
| Portal MiPyme | La plataforma opera el portal del SII con el certificado delegado | Máximo de 10 líneas de detalle. Los tres modos de emisión aplican |
Firma local (FULL_DTE) | La plataforma arma el XML, lo firma y lo envía al SII en lote | Hasta 60 líneas de detalle. El modo que pidas no aplica: la respuesta siempre viene con modo: "ASINCRONO", con el documento y su folio ya asignados, y con estadoSii: "PENDIENTE_ENVIO" |
| API Oficial SII | Sólo las boletas 39 y 41, con CAF y certificado digital propios | Hasta 500 líneas de detalle |
Integración a medida (API_EXTERNA) | La plataforma delega la emisión en el sistema que ya usas | El máximo de líneas lo fija ese sistema. El modo que pidas no aplica: la respuesta viene con modo: "ASYNC_EXTERNO", estado: "PENDIENTE_EXTERNO" y folio: 0 — el folio lo asigna el sistema externo y llega después |
Un RUT puede tener dos emisores: facturación y boletas
Sección titulada «Un RUT puede tener dos emisores: facturación y boletas»Las boletas electrónicas (39 y 41) salen de un emisor propio, el de boletas, distinto del de
facturación. Un mismo RUT puede tener los dos, y cada uno tiene su emisorDteId: el que mandas en
la petición decide por cuál sale el documento.
Cómo se dan de alta los dos, y cómo llegan sus ids, está en Emisores.
POST /{tenantSlug}/dteCuatro campos son obligatorios: emisorDteId, tipoDte, receptor y lineas. El
emisorDteId sale del panel web o de la tokenización — ver Antes de emitir.
Dentro de receptor, el giro es obligatorio en todos los tipos salvo las boletas 39 y 41: si
falta, la petición responde 400 con
receptor.El giro del receptor es obligatorio para este tipo de DTE.
El giro del receptor
Sección titulada «El giro del receptor»El camino natural para obtenerlo es POST /{tenantSlug}/herramientas/lookup-rut,
pero giroGlosa normalmente llega null: el SII solo entrega el giro cuando el RUT consultado
es el mismo del certificado que consulta, y al facturarle a un cliente nunca lo es. Hay que
resolverlo en cascada:
const { data } = await lookupRut(rutReceptor);
const giro = data.giroGlosa // null salvo lookup auto-referencial ?? data.actividadesEconomicas?.[0]?.descripcion // la actividad principal del SII ?? await pedirGiroAlUsuario(); // último recursoLos nombres de campo son literales: el array es data.actividadesEconomicas —no data.actividades—
y cada elemento trae { codigo, descripcion }. El SII trunca el giro a 40 caracteres al recibir
el DTE, así que conviene mandarlo ya recortado y revisado, no una glosa larga cortada a ciegas.
Factura Afecta (33)
Sección titulada «Factura Afecta (33)»curl -X POST https://api.redcumbre.cl/tu-tenant/dte \ -H "Authorization: Bearer $REDCUMBRE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "emisorDteId": "clxyz123abc456def", "tipoDte": "FACTURA_AFECTA", "formaPago": "CREDITO", "receptor": { "rut": "77438768-4", "razonSocial": "REDCUMBRE SPA", "giro": "VENTA AL POR MENOR DE PRODUCTOS EN COMERCIOS ESPECIALIZADOS", "direccion": "LOS PEUMOS ST. 3 LT B", "comuna": "BULNES", "email": "contacto@empresa.cl" }, "lineas": [ { "nombre": "Servicio de consultoría especializada", "cantidad": 1, "precioUnitario": 100000, "subtotal": 100000 } ], "idempotencyKey": "orden-12345" }'Respuesta (201). El documento va en data.dte y los montos en data.montos — no sueltos en
data:
{ "success": true, "data": { "modo": "SINC_PARCIAL", "dte": { "id": "dte_5fe4ff45-...", "tipoDte": "FACTURA_AFECTA", "folio": 25403, "dhdrCodigo": "2831022103", "estado": "EMITIDO", "modoEmision": "SINC_PARCIAL" }, "montos": { "montoNeto": 100000, "montoExento": 0, "montoIva": 19000, "montoTotal": 119000 }, "urls": { "pdfUrl": "https://api.redcumbre.cl/public/documentos/{token}/pdf", "xmlUrl": "https://api.redcumbre.cl/public/documentos/{token}/xml", "pdfSiiUrl": null, "webUrl": "https://app.redcumbre.cl/tu-tenant/dte/dte_5fe4ff45-..." }, "estadoPdfSii": "PENDIENTE", "mensaje": "DTE emitido exitosamente" }}Factura Exenta (34)
Sección titulada «Factura Exenta (34)»Igual que la 33, cambiando el tipo. Sin IVA: montoNeto y montoTotal coinciden.
curl -X POST https://api.redcumbre.cl/tu-tenant/dte \ -H "Authorization: Bearer $REDCUMBRE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "emisorDteId": "clxyz123abc456def", "tipoDte": "FACTURA_EXENTA", "receptor": { "rut": "77438768-4", "razonSocial": "REDCUMBRE SPA", "giro": "VENTA AL POR MENOR DE PRODUCTOS EN COMERCIOS ESPECIALIZADOS", "direccion": "LOS PEUMOS ST. 3 LT B", "comuna": "BULNES" }, "lineas": [ { "nombre": "Servicio educacional exento de IVA", "cantidad": 1, "precioUnitario": 250000, "subtotal": 250000 } ] }'Liquidación Factura (43)
Sección titulada «Liquidación Factura (43)»Es el tipo con más particularidades. Se usa cuando un mandatario liquida ventas a su mandante: las líneas describen lo vendido y las comisiones describen lo que el mandatario retiene.
curl -X POST https://api.redcumbre.cl/tu-tenant/dte \ -H "Authorization: Bearer $REDCUMBRE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "emisorDteId": "clxyz123abc456def", "tipoDte": "LIQUIDACION_FACTURA", "receptor": { "rut": "77438768-4", "razonSocial": "REDCUMBRE SPA", "giro": "VENTA AL POR MENOR DE PRODUCTOS EN COMERCIOS ESPECIALIZADOS", "direccion": "LOS PEUMOS ST. 3 LT B", "comuna": "BULNES" }, "lineas": [ { "nombre": "NETO FACTURAS ELECTRONICAS", "cantidad": 8, "precioUnitario": 18000, "subtotal": 144000, "tipoDocumentoLiquidar": 33 }, { "nombre": "EXENTO FACTURAS ELECTRONICAS", "cantidad": 3, "precioUnitario": 12000, "subtotal": 36000, "esExento": true, "tipoDocumentoLiquidar": 33 } ], "comisiones": [ { "tipoMovimiento": "C", "glosa": "Comisión por venta", "valorNeto": 5000 } ] }'tipoDocumentoLiquidar identifica qué tipo de documento se está liquidando en esa línea. Es
exclusivo del 43:
| Código | Documento |
|---|---|
0 | Sin especificar (es el valor que se envía si omites el campo) |
33 | Factura electrónica |
34 | Factura exenta |
39 | Boleta electrónica |
48 | Pago de cheque |
52 | Guía de despacho |
esExento en una línea permite mezclar afectos y exentos en el mismo documento, cosa que los
demás tipos no admiten.
Modos de emisión
Sección titulada «Modos de emisión»El modo aplica a los emisores que emiten por Portal MiPyme. Con firma local se ignora, y la
respuesta viene siempre con modo: "ASINCRONO" y el documento ya emitido.
modo | Qué hace | Cuándo usarlo |
|---|---|---|
SINC_COMPLETO | Emite y genera el PDF del SII antes de responder | Necesitas el PDF en la misma petición |
SINC_PARCIAL | Default. Emite en forma síncrona; el PDF del SII se genera en segundo plano con reintentos | El caso general |
ASINCRONO | Solo valida y encola. Todo ocurre en segundo plano | Estás emitiendo desde una petición web y no quieres que el usuario espere al SII |
Ramifica por data.dte, nunca por modo
Sección titulada «Ramifica por data.dte, nunca por modo»El modo de la respuesta informa cómo operó el carril; no anuncia la forma de la respuesta. Un
emisor de firma local responde modo: "ASINCRONO" y trae el documento igual, porque lo que ocurre
en segundo plano es el envío al SII, no la emisión.
La regla que sí se cumple en todos los canales es una sola:
if (respuesta.data.dte) { // El documento existe y tiene folio. Sigue con tu flujo.} else { // Quedó encolado: consulta respuesta.data.intentoId.}Un cliente escrito como if (modo === "ASINCRONO") poll(intentoId) busca un intentoId que no
existe en la mayoría de los canales.
Cuando la emisión queda encolada, la respuesta trae un intentoId en lugar del documento:
{ "success": true, "data": { "modo": "ASINCRONO", "intentoId": "dtei_3f2a1b8c-...", "estado": "PENDIENTE", "mensaje": "Solicitud de emisión registrada. El DTE se procesará en segundo plano." }}El estado del intento recorre PENDIENTE, PROCESANDO, REINTENTANDO y termina en EMITIDO o
FALLIDO. Se consulta con GET /{tenantSlug}/dte/intento/{intentoId}. Para enterarte sin hacer
polling, usa webhooks.
Borradores
Sección titulada «Borradores»Con "saveAsDraft": true el documento se guarda sin emitir. La respuesta es plana —no trae dte
ni montos— y no consume folio:
{ "success": true, "data": { "id": "dte_3b4e9827-...", "estado": "BORRADOR", "lineas": [{ "nombre": "Servicio de consultoría", "cantidad": 1, "precioUnitario": 100000, "subtotal": 100000 }], "trazaPrecios": [] }}Se puede editar y se emite después con POST /{tenantSlug}/dte/{id}/emitir.
Notificar al receptor
Sección titulada «Notificar al receptor»La emisión puede avisarle al receptor por email y por SMS. Son dos carriles independientes, y en ambos los destinatarios salen de la suma de tres orígenes, deduplicada:
| Campo | Qué hace |
|---|---|
receptor.email | Email del receptor. Recibe el PDF del documento |
receptor.telefono | Teléfono del receptor. Recibe el SMS con el enlace al PDF si notificarSmsDte está activo. Para el SMS tiene que ser un móvil chileno (569XXXXXXXX) |
emailsAdicionales | Hasta 20 destinatarios extra de email — el contador del cliente, por ejemplo |
telefonosSmsAdicionales | Hasta 10 destinatarios extra de SMS, móviles chilenos |
notificarSmsDte | Activa el SMS. Si no lo mandas, queda activo cuando tu tenant tiene el servicio de SMS habilitado |
emailVoid / smsVoid | Excluyen destinatarios de esta emisión. No borran nada de la agenda |
La agenda del cliente se puebla sola
Sección titulada «La agenda del cliente se puebla sola»Todo contacto que mandas en una emisión —los cuatro campos de arriba— queda guardado en la agenda de destinatarios DTE del cliente dentro de tu empresa, normalizado y sin duplicar. Desde la emisión siguiente al mismo receptor no hace falta repetirlo: ya está en la agenda y se notifica igual.
Eso vale también para los borradores: si guardas un borrador con contactos, la agenda se puebla ahí mismo, sin haber emitido.
Tres detalles que conviene tener presentes:
- El teléfono se normaliza al guardarlo (
+56 9 8430 6244→56984306244) y sólo entran móviles chilenos. Un fijo se acepta en el documento pero no llega a la agenda ni recibe SMS. - Las boletas a público general (
66666666-6) no alimentan la agenda. La ficha sería compartida por todos los compradores anónimos. emailVoidysmsVoidno borran de la agenda. Excluyen del envío de esa emisión y nada más; para sacar un destinatario definitivamente están los endpoints de la agenda del cliente.
El detalle de campos, largos y validaciones está en la especificación OpenAPI.
Metadata para la representación impresa
Sección titulada «Metadata para la representación impresa»metadataAdicional es un objeto de pares clave-valor que se guarda como JSON junto al documento.
No viaja al SII: no forma parte del XML firmado ni entra en el timbre. Sirve para alimentar la
plantilla PDF de tu empresa con datos que el formato tributario no tiene dónde poner —el número de
orden de compra, el centro de costo, el período facturado— y para dejarlos consultables después.
{ "emisorDteId": "clxyz123abc456def", "tipoDte": "FACTURA_AFECTA", "receptor": { "rut": "77438768-4", "razonSocial": "REDCUMBRE SPA", "giro": "VENTA AL POR MENOR", "direccion": "LOS PEUMOS ST. 3 LT B", "comuna": "BULNES" }, "lineas": [{ "nombre": "Servicio de consultoría", "cantidad": 1, "precioUnitario": 100000, "subtotal": 100000 }], "metadataAdicional": { "NumOrdenCompra": "OC-12345", "CentroCosto": "CC-001", "PeriodoFacturado": "FEB de 2026" }}Cuatro cosas que conviene saber antes de usarlo:
- Las claves las define tu plantilla PDF, no la API. No hay lista de nombres válidos ni tope de cantidad: lo que mandes se guarda tal cual. Si tu empresa no tiene plantilla personalizada, el dato queda almacenado y consultable, pero no se imprime en ninguna parte.
- Manda los valores como string. Es lo que declara el schema (
additionalProperties: string) y lo que la plantilla espera recibir. - No lo uses para datos que sí tienen campo propio. Un dato que el SII debe ver —referencias, descuentos, glosa del ítem— puesto acá no llega al documento tributario.
- Vuelve en el detalle del documento.
GET /{tenantSlug}/dte/{id}lo devuelve enmetadataAdicional, ynullsi no mandaste nada.
Idempotencia
Sección titulada «Idempotencia»idempotencyKey (máximo 128 caracteres) protege contra reintentos por timeout o doble click. Si
ya existe un documento emitido para la misma combinación de emisor, ambiente, tipo y clave, se
devuelve el original sin crear uno nuevo ni consumir folio.
Dos cosas que conviene tener claras antes de integrar:
- El ambiente forma parte del alcance. La misma clave puede usarse una vez en certificación y una vez en producción. Cuando pases tu emisor a producción, las claves que gastaste probando no te devuelven los documentos de prueba: emiten los reales.
- Anular libera la clave. Un documento anulado deja de ocuparla y la misma clave vuelve a emitir uno nuevo.
Un reintento sobre una clave ya usada responde 201 con "idempotent": true y el documento
original en data.dte — con el folio, el receptor y los montos de la primera emisión, no los
del payload que acabas de mandar. El campo a mirar para distinguir “emití” de “ya estaba emitido”
es idempotent, no el status.
Ver Reglas transversales.
Restricciones que conviene conocer antes
Sección titulada «Restricciones que conviene conocer antes»Estas son las que se descubren con un 400 en runtime si no se saben de antemano.
El precio que mandas es el precio final: las promociones no se aplican por API
Sección titulada «El precio que mandas es el precio final: las promociones no se aplican por API»Una venta emitida por la API de integración no recibe las promociones vigentes del tenant. El
precioUnitario que envías en cada línea es el que se factura, sin descuentos automáticos.
Es deliberado, no una limitación pendiente: quien integra por API ya calculó lo que va a cobrar. Un ERP que manda una línea de $10.000 y recibe una boleta por $6.666 lo trataría como un error — con razón, porque su propio cálculo dejó de ser el que salió en el documento.
Lo mismo aplica al endpoint XML (dte_xml_format1).
Precio unitario: el mínimo es 1, no 0
Sección titulada «Precio unitario: el mínimo es 1, no 0»Cada línea debe tener precioUnitario >= 1. Un 0 se rechaza:
{ "statusCode": 400, "message": "El precio unitario debe ser al menos 1 en cada línea. 1 línea(s) tienen precio inválido." }Hay tres excepciones, donde sí se aceptan líneas en 0:
- Guía de despacho (52) sin precios, cuando se envía marcada como tal
- Nota de crédito o débito (61 / 56) de corrección o anulación sin monto — las que sólo
corrigen un texto o anulan, con referencia de código
1o2. El SII las certifica con total0 - Liquidación factura (43), que admite líneas glosa con precio
0legítimo
El DTO además rechaza valores negativos en precioUnitario.
Cantidad de líneas: depende del canal
Sección titulada «Cantidad de líneas: depende del canal»No es un número fijo. El máximo lo determina el canal de integración del emisor: 10 líneas de detalle por Portal MiPyme, 60 con firma local y 500 por la API Oficial SII de boletas. Si te pasas:
{ "statusCode": 400, "message": "El documento tiene 12 líneas de detalle, pero el emisor ... permite máximo 10. Reduzca la cantidad de líneas." }El mensaje te dice el máximo aplicable a tu emisor. No lo asumas desde el código.
Largo del nombre de ítem: se trunca, no se rechaza
Sección titulada «Largo del nombre de ítem: se trunca, no se rechaza»El campo nombre acepta hasta 255 caracteres y no falla si te pasas de 80. Lo que ocurre es
que al enviarlo al SII se trunca a 80, que es el límite del organismo. El dato completo queda
guardado en la plataforma y aparece íntegro en el PDF interno; el que viaja al SII va cortado.
Si el nombre importa entero en el documento tributario, mantenlo bajo 80 caracteres. Para
detalle largo existe descripcionExtendida (hasta 1.000 caracteres), que no viaja al SII.
Revertir una Liquidación Factura (43)
Sección titulada «Revertir una Liquidación Factura (43)»Un DTE 43 no se anula con nota de crédito ni de débito. Si lo intentas:
{ "statusCode": 400, "message": "Las Liquidaciones Factura (DTE 43) no pueden anularse con Nota de Crédito. Emita una nueva Liquidación Factura con valores negativos referenciando el documento original." }La vía correcta es emitir otra liquidación con valores negativos, referenciando la original.
Y acá hay una asimetría que conviene entender, porque contradice la intuición:
- Las líneas de detalle no admiten valores negativos. El esquema XML del SII lo prohíbe.
- Las comisiones sí conservan el signo. Una comisión negativa —una devolución o un reverso— debe ir con su signo. Si se enviara en valor absoluto, la suma por línea contradiría el resumen de totales y el SII rechazaría el documento.
O sea: el signo de la reversión vive en las comisiones, no en las líneas.
Consultar y descargar
Sección titulada «Consultar y descargar»| Para | Endpoint |
|---|---|
| Listar documentos | GET /{tenantSlug}/dte |
| Detalle de uno | GET /{tenantSlug}/dte/{id} |
| PDF de la plataforma | GET /{tenantSlug}/dte/{id}/pdf |
| PDF timbrado del SII | GET /{tenantSlug}/dte/{id}/pdf-sii |
| Estado ante el SII | POST /{tenantSlug}/dte/{id}/verificar-estado-sii |
| Archivos asociados (XML, PDF) | GET /{tenantSlug}/dte/{id}/archivos |
| Historial de eventos | GET /{tenantSlug}/dte/{id}/logs |
El índice completo de rutas del dominio está en
/api-docs/index.txt.
Errores y reintentos
Sección titulada «Errores y reintentos»| Código | Causa típica | ¿Reintentar? |
|---|---|---|
400 | Payload inválido, precio bajo el mínimo, exceso de líneas, tipo de referencia no permitido | No. Corrige el payload |
403 | La API key no alcanza el endpoint, o el servicio de DTE no está habilitado en el tenant | No |
404 | El emisorDteId no existe en tu tenant | No. Verifícalo en el panel (Configuración → Emisores, campo ID) o en la respuesta de tu tokenización |
409 | Tu emisor tiene conflictos de sincronización pendientes | No. Se resuelve sobre el emisor; escribe a tu contacto en REDCUMBRE |
422 | Sin folios CAF disponibles, o límite de crédito del cliente excedido | No. Ver el aviso de abajo |
5xx | Falla de la API o del SII | Sí, con backoff. Usa idempotencyKey para que el reintento no duplique |
Un rechazo del SII no es un 5xx: el documento se emite y queda con estadoSii en estado de
rechazo. Se consulta con verificar-estado-sii, no se reintenta el POST.
Siguiente paso
Sección titulada «Siguiente paso»- Webhooks — enterarte del resultado sin hacer polling
- Reglas transversales — paginación, idempotencia, errores
- Procesos Batch — emisión masiva desde Excel
- Especificación OpenAPI — todos los campos, tipos y esquemas