¿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.

🌐
URL Base
Todos los endpoints parten de la URL base de tu instancia.
https://tu-servidor.cl/api
📦
Formato de datos
Todos los endpoints aceptan y devuelven JSON. El header Content-Type: application/json es obligatorio en requests con body.
🔐
Autenticación
Todos los endpoints (excepto POST /auth/*) requieren autenticación. Soporta JWT Bearer Token y API Key directa.
🏢
Multi-Tenant
El tenant (empresa) se resuelve automáticamente desde el token o API Key. No necesitas enviar el RUT de la empresa en cada request.
ℹ️ Esta API no requiere instalar ninguna librería propietaria. Funciona desde cualquier lenguaje o plataforma que soporte HTTP: Python, Node.js, PHP, Java, C#, Ruby, Go, etc.

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.

🔑 API Key · Integraciones (Tenant)
Envía tu API Key directamente en el header X-Api-Key. Sin expiración, sin renovar tokens. Ideal para backends y POS.
Cuándo usarlo: backends, ERP, POS, integración B2B, microservicios.
🪙 JWT Bearer · Portal Admin
Obtén un token en POST /auth/login o POST /auth/api-key/login. Válido por 24 horas. Envíalo en el header Authorization: Bearer <token>.
Cuándo usarlo: portal web de administración, sesiones de usuarios, dashboards.
🚫
Header incorrecto vs correcto para integraciones API
✗ INCORRECTO
Authorization: x-api-key {TU_API_KEY}
✓ CORRECTO
X-Api-Key: {TU_API_KEY}
La API Key va en su propio header X-Api-Key, no dentro del header Authorization. El header Authorization: Bearer es exclusivo para tokens JWT del portal admin.
Usando API Key directa — cualquier endpointcURL
# 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 '{ ... }'
Login con usuario y contraseña → obtener JWTcURL
# 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..."
Intercambiar API Key por JWT de 24hcURL
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

POST /auth/login Login tenant · email + password → JWT
POST /auth/api-key/login API Key → JWT de 24h
POST /auth/forgot-password Solicitar recuperación de contraseña → envía email con token
POST /auth/reset-password Restablecer contraseña con token recibido por email
POST /auth/super/login Login SuperAdmin (solo administración de plataforma)

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 JavaScript / Node.js Python C# / .NET PHP
Emitir Factura Electrónica · POST /dte/facturas/emitirbash
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
      }
    ]
  }'
Respuesta exitosaJSON
{
  "folio": 1042,
  "esSimulacion": false,
  "xmlBase64": "PD94bWwgdmVyc2lvbj0...",
  "pdfBase64": "JVBERi0xLjQgMS...",
  "documentos": {
    "pdf": "/api/dte/documentos/33/1042/pdf",
    "xml": "/api/dte/documentos/33/1042/xml"
  }
}
Emitir Factura · fetch (Node.js / browser)javascript
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}`);
Emitir Factura · requestspython
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)
Emitir Factura · HttpClientC#
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")}");
Emitir Factura · cURL PHPPHP
<?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

CampoTipoReq.Descripción
idOperacionstringoptIdentificador interno del sistema origen (ej. número de orden). No va al SII.
totalintreqMonto total del documento en pesos CLP (incluye IVA).
descuentoGlobalintoptDescuento global en porcentaje (0–100). Default: 0.
medioPagostringoptDescripción del medio de pago. Ej: "Transferencia", "Efectivo", "Cheque".
montoPagostringoptMonto recibido como pago (string para compatibilidad).
vueltostringoptVuelto entregado al cliente.
enviarCorreobooloptSi true, envía el DTE al email del cliente. Default: false.
sucursalEmisionstringoptNombre de la sucursal emisora.
rutOperadorstringoptRUT del operador/cajero que emite (sin dígito verificador).
clienteobjectreqDatos del receptor del documento. Ver tabla siguiente.
detallesarrayreqLíneas de detalle del documento. Mínimo 1 elemento.
referenciasarrayoptReferencias a documentos anteriores (para NC/ND).

Objeto cliente

CampoTipoReq.Descripción
rutstringreqRUT sin dígito verificador. Para consumidor final usar "66666666".
digitostringreqDígito verificador del RUT. Para consumidor final usar "6".
razonSocialstringreqNombre o razón social del receptor.
girostringoptGiro comercial del receptor.
direccionstringoptDirección del receptor.
ciudadstringoptCiudad del receptor.
comunastringoptComuna del receptor.
emailstringoptEmail para envío del DTE (si enviarCorreo=true).

Objeto detalles[]

CampoTipoReq.Descripción
lineaintreqNúmero de línea secuencial (1, 2, 3, …).
codigostringoptCódigo SKU o identificador del producto/servicio.
descripcionstringreqNombre corto del ítem → campo NmbItem en el XML SII. Máx. 80 caracteres.
DscItemstringoptDescripció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.
preciodecimalreqPrecio unitario neto (sin IVA).
cantidaddecimalreqCantidad del ítem.
precioSubtotaldecimalreqSubtotal de la línea (precio × cantidad − descuentos).
precioPorcentajeDescuentodecimaloptDescuento en porcentaje para la línea (0–100).
esExentobooloptSi 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

33Factura Electrónica
34Factura No Afecta / Exenta
39Boleta Electrónica
41Boleta Exenta Electrónica
46Factura de Compra
52Guía de Despacho
56Nota de Débito Electrónica
61Nota de Crédito Electrónica
110Factura de Exportación
111Nota de Débito de Exportación
112Nota de Crédito de Exportación
🧾
Facturas Electrónicas
DTE 33 · DTE 34
POST/dte/facturas/emitirEmitir Factura Electrónica (código 33)
GET/dte/facturas/folios/resumenEstado de folios y CAF activo
POST/dte/facturas-exentas/emitirEmitir Factura No Afecta / Exenta (código 34)
GET/dte/facturas-exentas/folios/resumenEstado de folios para DTE 34
🛍️
Boletas Electrónicas
DTE 39 · DTE 41
POST/dte/boletas/emitirEmitir Boleta Electrónica (código 39)
GET/dte/boletas/folios/resumenEstado de folios para boleta
POST/dte/boletas-exentas/emitirEmitir Boleta Exenta (código 41)
GET/dte/boletas-exentas/folios/resumenEstado de folios para boleta exenta
📝
Notas de Crédito y Débito
DTE 56 · DTE 61
POST/dte/notas-credito/emitirEmitir Nota de Crédito (código 61)
GET/dte/notas-credito/folios/resumenEstado de folios para NC
POST/dte/notas-debito/emitirEmitir Nota de Débito (código 56)
GET/dte/notas-debito/folios/resumenEstado de folios para ND
🚚
Guías de Despacho
DTE 52
POST/dte/guias/emitirEmitir Guía de Despacho (código 52)
GET/dte/guias/folios/resumenEstado de folios para guía
💡 Las Guías de Despacho admiten campos adicionales: codigoTipoGuia, rutChofer, patente, direccionDestino, etc. dentro del mismo objeto de request.
🛒
Factura de Compra
DTE 46 · IVA Retenido
POST/dte/facturas-compra/emitirEmitir Factura de Compra (código 46)
GET/dte/facturas-compra/folios/resumenEstado de folios para DTE 46
ℹ️ La Factura de Compra (DTE 46) se usa cuando el comprador retiene el IVA y lo declara directamente al SII (régimen de retención parcial). El proveedor solo recibe el monto neto — sin IVA. El PDF muestra: Monto Neto / IVA 19% / IVA Retenido 19% / Total a Pagar = Neto. Requiere CAF vigente para código 46.
✈️
Documentos de Exportación
DTE 110 · DTE 111 · DTE 112
POST/dte/exportaciones/emitirEmitir Factura de Exportación (código 110)
GET/dte/exportaciones/folios/resumenEstado de folios para DTE 110
POST/dte/notas-debito-exportacion/emitirEmitir Nota de Débito de Exportación (código 111)
POST/dte/notas-credito-exportacion/emitirEmitir Nota de Crédito de Exportación (código 112)
ℹ️ Los documentos de exportación (DTE 110/111/112) admiten campos adicionales en el objeto raíz: 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.
📂
Descarga de Documentos
PDF · XML · XML Envío
GET/dte/documentos/{codigoDte}/{folio}/pdfDescarga PDF binario (application/pdf)
GET/dte/documentos/{codigoDte}/{folio}/xmlDescarga XML firmado (application/xml)
GET/dte/documentos/{codigoDte}/{folio}/envio-xmlDescarga XML de envío (SetDTE/EnvioBoleta)
ℹ️ Los documentos también están disponibles como base64 en la respuesta de emisión (pdfBase64, xmlBase64). Estos endpoints son más eficientes para imprimir o mostrar el PDF directamente en el browser.
📊
DTEs Emitidos
Historial y consulta
GET/dte/emitidosListar todos los DTEs emitidos
GET/dte/emitidos?tipo=33Filtrar por tipo de DTE (33, 39, 41, 52, 56, 61)
🏛️
Envío al SII
Reenvío · Estado · Lotes
POST/dte/sii/reenviar/{tipoDte}/{folio}Reenviar un DTE específico al SII
GET/dte/sii/estado-envio/{trackId}Consultar estado de envío por TrackId
POST/dte/sii/reenviar-pendientes/{tipoDte}Reenviar en background todos los pendientes de un tipo
POST/dte/sii/enviar-loteEnviar lote seleccionado de DTEs en background
⚡ El envío al SII ocurre automáticamente en background al emitir cada DTE. Estos endpoints son para reenvíos manuales en caso de fallo o cuando el modo simulación estaba activo.
📋
CAF / Gestión de Folios
Autorización de Folios del SII
GET/dte/cafListar todos los CAFs con estado y uso
POST/dte/cafCargar nuevo CAF en base64 (XML del SII)
POST/dte/caf/solicitar-automaticoSolicitar CAF automático cuando quedan <3 folios
POST/dte/caf/folio-ficticioInsertar folio ficticio (para saltar folios usados)
🔐
Certificados Digitales
PFX · Firma · Representante
GET/dte/certificadosListar certificados digitales cargados
POST/dte/certificadosCargar certificado PFX (base64 + contraseña)
PATCH/dte/certificados/{id}/activarActivar un certificado (desactiva los demás)
PATCH/dte/certificados/{id}/rut-representanteActualizar RUT del representante legal
DELETE/dte/certificados/{id}Eliminar un certificado
📈
Registro de Compra y Venta
Períodos · IVA
GET/rcv/resumen?periodo=202504Resumen RCV por período (YYYYMM)
GET/rcv/detalle?periodo=202504&tipo=33Detalle RCV por período y tipo de documento
POST/rcv/simulacion-ivaSimular declaración de IVA para un período

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.

📥
Recepción automática
El sistema consulta el buzón SII periódicamente. Los DTE recibidos (facturas, NC, ND de proveedores) se almacenan con su XML original y generan un PDF de vista previa.
✅
Acuse / Reclamo / Rechazo
Cada documento recibido puede ser respondido formalmente al SII: Acuse de Recibo Conforme (ACD), Reclamo al Contenido (RCD) o Rechazo (RSC). La plataforma genera y firma el XML de respuesta automáticamente.
📊
Compras RCV
Los documentos aceptados alimentan el Registro de Compras (RCV) del período, facilitando la declaración de IVA crédito fiscal.

Endpoints Intercambio

GET/intercambio/documentosListar DTE recibidos (con filtros por período, tipo, estado)
GET/intercambio/documentos/{id}Detalle de un DTE recibido
GET/intercambio/documentos/{id}/xmlDescargar XML original del DTE recibido
GET/intercambio/documentos/{id}/pdfDescargar PDF generado del DTE recibido
POST/intercambio/documentos/{id}/acuseEnviar Acuse de Recibo Conforme (ACD) al SII
POST/intercambio/documentos/{id}/reclamoEnviar Reclamo al Contenido (RCD) o Rechazo (RSC)
GET/intercambio/resumenKPIs: total recibidos, pendientes, aceptados, reclamados
ℹ️ La configuración del buzón SMTP del SII se realiza desde el panel de administración (SystemSettings). Se requiere el correo electrónico de intercambio registrado ante el SII y las credenciales IMAP para que la plataforma descargue los mensajes automáticamente.

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.

🔁
Cesión de documentos emitidos
Permite ceder facturas electrónicas y documentos cedibles, conservando el folio, XML firmado y trazabilidad de la operación.
🧾
AEC firmado
Genera el Archivo Electrónico de Cesión (AEC), lo firma con certificado digital y lo deja disponible para descarga o envío.
✅
Validaciones previas
Antes de ceder, la API verifica condiciones básicas como documento existente, estado cedible y datos requeridos del cesionario.
📡
Consulta y seguimiento
Registra historial de cesiones, Track ID cuando aplica y consulta de estado para seguimiento operativo.

Endpoints principales de Cesión

GET/cesionListar cesiones registradas
GET/cesion/documento/{tipoDte}/{folio}Validar cedibilidad e historial del DTE
POST/cesion/cederGenerar y enviar AEC de cesión
GET/cesion/{id}/aecDescargar XML AEC firmado
GET/cesion/{trackId}/estadoConsultar estado de una cesión enviada
ℹ️ El módulo de Cesión DTE se administra como recurso comercial: puede estar visible u oculto por tenant según el plan del cliente. Requiere certificado digital activo y documentos emitidos con XML disponible.

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.

POST/dte/acuse/enviarEnviar evento sobre un DTE emitido (ACD / ERM / RCD / RSC)
GET/dte/emitidos/{tipo}/{folio}/eventosHistorial de eventos de un DTE emitido
⚠️ Si el receptor envía un evento RSC (Reclamo Sin Cargo) sobre una factura tuya, debes emitir una Nota de Crédito (DTE 61) referenciando esa factura para anularla ante el SII.

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.

🔐
Certificado próximo a vencer
Alerta de email cuando quedan <30 días para el vencimiento del certificado PFX. Incluye instrucciones para renovar y cargar el nuevo certificado.
📋
Folios CAF agotándose
Alerta cuando quedan <3 folios disponibles en un CAF. Permite activar la solicitud automática de nuevos folios desde el portal o la API.
❌
Errores de envío SII
Notificación inmediata cuando un DTE falla en el envío al SII. Incluye el mensaje de error y el folio afectado para facilitar el reprocesamiento.
GET/alertasListar alertas activas del tenant
PATCH/alertas/{id}/resolverMarcar alerta como resuelta
GET/admin/alertas/configuracionVer configuración de alertas del tenant
PUT/admin/alertas/configuracionActualizar emails receptores de alertas

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.

RolEmisión DTEVer reportesAdmin config.Gestionar usuarios
tenant_admin ✅ Sí ✅ Sí ✅ Sí ✅ Sí
tenant_viewer ❌ No ✅ Sí ❌ No ❌ No
GET/admin/usuariosListar usuarios del tenant
POST/admin/usuariosCrear nuevo usuario (email + rol + contraseña temporal)
PATCH/admin/usuarios/{id}/rolCambiar rol de un usuario
DELETE/admin/usuarios/{id}Eliminar usuario del tenant

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.

📧
Resend (recomendado)
Integración vía API key. Alta entregabilidad, logs de apertura y bounces. Configurar en SystemSettings con la clave ResendApiKey.
🖥️
SMTP personalizado
Conecta tu propio servidor SMTP (Gmail, Outlook, servidor corporativo). Configura host, puerto, usuario y contraseña desde el panel de administración.
📬
IMAP intercambio
Configuración separada para el buzón IMAP del SII desde donde se descargan los DTE recibidos (Intercambio). Requiere el correo registrado ante el SII.

¿Qué emails envía la plataforma?

EventoDestinatarioContenido
Emisión DTE (enviarCorreo: true)Email del clientePDF del DTE en adjunto + link de descarga
Certificado próximo a vencerAdmins del tenantAviso con días restantes + instrucciones de renovación
Folios CAF agotándoseAdmins del tenantTipo de DTE afectado + folios restantes
Error de envío SIIAdmins del tenantFolio, tipo y mensaje de error del SII
RAM > 85% (advertencia)SuperAdminAlerta temprana de uso de memoria · umbral configurable
RAM > 95% (crítico)SuperAdminAlerta crítica de memoria · riesgo de caída del servicio
Disco > 85% (advertencia)SuperAdminAdvertencia de espacio en disco del servidor
Disco > 95% (crítico)SuperAdminDisco casi lleno · puede interrumpir emisión y backups
MySQL binlogs sin retenciónSuperAdminVariable expire_logs_days = 0 (binlogs crecen sin límite)
Recuperación de contraseñaUsuario 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.

💾
Base de datos
Exportación completa de la base de datos MySQL/SQLite del tenant en formato SQL comprimido. Se sube a la carpeta configurada en Google Drive con timestamp.
📄
XMLs firmados
Respaldo de los archivos XML de EnvioDTE firmados, organizados por año/mes. Permite reconstruir cualquier DTE en caso de pérdida de datos locales.
⏰
Programación automática
Configura la frecuencia del backup (diario, semanal) y la hora de ejecución desde SystemSettings. El historial de respaldos queda registrado con estado y tamaño.

Configuración en 3 pasos

1
Crear Service Account en Google Cloud
Crea un Service Account en Google Cloud Console con permiso Google Drive API. Descarga las credenciales JSON del service account.
2
Compartir carpeta con el Service Account
En Google Drive, crea una carpeta y compártela con el email del service account (editor). Copia el ID de la carpeta desde la URL.
3
Configurar en el panel de administración
En SystemSettings → Google Drive, pega las credenciales JSON y el folder ID. Activa el backup automático y define la frecuencia.
💡 El respaldo en Google Drive es adicional al almacenamiento local. Los XML firmados también quedan disponibles localmente vía 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.

💾
Disco (Disk Usage)
Monitorea el espacio libre del volumen principal. Alertas configurables: advertencia al 85% y crítico al 95%. Umbral de limpieza de binlogs también configurable.
🧠
RAM (Memory Usage)
Mide memoria total, disponible y porcentaje usado. Advertencia al 85%, crítico al 95%. Ambos umbrales son configurables por variables de entorno sin tocar código.
🗃️
MySQL Binlogs
Verifica que la variable expire_logs_days esté configurada. Si es 0, los binlogs crecen indefinidamente hasta llenar el disco.
⏱️
Ejecución automática
El servicio corre en background cada N minutos (configurable). Las alertas de email tienen anti-spam integrado: no repite la misma alerta hasta que el estado cambia o pasa el intervalo mínimo.

Umbrales configurables · Variables de entorno

VariableDefaultDescripción
ServerOps__WarningDiskPercent85% de disco usado para alerta de advertencia
ServerOps__CriticalDiskPercent95% de disco usado para alerta crítica
ServerOps__CleanupDiskPercent95% a partir del cual se intenta limpieza automática de archivos temporales
ServerOps__WarningRamPercent85% de RAM usada para alerta de advertencia
ServerOps__CriticalRamPercent95% de RAM usada para alerta crítica
ServerOps__IntervalMinutes10Frecuencia de ejecución del monitoreo en minutos
ServerOps__AlertCooldownMinutes60Tiempo mínimo entre emails del mismo tipo de alerta
ℹ️ Las variables de entorno se configuran en el archivo 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:

Disco
usadoGB / totalGB · %
RAM
usadaMB / totalMB · %
MySQL Binlogs
retención (días) · estado
Hostname
nombre del servidor
💡 El monitoreo es exclusivo del Super Admin (quien gestiona la plataforma). Los tenants individuales no tienen acceso a métricas del servidor — solo a sus DTEs y configuraciones propias.

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.

ℹ️ Los eventos no requieren un endpoint separado. Se consultan junto con los DTEs emitidos vía GET /dte/emitidos?tipo=33. El campo estadoSiiEvento refleja el último evento reportado por el receptor al SII.

Códigos de evento

CódigoNombreSignificado 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

GET /dte/emitidos?tipo=33 Retorna facturas con campo estadoSiiEvento
GET /dte/emitidos Sin filtro — todos los tipos de DTE con su evento
⚠️ Si 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

GET /dte/emitidos?tipo=33 — campo estadoSiiEventoJSON
[
  {
    "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

Consultar eventos y detectar rechazosjavascript
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}`);
Consultar eventos · Pythonpython
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")
Consultar eventos · C#C#
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.

Emitir Boleta Electrónica · consumidor finalbash
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
      }
    ]
  }'
Boleta Electrónica · fetchjavascript
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));
Boleta Electrónica · Pythonpython
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)

Respuesta exitosa · HTTP 200JSON
{
  "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)

POST /dte/caf · subir archivo de autorización de foliospython
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

GET /dte/sii/estado-envio/{trackId}bash
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.

1
Autenticación
Tu sistema incluye el header X-Api-Key o un JWT en cada request. Sin pasos adicionales.
2
Verificar folios disponibles (opcional)
Consulta GET /dte/facturas/folios/resumen. La respuesta indica si puedes emitir y cuántos folios quedan.
3
Emitir el DTE
Envía el JSON al endpoint correspondiente. La API firma el XML, genera el PDF y envía al SII automáticamente.
4
Recibir PDF + XML
La respuesta contiene el folio, PDF en base64 y URL directa. Guarda el folio en tu sistema y muestra o imprime el PDF al usuario.
✓
SII notificado automáticamente
El envío al SII ocurre en background. Si falla, el endpoint POST /dte/sii/reenviar/{tipo}/{folio} permite reintentarlo.
⚠️ Antes de la primera emisión, asegúrate de haber cargado el certificado digital PFX (POST /dte/certificados) y al menos un CAF vigente (POST /dte/caf) para cada tipo de DTE que utilizarás.