¿Qué es esta API?
La API de Facturación Electrónica expone todos los servicios necesarios para emitir, firmar y enviar Documentos Tributarios Electrónicos (DTE) al SII de Chile, directamente desde cualquier plataforma o lenguaje. Opera con arquitectura multi-tenant: cada empresa (RUT) tiene su propia base de datos, certificado y folios.
https://tu-servidor.cl/api
Content-Type: application/json es obligatorio en requests con body.POST /auth/*) requieren autenticación. Soporta JWT Bearer Token y API Key directa.Métodos de acceso
La API soporta dos mecanismos de autenticación. Para integraciones sistema-a-sistema se recomienda el header X-Api-Key. Para sesiones de usuario, usa JWT.
X-Api-Key. Sin expiración, sin renovar tokens. Ideal para backends y POS.POST /auth/login o POST /auth/api-key/login. Válido por 24 horas. Envíalo en el header Authorization: Bearer <token>.X-Api-Key, no dentro del header Authorization. El header Authorization: Bearer es exclusivo para tokens JWT del portal admin.# Método 1: Header X-Api-Key (más simple para integraciones) curl -X POST https://tu-servidor.cl/api/dte/facturas/emitir \ -H "X-Api-Key: ak_live_xxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ ... }'
# 1. Obtener token curl -X POST https://tu-servidor.cl/api/auth/login \ -H "Content-Type: application/json" \ -d '{ "email": "admin@miempresa.cl", "password": "mi_password" }' # Respuesta { "access_token": "eyJhbGciOiJIUzI1NiIs...", "token_type": "Bearer" } # 2. Usar el token en cualquier endpoint curl -X GET https://tu-servidor.cl/api/dte/emitidos \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
curl -X POST https://tu-servidor.cl/api/auth/api-key/login \ -H "Content-Type: application/json" \ -d '{ "apiKey": "ak_live_xxxxxxxxxxxxxxxx" }' # Respuesta { "access_token": "eyJhbGciOiJIUzI1NiIs...", "token_type": "Bearer", "expires_in": 86400 }
Endpoints de autenticación
Emite tu primera factura
Ejemplo completo de emisión de una Factura Electrónica (código 33) en distintos lenguajes. El mismo patrón aplica para todos los tipos de DTE.
curl -X POST https://tu-servidor.cl/api/dte/facturas/emitir \ -H "X-Api-Key: ak_live_xxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "idOperacion": "ORD-2027-001", "total": 119000, "descuentoGlobal": 0, "medioPago": "Transferencia", "enviarCorreo": true, "cliente": { "rut": "12345678", "digito": "9", "razonSocial": "Empresa Cliente SpA", "giro": "Comercio al por mayor", "direccion": "Av. Principal 123", "ciudad": "Santiago", "comuna": "Las Condes", "email": "contacto@cliente.cl" }, "detalles": [ { "linea": 1, "codigo": "PROD-001", "descripcion": "Servicio de consultoría", "DscItem": "Descripción larga opcional del ítem (máx. 1000 chars, campo DscItem SII)", "precio": 100000, "cantidad": 1, "precioSubtotal": 100000, "esExento": false } ] }'
{ "folio": 1042, "esSimulacion": false, "xmlBase64": "PD94bWwgdmVyc2lvbj0...", "pdfBase64": "JVBERi0xLjQgMS...", "documentos": { "pdf": "/api/dte/documentos/33/1042/pdf", "xml": "/api/dte/documentos/33/1042/xml" } }
const API_BASE = 'https://tu-servidor.cl/api'; const API_KEY = 'ak_live_xxxxxxxxxxxxxxxx'; async function emitirFactura(datos) { const res = await fetch(`${API_BASE}/dte/facturas/emitir`, { method: 'POST', headers: { 'X-Api-Key': API_KEY, 'Content-Type': 'application/json' }, body: JSON.stringify(datos) }); if (!res.ok) { const err = await res.json(); throw new Error(err.error); } return res.json(); } // Uso const resultado = await emitirFactura({ idOperacion: 'ORD-2027-001', total: 119000, cliente: { rut: '12345678', digito: '9', razonSocial: 'Empresa Cliente SpA', giro: 'Comercio al por mayor', direccion: 'Av. Principal 123', ciudad: 'Santiago', comuna: 'Las Condes', email: 'contacto@cliente.cl' }, detalles: [{ linea: 1, codigo: 'PROD-001', descripcion: 'Servicio de consultoría', DscItem: 'Descripción larga opcional (máx. 1000 chars)', precio: 100000, cantidad: 1, precioSubtotal: 100000, esExento: false }] }); console.log(`Factura emitida. Folio: ${resultado.folio}`); console.log(`PDF: ${resultado.documentos.pdf}`);
import requests API_BASE = "https://tu-servidor.cl/api" API_KEY = "ak_live_xxxxxxxxxxxxxxxx" headers = { "X-Api-Key": API_KEY, "Content-Type": "application/json" } payload = { "idOperacion": "ORD-2027-001", "total": 119000, "descuentoGlobal": 0, "medioPago": "Transferencia", "enviarCorreo": True, "cliente": { "rut": "12345678", "digito": "9", "razonSocial": "Empresa Cliente SpA", "giro": "Comercio al por mayor", "direccion": "Av. Principal 123", "ciudad": "Santiago", "comuna": "Las Condes", "email": "contacto@cliente.cl" }, "detalles": [{ "linea": 1, "codigo": "PROD-001", "descripcion": "Servicio de consultoría", "DscItem": "Descripción larga opcional (máx. 1000 chars)", "precio": 100000, "cantidad": 1, "precioSubtotal": 100000, "esExento": False }] } response = requests.post( f"{API_BASE}/dte/facturas/emitir", json=payload, headers=headers ) response.raise_for_status() data = response.json() print(f"Factura emitida. Folio: {data['folio']}") print(f"PDF disponible en: {data['documentos']['pdf']}") # Guardar PDF localmente import base64 pdf_bytes = base64.b64decode(data['pdfBase64']) with open(f"factura_{data['folio']}.pdf", "wb") as f: f.write(pdf_bytes)
using System.Net.Http.Json; var client = new HttpClient(); client.DefaultRequestHeaders.Add("X-Api-Key", "ak_live_xxxxxxxxxxxxxxxx"); var payload = new { idOperacion = "ORD-2027-001", total = 119000, descuentoGlobal = 0, medioPago = "Transferencia", enviarCorreo = true, cliente = new { rut = "12345678", digito = "9", razonSocial = "Empresa Cliente SpA", giro = "Comercio al por mayor", direccion = "Av. Principal 123", ciudad = "Santiago", comuna = "Las Condes", email = "contacto@cliente.cl" }, detalles = new[] { new { linea = 1, codigo = "PROD-001", descripcion = "Servicio de consultoría", DscItem = "Descripción larga opcional (máx. 1000 chars)", precio = 100000m, cantidad = 1m, precioSubtotal = 100000m, esExento = false } } }; var response = await client.PostAsJsonAsync( "https://tu-servidor.cl/api/dte/facturas/emitir", payload ); response.EnsureSuccessStatusCode(); var result = await response.Content.ReadFromJsonAsync<JsonElement>(); Console.WriteLine($"Folio: {result.GetProperty("folio")}");
<?php $apiBase = 'https://tu-servidor.cl/api'; $apiKey = 'ak_live_xxxxxxxxxxxxxxxx'; $payload = [ 'idOperacion' => 'ORD-2027-001', 'total' => 119000, 'descuentoGlobal'=> 0, 'medioPago' => 'Transferencia', 'enviarCorreo' => true, 'cliente' => [ 'rut' => '12345678', 'digito' => '9', 'razonSocial'=> 'Empresa Cliente SpA', 'giro' => 'Comercio al por mayor', 'direccion' => 'Av. Principal 123', 'ciudad' => 'Santiago', 'comuna' => 'Las Condes', 'email' => 'contacto@cliente.cl', ], 'detalles' => [[ 'linea' => 1, 'codigo' => 'PROD-001', 'descripcion' => 'Servicio de consultoría', 'DscItem' => 'Descripción larga opcional (máx. 1000 chars)', 'precio' => 100000, 'cantidad' => 1, 'precioSubtotal' => 100000, 'esExento' => false, ]] ]; $ch = curl_init("$apiBase/dte/facturas/emitir"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "X-Api-Key: $apiKey", 'Content-Type: application/json', ], CURLOPT_POSTFIELDS => json_encode($payload), ]); $body = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $data = json_decode($body, true); echo "Folio emitido: {$data['folio']}\n"; // Guardar PDF localmente file_put_contents( "factura_{$data['folio']}.pdf", base64_decode($data['pdfBase64']) );
Campos del request de emisión
El mismo objeto aplica para Facturas (33/34), Notas de Crédito/Débito (56/61), Guías de Despacho (52), Factura de Compra (46) y Exportación (110/111/112). Las boletas (39/41) tienen un esquema similar con campos idBoletaOperacion en lugar de idOperacion.
Objeto raíz
| Campo | Tipo | Req. | Descripción |
|---|---|---|---|
| idOperacion | string | opt | Identificador interno del sistema origen (ej. número de orden). No va al SII. |
| total | int | req | Monto total del documento en pesos CLP (incluye IVA). |
| descuentoGlobal | int | opt | Descuento global en porcentaje (0–100). Default: 0. |
| medioPago | string | opt | Descripción del medio de pago. Ej: "Transferencia", "Efectivo", "Cheque". |
| montoPago | string | opt | Monto recibido como pago (string para compatibilidad). |
| vuelto | string | opt | Vuelto entregado al cliente. |
| enviarCorreo | bool | opt | Si true, envía el DTE al email del cliente. Default: false. |
| sucursalEmision | string | opt | Nombre de la sucursal emisora. |
| rutOperador | string | opt | RUT del operador/cajero que emite (sin dígito verificador). |
| cliente | object | req | Datos del receptor del documento. Ver tabla siguiente. |
| detalles | array | req | Líneas de detalle del documento. Mínimo 1 elemento. |
| referencias | array | opt | Referencias a documentos anteriores (para NC/ND). |
Objeto cliente
| Campo | Tipo | Req. | Descripción |
|---|---|---|---|
| rut | string | req | RUT sin dígito verificador. Para consumidor final usar "66666666". |
| digito | string | req | Dígito verificador del RUT. Para consumidor final usar "6". |
| razonSocial | string | req | Nombre o razón social del receptor. |
| giro | string | opt | Giro comercial del receptor. |
| direccion | string | opt | Dirección del receptor. |
| ciudad | string | opt | Ciudad del receptor. |
| comuna | string | opt | Comuna del receptor. |
| string | opt | Email para envío del DTE (si enviarCorreo=true). |
Objeto detalles[]
| Campo | Tipo | Req. | Descripción |
|---|---|---|---|
| linea | int | req | Número de línea secuencial (1, 2, 3, …). |
| codigo | string | opt | Código SKU o identificador del producto/servicio. |
| descripcion | string | req | Nombre corto del ítem → campo NmbItem en el XML SII. Máx. 80 caracteres. |
| DscItem | string | opt | Descripción larga del ítem → campo DscItem en el XML SII. Máx. 1.000 caracteres. Se imprime como sublínea en el PDF. Omitir o dejar vacío si no aplica. |
| precio | decimal | req | Precio unitario neto (sin IVA). |
| cantidad | decimal | req | Cantidad del ítem. |
| precioSubtotal | decimal | req | Subtotal de la línea (precio × cantidad − descuentos). |
| precioPorcentajeDescuento | decimal | opt | Descuento en porcentaje para la línea (0–100). |
| esExento | bool | opt | Si true, el ítem no lleva IVA. Default: false. |
Todos los endpoints
Listado completo organizado por módulo. Todos requieren autenticación con JWT Bearer o X-Api-Key salvo los de /auth.
Códigos de DTE soportados
codigoTipoGuia, rutChofer, patente, direccionDestino, etc. dentro del mismo objeto de request.
codigoPais, moneda, tipoCambio, formaPago, clausulaDeVenta. El monto se indica en la moneda original y la API convierte a CLP según el tipo de cambio informado.
pdfBase64, xmlBase64). Estos endpoints son más eficientes para imprimir o mostrar el PDF directamente en el browser.
Documentos recibidos desde el SII
Cuando un proveedor te emite una factura electrónica, el SII la deposita en tu buzón de intercambio. La plataforma consulta ese buzón automáticamente y los documentos quedan disponibles en el módulo de Intercambio, listos para ser aceptados, reclamados o rechazados.
Endpoints Intercambio
Cesión electrónica de facturas
La plataforma cuenta con módulo de Cesión DTE para operar facturas cedibles ante el RPETC/SII. Es un recurso opcional del tenant, habilitable según el plan contratado, y permite preparar, firmar, enviar y consultar cesiones directamente desde el portal o por API.
Endpoints principales de Cesión
Enviar acuse sobre DTE emitidos
Como emisor, puedes registrar el estado de entrega real de tus facturas: si el receptor aceptó la mercadería (ERM), reclamó el contenido (RCD) o rechazó la factura (RSC). Estos eventos quedan registrados en el SII y son visibles para ambas partes.
Notificaciones automáticas
La plataforma genera alertas automáticas por email cuando detecta eventos críticos: certificado digital próximo a vencer, folios CAF agotándose, o errores de envío al SII. Las alertas se configuran por tenant desde el portal de administración.
Control de acceso por rol (RBAC)
Cada tenant puede tener múltiples usuarios con roles diferenciados. El rol tenant_admin tiene acceso completo al portal y la API. El rol tenant_viewer puede consultar documentos y reportes, pero no emitir ni modificar configuraciones.
| Rol | Emisión DTE | Ver reportes | Admin config. | Gestionar usuarios |
|---|---|---|---|---|
| tenant_admin | ✅ Sí | ✅ Sí | ✅ Sí | ✅ Sí |
| tenant_viewer | ❌ No | ✅ Sí | ❌ No | ❌ No |
Envío de correos electrónicos
La plataforma envía emails de manera automática para la entrega de DTE a clientes y para las notificaciones de alertas. Soporta dos proveedores configurables desde el panel de administración: Resend (API key) y SMTP personalizado.
ResendApiKey.¿Qué emails envía la plataforma?
| Evento | Destinatario | Contenido |
|---|---|---|
| Emisión DTE (enviarCorreo: true) | Email del cliente | PDF del DTE en adjunto + link de descarga |
| Certificado próximo a vencer | Admins del tenant | Aviso con días restantes + instrucciones de renovación |
| Folios CAF agotándose | Admins del tenant | Tipo de DTE afectado + folios restantes |
| Error de envío SII | Admins del tenant | Folio, tipo y mensaje de error del SII |
| RAM > 85% (advertencia) | SuperAdmin | Alerta temprana de uso de memoria · umbral configurable |
| RAM > 95% (crítico) | SuperAdmin | Alerta crítica de memoria · riesgo de caída del servicio |
| Disco > 85% (advertencia) | SuperAdmin | Advertencia de espacio en disco del servidor |
| Disco > 95% (crítico) | SuperAdmin | Disco casi lleno · puede interrumpir emisión y backups |
| MySQL binlogs sin retención | SuperAdmin | Variable expire_logs_days = 0 (binlogs crecen sin límite) |
| Recuperación de contraseña | Usuario que solicitó | Link seguro con token de reset (expira en 1h) |
Respaldo automático en Google Drive
La plataforma puede respaldar automáticamente la base de datos y los XML firmados hacia una carpeta de Google Drive, sin dependencia de servidores externos propietarios. El respaldo incluye programación por cron y registro de historial.
Configuración en 3 pasos
GET /dte/documentos/{tipo}/{folio}/xml mientras existan en el servidor.
Monitoreo del servidor
La plataforma incluye un servicio de monitoreo interno (ServerOps) que mide en tiempo real el uso de disco, RAM y estado de MySQL. Cuando se superan los umbrales configurados, dispara alertas automáticas por email al SuperAdmin. No requiere ninguna herramienta externa.
expire_logs_days esté configurada. Si es 0, los binlogs crecen indefinidamente hasta llenar el disco.Umbrales configurables · Variables de entorno
| Variable | Default | Descripción |
|---|---|---|
| ServerOps__WarningDiskPercent | 85 | % de disco usado para alerta de advertencia |
| ServerOps__CriticalDiskPercent | 95 | % de disco usado para alerta crítica |
| ServerOps__CleanupDiskPercent | 95 | % a partir del cual se intenta limpieza automática de archivos temporales |
| ServerOps__WarningRamPercent | 85 | % de RAM usada para alerta de advertencia |
| ServerOps__CriticalRamPercent | 95 | % de RAM usada para alerta crítica |
| ServerOps__IntervalMinutes | 10 | Frecuencia de ejecución del monitoreo en minutos |
| ServerOps__AlertCooldownMinutes | 60 | Tiempo mínimo entre emails del mismo tipo de alerta |
profile.env del cliente y se inyectan automáticamente al servicio systemd en cada deploy. No requiere editar appsettings.json manualmente.
Snapshot del servidor · SuperAdmin Portal
El Super Admin Portal incluye la sección Métricas que muestra en tiempo real el estado del servidor del cliente seleccionado:
Eventos sobre DTE emitidos
Cuando tu empresa emite una factura, el receptor puede responder formalmente a través del SII.
Esa respuesta se llama Evento de DTE y queda registrada
en el campo estadoSiiEvento
de cada documento. Ejemplos comunes: que el cliente acuse recibo, reclame el contenido o rechace la factura.
GET /dte/emitidos?tipo=33.
El campo estadoSiiEvento refleja el último evento reportado por el receptor al SII.
Códigos de evento
| Código | Nombre | Significado para el emisor |
|---|---|---|
| ACD | Acuse de Recibo Conforme | El receptor confirma haber recibido el DTE y está conforme. ✅ Positivo. |
| RCD | Reclamo al Contenido del DTE | El receptor impugna el contenido (montos, datos). Requiere corrección con NC. |
| ERM | Entrega Real de Mercadería | El receptor confirma que recibió los bienes o servicios efectivamente. |
| RFB | Reclamo al Flete o Bodegaje | El receptor reclama por los costos de transporte o bodega indicados en la guía. |
| RSC | Reclamo Sin Cargo | Rechazo formal de la factura. El receptor no reconoce la deuda. ⚠️ Requiere atención. |
| — | Sin Evento | El receptor aún no ha enviado ningún evento al SII sobre este documento. |
Consultar eventos via API
estadoSiiEvento
estadoSiiEvento es RSC, el receptor rechazó la factura.
Debes emitir una Nota de Crédito (DTE 61) para anularla y regularizar la situación ante el SII.
Ejemplo de respuesta con eventos
[ { "codigoDte": 33, "tipoDte": "Factura Electrónica", "folio": 5184, "rut": "96876460-8", "razonSocial": "Empresa Receptora SpA", "neto": 11337500, "iva": 2154125, "total": 13491625, "fechaEmision": "2025-12-01T00:00:00", "enviadoSii": true, "trackId": "1234567890", "estadoSiiEvento": "ACD" // ← Acuse de Recibo Conforme del receptor }, { "folio": 5186, "rut": "96540490-2", "total": 253970, "estadoSiiEvento": "" // ← Sin Evento: el receptor aún no responde }, { "folio": 5189, "rut": "79903370-4", "total": 420070, "estadoSiiEvento": "RSC" // ⚠️ Rechazado — emitir Nota de Crédito } ]
Filtrar eventos en tu código
const res = await fetch('https://tu-servidor.cl/api/dte/emitidos?tipo=33', { headers: { 'X-Api-Key': 'ak_live_xxx' } }); const facturas = await res.json(); // Facturas rechazadas (RSC) → requieren Nota de Crédito const rechazadas = facturas.filter(f => f.estadoSiiEvento === 'RSC'); // Facturas con acuse de recibo conforme const aceptadas = facturas.filter(f => f.estadoSiiEvento === 'ACD'); // Facturas sin evento (receptor no ha respondido) const sinEvento = facturas.filter(f => !f.estadoSiiEvento); console.log(`Rechazadas: ${rechazadas.length} · Aceptadas: ${aceptadas.length} · Sin evento: ${sinEvento.length}`);
import requests facturas = requests.get( "https://tu-servidor.cl/api/dte/emitidos", params={"tipo": 33}, headers={"X-Api-Key": "ak_live_xxx"} ).json() rechazadas = [f for f in facturas if f.get("estadoSiiEvento") == "RSC"] aceptadas = [f for f in facturas if f.get("estadoSiiEvento") == "ACD"] sin_evento = [f for f in facturas if not f.get("estadoSiiEvento")] for f in rechazadas: print(f"⚠️ Folio {f['folio']} rechazado por {f['razonSocial']} — emitir NC")
using System.Net.Http.Json; var client = new HttpClient(); client.DefaultRequestHeaders.Add("X-Api-Key", "ak_live_xxx"); var facturas = await client.GetFromJsonAsync<List<DteEmitidoDto>>( "https://tu-servidor.cl/api/dte/emitidos?tipo=33" ); var rechazadas = facturas!.Where(f => f.EstadoSiiEvento == "RSC").ToList(); var aceptadas = facturas!.Where(f => f.EstadoSiiEvento == "ACD").ToList(); Console.WriteLine($"Rechazadas: {rechazadas.Count} · Aceptadas: {aceptadas.Count}"); // Emitir NC para cada rechazada foreach (var f in rechazadas) { Console.WriteLine($"Folio {f.Folio} rechazado por {f.RazonSocial} — pendiente NC"); } // DTO mínimo record DteEmitidoDto( int CodigoDte, long Folio, string Rut, string RazonSocial, long Total, string EstadoSiiEvento );
Emitir Boleta Electrónica
La boleta (DTE 39) sigue el mismo patrón. Para consumidor final, usa el RUT anónimo 66666666-6.
curl -X POST https://tu-servidor.cl/api/dte/boletas/emitir \ -H "X-Api-Key: ak_live_xxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -d '{ "idBoletaOperacion": "POS-0042", "total": 5950, "medioPago": "Efectivo", "montoPago": "10000", "vuelto": "4050", "cliente": { "rut": "66666666", "digito": "6", "razonSocial": "CONSUMIDOR FINAL" }, "detalles": [ { "linea": 1, "descripcion": "Café Americano", "precio": 2500, "cantidad": 1, "precioSubtotal": 2500, "esExento": false }, { "linea": 2, "descripcion": "Sándwich de Palta", "precio": 3450, "cantidad": 1, "precioSubtotal": 3450, "esExento": false } ] }'
const res = await fetch('https://tu-servidor.cl/api/dte/boletas/emitir', { method: 'POST', headers: { 'X-Api-Key': 'ak_live_xxxxxxxxxxxxxxxx', 'Content-Type': 'application/json' }, body: JSON.stringify({ idBoletaOperacion: 'POS-0042', total: 5950, medioPago: 'Efectivo', montoPago: '10000', vuelto: '4050', cliente: { rut: '66666666', digito: '6', razonSocial: 'CONSUMIDOR FINAL' }, detalles: [ { linea: 1, descripcion: 'Café Americano', precio: 2500, cantidad: 1, precioSubtotal: 2500, esExento: false }, { linea: 2, descripcion: 'Sándwich de Palta', precio: 3450, cantidad: 1, precioSubtotal: 3450, esExento: false } ] }) }); const boleta = await res.json(); // El PDF y XML están en base64 directamente const pdfBlob = new Blob( [Uint8Array.from(atob(boleta.pdfBase64), c => c.charCodeAt(0))], { type: 'application/pdf' } ); // Abrir en nueva pestaña window.open(URL.createObjectURL(pdfBlob));
import requests, base64 r = requests.post( "https://tu-servidor.cl/api/dte/boletas/emitir", headers={"X-Api-Key": "ak_live_xxx", "Content-Type": "application/json"}, json={ "idBoletaOperacion": "POS-0042", "total": 5950, "medioPago": "Efectivo", "cliente": {"rut": "66666666", "digito": "6", "razonSocial": "CONSUMIDOR FINAL"}, "detalles": [ {"linea": 1, "descripcion": "Café Americano", "precio": 2500, "cantidad": 1, "precioSubtotal": 2500, "esExento": False}, {"linea": 2, "descripcion": "Sándwich de Palta", "precio": 3450, "cantidad": 1, "precioSubtotal": 3450, "esExento": False} ] } ) r.raise_for_status() data = r.json() print(f"Boleta #{data['folio']} emitida") open(f"boleta_{data['folio']}.pdf", "wb").write(base64.b64decode(data["pdfBase64"]))
Estructura de respuesta (todos los DTE)
{ "folio": 1042, // número de folio asignado "esSimulacion": false, // true si el modo simulación estaba activo "xmlBase64": "PD94bWwg...", // DTE XML firmado en Base64 "pdfBase64": "JVBERi0x...", // PDF del DTE en Base64 "envioXmlBase64": "...", // solo en boletas: XML de EnvioBoleta "documentos": { "pdf": "/api/dte/documentos/33/1042/pdf", "xml": "/api/dte/documentos/33/1042/xml", "envioXml": "/api/dte/documentos/33/1042/envio-xml" } } // Respuesta de error · HTTP 400 { "success": false, "error": "No hay folios disponibles para el tipo de DTE 33." }
Cargar un CAF (XML del SII)
import requests, base64 # Leer el archivo XML del CAF descargado del SII with open("caf_33_001001.xml", "rb") as f: caf_b64 = base64.b64encode(f.read()).decode() r = requests.post( "https://tu-servidor.cl/api/dte/caf", headers={"X-Api-Key": "ak_live_xxx", "Content-Type": "application/json"}, json={ "codigoDte": 33, "cafBase64": caf_b64, "archivoNombre": "caf_33_001001.xml" } ) print(r.json()) # {"success": true, "codigoDte": 33, "desde": 1001, "hasta": 2000, "mode": "inserted"}
Consultar estado de envío al SII
curl https://tu-servidor.cl/api/dte/sii/estado-envio/1234567890 \ -H "X-Api-Key: ak_live_xxxxxxxxxxxxxxxx" # Respuesta del SII { "trackId": "1234567890", "estado": "EPR", // EPR=Enviado y procesado "glosa": "Envío Procesado", "numDoctos": 1 }
Flujo de integración típico
Cómo se conecta tu sistema con la API en un flujo completo de emisión.
X-Api-Key o un JWT en cada request. Sin pasos adicionales.GET /dte/facturas/folios/resumen. La respuesta indica si puedes emitir y cuántos folios quedan.POST /dte/sii/reenviar/{tipo}/{folio} permite reintentarlo.POST /dte/certificados) y al menos un CAF vigente (POST /dte/caf) para cada tipo de DTE que utilizarás.