Download OpenAPI specification:
API REST para emitir y consultar Documentos Tributarios Electrónicos (DTE) chilenos a través del SII: facturas, boletas, notas de crédito/débito y guías de despacho. Está pensada para integradores: tu ERP o sistema llama esta API y nosotros nos encargamos de folios (CAF), firma XMLDSig, timbre, envío al SII y la representación impresa (PDF).
Base URL: https://{host}/api/public/v1 (canal API Key). Antes de integrar,
revisa la sección Guía de la barra lateral —empieza por Onboarding y
requisitos del emisor y Autenticación—; la Referencia de la API documenta
cada endpoint.
Antes de emitir, cada centro debe estar habilitado como emisor electrónico ante el SII. Es un trámite del contribuyente (no del software) y depende de su situación tributaria:
.p12) del representante legal — con él se
firman sus DTE. Es obligatorio e intransferible entre empresas.Según el historial del centro:
| Situación del centro | Qué corresponde |
|---|---|
| Nunca emitió DTE | Postular, obtener la verificación de actividades y aprobar el set de pruebas de certificación (ambiente maullin) antes de pasar a producción. |
| Ya emite con otro proveedor | Solo migra: carga su certificado y solicita CAF nuevos. No recertifica. |
| Usa el sistema gratuito del SII (tipo 890) | Primero debe desvincularse de ese sistema ante el SII. |
La carga del certificado y de los CAF (folios) se realiza una sola vez por centro desde el portal web (no por esta API). Esta API es para emitir y consultar: una vez que el centro está habilitado y cuenta con folios, tu integración puede emitir y consultar sin restricciones.
Puesta en marcha asistida (servicio Pulsando). Dejamos a cada centro listo para emitir —acompañamiento en la postulación/certificación ante el SII y carga inicial de certificado y folios— como un servicio de onboarding. Escríbenos a contacto@pulsandotech.cl para coordinarlo.
Crea la cuenta de una empresa y devuelve su primera API Key de pruebas. No requiere autenticación: es por donde se empieza.
Existía desde el principio pero no estaba documentado, así que la única vía conocida era el formulario del portal. Con esto un partner o un ERP puede dar de alta a su cliente sin que nadie abra un navegador.
La api_key de la respuesta se muestra UNA sola vez. En la base queda solo
su hash: si no la guardas en ese momento, no hay forma de recuperarla y hay que
emitir otra desde el portal.
Es una sk_test_…, o sea que apunta a certificación (maullin). Para emitir
de verdad hacen falta el certificado digital de la empresa y sus folios; mira
los proximos_pasos que devuelve esta misma llamada.
Di de dónde viene tu cliente con tipo_onboarding. No es un dato
estadístico: cambia el trámite. Son cuatro casos —nueva,
migracion, en_certificacion y portal_gratuito— y mandar el valor
equivocado le exige a tu cliente un trámite que no le corresponde, o le
salta uno que sí.
Si no estás seguro, no adivines: llama antes a
POST /registro/validar-rut. Consultamos el RUT en el SII y te decimos de
dónde viene, con la evidencia. Es asíncrona (el SII tarda) y nunca
bloquea el alta: puedes registrar igual sin esperarla.
Lo que NO se migra: los folios que tu cliente tenga en su proveedor anterior se quedan allá. Hay que pedir CAF nuevos.
Límite: 20 registros por hora por IP.
| rut required | string <= 12 characters Cuerpo del RUT SIN el dígito verificador. Solo números; se aceptan puntos. Es inmutable: no se puede corregir después, porque la base de datos de la empresa se nombra a partir de él. |
| dv required | string <= 1 characters Dígito verificador. Se valida por módulo 11 contra el RUT. |
| razon_social required | string <= 200 characters |
| nombre_fantasia | string <= 200 characters |
| giro required | string <= 200 characters |
| direccion required | string <= 300 characters |
| comuna required | string <= 100 characters |
| ciudad required | string <= 100 characters |
| telefono required | string <= 20 characters Obligatorio — es por donde se avisa si algo se traba en el alta. |
| email required | string <email> Correo de la EMPRESA (facturación y cobro). Usa el real: se valida con la pasarela de pago al suscribirse. |
| admin_name required | string <= 100 characters |
| admin_email required | string <email> Correo de quien administra la cuenta. Único en toda la plataforma: no se puede repetir en dos empresas, porque el inicio de sesión no sabría a cuál entrar. Si tu cliente administra varias empresas, eso se resuelve con una cuenta de organización, no registrándose dos veces. |
| admin_password required | string <password> >= 8 characters |
| admin_password_confirmation required | string <password> |
| plan_id | integer Plan a contratar. Los ids salen de |
| tipo_onboarding | string Default: "nueva" Enum: "nueva" "migracion" "en_certificacion" "portal_gratuito" De dónde viene tu cliente. Son CUATRO casos y cada uno tiene otro trámite:
|
| proveedor_actual | string <= 100 characters Solo si |
| documentos_emitir | Array of integers Opcional, pero conviene mandarlo. Tipos de DTE que tu cliente va a emitir (33, 34, 39, 41, 46, 52, 56, 61, 110, 111, 112). Dos cosas dependen de esto: la reposición automática de folios sólo vigila los tipos declarados, y el set de pruebas del SII se pide POR TIPO y es de UN SOLO USO. |
| volumen_estimado | string <= 50 characters Opcional. Cuántos documentos al mes espera emitir tu cliente ("0-50", "50-500", "500+"). Sirve para dimensionar sus folios. |
| sistema_actual | string <= 100 characters Opcional. Qué sistema usa hoy ("Odoo", "planilla", "ninguno"). |
| acepta_contacto_comercial | boolean Default: false Opcional y separado de los otros consentimientos a propósito: el teléfono se pide para soporte, que es otro fin. Sin este |
| acepta_terminos required | boolean Debe ser |
| acepta_privacidad required | boolean Debe ser |
| acepta_dpa required | boolean Debe ser |
{- "rut": "76354771",
- "dv": "K",
- "razon_social": "Mi Empresa SpA",
- "giro": "Servicios de informática",
- "direccion": "Av. Providencia 1234, of. 501",
- "comuna": "Providencia",
- "ciudad": "Santiago",
- "telefono": "+56912345678",
- "email": "contacto@miempresa.cl",
- "admin_name": "Ana Pérez",
- "admin_email": "ana@miempresa.cl",
- "admin_password": "una-clave-larga-y-propia",
- "admin_password_confirmation": "una-clave-larga-y-propia",
- "tipo_onboarding": "migracion",
- "proveedor_actual": "OpenFactura",
- "acepta_terminos": true,
- "acepta_privacidad": true,
- "acepta_dpa": true
}{- "message": "¡Empresa registrada exitosamente!",
- "tenant_id": 42,
- "rut": "76.354.771-K",
- "razon_social": "Mi Empresa SpA",
- "plan": "profesional",
- "tipo_onboarding": "migracion",
- "proximos_pasos": {
- "property1": "string",
- "property2": "string"
}, - "api_key": "sk_test_8ea441f654413dc99893674ae3ca8353",
- "api_key_aviso": "string"
}Le pregunta al SII de dónde viene ese contribuyente: si ya es emisor
electrónico con software de mercado, si está a mitad de su certificación,
si todavía no se inscribió, o si está emitiendo con el sistema gratuito
del SII. Con eso sabes qué tipo_onboarding mandar en POST /register.
No requiere autenticación ni el certificado de tu cliente. La pantalla que se consulta —"Consultar Empresas Autorizadas"— es una consulta abierta entre contribuyentes: entramos con el nuestro.
Es asíncrona, y eso no es un detalle de implementación. Entrar al
portal del SII toma unos 40 segundos y el SII bloquea por "máximo de
sesiones", así que la consulta se hace en segundo plano. Esta llamada
responde 202 al instante; el resultado se pregunta con
GET /registro/validar-rut/{rut} cada ~5 segundos.
Nunca bloquea el alta. Si el SII no contesta, registra igual con lo que tu cliente declare: guardamos por separado lo declarado y lo verificado, y se puede revalidar después.
La respuesta se cachea 24 horas por RUT (lo que se lee sólo cambia por trámites ante el SII, que se mueven de un día para otro) y hay un solo trabajo en vuelo por RUT: repetir la llamada no abre más sesiones.
| rut required | string <= 12 characters Cuerpo del RUT SIN dígito verificador. |
| dv required | string <= 1 characters Dígito verificador. Se valida antes de salir al SII. |
{- "rut": "77123456",
- "dv": "5"
}{- "rut": "20141906-9",
- "estado": "pendiente",
- "origen": "nueva",
- "confianza": "verificado",
- "motivo": "El SII lo tiene dentro del sistema gratuito de boletas electrónicas (código 890, autorizado el 18-08-2026 y sin desautorizar).",
- "razon_social": "string",
- "documentos_sugeridos": [
- 33,
- 34,
- 39,
- 41,
- 52,
- 56,
- 61
], - "situacion_tributaria": {
- "inicio_actividades": true,
- "fecha_inicio": "23-07-2025",
- "razon_social_sii": "string",
- "puede_emitir": true,
- "aviso": "El SII no registra inicio de actividades para este RUT. Sin ese trámite no se puede emitir ningún documento tributario, y es una gestión que sólo puede hacer el contribuyente en sii.cl. Puedes registrarte igual y dejar todo listo: cuando lo tengas, empiezas a emitir."
}, - "evidencia": {
- "tipos_produccion": [
- 0
], - "tipos_certificacion": [
- 0
], - "emisor_desde": "2026-08-12",
- "portal_gratuito": {
- "presente": true,
- "vigente": true,
- "autorizado_desde": "string",
- "desautorizado_desde": "string"
}
}, - "mensaje": "string",
- "consultar_en": "string",
- "reintentar_en_segundos": 5,
- "desde_cache": true,
- "opciones": [
- {
- "valor": "string",
- "etiqueta": "string",
- "detalle": "string",
- "sugerido": true
}
]
}El resultado de POST /registro/validar-rut. Nunca falla: si nadie
consultó ese RUT devuelve estado: desconocido, y si la consulta al SII
se cayó devuelve estado: error con las cuatro opciones para que se lo
preguntes tú a tu cliente.
| rut required | string Example: 77123456-5 RUT con dígito verificador y sin puntos. |
{- "rut": "20141906-9",
- "estado": "pendiente",
- "origen": "nueva",
- "confianza": "verificado",
- "motivo": "El SII lo tiene dentro del sistema gratuito de boletas electrónicas (código 890, autorizado el 18-08-2026 y sin desautorizar).",
- "razon_social": "string",
- "documentos_sugeridos": [
- 33,
- 34,
- 39,
- 41,
- 52,
- 56,
- 61
], - "situacion_tributaria": {
- "inicio_actividades": true,
- "fecha_inicio": "23-07-2025",
- "razon_social_sii": "string",
- "puede_emitir": true,
- "aviso": "El SII no registra inicio de actividades para este RUT. Sin ese trámite no se puede emitir ningún documento tributario, y es una gestión que sólo puede hacer el contribuyente en sii.cl. Puedes registrarte igual y dejar todo listo: cuando lo tengas, empiezas a emitir."
}, - "evidencia": {
- "tipos_produccion": [
- 0
], - "tipos_certificacion": [
- 0
], - "emisor_desde": "2026-08-12",
- "portal_gratuito": {
- "presente": true,
- "vigente": true,
- "autorizado_desde": "string",
- "desautorizado_desde": "string"
}
}, - "mensaje": "string",
- "consultar_en": "string",
- "reintentar_en_segundos": 5,
- "desde_cache": true,
- "opciones": [
- {
- "valor": "string",
- "etiqueta": "string",
- "detalle": "string",
- "sugerido": true
}
]
}Cuando el SII tiene a la empresa en su sistema gratuito (Resolución 99
para facturas y/o código 890 para boletas), el ciclo de vida del cliente
se detiene en PORTAL_GRATUITO_DECIDE y le manda el correo «Estás en el
sistema gratuito del SII: elige» con un enlace firmado (7 días).
Sin login ni API Key. La autenticación es la firma de la URL
(tenant, expires, signature), que llega en el correo apuntando a la
página del front /ciclo/decision?tenant=…&expires=…&signature=…. La
página reenvía esos tres parámetros tal cual a este endpoint, en el
GET y en el POST (comparten URI a propósito: una sola firma vale para
leer y para decidir). Una firma inválida o vencida responde 403.
Devuelve el estado del ciclo, si la decisión sigue pendiente, qué dijo el
SII (nro_resol, con_890_vigente) y, por cada opción de tipos, los
trámites que haremos en nombre del cliente con el texto literal de cada
declaración que tiene que aceptar (tramites). desafiliacion_facturas
es siempre false: la Res. 99 se certifica sin desafiliarse; sólo el 890
(boletas) se renuncia, y sólo si elige certificarlas.
| tenant required | integer Id de la empresa (viene en el enlace). |
| expires required | integer Vencimiento de la firma (viene en el enlace). |
| signature required | string Firma HMAC del enlace (viene en el enlace). |
{- "tenant": {
- "id": 0,
- "razon_social": "string",
- "rut": "string"
}, - "estado": "PORTAL_GRATUITO_DECIDE",
- "estado_etiqueta": "string",
- "decision_pendiente": true,
- "decision": { },
- "nro_resol": 99,
- "con_890_vigente": true,
- "opciones": [
- "quedarme"
], - "tipos": [
- "facturas"
], - "tramites_por_tipos": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}, - "tramites": {
- "property1": {
- "etiqueta": "string",
- "irreversible": true,
- "declaraciones": {
- "property1": "string",
- "property2": "string"
}
}, - "property2": {
- "etiqueta": "string",
- "irreversible": true,
- "declaraciones": {
- "property1": "string",
- "property2": "string"
}
}
}, - "renuncia_890_aplica": true,
- "desafiliacion_facturas": false
}Misma URL y misma firma que el GET.
quedarme → el ciclo pasa a SII_FREE (terminal abierto): cero
trámites ante el SII, cero folios, cero certificación; se apagan los
recordatorios de certificado y de fin de prueba. Sale el correo
«Seguimos contigo en el sistema gratuito».certificar con tipos (facturas | boletas | ambas) → se registran
los consentimientos de cada trámite requerido (tramites_por_tipos
del GET), se declaran los documentos a emitir, se inicia el motor de
certificación y el ciclo pasa a EN_CERTIFICACION. Con boletas o
ambas y el 890 vigente, incluye renunciar_boleta_gratuita, que se
ensaya en seco de inmediato y sólo se ejecuta por el motor con ese
consentimiento (regla de oro: ningún trámite irreversible sin
consentimiento + ensayo).declaraciones tiene que traer todas las claves de todos los trámites
de la opción elegida (el texto literal viene en el GET). Si falta alguna,
422 con faltan. Si la empresa ya decidió, 409.
| tenant required | integer |
| expires required | integer |
| signature required | string |
| decision required | string Enum: "quedarme" "certificar" |
| tipos | string Enum: "facturas" "boletas" "ambas" Obligatorio con |
| declaraciones | Array of strings Claves aceptadas (p. ej. |
| nombre | string <= 120 characters Quién decide (queda en el consentimiento). |
| correo | string <email> |
{- "decision": "quedarme",
- "tipos": "facturas",
- "declaraciones": [
- "string"
], - "nombre": "string",
- "correo": "user@example.com"
}{- "message": "string",
- "estado": "SII_FREE",
- "certificacion_id": 0,
- "tramites_consentidos": [
- "string"
], - "renuncia_890": { }
}Hay tres ambientes. Dos de ellos hablan con el SII; el de desarrollo no.
| Ambiente | Valor de ambiente |
Habla con el SII | Validez tributaria |
|---|---|---|---|
| Desarrollo | mock |
No | No — el PDF lleva el sello SIN VALIDEZ TRIBUTARIA |
| Certificación | certificacion |
Sí (maullin) | No |
| Producción | produccion |
Sí (palena) | Sí |
En certificación y producción, el ambiente lo determina tu API Key:
sk_test_… → certificación (maullin) — documentos de prueba, sin validez tributaria.sk_live_… → producción (palena) — documentos reales con validez tributaria.Puedes usar una key sk_test_ aunque tu empresa ya esté en producción, para
probar sin emitir documentos reales. Los listados y reportes quedan acotados
al ambiente de la key (los documentos de prueba nunca se mezclan con los reales).
Al registrarte se crea automáticamente una empresa gemela en ambiente de
desarrollo, que copia la identidad de tu empresa (razón social, giro,
dirección, tipos de documento habilitados) sobre un RUT de prueba del rango
88.8xx.xxx, para no chocar con el RUT real de ningún contribuyente. La
API Key sk_test_ de esa empresa llega por correo al email de contacto
del registro.
Qué hace y qué no:
SIN VALIDEZ TRIBUTARIA.La empresa de desarrollo es dominante: aunque uses una key sk_live_
contra ella, el ambiente sigue siendo mock. Un documento de desarrollo no
puede convertirse en uno real por equivocación.
Cuota y vigencia. El ambiente admite 200 documentos; superado el tope,
la emisión responde 429 con el conteo (cuota.usados / cuota.limite) y un
contacto para ampliarlo o pasar a producción. Un ambiente sin uso durante
30 días se da de baja, con aviso por correo a los 23 días.
Webhooks. Se disparan igual que en producción, con la misma firma
HMAC. Distínguelos por el cuerpo del evento: livemode es false y
ambiente vale mock (ver el esquema WebhookEvent). livemode es true
solo en producción.
Probar el rechazo. La aceptación del SII es asíncrona y en desarrollo no
hay SII, así que ningún documento se rechaza solo. Para ejercitar esa rama usa
POST /dte/{id}/simular-estado, que fuerza el estado final y dispara los
mismos webhooks y notificaciones. Solo existe en desarrollo: en certificación
y producción responde 403.
Toda petición al canal de integradores va con tu API Key en el header
X-Api-Key:
X-Api-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
sk_live_… → producción (palena) · sk_test_… → certificación (maullin).
El prefijo decide el ambiente del DTE (ver Ambientes).Antes de tener certificado y folios: el ambiente de desarrollo. Al
registrarte recibes por correo una key sk_test_ de una empresa gemela en
ambiente de desarrollo, que emite, firma y genera PDF sin tocar el SII y sin
exigirte certificado digital ni CAF. Se usa igual que cualquier otra key, en
el mismo header. Ver Ambientes.
Dos alcances de clave. Una API Key puede pertenecer a una empresa o a una organización (estudio contable, holding, partner) que administra varios RUT emisores:
| Alcance | RUT emisor | Header X-Empresa-RUT |
|---|---|---|
| Empresa | El de la clave — no se puede cambiar desde el request | No se envía |
| Organización | El que indiques en cada llamada | Obligatorio |
Si tu clave administra varias empresas, lee Varias empresas (estudios contables y holdings).
Gestión de keys. Se crean desde el portal web (Configuración → API Keys) y se muestran una sola vez al crearlas — guárdalas de forma segura. Cada key puede tener uno o varios de estos permisos (scopes):
| Scope | Permite |
|---|---|
dte:create |
Emitir DTE (POST /dte) |
dte:read |
Leer/listar DTE emitidos, resumen, autocompletar receptor |
recepcion:read |
Leer DTE recibidos (intercambio) |
recepcion:write |
Aceptar/reclamar DTE recibidos, subir XML manual |
rcv:read |
Leer el Registro de Compras y Ventas |
rcv:write |
Reclamar/marcar en el RCV (muta en el SII) |
caf:read |
Ver estado de folios (CAF) disponibles |
caf:write |
Solicitar nuevos folios al SII (vía RPA con tu certificado) |
webhook:manage |
Registrar y administrar webhooks salientes |
organizacion:read |
Sólo claves de organización. Leer la administración de la organización: resumen y cobro, salud y actividad de la cartera, ventas consolidadas (GET /organizacion/*; las ventas exigen además dte:read). No viene en ninguna clave existente, ni en una «con todos los permisos»: se elige al crear la clave. No depende del ambiente: una sk_test_ con este permiso lee el cobro, la salud y la actividad reales de la organización |
⚠️ Nunca pongas una API Key en el frontend, apps móviles ni en repositorios. Úsala solo desde tu backend. Si se filtra, revócala desde el portal y crea otra.
Las rutas de acceso por token para el receptor (/api/portal/…) son la
única excepción: no usan API Key (ver Enlace para el receptor).
Sí: una sola cuenta puede emitir DTE para varios RUT emisores. Es el caso de un estudio contable que factura por sus empresas cliente, de un holding con varias sociedades, o de un SaaS que revende emisión.
Ese conjunto de RUT se llama cartera, y pertenece a una organización.
1. Una clave por empresa (recomendada para emitir)
Creas una sk_live para cada RUT. La clave es la empresa: no envías ningún
header extra. Si una se filtra, el daño se limita a esa empresa.
X-Api-Key: sk_live_...clave_de_la_panaderia...
POST /dte → emite por la Panadería
2. Una clave de organización (necesaria para el MCP / agentes de IA)
Una sola clave para toda la cartera. En cada llamada indicas por qué empresa
operas, con el header X-Empresa-RUT:
X-Api-Key: sk_live_...clave_del_estudio...
X-Empresa-RUT: 76354771-K
POST /dte → emite por la Panadería
X-Empresa-RUT: 78211386-0
POST /dte → emite por la Ferretería, con la MISMA clave
El RUT se acepta con o sin puntos y con o sin dígito verificador
(76354771, 76354771-K y 76.354.771-K son equivalentes).
Elige con criterio. Una clave de organización es cómoda, pero si se filtra expone toda la cartera, no una empresa. Para emitir desde tu ERP, preferimos claves por empresa. Reserva la de organización para orquestación y para el MCP, que necesita poder elegir la empresa en cada instrucción.
GET /empresas responde la cartera sin exigir haber elegido empresa (sería
circular: es la llamada con la que la descubres). Sirve para los dos tipos de
clave, con la misma forma de respuesta. Las lecturas de administración
(GET /organizacion/*, abajo) tampoco llevan X-Empresa-RUT: son de toda la
cartera.
Con una clave de organización que tenga el permiso organizacion:read, tu
ERP o tu agente de IA lee lo mismo que el socio ve en el panel del estudio,
sin X-Empresa-RUT (si lo envías, se ignora):
| Operación | Responde |
|---|---|
GET /organizacion |
Plan, cobro mensual neto y con IVA, cupo de DTE de la cartera |
GET /organizacion/salud |
Puntaje y pendientes de cada empresa |
GET /organizacion/actividad |
Llamadas a la API de la cartera, desde hasta 90 días atrás |
GET /organizacion/ventas |
Ventas válidas por empresa y el total, en un rango de hasta 366 días. Exige además dte:read |
Ojo con el ambiente: el resumen, la salud y la actividad son los reales
de la organización con cualquier clave, también con una sk_test_ (no hay
cobro ni actividad «de prueba»). Sólo las ventas cambian con el ambiente de la
clave. Si le das organizacion:read a una clave de pruebas, esa clave ve lo que
paga el estudio.
Agregar o quitar empresas, usuarios, la suscripción y las claves NO se hace por
API: se hace en el portal, con la cuenta del administrador. Una clave es una
credencial de máquina que puede filtrarse, y no puede tocar ni el cobro ni la
cartera. Una clave de empresa recibe 403 con
codigo: "requiere_llave_de_organizacion".
El header selecciona la empresa; no la inventa. El RUT emisor, la razón
social, el giro y el código de actividad del DTE se leen siempre del registro de
esa empresa. Si mandas un bloque emisor en el cuerpo, se ignora. Así, una
clave nunca puede facturar a nombre de un RUT que no le pertenece.
| Código | Cuándo | Qué hacer |
|---|---|---|
400 |
Clave de organización sin X-Empresa-RUT |
Indica la empresa. GET /empresas te dice cuáles |
403 |
El RUT no está en tu cartera (o está suspendido/retirado) | Revisa la cartera en el portal |
403 con codigo: "organizacion_suspendida" |
La organización no está vigente. Lo reciben todas sus claves y también las claves de empresa de su cartera (salvo la empresa que paga su propia suscripción) | El estudio regulariza su cuenta; no se arregla reintentando |
409 |
Reusaste una Idempotency-Key de otra empresa |
Usa claves de idempotencia distintas por empresa |
Idempotencia por empresa. Si tu ERP numera las facturas por empresa, vas a repetir
F-1001en dos de ellas. Está previsto: la clave de idempotencia es por empresa emisora. Ante una colisión entre empresas respondemos409antes que devolverte el documento equivocado.
El plan de organización trae un cupo de DTE compartido por toda la cartera
(no un tope por empresa): las que facturan poco le prestan cupo a las que
facturan mucho. Al agotarse, la emisión responde 429 con pool_dte y
emitidos_este_mes para todas las empresas de la cartera, y no se
reintenta hasta cambiar de plan o hasta el mes siguiente. El límite de
peticiones por minuto, en cambio, se cuenta por llave y empresa: el
peak de una no le consume la cuota a las demás.
Emitir un DTE es asíncrono: POST /dte responde 201 con el documento
en estado pendiente y lo encola para envío al SII. El estado final llega
después; consúltalo con GET /dte/{id} o suscríbete a webhooks.
Boletas y facturas se emiten sin esperar la validación del SII: ya son válidas con su folio y timbre (TED), y la aceptación del SII es posterior. La única excepción son las notas de crédito/débito, cuyo envío depende de que su documento referenciado exista en el SII (ver Notas de crédito y débito).
estado_local — el estado normalizado (úsalo para tu lógica)estado_local |
¿Final? | Significado |
|---|---|---|
pendiente |
No (en curso) | Creado, aún no enviado al SII. |
enviando |
No (en curso) | Envío en marcha. |
enviado |
No (en curso) | En el SII, esperando el acuse del sobre. |
error_envio |
No, pero no avanza solo | No logró llegar al SII, o la plataforma dejó de esperar el veredicto de un sobre que sí salió (el documento trae track_id). Los reintentos automáticos ocurren antes de marcarlo; una vez en error_envio se queda ahí hasta POST /dte/{id}/reintentar. No se reemite: el folio ya está tomado y otro documento declararía dos veces la misma venta. Única excepción: si glosa_sii dice «no valida XSD» o «viola reglas de negocio», el XML nunca llegó al SII, reintentar responde 409 causa: contenido_invalido, y se corrige emitiendo uno nuevo. |
aceptado |
Sí | Aceptado por el SII. Documento válido. |
aceptado_con_reparos |
Sí | Aceptado y VÁLIDO, con observaciones (SII RPR). NO es un rechazo. |
rechazado |
Sí | Rechazado por el SII (validación). Corregir y re-emitir. |
rechazado_sobre |
Sí | El sobre completo fue rechazado. |
anulado |
Sí | Anulado (p. ej. por una NC que lo reversa). |
Los estados en curso suelen durar segundos. Si el SII está caído, la plataforma reintenta el envío por su cuenta y un documento puede quedar horas en
pendienteoenviandoantes de llegar a un estado final o aerror_envio: eso no indica un problema de tu lado. Para decidir en caja,aceptadoyaceptado_con_reparosson ambos documento válido.
estado_sii — el código crudo del SII (trazabilidad)Aparte va estado_sii, el código tal cual lo entrega el SII (no es una lista
cerrada nuestra). Los que verás en producción: EPR (envío procesado), DOK
(documento aceptado), RPR (reparo → aceptado_con_reparos) y RCT/RCH/RFR
(rechazos). Para tu lógica usa estado_local; estado_sii es para trazabilidad.
Distinguibles por código HTTP, para avisar claro en caja —no un "falló" genérico:
| HTTP | Cuándo | Body | Qué hacer |
|---|---|---|---|
402 |
Suscripción impaga / trial vencido | subscription_required: true |
"Regulariza el pago para seguir emitiendo." Sin reintentos en bucle. |
503 |
Sin folios de ese tipo en ese ambiente | codigo: "folios_agotados", tipo_dte, ambiente, reintentar_en_segundos y el header Retry-After (30–300 s) |
"Sin folios; la reposición ya se pidió." Reintenta pasado Retry-After con la misma Idempotency-Key. Un 503 sin codigo es otra cosa: escálalo. |
422 |
Datos del documento inválidos | message (y errors si viene) |
Corregir el documento (no quema folio). |
422 |
Precondición de la empresa | codigo: acteco_ausente, resolucion_produccion_ausente, tipo_no_autorizado_sii o certificado_no_utilizable |
Corregir la ficha de la empresa o el certificado: reenviar el mismo payload no lo arregla. Ver la tabla del 422 en POST /dte. |
429 |
Límite de peticiones por minuto | message, codigo: "demasiadas_solicitudes", retry_after (segundos) y el header Retry-After |
Backoff respetando Retry-After. |
429 |
Cupo mensual del plan (emitidos_este_mes) o de la cartera (pool_dte) agotado |
message, emitidos_este_mes y, en una cartera, pool_dte |
No se reintenta: detén la emisión y avisa hasta cambiar de plan o hasta el mes siguiente. |
429 |
Cuota del ambiente de desarrollo agotada | message y cuota: {usados, limite} |
No se reintenta: pide ampliar la cuota o pasa a producción. |
409 |
Idempotency-Key en curso o reusada entre empresas |
message (en curso, además reintentar_en_segundos y Retry-After) |
En curso: espera y reintenta con la misma clave. Entre empresas: usa claves distintas por empresa. |
Todo error es JSON con message en español y, en estos casos, un codigo
estable para programar contra él. Ningún mensaje trae nombres de clases,
rutas de archivo ni SQL.
| HTTP | codigo |
Cuándo | Qué hacer |
|---|---|---|---|
400 |
json_invalido |
El cuerpo no es JSON válido, o es JSON pero llegó sin Content-Type: application/json (por ejemplo curl -d sin cabecera). Antes se descartaba en silencio y la respuesta era «falta el campo tipo_dte». |
Corrige el JSON o agrega la cabecera. |
401 |
no_autenticado |
Falta la credencial en rutas con sesión. En la API pública, sin X-Api-Key responde 401 con su propio mensaje. |
Envía la credencial. |
404 |
no_encontrado |
La ruta no existe, el recurso no existe o no es de tu empresa, o el identificador no es un número entero (por ejemplo /dte/abc o /dte/99999999999999999999). El mensaje es genérico: no dice qué tabla ni qué id. |
Revisa la URL y el identificador. |
405 |
metodo_no_permitido |
El método HTTP no existe para esa ruta. Trae el header Allow. |
Usa uno de los métodos de Allow. |
413 |
cuerpo_demasiado_grande |
El cuerpo supera 20 MB. | Divide el envío. |
422 |
parametro_invalido |
Un parámetro de query llegó como arreglo (?origen[]=api). Las listas van separadas por comas: ?origen=api,mcp. |
Envía un valor simple o una lista con comas. |
429 |
demasiadas_solicitudes |
Límite de peticiones (ver «Límites de peticiones»). Trae retry_after y el header Retry-After. |
Espera Retry-After y reintenta. |
500 |
error_interno |
Falla nuestra; queda registrada con su causa. | Reintenta más tarde; si persiste, escribe a soporte. |
Filtros con valores que no existen se ignoran.
GET /dte?origen=xyzo?tipo_dte=abcno responden422: el filtro inválido no se aplica y la lista sale sin él. Es deliberado, para no romper integraciones que ya mandan valores de más; valida tus filtros de tu lado.
Certificado vencido, no cargado o ilegible: la emisión responde
422concodigo: "certificado_no_utilizable"y no consume folio. Se corrige subiendo un.p12vigente en Empresa → Certificado.
| Límite | Alcance |
|---|---|
| 120 peticiones por minuto | Por API Key y empresa emisora, sobre toda la API |
30 POST por minuto sobre rutas de /dte |
Por API Key y empresa: cuentan emitir, reintentar, portal-link, simular-estado y las acciones sobre documentos recibidos |
| 30 peticiones por minuto | POST /sandbox/dte, por IP |
| 10 peticiones por minuto | GET /organizacion/ventas, por organización: todas sus claves suman |
Emite desde una cola con concurrencia acotada, no en ráfagas. Superar un
límite responde 429 con el header Retry-After, codigo: "demasiadas_solicitudes" y retry_after en segundos.
El límite por llave cuenta por llave y empresa, no por IP: dos
integraciones que salen por la misma IP (por ejemplo, todos los clientes del
MCP hospedado) no comparten cupo, y una llave inválida no gasta el de nadie
(responde 401 sin contar). Los límites por IP (sandbox, registro) usan la
IP real del cliente; la cabecera X-Forwarded-For que envía el cliente no
la cambia.
| Lista | Máximo | Fuente |
|---|---|---|
items en boletas (39, 41) |
1.000 | EnvioBOLETA_v11.xsd, Detalle maxOccurs=1000 |
items en el resto de los tipos |
60 | DTE_v10.xsd, Detalle maxOccurs=60 |
referencias |
40 | Referencia maxOccurs=40 en ambos esquemas |
totales.impuestos_adicionales |
20 | ImptoReten maxOccurs=20 |
| Cuerpo de la solicitud | 20 MB | 413 cuerpo_demasiado_grande |
Son los topes del esquema del SII: un documento con más filas lo rechazaría
el SII. Superarlos responde 422 con el error en la lista
(errors.items) y no consume folio. Si una venta tiene más líneas,
divídela en más de un documento.
Emitir un DTE es asíncrono: POST /dte responde 201 con el documento
en estado pendiente y lo encola para envío al SII. El estado final llega
después; consúltalo con GET /dte/{id} o suscríbete a webhooks.
Boletas y facturas se emiten sin esperar la validación del SII: ya son válidas con su folio y timbre (TED), y la aceptación del SII es posterior. La única excepción son las notas de crédito/débito, cuyo envío depende de que su documento referenciado exista en el SII (ver Notas de crédito y débito).
estado_local — el estado normalizado (úsalo para tu lógica)estado_local |
¿Final? | Significado |
|---|---|---|
pendiente |
No (en curso) | Creado, aún no enviado al SII. |
enviando |
No (en curso) | Envío en marcha. |
enviado |
No (en curso) | En el SII, esperando el acuse del sobre. |
error_envio |
No, pero no avanza solo | No logró llegar al SII, o la plataforma dejó de esperar el veredicto de un sobre que sí salió (el documento trae track_id). Los reintentos automáticos ocurren antes de marcarlo; una vez en error_envio se queda ahí hasta POST /dte/{id}/reintentar. No se reemite: el folio ya está tomado y otro documento declararía dos veces la misma venta. Única excepción: si glosa_sii dice «no valida XSD» o «viola reglas de negocio», el XML nunca llegó al SII, reintentar responde 409 causa: contenido_invalido, y se corrige emitiendo uno nuevo. |
aceptado |
Sí | Aceptado por el SII. Documento válido. |
aceptado_con_reparos |
Sí | Aceptado y VÁLIDO, con observaciones (SII RPR). NO es un rechazo. |
rechazado |
Sí | Rechazado por el SII (validación). Corregir y re-emitir. |
rechazado_sobre |
Sí | El sobre completo fue rechazado. |
anulado |
Sí | Anulado (p. ej. por una NC que lo reversa). |
Los estados en curso suelen durar segundos. Si el SII está caído, la plataforma reintenta el envío por su cuenta y un documento puede quedar horas en
pendienteoenviandoantes de llegar a un estado final o aerror_envio: eso no indica un problema de tu lado. Para decidir en caja,aceptadoyaceptado_con_reparosson ambos documento válido.
estado_sii — el código crudo del SII (trazabilidad)Aparte va estado_sii, el código tal cual lo entrega el SII (no es una lista
cerrada nuestra). Los que verás en producción: EPR (envío procesado), DOK
(documento aceptado), RPR (reparo → aceptado_con_reparos) y RCT/RCH/RFR
(rechazos). Para tu lógica usa estado_local; estado_sii es para trazabilidad.
Distinguibles por código HTTP, para avisar claro en caja —no un "falló" genérico:
| HTTP | Cuándo | Body | Qué hacer |
|---|---|---|---|
402 |
Suscripción impaga / trial vencido | subscription_required: true |
"Regulariza el pago para seguir emitiendo." Sin reintentos en bucle. |
503 |
Sin folios de ese tipo en ese ambiente | codigo: "folios_agotados", tipo_dte, ambiente, reintentar_en_segundos y el header Retry-After (30–300 s) |
"Sin folios; la reposición ya se pidió." Reintenta pasado Retry-After con la misma Idempotency-Key. Un 503 sin codigo es otra cosa: escálalo. |
422 |
Datos del documento inválidos | message (y errors si viene) |
Corregir el documento (no quema folio). |
422 |
Precondición de la empresa | codigo: acteco_ausente, resolucion_produccion_ausente, tipo_no_autorizado_sii o certificado_no_utilizable |
Corregir la ficha de la empresa o el certificado: reenviar el mismo payload no lo arregla. Ver la tabla del 422 en POST /dte. |
429 |
Límite de peticiones por minuto | message, codigo: "demasiadas_solicitudes", retry_after (segundos) y el header Retry-After |
Backoff respetando Retry-After. |
429 |
Cupo mensual del plan (emitidos_este_mes) o de la cartera (pool_dte) agotado |
message, emitidos_este_mes y, en una cartera, pool_dte |
No se reintenta: detén la emisión y avisa hasta cambiar de plan o hasta el mes siguiente. |
429 |
Cuota del ambiente de desarrollo agotada | message y cuota: {usados, limite} |
No se reintenta: pide ampliar la cuota o pasa a producción. |
409 |
Idempotency-Key en curso o reusada entre empresas |
message (en curso, además reintentar_en_segundos y Retry-After) |
En curso: espera y reintenta con la misma clave. Entre empresas: usa claves distintas por empresa. |
Todo error es JSON con message en español y, en estos casos, un codigo
estable para programar contra él. Ningún mensaje trae nombres de clases,
rutas de archivo ni SQL.
| HTTP | codigo |
Cuándo | Qué hacer |
|---|---|---|---|
400 |
json_invalido |
El cuerpo no es JSON válido, o es JSON pero llegó sin Content-Type: application/json (por ejemplo curl -d sin cabecera). Antes se descartaba en silencio y la respuesta era «falta el campo tipo_dte». |
Corrige el JSON o agrega la cabecera. |
401 |
no_autenticado |
Falta la credencial en rutas con sesión. En la API pública, sin X-Api-Key responde 401 con su propio mensaje. |
Envía la credencial. |
404 |
no_encontrado |
La ruta no existe, el recurso no existe o no es de tu empresa, o el identificador no es un número entero (por ejemplo /dte/abc o /dte/99999999999999999999). El mensaje es genérico: no dice qué tabla ni qué id. |
Revisa la URL y el identificador. |
405 |
metodo_no_permitido |
El método HTTP no existe para esa ruta. Trae el header Allow. |
Usa uno de los métodos de Allow. |
413 |
cuerpo_demasiado_grande |
El cuerpo supera 20 MB. | Divide el envío. |
422 |
parametro_invalido |
Un parámetro de query llegó como arreglo (?origen[]=api). Las listas van separadas por comas: ?origen=api,mcp. |
Envía un valor simple o una lista con comas. |
429 |
demasiadas_solicitudes |
Límite de peticiones (ver «Límites de peticiones»). Trae retry_after y el header Retry-After. |
Espera Retry-After y reintenta. |
500 |
error_interno |
Falla nuestra; queda registrada con su causa. | Reintenta más tarde; si persiste, escribe a soporte. |
Filtros con valores que no existen se ignoran.
GET /dte?origen=xyzo?tipo_dte=abcno responden422: el filtro inválido no se aplica y la lista sale sin él. Es deliberado, para no romper integraciones que ya mandan valores de más; valida tus filtros de tu lado.
Certificado vencido, no cargado o ilegible: la emisión responde
422concodigo: "certificado_no_utilizable"y no consume folio. Se corrige subiendo un.p12vigente en Empresa → Certificado.
| Límite | Alcance |
|---|---|
| 120 peticiones por minuto | Por API Key y empresa emisora, sobre toda la API |
30 POST por minuto sobre rutas de /dte |
Por API Key y empresa: cuentan emitir, reintentar, portal-link, simular-estado y las acciones sobre documentos recibidos |
| 30 peticiones por minuto | POST /sandbox/dte, por IP |
| 10 peticiones por minuto | GET /organizacion/ventas, por organización: todas sus claves suman |
Emite desde una cola con concurrencia acotada, no en ráfagas. Superar un
límite responde 429 con el header Retry-After, codigo: "demasiadas_solicitudes" y retry_after en segundos.
El límite por llave cuenta por llave y empresa, no por IP: dos
integraciones que salen por la misma IP (por ejemplo, todos los clientes del
MCP hospedado) no comparten cupo, y una llave inválida no gasta el de nadie
(responde 401 sin contar). Los límites por IP (sandbox, registro) usan la
IP real del cliente; la cabecera X-Forwarded-For que envía el cliente no
la cambia.
| Lista | Máximo | Fuente |
|---|---|---|
items en boletas (39, 41) |
1.000 | EnvioBOLETA_v11.xsd, Detalle maxOccurs=1000 |
items en el resto de los tipos |
60 | DTE_v10.xsd, Detalle maxOccurs=60 |
referencias |
40 | Referencia maxOccurs=40 en ambos esquemas |
totales.impuestos_adicionales |
20 | ImptoReten maxOccurs=20 |
| Cuerpo de la solicitud | 20 MB | 413 cuerpo_demasiado_grande |
Son los topes del esquema del SII: un documento con más filas lo rechazaría
el SII. Superarlos responde 422 con el error en la lista
(errors.items) y no consume folio. Si una venta tiene más líneas,
divídela en más de un documento.
Todo DTE tiene una representación impresa generada on-demand desde el XML firmado (no se almacena), con el timbre electrónico (TED) impreso como código PDF417:
Dos formas de obtenerla:
GET /dte/{id}/pdf → devuelve el PDF binario (application/pdf).POST /dte?incluir=pdf → el 201 de la emisión incluye pdf_base64
(sin segunda llamada).POST /dte/{id}/portal-link genera un enlace de acceso directo mediante un
token único que el receptor abre sin inicio de sesión ni API Key para
ver y descargar el documento. No es un recurso abierto ni indexable: el acceso
se controla por el token, que es opaco y no enumerable (64 caracteres
aleatorios, nunca expone IDs secuenciales). El enlace lleva X-Robots-Tag: noindex y su vigencia está atada a la retención legal del XML del documento
(6 años). Llamadas repetidas reutilizan el token vigente.
Antes de enviar al SII, validamos las referencias de una NC (61) o ND (56) a un documento propio ya emitido, para evitar rechazos del SII:
422 antes de
enviar al SII (previene el código SII REF-3-751).REF-3-750). Emites y el sistema gestiona el
orden; no tienes que esperar.Cuando el SII rechaza o repara un DTE, la respuesta de
GET /dte/{id} (y GET /dte) trae el objeto detalle_sii con la causa
traducida a lenguaje de negocio (codigo, glosa, causa, solucion).
Códigos frecuentes:
| Código | Significado |
|---|---|
REF-3-750 |
Documento referenciado aún no recibido por el SII (NC/ND). |
REF-3-751 |
RUT receptor distinto al del documento referenciado (NC/ND). |
HED-2-210 |
Monto neto no cuadra con el detalle (ítems deben ir netos). |
HED-2-260 |
Monto total no cuadra con los parciales (boletas: ítems con IVA). |
TED-2-510 |
Error en el timbre electrónico (TED/CAF). |
CRT-3-18 |
RUT receptor de la carátula inválido (boletas: 60803000-K). |
Rechazos del SOBRE (distintos de los de arriba). Antes de mirar el
contenido de un documento, el SII valida el envío que lo transporta. Si
falla ahí, estado_sii trae uno de estos tres códigos y detalle_sii.codigo
queda en null — el SII no emite un código granular para el sobre:
estado_sii |
Significado (manual SII) | Qué revisar |
|---|---|---|
RSC |
Rechazado por Error en Schema | El XML no cumple el XSD. Es un problema nuestro: repórtalo a soporte. |
RFR |
Rechazado por Error en Firma | Certificado digital vencido, revocado o no reconocido por el SII. |
RCT |
Rechazado por Error en Carátula | Ver detalle_sii.caratula_enviada: normalmente fecha_resol no coincide con la que el SII registró para tu RUT, o quien firma no está autorizado a enviar DTE por la empresa. |
Los estados SOK, CRT, FOK y PDR no son rechazos: son etapas
intermedias de un envío que va bien (CRT es "Carátula OK"). El cierre
exitoso del sobre es EPR.
Esta API es AI-native: puedes conectar un agente de IA (Claude,
Cursor, etc.) directamente a tu facturación mediante nuestro servidor MCP
(Model Context Protocol), y darle contexto a cualquier LLM con llms.txt.
1) Servidor MCP — local (npx):
{
"mcpServers": {
"facturador-pulsando": {
"command": "npx",
"args": ["-y", "@facturador-mcp-sii.cl/mcp"],
"env": { "PULSANDO_API_KEY": "sk_test_..." }
}
}
}
2) Servidor MCP — remoto (OAuth 2.1): agrega un conector remoto apuntando
a https://mcp.facturador.pulsandotech.cl/mcp; el cliente descubre
el OAuth y el usuario autoriza con su API Key.
Herramientas expuestas (26): listar_empresas, listar_sucursales,
emitir_dte, consultar_dte, consultar_estado_sii, listar_dtes,
consultar_contribuyente, estado_folios, estado_solicitud_folios,
tipos_autorizados, documentos_recibidos, detalle_recibido,
xml_recibido, sincronizar_rcv, listar_rcv, resumen_rcv,
acciones_rcv, historial_rcv, reporte_ventas, top_receptores,
mi_suscripcion, mis_facturas, resumen_organizacion, salud_cartera,
actividad_cartera y ventas_cartera. Las cuatro últimas son de la
administración de la organización: están siempre registradas, pero sólo
responden con una clave de organización con organizacion:read
(ventas_cartera, además, con dte:read); con otra clave responden 403.
El agente actúa con los permisos (scopes) de la API Key, así que los scopes
por empresa se respetan.
El canal de IA corresponde a los planes Profesional, Empresa, Estudio
contable y Plataforma; con otro plan puede responder 403 con
upgrade_required: true.
Varias empresas (estudios contables). Si la clave es de una organización,
el agente puede operar toda la cartera: cada herramienta acepta un parámetro
empresa con el RUT emisor, y listar_empresas le dice cuáles administra.
Así funciona "emite la factura de este mes para la Panadería" sin que el
agente tenga que adivinar el RUT.
→ listar_empresas
← Panadería Don Pedro (76354771-K) · Ferretería La Clave (78211386-0)
→ emitir_dte empresa="76354771-K" tipo_dte=33 …
← Folio 1042, estado pendiente — emitido por la Panadería
Requiere el paquete @facturador-mcp-sii.cl/mcp 0.3.0 o superior.
3) llms.txt: resumen de la API para LLMs en
https://www.facturador.pulsandotech.cl/llms.txt. Pégalo como contexto o
úsalo con herramientas que lo carguen automáticamente.
4) Prompt de integración listo para copiar en tu asistente: ver
PROMPT-MAESTRO-INTEGRACION.md en el repositorio de la documentación
(reemplaza al prompt anterior de AI-INTEGRATION.md).
Esta API procesa datos personales (RUT, razón social, direcciones, correos). Consulta la sección "Seguridad y cumplimiento" del README para tus obligaciones como responsable de datos y las medidas que aplicamos.
Prueba tu integración sin registrarte y sin API Key. Valida el payload con las mismas reglas que la emisión real, pero no crea nada ni envía al SII.
Prueba sin registrarte ni usar API Key. Envía el mismo cuerpo que a
POST /dte: no se crea ningún documento, no se consumen folios y
no se envía al SII. El emisor lo inyecta el sandbox (no lo envíes).
Rate limit: 30 req/min por IP.
QUÉ COMPRUEBA (ampliado el 23-08-2026). Además de las reglas de campo, el sandbox ahora construye el XML del documento con el mismo constructor de la emisión real y le corre las mismas validaciones de coherencia. Eso incluye la identidad de totales:
MntTotal = MntNeto + MntExe + IVA + impuestos adicionales − retenciones
Antes de este cambio un descuadre pasaba el sandbox y lo rechazaba (o lo reparaba el SII) la emisión de verdad. Eso ya no ocurre con los totales.
VALIDA IGUAL QUE LA EMISIÓN REAL (desde el 17-09-2026), CON EL MISMO
CÓDIGO. Además de lo anterior corre las mismas compuertas de contenido
que POST /dte aplica antes de tomar folio: dígito verificador y rango
del RUT del receptor, RUT marcador (66666666-6) en una factura, factura de
compra (46) sin dirección o comuna del proveedor o con IVA en cero,
retención parcial, transportista, tipo de cambio de exportación y
traducción de los códigos de Aduana. El RUT se normaliza igual
(76354771-K en un solo campo funciona en los dos). Y el 422 tiene la
misma forma en los dos: message, errors y, en los de contenido,
advertencias.
Y una cosa más que la emisión real hace recién al enviar: valida el
XML contra el esquema XSD oficial del SII. Un documento que el esquema
rechaza toma folio en POST /dte y queda en error_envio; acá responde
422, que es lo que va a pasar.
QUÉ NO PUEDE COMPROBAR, porque depende de tu cuenta: folios
disponibles, certificado vigente, resolución y autorización del SII,
habilitación del tipo en tu plan, el directorio de clientes (la emisión
real completa la dirección de un receptor conocido), referencias a
documentos tuyos (en una nota de crédito que referencia un documento
emitido en la plataforma, el cod_ref se reemplaza al emitir por el que
corresponda al monto) y si un local_id existe (se avisa en
advertencias). estado_sii_simulado: "aceptado" es un literal fijo,
no una predicción: el sandbox nunca le pregunta nada al SII.
Para una prueba fiel —documento completo, firmado, timbrado y validado contra el XSD— pide una empresa de pruebas: emite igual que la real y no consume folios ni toca al SII.
| tipo_dte required | integer Enum: 33 34 39 41 43 46 52 56 61 110 111 112 33 factura afecta · 34 factura exenta · 39 boleta · 41 boleta exenta · 43 liquidación · 46 factura de compra · 52 guía de despacho · 56 nota de débito · 61 nota de crédito · 110/111/112 exportación | |||||||||
| fecha_emision required | string <date> Fecha de emisión (YYYY-MM-DD) en hora de Chile. No puede ser futura: una fecha mayor a hoy (hora Chile) devuelve 422, porque el SII rechaza el DTE (RCT). | |||||||||
| ind_traslado | integer [ 1 .. 9 ] Obligatorio para guía (52). 1=venta, 2=ventas por efectuar, 3=consignación, 4=entrega gratuita, 5=traslado interno, 6=otros, 7=devolución, 8=traslado exportación, 9=venta exportación | |||||||||
| tipo_despacho | integer [ 1 .. 3 ] Guía (52). 1=por cuenta del receptor, 2/3=por cuenta del emisor | |||||||||
| forma_pago | integer Enum: 1 2 3 1=contado, 2=crédito, 3=sin costo | |||||||||
| ind_servicio | integer Enum: 1 2 3 4 Indicador de servicio. Facturas: 1=servicios periódicos domiciliarios, 2=otros servicios periódicos, 3=factura de servicio. Boletas (39/41) admiten además 4=espectáculo por cuenta de terceros. Un valor fuera de rango devuelve 422. | |||||||||
| fecha_vencimiento | string <date> | |||||||||
| ambiente | string Enum: "certificacion" "produccion" Para el portal, donde una empresa que ya está en producción puede emitir un documento de prueba en certificación. Con API Key se ignora: el documento sale en el ambiente de la llave ( | |||||||||
| local_id | integer or null >= 1 Local desde el que se emite, para una empresa con varios negocios bajo el MISMO RUT (por ejemplo una botillería y una ferretería, con distinto giro y a veces distinta sucursal ante el SII). El giro, el código de actividad, la dirección y el código de sucursal del SII salen del local, no de esta petición: acá va sólo el Si se omite, el documento se emite con los datos de la ficha de tu empresa, exactamente como antes de que existiera este campo. Un | |||||||||
object (Receptor) Opcional para boletas y NC/ND de boleta; obligatorio para el resto. En factura de compra (46) el receptor es el proveedor y | ||||||||||
required | Array of objects (Item) [ 1 .. 1000 ] items Máximo 60 ítems ( | |||||||||
required | object (Totales) Montos enteros, en pesos.
| |||||||||
Array of objects (Referencia) <= 40 items | ||||||||||
object Arriendo de inmuebles amoblados — rebaja del 11% del avalúo fiscal (Art. 17 del DL 825). Sólo en boleta 39 y factura 33. El IVA se calcula sobre la renta menos el 11% anual del avalúo fiscal, prorrateado al período. Es obligatorio desde el 01-03-2020: la Ley 21.210 reemplazó "podrá" por "deberá", y el Oficio 3000/2016 ya había dicho que no es una facultad del arrendador. No rebajar no es ser conservador: es declarar IVA en exceso y recargarle al arrendatario un impuesto mayor al legal. Tú mandas el avalúo; la rebaja, el IVA y la base los deriva el backend. No hay forma de mandar el monto de la rebaja ni el IVA, y es a propósito: un monto copiado del payload es un monto que se puede mandar mal, y un DTE no se corrige — se anula con nota de crédito. 🔴 El documento sale con el IVA distinto del 19% del neto, y está bien. Los Oficios 1183/2022 y 2356/2025 lo anuncian: "podría generarse alguna descuadratura o desajuste en los montos de los documentos emitidos, los que son aceptados por el Servicio... fue aceptado con reparos, circunstancia que no tiene efectos para el contribuyente". El SII avisa ese reparo por correo al emisor. La rebaja NO es una exención: no va en Las dos convenciones, según el documento:
Si la rebaja supera la renta del período, el IVA es 0 y nunca negativo (la operación sigue gravada: el Oficio 1536/2020 aclara que tampoco corresponde emitir una factura exenta por eso). La deducción queda escrita en la glosa del documento ( Requiere que tu cuenta tenga habilitada la función: escríbenos. | ||||||||||
object (Transportista) Solo para guía (52). dir_dest y cmna_dest son obligatorios para 52. Desde el 1-nov-2026 la Res. Ex. SII N°154/2025 exige además chofer (rut_chofer, dv_chofer, nombre_chofer), patente_carro, fecha_salida, hora_salida y fecha_llegada. El SII no rechaza la guía si faltan (su ausencia se sanciona en fiscalización), así que la API tampoco: sólo valida el formato. | ||||||||||
object (Impresion) Datos que se imprimen en el documento pero NO viajan al SII: su esquema no los tiene. Se guardan junto al documento y aparecen en el ticket. Todo opcional. Pensado para retail: identificar quién atendió, en qué local y con qué medio pagó el cliente.
Para el código de caja y de vendedor —que sí viajan al SII— usa
| ||||||||||
object (Exportacion) Obligatorio en los tipos 110/111/112 (factura, nota de débito y nota
de crédito de exportación), con Montos: los de Códigos de Aduana (Anexo 51): el SII exige el código NUMÉRICO en
cláusula, modalidad, vía de transporte, puertos, bulto, países y forma de
pago. Puedes mandar el número ( Lo que el SII exija según la operación y falte (por ejemplo país de
destino en una exportación de bienes) no lo bloqueamos: se descubre en el
estado asíncrono ( Dos escenarios típicos:
| ||||||||||
Array of objects <= 20 items Sólo liquidación-factura (43). Comisiones y otros cargos que el
mandatario le cobra al mandante; RESTAN del total (ver
| ||||||||||
| permitir_duplicado | boolean Default: false Escotilla del freno de reemisión por contenido: Equivale al header |
{- "tipo_dte": 33,
- "fecha_emision": "2019-08-24",
- "ind_traslado": 1,
- "tipo_despacho": 1,
- "forma_pago": 1,
- "ind_servicio": 1,
- "fecha_vencimiento": "2019-08-24",
- "ambiente": "certificacion",
- "local_id": 3,
- "receptor": {
- "rut": "12345678",
- "dv": "5",
- "razon_social": "string",
- "giro": "string",
- "direccion": "string",
- "comuna": "string",
- "ciudad": "string",
- "email": "user@example.com"
}, - "items": [
- {
- "nombre": "string",
- "cantidad": 0,
- "precio_unitario": 0,
- "monto_item": 0,
- "descuento_pct": 0,
- "unidad_medida": "UN",
- "ind_exe": 1,
- "tipo_doc_liq": "33",
- "cod_imp_adic": 24
}
], - "totales": {
- "monto_neto": 0,
- "monto_iva": 19000,
- "monto_exento": 0,
- "monto_total": 0,
- "tasa_iva": 19,
- "monto_nf": 0,
- "iva_retenido": 19000,
- "tipo_retencion": 15,
- "iva_no_retenido": 0,
- "impuestos_adicionales": [
- {
- "tipo_imp": 24,
- "tasa_imp": 31.5,
- "monto_imp": 31500
}
]
}, - "referencias": [
- {
- "tipo_dte_ref": 39,
- "folio_ref": 45,
- "fecha_ref": "2019-08-24",
- "cod_ref": 1,
- "razon_ref": "string",
- "cod_vendedor": "V0034",
- "cod_caja": "CAJ01"
}
], - "rebaja_arriendo": {
- "avaluo_fiscal": 9600000,
- "dias_arrendados": 10
}, - "transportista": {
- "patente": "string",
- "rut_trans": "string",
- "dv_trans": "s",
- "rut_chofer": "string",
- "dv_chofer": "s",
- "nombre_chofer": "string",
- "dir_dest": "string",
- "cmna_dest": "string",
- "ciudad_dest": "string",
- "patente_carro": "XY1234",
- "fecha_salida": "2026-11-02",
- "hora_salida": "08:30",
- "fecha_llegada": "2026-11-03"
}, - "impresion": {
- "cajero": "María Pérez",
- "local": "Sucursal Centro",
- "medio_pago": "Efectivo"
}, - "exportacion": {
- "tipo_moneda": "USD",
- "tipo_cambio": 923.23,
- "clausula": "FOB",
- "tot_clausula": 0,
- "via_transporte": "MARITIMA",
- "modal_venta": "A FIRME",
- "monto_moneda": 0,
- "flete": 0,
- "seguro": 0,
- "puerto_embarque": "SAN ANTONIO",
- "puerto_desembarque": "MIAMI",
- "pais_receptor": "US",
- "pais_destino": "US",
- "forma_pago": "ANTICIPO",
- "total_items": 0,
- "total_bultos": 0,
- "tipo_bulto": "CAJAS DE CARTON",
- "nacionalidad": "string"
}, - "comisiones": [
- {
- "tipo_movimiento": "C",
- "glosa": "string",
- "tasa": 0.01,
- "valor_neto": 0,
- "valor_exento": 0,
- "valor_iva": 0
}
], - "permitir_duplicado": false
}{- "sandbox": true,
- "message": "string",
- "simulacion": {
- "tipo_dte": 0,
- "folio": 0,
- "estado_local": "pendiente",
- "estado_sii_simulado": "aceptado",
- "monto_total": 0
}, - "advertencias": [
- "El campo `totales.iva` no existe en la API de emisión: se DESCARTÓ y no llegó al documento. ¿Quisiste decir `totales.monto_iva`? Revisa el documento emitido antes de darlo por bueno."
]
}Qué empresas emisoras administra tu API Key. Punto de partida para las claves de organización (estudios contables, holdings): responde la cartera sin exigir que hayas elegido una empresa.
Responde por qué RUT emisores puede operar esta clave.
No exige haber seleccionado empresa: pedirte el RUT que justamente vienes a
averiguar sería circular (las lecturas de /organizacion/* tampoco lo
exigen, porque son de toda la cartera). Por eso es el punto de partida de
cualquier integración de estudio contable — y lo que llama la herramienta
listar_empresas del MCP.
Con una clave de una organización suspendida responde 403 con
codigo: "organizacion_suspendida" y no lista la cartera.
Responde con la misma forma para los dos tipos de clave; mira
requiere_seleccion para saber cómo seguir:
false → clave de una empresa. No envíes X-Empresa-RUT.true → clave de organización. Envía X-Empresa-RUT en cada llamada.El campo ambiente de cada empresa importa: mock es el ambiente de
desarrollo (no habla con el SII); certificacion emite contra maullin con
folios de prueba; produccion factura de verdad en palena. Es el ambiente
de la empresa, no el de la llave: una sk_test_ sobre una empresa en
producción emite en certificación. El ambiente real de cada documento
viene en GET /dte/{id} → ambiente.
{- "alcance": "organizacion",
- "organizacion": {
- "rut": "76.900.000-1",
- "razon_social": "Finaxa SpA",
- "tipo": "estudio"
}, - "requiere_seleccion": true,
- "como_seleccionar": "Envía el header X-Empresa-RUT con el RUT de la empresa emisora en cada llamada.",
- "data": [
- {
- "rut": "76.354.771-K",
- "razon_social": "Panadería Don Pedro SpA",
- "alias": "Don Pedro",
- "ambiente": "produccion",
- "estado": "activo"
}, - {
- "rut": "78.211.386-0",
- "razon_social": "Ferretería La Clave Ltda",
- "alias": null,
- "ambiente": "certificacion",
- "estado": "activo"
}
]
}Lecturas de administración de un estudio contable u holding: resumen y cobro, salud y actividad de la cartera, y el consolidado de ventas. Sólo lectura: agregar o quitar empresas, usuarios, la suscripción y las claves se hace en el portal.
Requieren una clave de organización vigente con el permiso
organizacion:read, que se elige al crear la clave (ninguna clave existente lo
trae). GET /organizacion/ventas exige además dte:read: son documentos
de cada empresa, y es el mismo permiso que GET /reportes/ventas. No llevan
X-Empresa-RUT: la consulta es de toda la cartera vigente; las empresas
retiradas de la cartera no aparecen.
No dependen del ambiente de la clave (salvo las ventas): una sk_test_
con organizacion:read lee el cobro, la salud y la actividad reales de la
organización. Dale el permiso sólo a claves que puedan verlo.
403 con… |
Significa | Qué hacer |
|---|---|---|
codigo: "requiere_llave_de_organizacion" |
La clave es de una empresa | Crea en el portal una clave de organización con organizacion:read |
codigo: "organizacion_suspendida" |
La organización no está vigente | Revisa la suscripción del estudio en el portal |
| «no tiene el permiso requerido: organizacion:read» | Clave de organización sin el permiso | Crea una clave nueva con el permiso (las claves no se editan) |
«no tiene el permiso requerido: dte:read» (sólo en /organizacion/ventas) |
La clave tiene organizacion:read pero no dte:read |
Crea una clave nueva con los dos permisos |
GET /organizacion/ventas tiene además su propio límite: 10 peticiones por
minuto por organización, sumando todas sus claves. Al pasarlo responde 429
con codigo: "demasiadas_solicitudes", retry_after y el header
Retry-After.
La organización dueña de la clave, su plan, lo que paga por mes y el cupo de DTE de toda la cartera. Es lo mismo que el socio ve en el panel del estudio.
Montos: precio_por_rut_neto, mensual_neto, anual_neto e
implementacion_pendiente_neto son NETOS (los precios se publican
«+ IVA»). mensual_con_iva, anual_con_iva e
implementacion_pendiente_con_iva son lo que se cobra de verdad; no
recalcules el IVA de tu lado. El anual son 10 meses.
Se cobra por cada empresa activa de la cartera, esté en certificación o en
producción (cobro.empresas_facturables); empresas_en_cartera incluye
además las suspendidas sin retirar. pool.cupo = 0 significa sin tope, y
entonces pool.disponible es null.
Nada de medios de pago, tokens de la pasarela ni correos de usuarios.
Requiere clave de organización con organizacion:read.
{- "organizacion": {
- "rut": "76.900.000-1",
- "razon_social": "Finaxa SpA",
- "tipo": "estudio",
- "estado": "activo"
}, - "plan": {
- "nombre": "Estudio contable",
- "precio_por_rut_neto": [
- {
- "hasta": 10,
- "precio": 14990
}, - {
- "hasta": null,
- "precio": 12990
}
], - "dte_por_rut": 300,
- "implementacion_por_rut_neto": 9900
}, - "empresas_en_cartera": 2,
- "cobro": {
- "empresas_facturables": 2,
- "tramos": [
- {
- "desde": 1,
- "hasta": 2,
- "empresas": 2,
- "precio_unitario": 14990,
- "subtotal": 29980
}
], - "mensual_neto": 29980,
- "mensual_con_iva": 35676,
- "anual_neto": 299800,
- "anual_con_iva": 356762,
- "tasa_iva": 19,
- "implementacion_pendiente_neto": 0,
- "implementacion_pendiente_con_iva": 0
}, - "pool": {
- "cupo": 600,
- "consumido": 42,
- "disponible": 558,
- "periodo": "2026-09"
}
}El puntaje (0–100) y la banda de cada empresa de la cartera vigente, con lo
que le falta hacer, desde la foto diaria del centro de mando. Ordenadas de la
peor a la mejor; una empresa sin foto viene con banda: "sin_foto" y
score: null.
pendientes[].quien dice de quién es la tarea: empresa (la tiene que hacer
la empresa o el estudio) o pulsando (la resolvemos nosotros). Las tareas
internas de la plataforma no se muestran.
Requiere clave de organización con organizacion:read.
{- "data": [
- {
- "rut": "76.354.771-K",
- "razon_social": "string",
- "ambiente": "mock",
- "score": 0,
- "banda": "sano",
- "foto_at": "2019-08-24T14:15:22Z",
- "ultimo_dte_at": "string",
- "dte_30d": 0,
- "pendientes": [
- {
- "clave": "certificado_ausente",
- "detalle": "string",
- "que": "string",
- "quien": "empresa"
}
]
}
], - "por_banda": {
- "sano": 0,
- "vigilar": 0,
- "riesgo": 0,
- "critico": 0,
- "nuevo": 0,
- "sin_foto": 0,
- "omitido": 0,
- "property1": 0,
- "property2": 0
}, - "foto_at": "string"
}Las llamadas a la API de las empresas de la cartera vigente desde desde:
total, cuántas fallaron (status ≥ 400), por origen (api, mcp, portal),
por empresa y las 50 más recientes. Sin IP, sin user-agent, sin cuerpos ni
mensajes de error internos.
En ultimas[].path las partes variables de la ruta vienen enmascaradas:
un RUT (con o sin puntos y dígito verificador) sale como {rut}, un número
como {id} y un UUID o token largo como {token}. Por ejemplo,
api/public/v1/contribuyentes/{rut} o api/public/v1/dte/{id}/pdf.
desde es opcional (por defecto, los últimos 7 días) y puede ir hasta
90 días atrás; una fecha anterior o futura responde 422. Ojo: los
registros se conservan retencion_dias días, así que pedir más atrás no trae
nada más viejo que eso.
Requiere clave de organización con organizacion:read.
| desde | string <date> Fecha |
{- "periodo": {
- "desde": "2026-09-10 10:00:00",
- "hasta": "2026-09-17 10:00:00"
}, - "retencion_dias": 0,
- "total": 0,
- "errores": 0,
- "por_origen": {
- "property1": 0,
- "property2": 0
}, - "por_empresa": [
- {
- "rut": "string",
- "razon_social": "string",
- "llamadas": 0
}
], - "ultimas": [
- {
- "rut": "string",
- "method": "POST",
- "path": "api/public/v1/dte/{id}/pdf",
- "status": 0,
- "source": "mcp",
- "duration_ms": 0,
- "created_at": "2019-08-24T14:15:22Z"
}
]
}Las ventas válidas de cada empresa de la cartera vigente en el rango, y la
suma. Por cada empresa, los campos son los mismos que daría
GET /reportes/ventas de esa empresa sumado en el mismo rango (misma fórmula:
ver GET /reportes/ventas), y totales los suma. totales.suma_total es la
suma de las ventas válidas, no de total_bruto_emitido.
/reportes/ventas:
sk_test_ suma documentos de certificación y sk_live_ los de
producción, en todas las empresas. Cada fila dice en ambiente qué
documentos sumó (una empresa de desarrollo se queda en mock).desde y hasta en YYYY-MM-DD; por defecto, desde el día 1
del mes en curso hasta hoy (hora de Chile). Hasta 366 días contando
los dos extremos; hasta anterior a desde o un rango más largo responde
422.marca_operativa) no se suman.errores[]
con su codigo y las demás se suman. empresa_suspendida y
upgrade_required (el plan de esa empresa no trae la función ERP) son los
mismos cortes que tendría su propio /reportes/ventas;
empresa_no_disponible es un problema transitorio: reintenta.Cuesta dos consultas agregadas por empresa: con carteras grandes, pide
períodos acotados. Límite propio: 10 peticiones por minuto por
organización (todas sus claves suman); al pasarlo, 429 con
Retry-After.
Requiere clave de organización con organizacion:read y dte:read.
| desde | string <date> Fecha |
| hasta | string <date> Fecha |
{- "periodo": {
- "desde": "2019-08-24",
- "hasta": "2019-08-24"
}, - "empresas": [
- {
- "suma_total": 0,
- "suma_neto": 0,
- "suma_iva": 0,
- "suma_exento": 0,
- "documentos_venta": 0,
- "total_bruto_emitido": 0,
- "notas_credito": {
- "documentos": 0,
- "suma_total": 0
}, - "en_proceso": {
- "documentos": 0,
- "suma_total": 0
}, - "excluidos": {
- "documentos": 0,
- "suma_total": 0,
- "por_motivo": [
- {
- "motivo": "guia_despacho",
- "documentos": 0,
- "suma_total": 0
}
]
}, - "rut": "76.354.771-K",
- "razon_social": "string",
- "ambiente": "mock",
- "total_documentos": 0
}
], - "totales": {
- "suma_total": 0,
- "suma_neto": 0,
- "suma_iva": 0,
- "suma_exento": 0,
- "documentos_venta": 0,
- "total_bruto_emitido": 0,
- "notas_credito": {
- "documentos": 0,
- "suma_total": 0
}, - "en_proceso": {
- "documentos": 0,
- "suma_total": 0
}, - "excluidos": {
- "documentos": 0,
- "suma_total": 0,
- "por_motivo": [
- {
- "motivo": "guia_despacho",
- "documentos": 0,
- "suma_total": 0
}
]
}, - "empresas": 0,
- "total_documentos": 0
}, - "errores": [
- {
- "rut": "string",
- "razon_social": "string",
- "codigo": "empresa_suspendida",
- "message": "string"
}
]
}Crea y encola un DTE para envío al SII. El bloque emisor se toma automáticamente de tu empresa ("Mi empresa"); no lo envíes.
Reglas por tipo de documento:
receptor es opcional (consumidor final).receptor opcional (hereda consumidor final).ind_traslado obligatorio y destino
(transportista.dir_dest + transportista.cmna_dest) obligatorio.cod_ref) se deriva del monto
(total → anula, 0 → corrige texto, parcial → corrige montos) y reemplaza
al que envíes. Si lo emitiste en otro sistema, manda cod_ref
explícito (1 anula, 2 corrige texto, 3 corrige montos): sin él se declara
ante el SII como anulación (1).Σ items[].monto_item = monto_total. Lo más simple es mandar sólo
monto_total y dejar que la plataforma calcule el desglose. Si mandas
monto_neto o monto_iva, tienen que ser
monto_neto = round((monto_total − monto_exento) / 1,19) y
monto_iva = monto_total − monto_exento − monto_neto: un neto o un IVA
que difiera en más de un peso responde 422.receptor es el proveedor (típicamente
extranjero). direccion y comuna son obligatorias — sin ellas el SII
RECHAZA (HED-3-845 / HED-3-846) y el folio se pierde. El giro es
recomendado (si falta, el SII observa con REPARO HED-1-844, pero el
documento es válido). El IVA lo retiene el comprador (retención total).Validación de notas (NC/ND) que referencian un documento propio:
422 (con el mensaje en message) antes de
enviar al SII (previene el código SII REF-3-751).REF-3-750). No es necesario que esperes: el sistema gestiona el orden de envío.PDF en la misma respuesta (paridad caja, 1 sola llamada): agrega
?incluir=pdf para que el 201 incluya pdf_base64 + pdf_mime con la
representación impresa lista para imprimir.
⚠️ Si el PDF falla, el documento IGUAL SE EMITIÓ. Son dos cosas
distintas y confundirlas cuesta caro: la respuesta trae emitido: true,
el folio ya asignado y pdf.disponible: false. Pide la impresión
después con GET /dte/{id}/pdf. No reintentes la emisión: crearías un
documento duplicado que hay que anular con nota de crédito.
Freno de reemisión por contenido (automático). Además de la
Idempotency-Key, si el mismo emisor manda un documento con el mismo
tipo, fecha de emisión, receptor, local, totales, ítems y referencias,
desde el tercero dentro de 30 minutos dejamos de emitir folios
nuevos y te devolvemos uno que ya existe, con duplicado: true y
motivo_duplicado: "contenido" (status 201, más el header
X-Dte-Duplicado: contenido). Los dos primeros documentos idénticos se
emiten normalmente. Con la configuración por defecto el freno no
bloquea boletas 39/41 (en ellas sólo registra lo que habría hecho): ahí
tu Idempotency-Key es la única defensa contra el duplicado.
Existe porque la idempotencia por clave sólo protege a quien reusa la clave: un cliente cuyo POS acuñaba una marca de tiempo nueva en cada reintento emitió 52 boletas idénticas en 24 minutos.
Si de verdad es otra venta idéntica (dos clientes compran lo mismo al
mismo precio), indícalo explícitamente con el header
X-Permitir-Duplicado: true (o el campo permitir_duplicado: true en el
cuerpo) y una Idempotency-Key nueva, y se emite un folio nuevo. Con
la clave de la petición anterior te vuelve el documento anterior: la
idempotencia se resuelve antes que el freno.
Idempotencia (recomendado en producción): envía el header
Idempotency-Key con un valor estable por venta: se genera una sola
vez cuando nace la venta, se guarda junto a ella y se reusa en todos los
reintentos (si usas un UUID, es uno por venta, nunca uno nuevo por
intento). Si un reintento de red repite la petición con la MISMA clave,
no se emite un
segundo DTE ni se consume otro folio: se devuelve la respuesta original
con el header Idempotent-Replayed: true. Si el original aún está en curso
se responde 409 (reintenta en unos segundos: el cuerpo trae
reintentar_en_segundos y viene el header Retry-After); si reutilizas la
misma clave con un cuerpo distinto, 422. La clave es única por empresa.
Una clave ESTABLE por venta es lo correcto (por ejemplo
{id_de_la_venta}-{hash_del_cuerpo}), no una marca de tiempo nueva por
intento: la clave es lo que distingue un reintento de una venta nueva, y si
cambia en cada intento la idempotencia no protege nada. Y no quedas
atrapado en el 409: una reserva cuyo proceso murió expira sola pasado el
plazo, así que la misma clave vuelve a poder emitir.
El emisor no va en el cuerpo: sale de la ficha de la empresa. Razón
social, giro, dirección y el código de actividad económica (acteco)
se leen de la empresa dueña de la API key. El SII exige acteco en todo
documento salvo las boletas (39/41): si la empresa no lo tiene configurado,
la emisión responde 422 explicándolo y no consume folio. Se configura
una sola vez en el panel (Empresa → «Código de actividad») o con
PATCH /api/v1/empresa (acteco, 6 dígitos). Aplica a facturas, notas,
guías de despacho (52), liquidaciones (43) y documentos de exportación.
La emisión es asíncrona después del 201. La respuesta confirma que el
documento se construyó, se firmó y tomó folio; el envío al SII ocurre en
segundos, en segundo plano. El resultado llega por los webhooks
dte.enviado → dte.aceptado / dte.rechazado / dte.reparado, y si el
documento no logra salir (falla nuestra validación previa, certificado,
SII caído) por dte.error_envio. Los webhooks se entregan por separado y
con reintentos, así que pueden llegar en otro orden: el estado lo dice
GET /dte/{id}, que también sirve si no usas webhooks.
Un error_envio no avanza solo: se sale con POST /dte/{id}/reintentar,
nunca reemitiendo (el folio ya está tomado y un documento nuevo
declararía dos veces la misma venta).
Lo que falta en la ficha de la empresa se dice ANTES de tomar folio.
Acteco, resolución del SII (sólo en producción) y autorización del SII
para ese tipo en ese ambiente (sólo en producción, y sólo si el SII ya
dijo que no) se comprueban antes de asignar folio: responden 422 con un
codigo estable y no consumen folio. Ver la tabla del 422.
Un 422 nunca toca el contador de folios. Las reglas del documento
(totales, desglose, referencias, receptor) y el certificado se verifican
antes de asignar folio. Si algo falla de nuestro lado después de
asignarlo (un 500), el folio no se pierde: vuelve al contador o lo usa
la siguiente emisión. Y un 500 no deja tomada la Idempotency-Key:
reintentar con la misma clave vuelve a intentar la emisión en vez de
responder 409.
| incluir | string Value: "pdf" Si vale |
| formato | string Enum: "carta" "pos80" Sólo tiene efecto junto a |
| copia | string Enum: "cedible" "tributaria" Sólo tiene efecto junto a |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
| Idempotency-Key | string <= 255 characters Clave estable por venta (generada una vez, guardada y reusada en
cada reintento; nunca una nueva por intento) para hacer la petición
idempotente. Un reintento con la misma clave devuelve el mismo DTE
(header La clave es por empresa emisora. Si tu ERP numera las facturas por
empresa y repite |
| X-Permitir-Duplicado | boolean Escotilla del freno de reemisión por contenido: Úsalo sólo cuando el duplicado sea legítimo, y con una
|
| tipo_dte required | integer Enum: 33 34 39 41 43 46 52 56 61 110 111 112 33 factura afecta · 34 factura exenta · 39 boleta · 41 boleta exenta · 43 liquidación · 46 factura de compra · 52 guía de despacho · 56 nota de débito · 61 nota de crédito · 110/111/112 exportación | |||||||||
| fecha_emision required | string <date> Fecha de emisión (YYYY-MM-DD) en hora de Chile. No puede ser futura: una fecha mayor a hoy (hora Chile) devuelve 422, porque el SII rechaza el DTE (RCT). | |||||||||
| ind_traslado | integer [ 1 .. 9 ] Obligatorio para guía (52). 1=venta, 2=ventas por efectuar, 3=consignación, 4=entrega gratuita, 5=traslado interno, 6=otros, 7=devolución, 8=traslado exportación, 9=venta exportación | |||||||||
| tipo_despacho | integer [ 1 .. 3 ] Guía (52). 1=por cuenta del receptor, 2/3=por cuenta del emisor | |||||||||
| forma_pago | integer Enum: 1 2 3 1=contado, 2=crédito, 3=sin costo | |||||||||
| ind_servicio | integer Enum: 1 2 3 4 Indicador de servicio. Facturas: 1=servicios periódicos domiciliarios, 2=otros servicios periódicos, 3=factura de servicio. Boletas (39/41) admiten además 4=espectáculo por cuenta de terceros. Un valor fuera de rango devuelve 422. | |||||||||
| fecha_vencimiento | string <date> | |||||||||
| ambiente | string Enum: "certificacion" "produccion" Para el portal, donde una empresa que ya está en producción puede emitir un documento de prueba en certificación. Con API Key se ignora: el documento sale en el ambiente de la llave ( | |||||||||
| local_id | integer or null >= 1 Local desde el que se emite, para una empresa con varios negocios bajo el MISMO RUT (por ejemplo una botillería y una ferretería, con distinto giro y a veces distinta sucursal ante el SII). El giro, el código de actividad, la dirección y el código de sucursal del SII salen del local, no de esta petición: acá va sólo el Si se omite, el documento se emite con los datos de la ficha de tu empresa, exactamente como antes de que existiera este campo. Un | |||||||||
object (Receptor) Opcional para boletas y NC/ND de boleta; obligatorio para el resto. En factura de compra (46) el receptor es el proveedor y | ||||||||||
required | Array of objects (Item) [ 1 .. 1000 ] items Máximo 60 ítems ( | |||||||||
required | object (Totales) Montos enteros, en pesos.
| |||||||||
Array of objects (Referencia) <= 40 items | ||||||||||
object Arriendo de inmuebles amoblados — rebaja del 11% del avalúo fiscal (Art. 17 del DL 825). Sólo en boleta 39 y factura 33. El IVA se calcula sobre la renta menos el 11% anual del avalúo fiscal, prorrateado al período. Es obligatorio desde el 01-03-2020: la Ley 21.210 reemplazó "podrá" por "deberá", y el Oficio 3000/2016 ya había dicho que no es una facultad del arrendador. No rebajar no es ser conservador: es declarar IVA en exceso y recargarle al arrendatario un impuesto mayor al legal. Tú mandas el avalúo; la rebaja, el IVA y la base los deriva el backend. No hay forma de mandar el monto de la rebaja ni el IVA, y es a propósito: un monto copiado del payload es un monto que se puede mandar mal, y un DTE no se corrige — se anula con nota de crédito. 🔴 El documento sale con el IVA distinto del 19% del neto, y está bien. Los Oficios 1183/2022 y 2356/2025 lo anuncian: "podría generarse alguna descuadratura o desajuste en los montos de los documentos emitidos, los que son aceptados por el Servicio... fue aceptado con reparos, circunstancia que no tiene efectos para el contribuyente". El SII avisa ese reparo por correo al emisor. La rebaja NO es una exención: no va en Las dos convenciones, según el documento:
Si la rebaja supera la renta del período, el IVA es 0 y nunca negativo (la operación sigue gravada: el Oficio 1536/2020 aclara que tampoco corresponde emitir una factura exenta por eso). La deducción queda escrita en la glosa del documento ( Requiere que tu cuenta tenga habilitada la función: escríbenos. | ||||||||||
object (Transportista) Solo para guía (52). dir_dest y cmna_dest son obligatorios para 52. Desde el 1-nov-2026 la Res. Ex. SII N°154/2025 exige además chofer (rut_chofer, dv_chofer, nombre_chofer), patente_carro, fecha_salida, hora_salida y fecha_llegada. El SII no rechaza la guía si faltan (su ausencia se sanciona en fiscalización), así que la API tampoco: sólo valida el formato. | ||||||||||
object (Impresion) Datos que se imprimen en el documento pero NO viajan al SII: su esquema no los tiene. Se guardan junto al documento y aparecen en el ticket. Todo opcional. Pensado para retail: identificar quién atendió, en qué local y con qué medio pagó el cliente.
Para el código de caja y de vendedor —que sí viajan al SII— usa
| ||||||||||
object (Exportacion) Obligatorio en los tipos 110/111/112 (factura, nota de débito y nota
de crédito de exportación), con Montos: los de Códigos de Aduana (Anexo 51): el SII exige el código NUMÉRICO en
cláusula, modalidad, vía de transporte, puertos, bulto, países y forma de
pago. Puedes mandar el número ( Lo que el SII exija según la operación y falte (por ejemplo país de
destino en una exportación de bienes) no lo bloqueamos: se descubre en el
estado asíncrono ( Dos escenarios típicos:
| ||||||||||
Array of objects <= 20 items Sólo liquidación-factura (43). Comisiones y otros cargos que el
mandatario le cobra al mandante; RESTAN del total (ver
| ||||||||||
| permitir_duplicado | boolean Default: false Escotilla del freno de reemisión por contenido: Equivale al header |
{- "tipo_dte": 33,
- "fecha_emision": "2026-06-11",
- "receptor": {
- "rut": "12345678",
- "dv": "5",
- "razon_social": "Cliente Ejemplo SpA",
- "giro": "Comercio",
- "direccion": "Av. Siempre Viva 123",
- "comuna": "Santiago",
- "ciudad": "Santiago",
- "email": "pagos@cliente.cl"
}, - "items": [
- {
- "nombre": "Servicio de desarrollo",
- "cantidad": 1,
- "precio_unitario": 100000,
- "monto_item": 100000
}
], - "totales": {
- "monto_neto": 100000,
- "monto_iva": 19000,
- "monto_total": 119000
}
}{- "id": 123,
- "tipo_dte": 33,
- "folio": 45,
- "estado_local": "pendiente",
- "monto_total": 119000,
- "origen": "api",
- "emitido": true,
- "duplicado": false,
- "motivo_duplicado": "idempotency_key",
- "message": "DTE creado y encolado para envío al SII.",
- "advertencias": [
- "La fecha de emisión (2026-07-10) tiene 10 días. El SII permite enviar hasta 3 días después de emitido: es probable que observe el documento con el reparo 650. El documento igual queda VÁLIDO y el folio no se pierde.",
- "El campo `totales.iva` no existe en la API de emisión: se DESCARTÓ y no llegó al documento. ¿Quisiste decir `totales.monto_iva`? Revisa el documento emitido antes de darlo por bueno."
], - "pdf_base64": "string",
- "pdf_mime": "application/pdf",
- "pdf_error": "El documento SÍ fue emitido y tiene folio 45. Sólo falló la representación impresa: pídela con GET /dte/123/pdf. NO reintentes la emisión — crearía un documento duplicado que hay que anular con nota de crédito.",
- "pdf": {
- "disponible": false,
- "motivo": "No se pudo generar la representación impresa en esta llamada.",
- "reintentable": true,
- "obtener_en": "/api/public/v1/dte/123/pdf"
}, - "impuestos": [
- {
- "codigo": 24,
- "nombre": "Licores, piscos, whisky, aguardientes y vinos licorosos o aromatizados",
- "tasa": 31.5,
- "monto": 31500,
- "resta": false
}
], - "monto_imp_adicional": 31500
}| q | string <= 200 characters Búsqueda libre por razón social o RUT del receptor |
| rut_receptor | string <= 20 characters |
| tipo_dte | string Un tipo o CSV, ej. "33,34" |
| grupo | string Enum: "facturas" "boletas" "todos" |
| estado_local | string Enum: "pendiente" "enviando" "enviado" "error_envio" "aceptado" "aceptado_con_reparos" "rechazado" "rechazado_sobre" "anulado" Estado normalizado. Finales: aceptado, aceptado_con_reparos (ambos VÁLIDOS), rechazado, rechazado_sobre, anulado. En curso: pendiente, enviando, enviado, error_envio. |
| estado_sii | string Un estado SII o CSV |
| origen | string Example: origen=api,mcp Filtra por el canal de emisión: |
| desde | string <date> Filtra por fecha de emisión (no por hora de creación). Rango INCLUSIVO: desde=hasta=2026-07-01 devuelve el día 1 completo. |
| hasta | string <date> Inclusivo, ver |
| monto_min | integer >= 0 |
| monto_max | integer >= 0 |
| incluir_pruebas | boolean Default: false Por defecto NO se devuelven los documentos que emitió Facturador Pulsando con tu RUT al poner en marcha el sistema (set de certificación, prueba inicial y sus notas de crédito; llevan |
| ambiente | string Enum: "certificacion" "produccion" Ambiente de los documentos a mirar, desde el portal. Con API Key se ignora: se ven siempre los del ambiente de la llave ( |
| sort | string Enum: "fecha_emision" "monto_total" "folio" "created_at" |
| dir | string Enum: "asc" "desc" |
| per_page | integer [ 1 .. 200 ] Default: 50 |
| page | integer >= 1 Default: 1 |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "data": [
- {
- "id": 0,
- "folio": 0,
- "tipo_dte": 0,
- "fecha_emision": "2019-08-24",
- "razon_social_receptor": "string",
- "rut_receptor": "12345678-5",
- "monto_neto": 0,
- "monto_iva": 0,
- "monto_exento": 0,
- "monto_total": 0,
- "estado": "string",
- "estado_sii": "string",
- "err_code": "DTE-3-101",
- "detalle_sii": {
- "codigo": "REF-3-751",
- "glosa": "RUT Receptor Diferente en Documento Referenciado",
- "causa": "string",
- "solucion": "string",
- "fuente": "string",
- "raw": null,
- "num_atencion": "927451 ( 2026/08/07 11:28:48)",
- "caratula_enviada": {
- "rut_emisor": "76227474-4",
- "rut_envia": "17451736-3",
- "rut_receptor": "60803000-K",
- "fecha_resol": "2026-05-07",
- "nro_resol": 0,
- "ambiente": "certificacion"
}
}, - "tiene_nc": true,
- "nc_count": 0,
- "track_id": "string",
- "ambiente": "mock",
- "origen": "api",
- "puede_reintentar": true,
- "created_at": "2019-08-24T14:15:22Z",
- "enviado_at": "2019-08-24T14:15:22Z",
- "respondido_at": "2019-08-24T14:15:22Z"
}
], - "meta": {
- "current_page": 0,
- "last_page": 0,
- "per_page": 0,
- "total": 0
}
}Totales y desglose por tipo y estado sobre el conjunto filtrado (mismos
filtros que el listado). total_documentos cuenta TODO el conjunto; las
facetas por_tipo y por_estado traen el monto EMITIDO de cada grupo.
suma_total son VENTAS VÁLIDAS, no la suma de todo lo emitido (desde el
17-sep-2026; antes sumaba todo, incluso notas de crédito en positivo y
rechazados):
suma_total = Σ (33, 34, 39, 41, 43, 56 válidos) − Σ (61 válidas)
estado_local aceptado o aceptado_con_reparos, o
anulado por una nota de crédito emitida acá (el original suma y la
nota resta: neto 0, sin restar dos veces).suma_neto, suma_iva y suma_exento siguen la misma regla.excluidos.por_motivo): guías de despacho 52
(guia_despacho), facturas de compra 46 (factura_compra),
exportación 110/111/112 (exportacion_moneda_extranjera: su monto
está en la moneda del documento, no en pesos), rechazados
(rechazado), error_envio y anulado sin nota de crédito acá
(anulado_sin_nota_credito).en_proceso): pendiente, enviando y enviado, sin
veredicto del SII todavía. No se suman; súmalos tú si quieres una
cifra temprana.total_bruto_emitido es la suma de monto_total de todo el conjunto
(la cifra que antes venía en suma_total).| desde | string <date> Inclusivo, igual que en el listado. |
| hasta | string <date> Inclusivo, igual que en el listado. |
| tipo_dte | string Un tipo o CSV, ej. "33,34" |
| estado_local | string Mismos valores que en el listado. |
| incluir_pruebas | boolean Default: false Por defecto NO se devuelven los documentos que emitió Facturador Pulsando con tu RUT al poner en marcha el sistema (set de certificación, prueba inicial y sus notas de crédito; llevan |
| ambiente | string Enum: "certificacion" "produccion" Ambiente de los documentos a mirar, desde el portal. Con API Key se ignora: se ven siempre los del ambiente de la llave ( |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "suma_total": 0,
- "suma_neto": 0,
- "suma_iva": 0,
- "suma_exento": 0,
- "documentos_venta": 0,
- "total_bruto_emitido": 0,
- "notas_credito": {
- "documentos": 0,
- "suma_total": 0
}, - "en_proceso": {
- "documentos": 0,
- "suma_total": 0
}, - "excluidos": {
- "documentos": 0,
- "suma_total": 0,
- "por_motivo": [
- {
- "motivo": "guia_despacho",
- "documentos": 0,
- "suma_total": 0
}
]
}, - "total_documentos": 0,
- "por_tipo": [
- {
- "tipo_dte": 0,
- "count": 0,
- "suma_total": 0
}
], - "por_estado": [
- {
- "estado_local": "string",
- "count": 0,
- "suma_total": 0
}
]
}| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "id": 0,
- "tipo_dte": 0,
- "tipo_nombre": "string",
- "folio": 0,
- "fecha_emision": "2019-08-24",
- "rut_receptor": "string",
- "dv_receptor": "string",
- "razon_receptor": "string",
- "giro_receptor": "string",
- "direccion_receptor": "string",
- "comuna_receptor": "string",
- "ciudad_receptor": "string",
- "email_receptor": "string",
- "monto_neto": 0,
- "monto_iva": 0,
- "monto_exento": 0,
- "monto_total": 0,
- "estado_sii": "string",
- "estado_local": "string",
- "glosa_sii": "string",
- "err_code": "DTE-3-101",
- "detalle_sii": {
- "codigo": "REF-3-751",
- "glosa": "RUT Receptor Diferente en Documento Referenciado",
- "causa": "string",
- "solucion": "string",
- "fuente": "string",
- "raw": null,
- "num_atencion": "927451 ( 2026/08/07 11:28:48)",
- "caratula_enviada": {
- "rut_emisor": "76227474-4",
- "rut_envia": "17451736-3",
- "rut_receptor": "60803000-K",
- "fecha_resol": "2026-05-07",
- "nro_resol": 0,
- "ambiente": "certificacion"
}
}, - "track_id": "string",
- "ambiente": "mock",
- "origen": "api",
- "enviado_at": "2019-08-24T14:15:22Z",
- "respondido_at": "2019-08-24T14:15:22Z",
- "anulado_por": {
- "id": 0,
- "tipo_dte": 0,
- "folio": 0
}, - "notas_credito": [
- {
- "id": 0,
- "tipo_dte": 0,
- "folio": 0,
- "estado_local": "string",
- "monto_total": 0,
- "cod_ref": 0,
- "motivo": "anula"
}
], - "referencia_a": {
- "id": 0,
- "tipo_dte": 0,
- "folio": 0,
- "cod_ref": 0,
- "motivo": "anula"
}, - "items": [
- {
- "nombre": "string",
- "cantidad": 0,
- "precio_unitario": 466.6667,
- "monto_item": 0
}
], - "impuestos": [
- {
- "codigo": 24,
- "nombre": "Licores, piscos, whisky, aguardientes y vinos licorosos o aromatizados",
- "tasa": 31.5,
- "monto": 31500,
- "resta": false
}
], - "monto_imp_adicional": 31500,
- "reclamo": {
- "fecha_reclamo": "2019-08-24",
- "reclamo_at": "2019-08-24T14:15:22Z",
- "rut_usuario": "string",
- "glosa": "Reclamo al contenido del documento",
- "rcv_id": 0
}, - "acuse": {
- "fecha_acuse": "2019-08-24",
- "codigo": "ACD",
- "codigo_glosa": "Otorga recibo de mercaderías o servicios",
- "rcv_id": 0
}, - "respuestas_receptor": [
- {
- "id": 0,
- "tipo": "recepcion_envio",
- "estado_codigo": "string",
- "estado_glosa": "DTE Rechazado",
- "cod_rch_dsc": "string",
- "rut_responde": "77111222-3",
- "rut_firma": "string",
- "recinto": "string",
- "tmst_firma": "string",
- "email_recibido_at": "2019-08-24T14:15:22Z",
- "efecto_legal": false
}
]
}El <DTE> firmado del documento (con su Signature y el TED), no el
sobre EnvioDTE con que se envió al SII. Content-Disposition: attachment; filename="DTE_{tipo}_{folio}.xml".
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "message": "string",
- "codigo": "string"
}Devuelve el PDF binario (application/pdf, no JSON), listo para
imprimir, con el timbre electrónico (TED) impreso como código PDF417.
Formato por defecto (si no envías formato):
Con formato=pos80 cualquier documento sale en papel continuo de 80mm
(§1.1.7 del Manual de Muestras Impresas del SII, "Formato Papel Continuo,
por ejemplo formato POS"). Útil si imprimes todo en la impresora térmica.
También puedes fijarlo una vez por empresa con
PATCH /empresa {"formato_impresion": "pos80"}, y entonces no hace falta
mandar el parámetro en cada llamada. La precedencia es:
formato de la query → preferencia de la empresa → default por tipo.
El formato de impresión no afecta lo que se le envía al SII: al SII viaja el XML, y el PDF se deriva de él. Tampoco cambia el PDF que recibe tu cliente por correo o por el portal del receptor.
El PDF se genera on-demand desde el XML firmado (no se almacena).
Se puede pedir apenas emitido (tras el 201 de POST /dte): la boleta ya
tiene folio y timbre. El estado del SII (aceptado/rechazado) no es
necesario para imprimir. El TED también viaja en el XML (/dte/{id}/xml)
si prefieres renderizar tu propia representación.
| id required | integer |
| formato | string Enum: "carta" "pos80"
|
| copia | string Enum: "cedible" "tributaria"
|
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "message": "string",
- "codigo": "string"
}Devuelve un enlace de acceso directo mediante un token único que el receptor puede abrir sin inicio de sesión ni API Key para ver y descargar el documento (sus metadatos y el PDF). Útil para enviárselo por correo, WhatsApp u otro canal.
url: página web del documento para una persona
(https://www.facturador.pulsandotech.cl/portal/dte/{token}), con el
botón para descargar el PDF. Hasta el 17-sep-2026 apuntaba al JSON de
la API.
pdf_url: descarga directa del PDF.
api_url: los metadatos en JSON (GET /api/portal/dte/{token}), para
integraciones.
El acceso se controla por el token: es opaco y no enumerable (64 caracteres aleatorios) y nunca expone IDs secuenciales de tus documentos. No es un recurso abierto ni indexable.
Vigencia de 6 años (la retención legal del XML); cumplido el plazo, el emisor genera uno nuevo.
Llamadas repetidas sobre el mismo DTE reutilizan el token vigente (no generan uno nuevo cada vez).
Requiere el scope dte:read. Las rutas que abre el receptor están en el
servidor /api/portal (sin API Key).
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "expires_at": "2019-08-24T14:15:22Z"
}Consulta síncrona al SII del estado del documento por su track_id: la
misma del botón «Consultar estado» del panel. Si el SII tiene un veredicto
nuevo, se aplica y se disparan los mismos webhooks que por el camino
automático (dte.aceptado, dte.reparado, dte.rechazado, dte.anulado).
Para qué sirve. Un documento ya aceptado no se vuelve a consultar
solo. Si después el SII lo informa anulado (FAN «Documento Anulado»,
ANC/AND «Nota de Crédito/Débito anula el documento») —por ejemplo porque la
nota de crédito se emitió fuera de esta plataforma—, la única forma de
enterarse es esta consulta: el documento pasa a anulado y sale
dte.anulado.
No reenvía nada ni gasta folio. Un documento sin track_id (nunca salió)
responde 422. Si el SII todavía no tiene veredicto, procesado: false y
el documento queda como estaba.
Enfriamiento: una consulta por documento cada 60 segundos; dentro de la
ventana responde 429 con codigo: consulta_en_enfriamiento,
reintentar_en_segundos y Retry-After, sin consultar al SII.
Requiere el scope dte:create: sale hacia el SII con el certificado de la
empresa, igual que reintentar.
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "estado_local": "anulado",
- "estado_sii": "FAN",
- "glosa": "string",
- "procesado": true,
- "mensaje": "Estado actualizado desde el SII."
}Es la salida de un documento en error_envio (también sirve para uno en
pendiente). Es lo que se hace al recibir el webhook dte.error_envio
una vez corregida la causa. Mismo comportamiento que el botón
«Reintentar» del panel. No reemitas un documento en error_envio: su
folio ya está tomado.
Qué hace depende de si el documento alcanzó a salir, y lo dice accion:
reenviar — no tenía track_id (nunca llegó al SII: SII caído,
timeout, certificado corregido después). Se reencola el envío y
estado_local queda en pendiente.consultar_sobre — ya tenía track_id (el sobre salió y la
plataforma dejó de esperar el veredicto). No se reenvía, porque
declararía dos veces el mismo documento: se vuelve a consultar su
estado al SII, y estado_local sigue siendo el real (normalmente
error_envio) hasta que el SII conteste.consulta_en_curso — hubo una consulta en los últimos 300
segundos. No se encola otra. Trae reintentar_en_segundos y el header
Retry-After.Con consultar_sobre y consulta_en_curso la respuesta trae el
track_id. El resultado llega por webhook o consultando GET /dte/{id}.
No reintenta lo que el SII ya respondió. Un documento aceptado,
aceptado_con_reparos, rechazado, rechazado_sobre, anulado o
todavía enviado/enviando responde 409 con
codigo: "reintento_no_aplica" y la clasificacion que explica por qué:
un rechazo del SII se corrige emitiendo un documento nuevo (el mismo
XML no se reenvía; el folio rechazado no se reutiliza).
Tampoco reintenta un XML que no pasó nuestra validación previa al
envío. Un error_envio cuyo glosa_sii dice «no valida XSD» o «viola
reglas de negocio» nunca llegó al SII, y reenviar el mismo XML firmado
falla igual: responde 409 con clasificacion: "permanente" y
causa: "contenido_invalido" (y GET /dte lo lista con
puede_reintentar: false). Ése es el único error_envio que se resuelve
emitiendo un documento nuevo con los datos corregidos: como el SII
nunca lo recibió, no hay venta declarada dos veces. Un certificado
vencido, la resolución de la carátula o el SII caído siguen siendo
reintentables: se corrige la causa y se reintenta.
Requiere el scope dte:create y la suscripción al día, igual que
emitir: el reenvío sale hacia el SII con el certificado de la empresa.
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "message": "DTE reencolado para envío al SII.",
- "id": 1234,
- "estado_local": "pendiente",
- "clasificacion": "transitorio",
- "accion": "reenviar",
- "track_id": "string",
- "reintentar_en_segundos": 0
}Solo funciona en el ambiente de desarrollo. En certificación y
producción el estado lo determina el SII, y este endpoint responde 403.
La emisión es asíncrona: POST /dte devuelve 201 pendiente y el
estado final llega después, cuando el SII responde. En desarrollo no hay
SII, así que ningún documento se rechaza ni se repara por su cuenta y
nunca ves la rama de error de tu código. Este endpoint la dispara.
El estado no se escribe a mano: pasa por el mismo servicio que usa la
respuesta real del SII, así que produce los mismos efectos que en
producción — webhook firmado con HMAC (dte.aceptado, dte.rechazado o
dte.reparado), notificaciones según tu política y asiento contable.
Esto cubre solo lo que el ambiente no puede producir por sí mismo: la
respuesta del SII. Los errores de integración (payload mal armado, campo
faltante, tipo de dato equivocado) ya salen solos con los mismos 422 que
en producción, porque es exactamente el mismo código de validación.
Requiere el scope dte:read.
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
| estado required | string Enum: "aceptado" "rechazado" "reparado" Estado final a forzar. Se traduce al estado del SII
correspondiente: |
| codigo | string or null <= 20 characters Código de error del SII a simular (ver Errores del SII). Si lo envías y está en el catálogo, la glosa del documento queda con el texto real de esa causa, para que puedas probar tu manejo por código. Opcional. |
{- "estado": "rechazado",
- "codigo": "HED-2-210"
}{- "message": "string",
- "id": 0,
- "estado_local": "string",
- "estado_sii": "RCH",
- "glosa_sii": "string",
- "simulado": true
}Consulta del padrón público del SII (razón social, giros/actividades) para autocompletar y validar el receptor. Requiere el scope dte:read.
Consulta la Situación Tributaria de un contribuyente en el padrón público del SII (datos abiertos: razón social, giros/actividades económicas, cumplimiento). Úsalo para autocompletar y validar el receptor antes de emitir un DTE.
Los datos provienen directamente del SII (no de terceros) y una respuesta
del padrón se cachea 24h. Si el SII no responde (cola virtual /
mantención) o pide captcha, se devuelve 503 o captcha_requerido: true
para que hagas fallback a carga manual. Esas fallas NO se cachean: la
siguiente consulta del mismo RUT vuelve a preguntarle al SII (hasta el
17-sep-2026 un 503 quedaba pegado 24h para ese RUT). Requiere el scope
dte:read.
| rut required | string RUT con o sin puntos y DV, ej. "76354771-K" o "76.354.771-K". |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "registrado": true,
- "razon_social": "string",
- "fecha_inicio": "string",
- "cumple_obligacion": true,
- "captcha_requerido": true,
- "giros": [
- {
- "codigo": "string",
- "glosa": "string",
- "rubro": "string",
- "categoria": "string",
- "fecha_inicio": "string",
- "afecto_iva": true
}
]
}Documentos que otros contribuyentes te emiten (intercambio). Léelos y acéptalos/recházalos comercialmente por API — la API deja de ser "solo emisión". Lectura con recepcion:read; aceptar/rechazar/ingesta con recepcion:write.
Lista los DTE que otros contribuyentes te emitieron (recibidos por
intercambio). Paginado. Requiere el scope recepcion:read.
Fechas: fecha_emision sale como fecha-hora UTC
(2026-09-16T03:00:00.000000Z): es la medianoche de Chile del día de
emisión. El día tributario son los primeros 10 caracteres. Las marcas
de tiempo (email_recibido_at, created_at, …) también van en UTC con
Z, a diferencia de los DTE emitidos, que usan hora de Chile (-03:00).
| pendientes | boolean Solo los sin decisión comercial |
| estado_comercial | integer 0=aceptado, 2=rechazado |
| rut_emisor | string RUT del proveedor, con o sin puntos y con o sin DV: |
| per_page | integer Default: 50 |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{ }Los atributos del registro (emisor, folio, montos, estado comercial,
acuses). El XML del proveedor no viene acá: se descarga con
GET /dte/recibidos/{id}/xml.
Trae cesion: null si el documento no fue cedido; si el SII avisó una
cesión (factoring), el cesionario, su RUT, el monto cedido y el último
vencimiento. A ese cesionario es a quien se le paga.
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "id": 0,
- "tipo_dte": 0,
- "folio": 0,
- "fecha_emision": "2026-09-16T03:00:00.000000Z",
- "rut_emisor": "string",
- "dv_emisor": "string",
- "razon_emisor": "string",
- "monto_total": 0,
- "estado_comercial": 0,
- "email_remitente": "string",
- "email_recibido_at": "2019-08-24T14:15:22Z",
- "cesion": {
- "cesionario": "string",
- "rut_cesionario": "string",
- "monto": 0,
- "vencimiento": "2019-08-24",
- "avisada_at": "2019-08-24T14:15:22Z"
}
}El XML del documento tal como lo firmó el proveedor, con sus líneas de
detalle. Es la única fuente de ese detalle: el RCV del SII (GET /rcv)
sólo entrega totales.
Se devuelve el fragmento <DTE> propio del documento; si el sobre traía
varios documentos y sólo quedó el EnvioDTE completo, se devuelve ese.
La firma del proveedor verifica (digest y SignatureValue): el
<DTE> sale canonicalizado (C14N) tal como estaba dentro del sobre,
con las declaraciones de namespace heredadas escritas en el propio
<DTE>. Hasta el 17-sep-2026 salía con un prefijo default: inventado
y la firma no verificaba; los documentos guardados antes se corrigen al
descargarlos.
Cómo llegar desde el RCV: cada fila de compra de GET /rcv trae
dte_recibido_id. Si no es null, ese es el {id} de esta ruta. Si es
null, el proveedor no mandó el sobre a tu casilla de intercambio (o lo
mandó a otro RUT) y el XML sólo está en el portal del SII.
Charset: application/xml; charset=utf-8 por defecto. Si el XML
declara encoding="ISO-8859-1", se responde en ISO-8859-1: cabecera,
declaración y bytes coinciden. Requiere el scope recepcion:read, el
mismo que el detalle.
| id required | integer El |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "message": "string",
- "codigo": "string"
}Persiste un EnvioDTE que recibiste por fuera del intercambio automático.
Acepta multipart (envioDte), xml_base64 en JSON, o el XML crudo en el
cuerpo. Requiere el scope recepcion:write.
201: el sobre se procesó. dtes_recibidos trae cada documento tuyo
del sobre (también los que ya estaban: reenviar no es error), nuevos
sólo los que se crearon ahora y omitidos los de otros receptores.
Mira estado_recep_dte de cada documento (0 OK, 1 firma/schema,
3 receptor, 4 repetido).422 con codigo: el sobre NO se registró (sobre_invalido: no
cumple el schema; sobre_ilegible; sobre_de_otro_receptor;
sobre_rechazado). Hasta el 17-sep-2026 estos casos respondían 201
con dtes_recibidos: [].| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
| xml_base64 | string |
| email_remitente | string |
| email_message_id | string |
{- "xml_base64": "string",
- "email_remitente": "string",
- "email_message_id": "string"
}{- "estado_envio": 0,
- "glosa_envio": "string",
- "envio_dte_id": "string",
- "nombre_archivo": "string",
- "dtes_recibidos": [
- { }
], - "nuevos": [
- { }
], - "omitidos": 0
}Marca el documento como aceptado y genera el ResultadoDTE firmado
(base64) para el emisor; si tienes casilla configurada, se le envía.
Requiere el scope recepcion:write.
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "message": "string",
- "estado_comercial": 0,
- "resultado_xml_b64": "string",
- "acuse_enviado": true
}Marca el documento como rechazado (requiere motivo) y genera el
ResultadoDTE firmado para el emisor. Requiere el scope recepcion:write.
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
| motivo required | string <= 256 characters |
| cod_rch_dsc | integer Código SII de rechazo (opcional) |
{- "motivo": "string",
- "cod_rch_dsc": 0
}{- "message": "string",
- "estado_comercial": 2,
- "resultado_xml_b64": "string"
}Sincroniza y consulta el Registro de Compras y Ventas que el SII mantiene (para conciliación contable). Scope rcv:read.
Encola la sincronización del Registro de Compras y Ventas del SII
para un periodo tributario. Es asíncrono (202): un periodo puede
traer muchas filas. Consulta el resultado con GET /rcv. Idempotente:
re-sincronizar un periodo no duplica. Requiere el scope rcv:read.
Requiere una API key sk_live_. El RCV son documentos reales del SII y
no tiene contraparte de prueba, asi que una key sk_test_ recibe 409.
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
| periodo required | string Periodo tributario YYYYMM |
| operacion | string Default: "ambas" Enum: "compra" "venta" "ambas" |
{- "periodo": "202607",
- "operacion": "compra"
}{- "message": "string",
- "periodo": "string",
- "operaciones": [
- "string"
]
}El Registro de Compras y Ventas tal como lo tiene el SII.
Requiere una API key sk_live_: son documentos reales y no existe una
version de prueba de este registro. Una key sk_test_ recibe 409. El
motivo no es de permisos — es que actuar sobre estos documentos (aceptar o
reclamar) tiene efecto legal bajo la Ley 19.983 y no se deshace.
Ademas del listado, la respuesta puede traer aviso: el motivo por el cual
no hay documentos que mostrar (por ejemplo, falta cargar el certificado
digital). Es null cuando no hay nada que advertir.
Fechas: en el RCV (como en recibidos y locales) las fechas salen en
UTC con Z. fecha_emision llega como fecha-hora
(2026-07-05T04:00:00.000000Z, la medianoche de Chile de ese día): el
día tributario son los primeros 10 caracteres. Los DTE emitidos
(GET /dte) usan otro formato: fecha_emision como fecha pura y las
marcas de tiempo en hora de Chile (-03:00/-04:00).
| periodo | string YYYYMM | ||||||||||
| operacion | string Enum: "compra" "venta" | ||||||||||
| estado_contable | string Enum: "REGISTRO" "PENDIENTE" "NO_INCLUIR" "RECLAMADO" En qué pestaña del registro del SII está la compra. Sin este filtro vienen todas, que suele ser lo que quieres.
Si llevas tu propio libro de compras, filtra por | ||||||||||
| tipo_dte | integer | ||||||||||
| rut_contraparte | string | ||||||||||
| orden | string Enum: "fecha" "proveedor" "tipo_dte" "folio" "neto" "iva" "total" "plazo" Campo por el que ordenar. Omítelo y manda el orden por defecto, que pone arriba lo que está por vencer — que es lo que hace útil esta pantalla. Un valor no reconocido se ignora (vuelve al defecto).
| ||||||||||
| dir | string Default: "asc" Enum: "asc" "desc" Sentido del | ||||||||||
| solo_reclamadas | boolean Solo los documentos que la contraparte RECLAMO ante el SII. Combinado con El filtro usa | ||||||||||
| solo_por_vencer | boolean Sólo lo que se vence YA: sin reclamo y con 0 a 3 días restantes del plazo de 8 días corridos desde la recepción (Ley 19.983). Es el filtro para actuar sobre las COMPRAS antes de que operen la aceptación tácita. | ||||||||||
| per_page | integer Default: 50 |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "data": [
- {
- "id": 0,
- "periodo": "string",
- "operacion": "COMPRA",
- "estado_contable": "PENDIENTE",
- "tipo_dte": 0,
- "folio": 0,
- "rut_contraparte": "string",
- "razon_contraparte": "string",
- "fecha_emision": "2026-07-05T04:00:00.000000Z",
- "fecha_recepcion": "2019-08-24T14:15:22Z",
- "monto_exento": 0,
- "monto_neto": 0,
- "monto_iva": 0,
- "monto_total": 0,
- "estado_sii": "string",
- "evento_sii": "string",
- "evento_sii_glosa": "string",
- "fecha_reclamo": "2019-08-24",
- "reclamo_at": "2019-08-24T14:15:22Z",
- "reclamo_rut_usuario": "string",
- "reclamo_glosa": "string",
- "reclamo_notificado_at": "2019-08-24T14:15:22Z",
- "acuse_codigo": "ACD",
- "acuse_notificado_at": "2019-08-24T14:15:22Z",
- "aceptacion_tacita_notificada_at": "2019-08-24T14:15:22Z",
- "accion_sii": "ACD",
- "accion_sii_at": "2019-08-24T14:15:22Z",
- "iva_no_recuperable": 0,
- "desc_tipo_transaccion": "string",
- "emisor_agresivo": "string",
- "monto_activo_fijo": 0,
- "monto_iva_activo_fijo": 0,
- "fecha_acuse": "2019-08-24",
- "codigo_sucursal_sii": "string",
- "tipo_doc_ref": 0,
- "folio_doc_ref": "string",
- "codigo_no_recuperable": "string",
- "otros_impuestos_monto": 0,
- "ambiente": "mock",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "dias_para_reclamar": 0,
- "puede_reclamar": true,
- "reclamado": true,
- "dte_recibido_id": 0
}
], - "total": 0,
- "last_page": 0,
- "aviso": {
- "codigo": "simulado",
- "mensaje": "string",
- "accion": "cargar_certificado"
}
}Lo que un ERP necesita para poner un semaforo, sin tener que recorrer y clasificar 330 documentos por su cuenta.
credito_fiscal — el IVA de tus compras: lo que DESCUENTAS en el
F29. No lo confundas con el debito fiscal, que es el IVA de tus
ventas y es lo que PAGAS. El F29 resta uno del otro.por_vencer — facturas a las que les quedan 3 dias o menos de
plazo para reclamar. Pasado el plazo se aceptan solas y se vuelven titulo
ejecutivo (Ley 19.983).aceptadas_por_plazo + pendientes + reclamadas suman el total.
Las reclamadas NO otorgan credito fiscal.El plazo de reclamo (por_vencer) corre desde la RECEPCION del documento,
no desde su emision (Ley 19.983).
Scope rcv:read. Requiere una API key sk_live_: agrega documentos
reales del SII y no existe una version de prueba. Una key sk_test_ recibe
409 (igual que GET /rcv).
| periodo | string YYYYMM (default: mes en curso) |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "periodo": "202607",
- "documentos": 0,
- "credito_fiscal": 0,
- "por_vencer": 0,
- "monto_por_vencer": 0,
- "aceptadas_por_plazo": 0,
- "pendientes": 0,
- "reclamadas": 0,
- "dias_de_plazo": 8,
- "ultima_sincronizacion": {
- "rcv_compras": "2026-09-02 01:00:12",
- "rcv_ventas": "2026-09-01 23:05:44",
- "buzon_correo": "string",
- "rcv_vencido": true
}
}Las cinco acciones del SII y cual de ellas detiene la aceptacion tacita.
Solo lectura (rcv:read): poder LEER que acciones existen no habilita a
ejecutarlas — eso exige rcv:write.
Incluye enlaces_sii, para mandar al contribuyente al portal del SII a ver
el documento. Ojo: el RCV entrega el RESUMEN de cada factura, no el
documento — ni XML ni PDF, ni el detalle de productos. Para las lineas de
la factura hace falta el XML, y ese llega por el intercambio por correo (el
emisor esta obligado a enviarlo) o bajandolo a mano del portal del SII. Y el
SII no permite enlazar a un documento puntual: el enlace va al modulo.
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "acciones": [
- {
- "codigo": "RCD",
- "descripcion": "string",
- "es_reclamo": true
}
], - "dias_de_plazo": 8,
- "advertencia": "string",
}Esta es la unica defensa de tu cliente contra una factura que no corresponde.
Cuando recibes una factura de un proveedor, empieza a correr un plazo de 8 dias corridos desde su recepcion (no desde la emision: el proveedor puede emitir el 1 y el sobre llegar el 18). Si nadie la reclama, opera la aceptacion tacita (Ley 19.983) y la factura se convierte en titulo ejecutivo: el proveedor puede cobrarla judicialmente aunque nunca haya entregado la mercaderia, aunque el monto este malo, aunque sea falsa. No hacer nada tiene consecuencias irreversibles.
No confundir con el acuse comercial de POST /dte/recibidos/{id}/aceptar, que
es un correo al proveedor. Un correo no detiene la aceptacion tacita. Esto si.
Acciones (accion):
| Codigo | Que hace | Detiene la aceptacion tacita |
|---|---|---|
ACD |
Acepta el contenido | No — renuncia al reclamo |
RCD |
Reclama el CONTENIDO (monto/detalle malo, no reconozco la compra) | Si |
RFP |
Reclama por falta PARCIAL de mercaderias | Si |
RFT |
Reclama por falta TOTAL (llego la factura, no la mercaderia) | Si |
ERM |
Otorga recibo de mercaderias | No — deja el documento cedible y cierra el plazo |
Cuidado con ERM: es lo contrario de un reclamo y es irreversible.
Requiere el scope rcv:write (no rcv:read): esto MUTA en el SII.
El {id} es el del registro devuelto por GET /rcv.
Requiere una API key sk_live_. Reclamar tiene efecto legal e
irreversible (Ley 19.983) sobre documentos reales del SII; una key sk_test_
recibe 409 (igual que GET /rcv), para que un flujo "de prueba" no reclame
una factura real creyendola de juguete.
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
| accion required | string Enum: "ACD" "RCD" "ERM" "RFP" "RFT" |
{- "accion": "RCD"
}{- "ok": true,
- "accion": "RCD",
- "descripcion": "string",
- "es_reclamo": true,
- "glosa_sii": "string",
- "dias_de_plazo_restantes": 0
}Historial de eventos del documento tal como lo tiene el SII — no nuestra base. En un juicio ejecutivo lo que vale es su registro: esto es lo que prueba que el reclamo entro dentro de los 8 dias.
Sirve para COMPRAS (lo que te emitieron) y para VENTAS (lo que emitiste): en una venta muestra quién te reclamó, aceptó o dio recibo, y cuándo. Hasta el 17-sep-2026 una venta se consultaba con el RUT del cliente como emisor y volvía vacía.
Scope rcv:write. Requiere una API key sk_live_: es el historial de un
documento real del SII y no existe una version de prueba. Una key sk_test_
recibe 409 (igual que GET /rcv).
En una empresa de desarrollo (ambiente simulado) responde 200 con
eventos: []: nunca se registró nada ante el SII.
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "documento": { },
- "dias_de_plazo_restantes": 0,
- "eventos": [
- {
- "codigo": "string",
- "descripcion": "string",
- "fecha": "string",
- "es_reclamo": true
}
]
}Estado de folios disponibles (CAF) con el scope caf:read, y solicitud de nuevos folios al SII (vía robot/RPA con tu certificado) con el scope caf:write.
Folios disponibles, próximo folio y ambiente por tipo de documento.
Cada tipo trae además uso_del_rango: si el rango en curso ya viene usado ante el
SII y desde qué folio se emite. Sirve para detectar antes de chocar que el mismo CAF
está cargado en dos sistemas a la vez — el caso que termina en
(DTE-3-101) Folio ya fue recibido en el SII. Se recalcula en cada lectura contra el
RCV ya sincronizado; no consulta al SII.
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "data": [
- {
- "tipo_dte": 0,
- "tipo_nombre": "string",
- "proximo_folio": 0,
- "maximo_folio": 0,
- "disponibles": 0,
- "minimo_alerta": 0,
- "estado": "string",
- "en_alerta": true,
- "ambiente": "mock",
- "uso_del_rango": {
- "estado": "sin_choque",
- "motivo": "tipo_no_figura_en_rcv",
- "ultimo_recibido_sii": 0,
- "desde_folio": 0,
- "periodos_revisados": [
- "string"
], - "otro_sistema": true,
- "mensaje": "string"
}
}
]
}Las ultimas ejecuciones del robot que pide folios (CAF) al SII, con lo que se solicito, lo que el SII autorizo y el error si lo hubo.
Existe para que la solicitud de folios no sea una caja negra: el SII puede
autorizar MENOS de lo pedido (acotado: true) segun el comportamiento
tributario del contribuyente, y sin este historial esa diferencia no se puede
explicar ni auditar.
Qué mostrarle a una persona. error y resultado.errores[].mensaje son el
detalle técnico tal como lo registró el robot (pueden traer JSON, trazas y
diálogos del portal del SII que no son la causa). Para una pantalla o un correo
usa mensaje_cliente (o errores_cliente + referencia): la explicación en
español, qué hacer (casi siempre nada, porque se reintenta solo) y el código
de referencia para soporte. error y resultado no cambian.
Scope caf:read.
| limit | integer <= 50 Default: 20 Cuantas ejecuciones traer (tope 50). |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "data": [
- {
- "id": 0,
- "tipo": "descargar_caf",
- "estado": "completado",
- "solicitado": { },
- "resultado": { },
- "error": "string",
- "mensaje_cliente": "Tipo 33: No pudimos completar la solicitud de folios en el SII por un problema técnico de nuestro lado. La volvemos a intentar automáticamente y no tienes que hacer nada.\nCódigo de referencia: 511f445d-b59a-4336-80dd-8664210cdbfd",
- "errores_cliente": [
- {
- "tipo_dte": 0,
- "motivo": "tecnico",
- "mensaje": "string"
}
], - "referencia": "511f445d-b59a-4336-80dd-8664210cdbfd",
- "ejecutado_at": "2019-08-24T14:15:22Z"
}
]
}| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "data": [
- {
- "tipo_dte": 0,
- "tipo_nombre": "string",
- "proximo_folio": 0,
- "maximo_folio": 0,
- "disponibles": 0,
- "minimo_alerta": 0,
- "estado": "string",
- "en_alerta": true,
- "ambiente": "mock",
- "uso_del_rango": {
- "estado": "sin_choque",
- "motivo": "tipo_no_figura_en_rcv",
- "ultimo_recibido_sii": 0,
- "desde_folio": 0,
- "periodos_revisados": [
- "string"
], - "otro_sistema": true,
- "mensaje": "string"
}
}
]
}Solo lectura: los tipos de documento que el SII tiene habilitados para el contribuyente, tal como el robot de folios los fue registrando. No pide ni aloca folios: solo lee la memoria de autorizaciones.
autorizado_max (cupo maximo que el SII deja pedir) puede venir null, y
techo_estado dice POR QUE:
leido: el SII publico el numero y ahi esta.sin_techo_publicado: el SII NO publica techo para ese documento. Solo
lo publica para los que tienen credito fiscal (33, 43, 46, 56, 61); para
boleta, exenta, guia y exportacion no hay tope publicado. Es un hecho del
SII, no una falla de lectura.error: no se pudo leer. techo_motivo lo explica. Si igual hay un
autorizado_max, es el ultimo valor que el SII si nos dijo.null: todavia no se consulto para ese tipo.techo_al es cuando se leyo el techo (distinto de ultima_consulta_at,
que se mueve con cada SOLICITUD de folios) y folios_disponibles_sii son
los folios que el SII cree que el contribuyente tiene sin usar.
Si un tipo entro en backoff por fallos, se expone bloqueado_hasta y
ultimo_error.
Scope caf:read.
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "data": [
- {
- "tipo_dte": 33,
- "tipo_nombre": "Factura electronica",
- "autorizado": true,
- "autorizado_max": 0,
- "techo_estado": "leido",
- "techo_motivo": "string",
- "techo_al": "2019-08-24T14:15:22Z",
- "folios_disponibles_sii": 0,
- "ambiente": "certificacion",
- "ultimo_solicitado": 0,
- "ultimo_otorgado": 0,
- "ultima_consulta_at": "2019-08-24T14:15:22Z",
- "bloqueado_hasta": "2019-08-24T14:15:22Z",
- "ultimo_error": "string"
}
]
}Pide folios (CAF) al SII y los deja cargados y listos para emitir.
El SII no tiene API de folios. No es una limitacion nuestra: no existe. La unica puerta es su portal web, y ahi se entra con el certificado digital (.p12) del contribuyente. Nosotros automatizamos ese tramite con un robot, y te lo damos como un endpoint.
Es el unico punto de toda la integracion donde hay un robot de por medio. Todo lo demas (emitir, consultar estado, RCV, reclamar) va por servicios.
Certificado cargado. Sin el no hay como entrar al portal del SII.
Sin certificado: 422 con codigo: "sin_certificado".
Estudios contables: el certificado en Chile es de una persona (el representante legal), no de la empresa. NO existe un certificado "del estudio" que sirva para toda la cartera: cada empresa necesita el suyo. Cárgalos por empresa antes de integrar.
Que el SII le tenga ese tipo autorizado a ese contribuyente. El SII
autoriza los tipos de documento uno por uno. Si el tuyo no lo tiene,
respondemos 422 con codigo: "tipo_no_solicitable" y te decimos que
el tramite se hace en el portal del SII. No mandamos al robot a pelear
con el portal: cada sesion perdida acerca el bloqueo por "maximo de
sesiones" del SII.
Scope caf:write.
cantidad es opcional, y lo normal es NO mandarla. Si la omites,
decidimos nosotros: tu consumo real, acotado por lo que el SII te
autoriza (a un emisor nuevo el SII suele autorizar entre 1 y 5).
Si la mandas, la respetamos — pero nunca por encima del techo del SII. Pedir 500 cuando el SII autoriza 5 no da 500 folios: da un rechazo y una sesion perdida. La respuesta te dice cuantos se pidieron de verdad.
Los folios son un recurso secuencial y finito del contribuyente: los que no se usan hay que declarárselos al SII. Pedir de mas no desperdicia CPU, le quema algo suyo.
Lo define tu API Key: sk_test_… baja folios de certificacion (maullin) y
sk_live_… de produccion (palena). Nunca un default global — mezclar
ambientes hace que el SII rechace el DTE con CAF-3-516.
Con una clave de organizacion, elige la empresa con X-Empresa-RUT. Los
folios son del contribuyente, no de quien lo administra.
Pedir folios aloca un rango real e irreversible en el SII, asi que este endpoint se protege solo. No necesitas mandar ninguna cabecera:
429 con
codigo: "solicitud_en_curso" y Retry-After. No abrimos una segunda
sesion en el SII. Espera lo que dice Retry-After (la solicitud en
curso puede tardar minutos) y consulta GET /caf/status.201, con
idempotente: true) en vez de pedir otro rango. Pasados 2 minutos, sin
Idempotency-Key, un nuevo POST es un pedido nuevo (pide otro rango).Idempotency-Key la proteccion no vence: la misma
clave devuelve siempre la misma solicitud (201 con idempotente: true
si termino con folios; 429/409 si sigue en curso o verificandose). Si
termino sin folios (fallida u omitida), la misma clave se puede usar
para intentar de nuevo. Una clave reusada con otro tipo, cantidad o
ambiente responde 422 idempotency_key_reutilizada. Recomendado:
una clave estable por intencion de pedir folios.409 con codigo: "folios_sin_usar_en_el_sii". Mientras
queden folios sin emitir el SII no entrega nuevos: hay que emitirlos
o anularlos en su portal.Sincrono (sin Prefer): la respuesta llega cuando el robot termino en
el portal del SII. Lo normal es 1 a 3 minutos; el robot tiene hasta
300 s y la plataforma sostiene la peticion hasta 630 s. Configura tu
cliente HTTP con un timeout de al menos 600 s. Si tu infraestructura no
aguanta eso, usa el modo asincrono.
Prefer: respond-async)Con la cabecera Prefer: respond-async validamos en la misma peticion todo
lo que no toca el SII (422, 409, 429) y respondemos 202 con
solicitud_id, estado: "en_cola" y la cabecera Location
(/caf/solicitudes/{id}). El tramite lo hace un proceso en segundo plano:
GET /caf/solicitudes/{id} (respeta Retry-After) hasta que
estado sea completado, fallido u omitido. Completada trae las
mismas claves que el 201 (desde, hasta, caf_id, …).folios.recibidos y
folios.solicitud_fallida.202
devuelve esa misma (no se encola otra).Sin la cabecera, el comportamiento es el de siempre (201 sincrono).
504 resultado_inciertoSi la llamada al robot se corta sin respuesta, no sabemos si el SII
alcanzo a timbrar. Respondemos 504 con codigo: "resultado_incierto" y
solicitud_id. No reintentes pidiendo otro rango: verificamos en el
SII (a partir de verificar_desde, ~10 min despues del corte) y, si el SII
timbro, rescatamos ese CAF y queda cargado. Mientras tanto, cualquier
pedido del mismo tipo y ambiente responde 409
verificando_solicitud_anterior con Retry-After. El desenlace queda en
GET /caf/solicitudes/{solicitud_id} (completado con
codigo: "rescatado_tras_corte", o fallido con
codigo: "sin_timbraje_en_el_sii", que significa que puedes volver a pedir)
y en los webhooks de folios.
Con Idempotency-Key: repite el POST con la misma clave. Sin clave:
consulta GET /caf/status o GET /caf/actividad antes de volver a pedir.
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
| Prefer | string Example: respond-async
|
| Idempotency-Key | string <= 255 characters Identifica UNA intencion de pedir folios (hasta 255 caracteres). La misma clave devuelve la misma solicitud, sin plazo de vencimiento. |
| tipo_dte required | integer Enum: 33 34 39 41 46 52 56 61 110 111 112 Tipo de documento para el que se solicitan folios. |
| cantidad | integer [ 1 .. 500 ] Default: 100 Cantidad de folios a solicitar. |
| ambiente | string Enum: "certificacion" "produccion" Para el portal. Con API Key se ignora: los folios se piden en el ambiente de la llave ( |
{- "tipo_dte": 39
}{- "tipo_dte": 0,
- "tipo_nombre": "string",
- "desde": 0,
- "hasta": 0,
- "total_folios": 0,
- "fecha_autorizacion": "string",
- "caf_id": 0,
- "uso_del_rango": {
- "estado": "sin_choque",
- "motivo": "tipo_no_figura_en_rcv",
- "ultimo_recibido_sii": 0,
- "desde_folio": 0,
- "periodos_revisados": [
- "string"
], - "otro_sistema": true,
- "mensaje": "string"
}, - "message": "string",
- "idempotente": true,
- "solicitud_id": "696a0b13-577b-49ee-8881-cabf30a611ca"
}Solicita CAF de varios tipos de documento en un solo ingreso al
SII (una sola sesión del robot/RPA), usando el certificado digital
(.p12) de tu empresa. Por defecto solicita los tipos habilitados de tu
empresa; puedes acotarlos con tipos.
El ambiente lo define tu API Key (sk_test_…→certificación /
sk_live_…→producción); opcionalmente puedes forzarlo por documento con
el campo ambiente del body (por ejemplo para bajar folios de producción
sin cambiar el ambiente por defecto). Nunca se usa un default global.
Requiere el scope caf:write. Sin certificado cargado responde 422.
La respuesta lista los CAF cargados, los errores por tipo (carga
parcial: algunos tipos pueden cargarse aunque otros fallen) y los
omitidos: tipos que no se le pidieron al SII a proposito —porque ya
habia una solicitud de ese tipo en curso, porque se acababa de aprovisionar,
o porque el SII declara folios de ese tipo sin usar—. Un omitido no es
un error: nada fallo, no se pidio.
Duracion: una sola sesion para todos los tipos; el robot tiene hasta
120 + 120 x tipos segundos (tope 540). Pon un timeout de cliente de al
menos 600 s. Este endpoint es solo sincrono.
Si el robot no responde, 504 con codigo: "resultado_incierto": igual
que en POST /caf/solicitar, no se sabe si el SII timbro, se verifica sola,
y mientras tanto esos tipos aparecen en omitidos con
motivo: "verificando_solicitud_anterior".
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
| cantidad | integer [ 1 .. 500 ] Default: 1 Folios a solicitar por cada tipo. |
| tipos | Array of integers Items Enum: 33 34 39 41 46 52 56 61 Tipos de documento a solicitar. Omitir = los tipos habilitados de tu empresa (o boleta 39 si no hay configuración). |
| ambiente | string Enum: "certificacion" "produccion" Override opcional del ambiente por documento. Si se omite, manda el
ambiente de la API Key ( |
{ }{- "message": "string",
- "cargados": [
- {
- "tipo_dte": 0,
- "tipo_nombre": "string",
- "desde": 0,
- "hasta": 0,
- "total_folios": 0,
- "fecha_autorizacion": "string",
- "caf_id": 0,
- "uso_del_rango": {
- "estado": "sin_choque",
- "motivo": "tipo_no_figura_en_rcv",
- "ultimo_recibido_sii": 0,
- "desde_folio": 0,
- "periodos_revisados": [
- "string"
], - "otro_sistema": true,
- "mensaje": "string"
}
}
], - "errores": [
- {
- "tipo_dte": 0,
- "mensaje": "string"
}
], - "omitidos": [
- {
- "tipo_dte": 0,
- "motivo": "precondiciones",
- "mensaje": "string"
}
]
}El estado de UNA solicitud de folios: la del 202 de Prefer: respond-async,
la del 504 resultado_incierto, o la que identifica tu Idempotency-Key
(todas traen solicitud_id; el 201 sincrono tambien).
| estado | Significa |
|---|---|
en_cola |
Aceptada, esperando turno (el certificado abre una sesion a la vez en el SII). |
procesando |
El robot esta en el portal del SII. |
incierto |
El robot no respondio; estamos verificando en el SII si timbro (verificacion). No pidas otro rango. |
completado |
Folios cargados. Trae las mismas claves que el 201 (desde, hasta, total_folios, fecha_autorizacion, caf_id). codigo: rescatado_tras_corte si se rescato tras un corte. |
omitido |
No se le pidio al SII a proposito (codigo: precondiciones, solicitud_en_curso, folios_sin_usar_en_el_sii, tope_diario_solicitudes, verificando_solicitud_anterior). |
fallido |
No se cargaron folios (codigo: rpa_no_disponible, rpa_error, sii_maximo_de_sesiones, caf_invalido, sin_timbraje_en_el_sii, timbraje_sin_recuperar, expirada, no_procesada, plan_sin_folios, verificacion_vencida, cola_no_disponible). |
Mientras la solicitud este abierta la respuesta trae Retry-After.
Scope caf:read.
| solicitud_id required | string <uuid> |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "solicitud_id": "696a0b13-577b-49ee-8881-cabf30a611ca",
- "estado": "en_cola",
- "tipo_dte": 0,
- "tipo_nombre": "string",
- "ambiente": "certificacion",
- "cantidad": 0,
- "modo": "sincrono",
- "codigo": "string",
- "mensaje": "string",
- "creada_at": "2019-08-24T14:15:22Z",
- "iniciada_at": "2019-08-24T14:15:22Z",
- "terminada_at": "2019-08-24T14:15:22Z",
- "verificacion": {
- "estado": "pendiente",
- "verificar_desde": "2019-08-24T14:15:22Z",
- "vence_at": "2019-08-24T14:15:22Z"
}, - "message": "string",
- "desde": 0,
- "hasta": 0,
- "total_folios": 0,
- "fecha_autorizacion": "string",
- "caf_id": 0
}Una fila por día o mes. documentos cuenta TODO lo emitido en el período.
suma_total son VENTAS VÁLIDAS, no la suma de todo lo emitido (desde el
17-sep-2026; antes sumaba todo, incluso notas de crédito en positivo y
rechazados):
suma_total = Σ (33, 34, 39, 41, 43, 56 válidos) − Σ (61 válidas)
estado_local aceptado o aceptado_con_reparos, o
anulado por una nota de crédito emitida acá (el original suma y la
nota resta: neto 0, sin restar dos veces).suma_neto, suma_iva y suma_exento siguen la misma regla.excluidos.por_motivo): guías de despacho 52
(guia_despacho), facturas de compra 46 (factura_compra),
exportación 110/111/112 (exportacion_moneda_extranjera: su monto
está en la moneda del documento, no en pesos), rechazados
(rechazado), error_envio y anulado sin nota de crédito acá
(anulado_sin_nota_credito).en_proceso): pendiente, enviando y enviado, sin
veredicto del SII todavía. No se suman; súmalos tú si quieres una
cifra temprana.total_bruto_emitido es la suma de monto_total de todo el conjunto
(la cifra que antes venía en suma_total).| group_by | string Default: "mes" Enum: "dia" "mes" |
| desde | string <date> |
| hasta | string <date> |
| q | string <= 200 characters Búsqueda libre por razón social o RUT del receptor (mismos filtros que |
| rut_receptor | string <= 20 characters |
| tipo_dte | string Un tipo o CSV, ej. "33,34" |
| grupo | string Enum: "facturas" "boletas" "todos" |
| estado_local | string <= 30 characters Un estado o CSV (ver |
| estado_sii | string <= 60 characters Un estado SII o CSV |
| monto_min | integer >= 0 |
| monto_max | integer >= 0 |
| incluir_pruebas | boolean Default: false Por defecto NO se devuelven los documentos que emitió Facturador Pulsando con tu RUT al poner en marcha el sistema (set de certificación, prueba inicial y sus notas de crédito; llevan |
| ambiente | string Enum: "certificacion" "produccion" Ambiente de los documentos a mirar, desde el portal. Con API Key se ignora: se ven siempre los del ambiente de la llave ( |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "group_by": "string",
- "serie": [
- {
- "suma_total": 0,
- "suma_neto": 0,
- "suma_iva": 0,
- "suma_exento": 0,
- "documentos_venta": 0,
- "total_bruto_emitido": 0,
- "notas_credito": {
- "documentos": 0,
- "suma_total": 0
}, - "en_proceso": {
- "documentos": 0,
- "suma_total": 0
}, - "excluidos": {
- "documentos": 0,
- "suma_total": 0,
- "por_motivo": [
- {
- "motivo": "guia_despacho",
- "documentos": 0,
- "suma_total": 0
}
]
}, - "periodo": "2026-06",
- "documentos": 0
}
]
}Receptores ordenados por suma_total descendente. suma_total son las
VENTAS VÁLIDAS a ese receptor, con la misma fórmula que GET /dte/resumen
(notas de crédito restan; guías 52, compras 46, exportación, rechazados,
error_envio y en proceso no suman). documentos cuenta todo lo emitido
a ese receptor y total_bruto_emitido suma su monto_total sin filtrar.
Un receptor sólo con documentos excluidos aparece con suma_total: 0.
| limit | integer [ 1 .. 100 ] Default: 10 |
| desde | string <date> |
| hasta | string <date> |
| q | string <= 200 characters Búsqueda libre por razón social o RUT del receptor (mismos filtros que |
| rut_receptor | string <= 20 characters |
| tipo_dte | string Un tipo o CSV, ej. "33,34" |
| grupo | string Enum: "facturas" "boletas" "todos" |
| estado_local | string <= 30 characters Un estado o CSV (ver |
| estado_sii | string <= 60 characters Un estado SII o CSV |
| monto_min | integer >= 0 |
| monto_max | integer >= 0 |
| incluir_pruebas | boolean Default: false Por defecto NO se devuelven los documentos que emitió Facturador Pulsando con tu RUT al poner en marcha el sistema (set de certificación, prueba inicial y sus notas de crédito; llevan |
| ambiente | string Enum: "certificacion" "produccion" Ambiente de los documentos a mirar, desde el portal. Con API Key se ignora: se ven siempre los del ambiente de la llave ( |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "data": [
- {
- "rut_receptor": "string",
- "razon_receptor": "string",
- "documentos": 0,
- "suma_total": 0,
- "documentos_venta": 0,
- "total_bruto_emitido": 0
}
]
}Acceso por token para que el receptor consulte y descargue el DTE, sin inicio de sesión ni API Key. El token se obtiene con POST /dte/{id}/portal-link.
Acceso por token (sin inicio de sesión ni API Key) que abre el
receptor con el token generado por POST /dte/{id}/portal-link. El token
es opaco y no enumerable, y su vigencia es de 6 años (la retención legal
del XML). Ruta real: GET /api/portal/dte/{token}.
| token required | string Token opaco de 64 caracteres |
{- "folio": 0,
- "tipo_dte": 0,
- "tipo_nombre": "string",
- "fecha_emision": "2019-08-24",
- "razon_emisor": "string",
- "rut_emisor": "78211386-0",
- "razon_receptor": "string",
- "rut_receptor": "12345678-5",
- "monto_total": 0,
- "estado_sii": "string",
}Devuelve el PDF binario del documento (ticket 80mm para boletas,
carta para el resto). Acceso por token (sin inicio de sesión ni API Key)
con el token de POST /dte/{id}/portal-link; vigencia de 6 años (la
retención legal del XML). Ruta real: GET /api/portal/dte/{token}/pdf.
| token required | string |
Qué te cobramos por usar el Facturador Pulsando y las facturas que te emitimos por eso — el gasto que este servicio representa para tu empresa. Sólo lectura, con el scope dte:read. Darte de baja NO se puede hacer por esta API ni por el MCP: se hace en el portal, con la cuenta del administrador de la empresa. La razón es que una clave sk_live_ es una credencial de máquina, puede vivir en el servidor de un tercero y no distingue quién la está usando.
Qué te estamos cobrando por usar el servicio, y qué implicaría darte de baja.
El bloque baja es informativo: dice hasta cuándo conservarías acceso, qué
se apagaría y qué conservarías, más donde_darse_de_baja con la dirección
del portal.
La baja NO se puede ejecutar por esta API ni por el MCP. No es un
endpoint que falte: esta API se autentica con una clave de máquina
(sk_live_), que puede vivir en el servidor de un tercero, y no distingue
quién de tu empresa la está usando. Dar de baja el servicio es una decisión
del administrador y se hace desde el portal, con su cuenta.
Empresas de la cartera de un estudio contable u holding. Si tu empresa
está en la cartera de una organización, la suscripción no es tuya: la
administra y la paga esa organización. En ese caso estado, plan, ciclo,
monto y periodo_fin son los de la suscripción de la organización —el
monto es el de toda su cartera, no sólo el de tu empresa— y quien_paga
lo dice con tipo: organizacion y su razón social. De la organización no
sale nada más: ni sus otras empresas ni sus datos de pago.
Requiere scope dte:read.
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "data": {
- "estado": "activa",
- "plan": "Empresa",
- "ciclo": "mensual",
- "monto": 71281,
- "periodo_fin": "2026-09-30",
- "cancelada_at": null,
- "quien_paga": {
- "tipo": "empresa",
- "razon_social": "COMERCIAL EJEMPLO SPA",
- "detalle": "La suscripción es de tu empresa y la paga tu empresa."
}, - "baja": {
- "puede_darse_de_baja": true,
- "bloqueo": null,
- "acceso_hasta": "2026-09-30",
- "corta_de_inmediato": false,
- "se_apaga": [
- "Emitir facturas, boletas, notas de crédito y guías de despacho.",
- "Solicitar folios al SII."
], - "se_conserva": [
- "Descargar los documentos que ya emitiste, en PDF y XML."
],
}
}
}Lo que le pagaste al Facturador Pulsando y el documento tributario que te emitimos por cada pago — o sea, el gasto que este servicio representa para tu empresa. Sirve para incorporarlo a tu libro de compras junto con los DTE de tus otros proveedores.
pdf_url es un enlace público y sin login al PDF, con la misma vigencia que
el XML (6 años). Cuando todavía no hay documento emitido, dte_motivo
explica por qué (por ejemplo, que faltan datos de tu empresa).
Este listado sigue disponible aunque la suscripción esté morosa o dada de baja: son documentos de lo que ya pagaste.
Requiere scope dte:read.
| page | integer >= 1 |
| per_page | integer [ 1 .. 200 ] Default: 50 |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "data": [
- {
- "id": 0,
- "fecha": "2019-08-24T14:15:22Z",
- "concepto": "suscripcion",
- "plan": "string",
- "ciclo": "string",
- "monto": 0,
- "neto": 0,
- "iva": 0,
- "estado_pago": "string",
- "dte_estado": "string",
- "dte_motivo": "string",
- "tipo_dte": 0,
- "folio": 0,
- "emitido_at": "2019-08-24T14:15:22Z",
}
], - "meta": {
- "current_page": 0,
- "last_page": 0,
- "per_page": 0,
- "total": 0
}
}Registro y gestión de webhooks salientes (requiere el scope webhook:manage). También gestionables desde el portal. La plataforma envía un POST firmado (HMAC-SHA256) a tu endpoint cuando el SII responde.
Requisitos de tu endpoint. Tiene que ser https, con un dominio que resuelva a una IP pública y un certificado TLS emitido por una CA pública. Un certificado autofirmado supera el registro pero falla en cada entrega con cURL error 60: SSL certificate problem — lo vas a ver en GET /webhooks/{id}/deliveries. Para probar desde tu máquina usa un túnel (Cloudflare Tunnel, ngrok): ya entregan https con certificado válido.
Si el dominio todavía no resuelve el registro se rechaza pidiéndote que reintentes: es transitorio, no hace falta cambiar la URL.
Entrega y reintentos. Cada evento tiene un id y un created_at que no cambian entre reintentos ni entre endpoints: deduplica por id. El header X-Webhook-Delivery, en cambio, identifica al intento y cambia en cada uno. Cada endpoint suscrito recibe su propia entrega, independiente de las demás.
Se reintenta ante un error de conexión, un timeout de 10 segundos o una respuesta 5xx, 408, 425 o 429: tres intentos como máximo, uno inmediato, otro a los 60 segundos y un último 5 minutos después.
No se reintenta ante una respuesta 3xx (las redirecciones no se siguen) ni ante el resto de los 4xx (por ejemplo, 401 por firma inválida o 404): el intento queda registrado en GET /webhooks/{id}/deliveries y no llega de nuevo. Tampoco se reintenta una URL que la plataforma bloquea por seguridad.
Qué responder. Responde 2xx apenas verifiques la firma y guardes el evento, y procésalo después: el cuerpo es una señal, y el estado de un documento lo dice GET /dte/{id}. Responde 5xx sólo si no pudiste guardar el evento, para que vuelva a llegar. Y deduplica por id: un mismo evento puede llegarte más de una vez.
El orden de llegada no está garantizado. Cada evento y cada endpoint se entregan por separado, y un reintento llega minutos después: un dte.aceptado puede llegarte antes que su dte.enviado. Decide con GET /dte/{id}, nunca por el orden en que llegan.
Firma con marca de tiempo (anti-replay). Además de X-Webhook-Signature, cada entrega trae X-Webhook-Timestamp (segundos Unix) y X-Webhook-Signature-V2: t=<timestamp>,v1=<hex>, donde v1 es HMAC-SHA256 con tu secret sobre <timestamp>.<cuerpo crudo> (el timestamp, un punto y el cuerpo). Verifica la V2 y rechaza un t con más de 5 minutos de diferencia con tu reloj: así un cuerpo capturado no sirve para reenviártelo después. La firma original sigue llegando igual.
Endpoints que fallan. GET /webhooks informa fallas_consecutivas (eventos seguidos que no se pudieron entregar) y fallando_desde. Al quinto evento seguido sin entregar avisamos por correo a los usuarios de la empresa, una vez por racha. El endpoint no se desactiva solo: la primera entrega buena reinicia la racha. Lo que no llegó se recupera con POST /webhooks/{id}/deliveries/{delivery}/reenviar, con el mismo id de evento.
Llaves de prueba en producción. Si la empresa está en producción, una llave sk_test_ puede consultar sus webhooks, pero no crearlos, modificarlos, borrarlos, probarlos, reenviar eventos ni rotar el secreto: responde 403 con codigo: webhook_requiere_llave_live. Esos endpoints reciben eventos de documentos con validez tributaria.
Historial. Se conservan 90 días de entregas. Borrar un endpoint borra su historial; para dejar de recibir sin perderlo, usa PATCH con activo: false.
A dónde se conecta. La plataforma resuelve tu dominio, comprueba que TODAS sus IP sean públicas y conecta a esas mismas IP. El puerto tiene que ser el 443 o uno sobre 1024 que no sea de un servicio interno conocido (por ejemplo 3306, 5432 o 6379).
Lista los endpoints de webhook registrados por tu empresa. También se pueden gestionar desde el portal (Configuración → Webhooks).
Requiere una API Key con el scope webhook:manage.
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "data": [
- {
- "id": 0,
- "eventos": [
- "string"
], - "descripcion": "string",
- "activo": true,
- "fallas_consecutivas": 0,
- "fallando_desde": "2019-08-24T14:15:22Z",
- "deliveries_count": 0,
- "exitosos_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Registra un endpoint al que enviaremos un POST firmado cuando ocurran
los eventos suscritos. El secret se devuelve una sola vez en esta
respuesta — guárdalo para verificar la firma X-Webhook-Signature.
La url debe ser https, no puede apuntar a hosts internos ni a
direcciones privadas o de uso especial (todas las IP a las que resuelva
tienen que ser públicas) y el puerto tiene que ser el 443 o uno sobre
1024 que no sea de un servicio interno. Máximo 10 endpoints por empresa.
Requiere una API Key con el scope webhook:manage. Si la empresa está en
producción, la llave tiene que ser sk_live_ (ver 403).
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
| url required | string <uri> URL https a la que enviaremos los POST. No puede apuntar a hosts internos ni a direcciones privadas/reservadas. |
| eventos | Array of strings Items Enum: "dte.aceptado" "dte.rechazado" "dte.reparado" "dte.anulado" "dte.enviado" "dte.error_envio" "dte.reclamado" "dte.acuse_receptor" "dte.aceptado_tacitamente" "dte.respuesta_receptor" "factura_compra.recibida" "folios.por_agotarse" "folios.recibidos" "folios.solicitud_fallida" Eventos a los que suscribirse. Omitirlo, |
| descripcion | string or null <= 200 characters |
{- "eventos": [
- "dte.aceptado",
- "dte.rechazado"
], - "descripcion": "Notificaciones de estado SII"
}{- "message": "string",
- "data": {
- "id": 0,
- "eventos": [
- "string"
], - "descripcion": "string",
- "activo": true,
- "fallas_consecutivas": 0,
- "fallando_desde": "2019-08-24T14:15:22Z",
- "deliveries_count": 0,
- "exitosos_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "secret": "a1b2c3…64hex"
}
}Actualiza la url, los eventos, la descripcion o el estado activo.
Requiere una API Key con el scope webhook:manage.
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
| url required | string <uri> URL https a la que enviaremos los POST. No puede apuntar a hosts internos ni a direcciones privadas/reservadas. |
| eventos | Array of strings Items Enum: "dte.aceptado" "dte.rechazado" "dte.reparado" "dte.anulado" "dte.enviado" "dte.error_envio" "dte.reclamado" "dte.acuse_receptor" "dte.aceptado_tacitamente" "dte.respuesta_receptor" "factura_compra.recibida" "folios.por_agotarse" "folios.recibidos" "folios.solicitud_fallida" Eventos a los que suscribirse. Omitirlo, |
| descripcion | string or null <= 200 characters |
{- "eventos": [
- "dte.aceptado"
], - "descripcion": "string"
}{- "message": "string",
- "codigo": "string"
}Elimina el endpoint y todo su historial de entregas, sin vuelta atrás.
Para dejar de recibir eventos sin perder el historial, usa PATCH con
activo: false.
Requiere una API Key con el scope webhook:manage.
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "message": "string",
- "codigo": "string"
}Envía un evento dte.aceptado de prueba sólo a este endpoint, para
verificar que recibe y valida la firma. Llega con data.test = true y
data.dte_id = 0: tu receptor debe responder 2xx sin tocar ningún
documento. Si responde 2xx, la respuesta es 200 con el http_status
que devolvió. Si no, es 502 con error y http_status, que viene en
null cuando no hubo respuesta: error de conexión, timeout o URL
bloqueada por seguridad. Requiere el scope webhook:manage.
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "message": "Evento de prueba enviado.",
- "http_status": 200
}Últimas 50 entregas del endpoint, de la más nueva a la más vieja. Cada
intento es una fila, con el evento_id del evento, el cuerpo enviado
(payload) y lo que respondió tu endpoint. Los que no se reintentan
—3xx y los 4xx distintos de 408, 425 y 429— quedan registrados
sólo acá. Las entregas de POST /webhooks/{id}/test vienen con
es_prueba: true. Se conservan 90 días.
Requiere el scope webhook:manage.
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "data": [
- {
- "id": 0,
- "evento": "dte.aceptado",
- "evento_id": "wh_a1b2c3d4e5f6a7b8",
- "es_prueba": true,
- "intento": 1,
- "http_status": 0,
- "exitoso": true,
- "respuesta": "string",
- "payload": {
- "id": "wh_a1b2c3d4e5f6a7b8",
- "event": "dte.aceptado",
- "created_at": "2019-08-24T14:15:22Z",
- "livemode": false,
- "ambiente": "mock",
- "data": {
- "dte_id": 0,
- "test": true,
- "error": "string",
- "fallo_at": "2019-08-24T14:15:22Z",
- "tipo_dte": 0,
- "folio": 0,
- "estado_sii": "string",
- "glosa_sii": "string",
- "monto_total": 0,
- "rut_receptor": "string",
- "rut_receptor_completo": "66666666-6",
- "dv_receptor": "6",
- "track_id": "string",
- "respondido_at": "2019-08-24T14:15:22Z",
- "razon_receptor": "string",
- "fecha_reclamo": "2019-08-24",
- "reclamo_at": "2019-08-24T14:15:22Z",
- "rut_usuario": "string",
- "glosa": "string",
- "version": 1,
- "periodo": "202609",
- "rut_proveedor": "76123456-K",
- "rut_proveedor_completo": "76123456-K",
- "dv_proveedor": "K",
- "razon_proveedor": "string",
- "fecha_emision": "2019-08-24",
- "monto_exento": 0,
- "monto_neto": 0,
- "monto_iva": 0,
- "tipo_nombre": "string",
- "disponibles": 0,
- "dias_restantes": 0,
- "fecha_agotamiento": "2019-08-24",
- "cantidad_sugerida": 0,
- "solicitud_id": "696a0b13-577b-49ee-8881-cabf30a611ca",
- "ambiente": "certificacion",
- "cantidad": 0,
- "desde": 0,
- "hasta": 0,
- "total_folios": 0,
- "caf_id": 0,
- "estado": "fallido",
- "mensaje": "string",
- "codigo": "DTE-3-101",
- "causa": "string",
- "que_hacer": "Este folio ya lo recibió el SII desde otro sistema…",
- "codigo_glosa": "string",
- "fecha_acuse": "2019-08-24",
- "plazo_desde": "2019-08-24",
- "plazo_vencio_el": "2019-08-24",
- "leyenda_sii": "string",
- "respuesta": {
- "id": 0,
- "tipo": "recepcion_envio",
- "estado_codigo": "string",
- "estado_glosa": "DTE Rechazado",
- "cod_rch_dsc": "string",
- "rut_responde": "77111222-3",
- "rut_firma": "string",
- "recinto": "string",
- "tmst_firma": "string",
- "email_recibido_at": "2019-08-24T14:15:22Z",
- "efecto_legal": false
}, - "efecto_legal": false
}
}, - "enviado_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z"
}
]
}Vuelve a mandar a este endpoint el mismo evento de esa entrega: el mismo
cuerpo y el mismo id, así que tu receptor lo deduplica si ya lo tenía.
Sirve para recuperar lo que no llegó mientras tu servidor estuvo caído.
Es síncrono y de un intento, y queda como una fila nueva en el historial.
Responde igual que POST /webhooks/{id}/test: 200 si tu endpoint
respondió 2xx, 502 si no. Requiere el scope webhook:manage (y
sk_live_ si la empresa está en producción).
| id required | integer |
| delivery required | integer
|
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "message": "Evento reenviado.",
- "http_status": 200,
- "evento_id": "wh_a1b2c3d4e5f6a7b8"
}Genera un secret nuevo y lo devuelve una sola vez. El anterior deja de
valer en el acto: la próxima entrega ya va firmada con el nuevo, así que
actualiza tu receptor antes (o acepta los dos secretos por un rato). El
historial de entregas no se pierde. Requiere el scope webhook:manage (y
sk_live_ si la empresa está en producción).
| id required | integer |
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "message": "string",
- "data": {
- "id": 0,
- "eventos": [
- "string"
], - "descripcion": "string",
- "activo": true,
- "fallas_consecutivas": 0,
- "fallando_desde": "2019-08-24T14:15:22Z",
- "deliveries_count": 0,
- "exitosos_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "secret": "a1b2c3…64hex"
}
}Lista los eventos a los que un webhook puede suscribirse.
| X-Empresa-RUT | string Example: 76354771-K RUT de la empresa emisora. Se acepta en TODOS los endpoints de este canal.
Formato libre: Este header selecciona la empresa; no la inventa. Los datos del emisor (RUT, razón social, giro, actividad económica) se leen siempre del registro de esa empresa, nunca del cuerpo de la petición. |
{- "data": [
- {
- "evento": "dte.aceptado",
- "descripcion": "string"
}
]
}