Autenticación
Cada empresa tiene sus claves, que crea el dueño del negocio desde el portal y se muestran una sola vez. Van en el header Authorization:
Authorization: Bearer fl_live_su_clave- La clave es secreta y de servidor: nunca la pongas en un navegador, una app móvil o un repositorio. La API no sirve CORS a propósito.
- Si se filtra, revócala desde tu panel: deja de servir al instante.
GET /pingverifica la clave y responde con la empresa y el ambiente — el primer request de toda integración.- Rotación sin downtime: tu empresa admite hasta 5 claves activas a la vez. Para rotar sin cortar la emisión: crea la clave nueva, despliégala en tu sistema, verifica que emite, y recién entonces revoca la anterior. Las claves se administran desde Integraciones → API.
Ambientes
El prefijo de la clave declara su ambiente: fl_live_ emite documentos reales y solo opera con la empresa en producción; fl_test_ opera en el ambiente de pruebas de tu misma empresa, esté o no en producción: el motor real —folio, timbre, firma, PDF, webhooks— contra un SII simulado, sin validez tributaria. Una clave de prueba filtrada jamás emite un documento real, y cada clave ve únicamente los documentos de su ambiente. Las dos se crean en Integraciones → API; en el portal, Configuración → Ambiente te lleva al de pruebas para ver lo que emitiste ahí.
Modo prueba
Para ensayar tu integración —incluso contra tu clave de producción— sin quemar folios reales, usa los endpoints de validación: POST /eventos/validar y POST /documentos/validar. Aceptan el mismo cuerpo que sus gemelos de emisión, corren toda la validación y el cálculo de totales —incluida toda la revisión de una nota: el total exacto al anular, que el original se pueda anular o corregir y que le quede crédito—, y te devuelven qué documento se emitiría — tipo, decisión, montos y receptor — sin tomar folio, sin firmar y sin tocar el SII. Cero efectos secundarios, no cuentan contra tu límite de emisión.
curl -X POST https://app.facturalibre.cl/api/v1/eventos/validar \
-H "Authorization: Bearer fl_live_su_clave" \
-H "Content-Type: application/json" \
-d '{ "tipo": "venta", "origen": "mi-sistema", "referencia": "prueba-1",
"items": [{ "nombre": "Plan", "cantidad": 1, "precioUnitario": 12990 }] }'
# → 200 OK, SIN tomar folio ni emitir:
{
"validado": true,
"documento": { "tipoDte": 39, "totales": { "neto": 10916, "iva": 2074, "total": 12990 }, … },
"decision": { "tipoDte": 39, "motivo": "cliente sin datos tributarios completos → boleta" },
"nota": "Validación sin efecto: no se tomó folio ni se emitió."
}Úsalos para verificar que tu payload es correcto y que tu código maneja bien la respuesta antes de emitir de verdad.
Para recorrer el ciclo completo —folio, timbre, firma, veredicto por webhook, PDF y XML— crea una clave fl_test_ en Integraciones → API: emite en el ambiente de pruebas de tu empresa, con el motor real y un SII simulado. El documento sale al instante con su folio y Track ID SIM-… (la factura, la nota y la guía también vuelven ya enviadas en su respuesta, como la boleta), y el veredicto te llega como con el SII real: por webhook (o en GET /documentos/{id}) con la siguiente pasada de la cola, en general en alrededor de un minuto, también si tu empresa ya factura en producción. El PDF dice «sin validez tributaria», el XML lo declara en su cabecera y el correo del documento te llega a ti, nunca al receptor. El RUT del receptor elige el escenario, como las tarjetas de prueba de un medio de pago:
- cualquier otro RUT: aceptado (el SII simulado lo acepta a los 20 segundos);
11.111.111-1: aceptado con reparos;22.222.222-2: rechazado («RUT del receptor no vigente»);33.333.333-3: el SII tarda 10 minutos en responder;44.444.444-4: el SII está caído 20 minutos: el documento queda firmado y la cola lo reintenta sola hasta que entra.
La misma Idempotency-Key —o el mismo origen y referencia de un evento— en pruebas y en producción son dos documentos distintos: puedes ensayar con los ids reales de tus pedidos. Hasta 300 documentos al día por empresa, y 3.000 con el plan contratado (429 con Retry-After hasta la medianoche de Chile; escríbenos si necesitas más). Los webhooks del ambiente de pruebas son un set aparte, para que separes tu staging del nuestro. El plugin de WooCommerce y el asistente de IA (con empresa: "<RUT>:pruebas") usan el mismo ambiente.
Lo que no está en el ambiente de pruebas, porque el SII no tiene dónde simularlo: ceder una factura a un factoring, aceptar o reclamar compras y las boletas de honorarios (una fl_test_ recibe 403 en /boletas-honorarios).
Emitir un documento
POST /documentos emite facturas (33), guías de despacho (52), facturas exentas (34), boletas (39/41), facturas de compra (46) y notas de crédito y débito (61/56). Para facturas, notas y guías la llamada no espera al SII: valida, asigna folio, timbra, firma y responde 201 con el documento en firmado. El envío sale al instante por nuestra cola y el veredicto llega por webhook — tu request nunca queda colgado.
curl -X POST https://app.facturalibre.cl/api/v1/documentos \
-H "Authorization: Bearer fl_live_su_clave" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: pedido-8841" \
-d '{
"tipoDte": 33,
"receptor": {
"rut": "76543210-3",
"razonSocial": "Cliente SpA",
"giro": "Comercio",
"direccion": "Providencia 1234",
"comuna": "Providencia",
"email": "facturas@cliente.cl"
},
"lineas": [
{ "nombre": "Plan mensual", "cantidad": 1, "precioUnitario": 100000 }
]
}'HTTP/1.1 201 Created
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
{
"documento": {
"id": "5f0c…",
"tipoDte": 33,
"folio": 124,
"estado": "firmado",
"ambiente": "produccion",
"fechaEmision": "2026-08-11",
"montos": { "neto": 100000, "exento": 0, "iva": 19000, "total": 119000 },
"fechaVencimiento": null,
"referencias": [],
"respuestaReceptor": null, // ← lo que el software de tu cliente responda por la casilla de intercambio
"trackId": null,
"entregable": false,
"createdAt": "2026-08-11T14:03:22.000Z"
},
"enviado": false,
"aviso": "El envío al SII está en curso; el veredicto llega por webhook."
}Una boleta (39/41) nueva sí espera su envío al SII dentro de la petición —la API de boletas del SII responde en uno o dos segundos— y te devolvemos el documento como quedó: en enviado, con su trackId y "enviado": true, si el SII la recibió; en firmado si no alcanzó (la sigue subiendo nuestra cola, con reintentos, y el webhook dte.enviado te avisa cuando el SII la recibe). El reintento con la misma Idempotency-Key de una boleta que ya existe, o una emisión que tardó más de 8 segundos, responde al tiro con su folio y el envío sigue en segundo plano. La espera tiene plazo: con el SII al día respondemos en 2 a 4 segundos, y con el SII lento, en unos 15 segundos con la boleta firmada —no empezamos un envío que no alcance a terminar, y el que ya empezó lo dejamos terminar: en el peor caso, unos 25 segundos—. Una boleta que no alcanzó a subir la reintenta nuestra cola cada minuto. En cualquiera de esos casos la boleta ya es válida: el campo entregable en true dice que su PDF es la boleta del cliente y se le entrega al emitirse, sin esperar el veredicto. En facturas, notas y guías entregable es siempre false: su señal es dte.aceptado.
HTTP/1.1 201 Created
{
"documento": {
"id": "7d2e…",
"tipoDte": 39,
"folio": 35034,
"estado": "enviado", // ← ya está en el SII: se subió dentro de la petición
"trackId": "23998511774",
"entregable": true, // ← su PDF ya es la boleta del cliente: imprímelo
…
},
"enviado": true,
"aviso": "El SII ya recibió el documento; el veredicto llega por webhook."
}Los precios de boletas (39/41) van con IVA incluido; los de facturas (33/34) son netos. El IVA lo calculamos nosotros en el servidor. Las notas (61/56) exigen referencias al documento que modifican, con su codigo: 1 anula, 2 corrige un texto, 3 corrige montos. Una nota con código 1 o 2 lleva un solo documento de referencia (lo exige el SII): para anular varios documentos se emite una nota por cada uno, y solo la que corrige montos (código 3) puede citar varios, hasta 40. Las referencias comerciales (orden de compra 801, HES…) no cuentan. Una nota con código 2 (corrige el giro, la dirección) va en $0: todos los precios en 0. Una con código 1 tiene que ser por el total exacto del documento que anula (la 112 que anula una factura de exportación, en su moneda y con el mismo tipo de cambio de la 110, para que rebaje los mismos pesos que ella sumó), y se rechaza con 422, antes de tomar folio, si ese documento ya está anulado, si otra nota que lo anula todavía no llega al SII, o si el SII lo rechazó (no existe para el SII). Si el documento ya tiene notas de crédito, lo que le queda se acredita con código 3: ninguna nota de crédito acredita más de lo que queda ni rebaja más IVA que el que se cobró, y la que lo intenta también se rechaza con 422 antes del folio. En una nota de crédito (61), avisos dice además cuando el plazo no acompaña: la que anula un documento de antes del mes anterior (fuera de ese plazo, la rebaja del IVA se pide al SII con el formulario 2117) y la que rebaja uno de hace más de 6 meses (ya no baja el IVA, solo el crédito del cliente). Son avisos: la nota se emite igual.
Más reglas de las notas, todas revisadas antes de tomar folio:
- Van al mismo receptor (RUT) del documento que corrigen, y ninguna —con código 1, 2 o 3— corrige un documento que el SII rechazó o que quedó con error. En exportación todo cliente lleva el RUT 55.555.555-5, así que la nota que anula o corrige montos (código 1 o 3) va además al mismo cliente de su factura: la misma razón social (como la agrupa Clientes: «S.A.» y «SA» son dos) y, si las dos las traen, la misma identificación y el mismo país; si no, 422. Con código 2 (corrige el texto, en $0) sí se pueden corregir esos datos, y
avisoslo dice. Sobre una factura de tu software anterior solo se avisa, por el nombre que registró el SII. - Una nota de crédito no anula ni corrige los montos de otra nota de crédito. Para acreditar más, emítela sobre el documento original. Para revertir una nota de crédito se usa una nota de débito (56; 111 en exportación): con código 1 anula una sola y reproduce lo que le queda (mismo neto, exento e IVA); con código 3 revierte una parte.
- El documento se busca por el tipo, el folio y la fecha de la referencia: usa su fecha de emisión. Con otra fecha no lo encontramos: en una nota nacional nada de esto se puede revisar, y en una de exportación que anula o corrige montos, en producción, es un 422 que te dice la fecha que tiene (si no está ni en FacturaLibre ni en lo que el SII registró de tu software anterior, también).
- Lo que emitiste con tu software anterior se mide igual, si aparece en tu registro de ventas del SII (solo producción; una factura de exportación, en su moneda si ya se conocen su total y su tipo de cambio —los declara una nota en
exportacion.facturaAnterioro los dice su XML, si ya lo cargamos: ver Exportación— y, si no, en pesos). Si ya tiene una nota de crédito emitida con ese software, no recibe más desde FacturaLibre: no sabemos cuánto le queda. Escríbenos a soporte@facturalibre.cl. - Dos notas sobre el mismo documento que llegan a la vez se revisan de a una.
Cualquiera de estos rechazos es un 422 con reintentable: false y, salvo codigo: "falta_factura_anterior" (abajo, en Exportación), sin codigo propio: el motivo, con los montos (cuánto queda por acreditar, qué nota lo anula), va en error. No se tomó folio ni quedó nada registrado: corrige la nota y vuelve a emitirla. Dos se resuelven solo esperando y llegan con reintentable: true: el documento que corrige todavía no tiene veredicto del SII —firmado, en cola, esperando folios o enviado sin respuesta; una exportación, también mientras confirmamos con el SII una nueva subida— (codigo: "original_en_proceso"), u otra nota sobre él se está emitiendo en este momento (codigo: "nota_en_curso"). Repite la misma nota más tarde, con la misma Idempotency-Key.
Para anular una boleta se emite una nota de crédito (61) que la referencia con codigo: 1. Ojo con tres cosas. La nota exige el receptor completo (RUT, razón social, giro, dirección y comuna) aunque la boleta no tuviera ninguno. Su total tiene que calzar con el de la boleta, a lo más un peso de diferencia por el redondeo del IVA, y lo exento, exacto: como la nota lleva precios netos y la boleta los lleva con IVA, lo afecto va en una línea por el neto que reproduce su parte con IVA. Y si la boleta tenía ítems exentos, lo exento va en una línea exenta aparte (exento: true), por su monto: una nota no rebaja más IVA que el que cobró la boleta, y la que lo hace se rechaza. El ejemplo anula una boleta de $1.500 con $500 exentos: $1.000 con IVA son $840 netos, más los $500 exentos. Una boleta a consumidor final viaja al SII con el RUT genérico 66666666-6 y razón social Sin Razon Social: usa esos mismos datos en la nota.
{
"tipoDte": 61,
"receptor": {
"rut": "66666666-6",
"razonSocial": "Sin Razon Social",
"giro": "Particular",
"direccion": "Sin direccion",
"comuna": "Santiago"
},
"lineas": [
{ "nombre": "Anula boleta N 35021", "cantidad": 1, "precioUnitario": 840 },
{ "nombre": "Anula boleta N 35021 (exento)", "cantidad": 1, "precioUnitario": 500, "exento": true }
],
"referencias": [
{
"tipoDocumento": 39,
"folio": "35021",
"fecha": "2026-09-19",
"codigo": 1,
"razon": "Anulacion"
}
]
}Orden de compra y HES. Si tu cliente exige que la factura cite su orden de compra o su hoja de entrada de servicios, van en el mismo arreglo referencias, con tipoDocumento como texto: "801" (orden de compra), "HES", "HEM", "802" (nota de pedido) o "803" (contrato). Llevan folio (alfanumérico, hasta 18 caracteres) y fecha, y no llevan codigo: citan un documento, no lo corrigen. Viajan en el XML que recibe tu cliente y salen impresas en el PDF por su nombre.
Cada una admite además razon (hasta 90 caracteres), que viaja como RazonRef. Hay clientes que la exigen y reclaman la factura que no la trae: por ejemplo, los que leen la HES como una "802" con el número de la HES en folio y el de su orden de compra en razon, justo después de la "801" de esa orden. Las referencias viajan en el orden del arreglo: con varias órdenes, cada una seguida de la suya.
{
"tipoDte": 33,
"receptor": {
"rut": "76543210-3",
"razonSocial": "Cliente SpA",
"giro": "Acuicultura",
"direccion": "Diego Portales 2000",
"comuna": "Puerto Montt"
},
"lineas": [
{ "nombre": "Servicio de diagnóstico histopatológico", "cantidad": 7, "precioUnitario": 37595 }
],
"referencias": [
{ "tipoDocumento": "801", "folio": "PC003740", "fecha": "2026-10-01" },
{ "tipoDocumento": "802", "folio": "CM01-025567", "fecha": "2026-10-20", "razon": "PC003740" }
]
}Desde TypeScript:
const res = await fetch("https://app.facturalibre.cl/api/v1/documentos", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.FACTURALIBRE_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": `pedido-${pedido.id}`,
},
body: JSON.stringify({
tipoDte: 39, // boleta electrónica
lineas: [{ nombre: "Entrada general", cantidad: 2, precioUnitario: 12000 }],
}),
})
if (res.status === 201 || res.status === 200) {
const { documento } = await res.json()
// documento.folio ya está asignado; el veredicto del SII llega por webhook
}Borrador programado. Con "borrador": true (y ventanaMinutos, de 5 a 1.440; por defecto 30) el documento no se emite al instante: responde 201 en borrador, sin folio, y se emite solo en autoAdvanceAt. Hasta entonces, PATCH /documentos/{id} con el mismo cuerpo de la emisión lo reemplaza entero (sin cambiar el tipo), o con {"accion": "emitir_ahora"} lo emite ya; DELETE /documentos/{id} lo cancela sin consumir folio. Ya emitido, los dos responden 409. Las boletas no admiten borrador (422). Una nota programada (61, 56, 111, 112) no se edita: el PATCH responde 422; cancélala y créala de nuevo, así se revisa otra vez contra el documento que corrige. Y justo antes de tomar folio se revisa de nuevo: si ya no pasa (por ejemplo, el SII rechazó el documento mientras esperaba), queda en error sin consumir folio, con el porqué en siiGlosa.
Las guías de despacho (52) llevan además el objeto traslado — obligatorio en la guía, opcional en facturas que amparan traslado de bienes (Resolución 154, vigente desde el 1-nov-2026): tipo de traslado (indTraslado 1 venta, 2 ventas por efectuar, 3 consignación, 4 entrega gratuita, 5 traslado interno, 6 otros no venta, 7 devolución; los de exportación, 8 y 9, todavía no se emiten y se rechazan con 400), datos del transporte (patente, transportista, chofer, destino) y salida/llegada. Desde el 1-nov-2026 la guía y la factura que ampara traslado exigen la patente, el RUT del transportista, el chofer (RUT y nombre) y el destino (vacío, el domicilio del receptor); lo que no se sepa al emitir se declara en sinInformacion (patente, carro, transportista, chofer) y sale escrito en la guía. Sin fchSalida/hraSalida, la salida es la de la emisión; una llegada otro día lleva prolongado (motivo: distancia, carga u otro). La guía va con la fecha de hoy. Lo que falte responde 422 traslado_incompleto con todos los faltantes, también en el modo prueba (/documentos/validar) y al editar un borrador programado. Una guía sin venta (traslado interno, entrega gratuita) puede ir con precios en 0 y el motivo del traslado: se emite con total 0, como exige el SII. El peso o volumen de una línea va en cantidadReferencia y unidadReferencia. Con la Res. 144 del SII (desde el 1-nov-2026) la hora de salida es opcional y, si el cliente retira en tu local (tipoDespacho: 1), no se piden datos de transporte.
Facturar guías (art. 55 de la Ley del IVA): la factura 33 o 34 cita cada guía con una referencia { tipoDocumento: 52, folio, fecha }, sin codigo, hasta 40. Antes del folio se revisa cada guía que emitiste con FacturaLibre: del mismo receptor, de venta, aceptada, no anulada, no facturada por otra factura viva y del mismo mes que la fecha de la factura. Lo que no cuadra responde 422 guias_invalidas con todos los problemas ({ codigo, folio, mensaje }); una guía de tu software anterior pasa, con un aviso. Corregir una guía (Res. 144, 1°): emite la nueva con traslado.reemplaza = el id de la anterior; se agrega la referencia 52 y la anterior queda anulada cuando el SII acepta la nueva (422 guia_reemplazo_invalido si no es una guía aceptada tuya).
{
"tipoDte": 52,
"receptor": {
"rut": "76543210-3",
"razonSocial": "Cliente SpA",
"giro": "Comercio",
"direccion": "Providencia 1234",
"comuna": "Providencia"
},
"lineas": [
{ "nombre": "Caja de repuestos", "cantidad": 4, "unidad": "UN", "precioUnitario": 25000,
"cantidadReferencia": 18, "unidadReferencia": "KG" }
],
"traslado": {
"indTraslado": 1,
"tipoDespacho": 2,
"transporte": {
"patente": "ABCD12",
"rutTransportista": "76123456-0",
"chofer": { "rut": "12345678-5", "nombre": "Juan Pérez" },
"dirDestino": "Bodega Norte, Camino Interior 5",
"cmnaDestino": "Lampa"
},
"sinInformacion": ["carro"]
}
}La factura de compra (46) invierte los roles: tú emites por algo que compraste y el receptor es tu proveedor. Lleva retención total del IVA (código 15): los precios van netos, el IVA se declara completo y se retiene entero, y el total del documento es el neto — lo que le pagas al proveedor. El IVA retenido lo declara tu empresa en su F29 (código 39); en la respuesta viene como montos.ivaRetenido. Es el documento del cambio de sujeto — por ejemplo, servicios de proveedores extranjeros que facturan sin IVA. Una nota de crédito o débito sobre una 46 lleva la misma retención, espejada: su total también es el neto.
El impuesto específico a los combustibles va en cada línea, en impuestoEspecifico: el código (35 gasolina, 28 diésel) y, en pesos de la línea, el componente base y el variable (MEPCO, que puede ser negativo). No es base del IVA: el precioUnitario va sin él y el total lo suma aparte. En factura, guía y notas se informa por código (CodImpAdic en la línea e ImptoReten en los totales, con su tasa: 6 la gasolina y 1,5 el diésel), con los dos componentes en la descripción de la línea. Si es negativo, se hace como indica el SII (pregunta frecuente 001.003.8044.003): 1 en el impuesto, la glosa «Impuesto específico diesel negativo de N» en la línea y un total que refleja el descuento. Por eso el SII lo acepta con reparos: anota que el total no es la suma de los montos (HED-2-260), y el estado queda aceptado_reparos. El documento vale. La boleta no tiene campo de impuestos adicionales: el positivo va como una línea exenta y el negativo, en la glosa y el total. La respuesta trae montos.impuestoEspecifico (el monto real y el informado) en el POST y en el GET de un documento.
{
"tipoDte": 33,
"receptor": {
"rut": "76543210-3",
"razonSocial": "Transportes Cliente SpA",
"giro": "Transporte de carga",
"direccion": "Ruta 5 Norte km 20",
"comuna": "Colina"
},
"lineas": [
{ "nombre": "Petróleo diésel", "cantidad": 20, "unidad": "LT", "precioUnitario": 1385.3,
"impuestoEspecifico": { "codigo": 28, "base": 2165, "variable": -4955 } }
]
}
→ neto 27.706 · IVA 5.264 · impuesto específico -2.790 (en el XML, 1) · total 30.180La factura de exportación (110) y sus notas (111 débito, 112 crédito) van sin IVA y en la moneda de la operación: los precioUnitario admiten hasta 6 decimales y el objeto exportacion es obligatorio — moneda con el literal de la tabla del SII (se emiten en DOLAR USA o EURO, las monedas con tipo de cambio oficial del Banco Central) y naturaleza, qué exportas: "servicios" o "bienes" (mercadería). Un servicio lleva indServicio (3 servicios calificados por Aduana; 4 hotelería y 5 transporte terrestre internacional solo si tu negocio los tiene habilitados, porque cada uno tiene requisitos propios —escríbenos—; el 6, prestados y utilizados en el extranjero, todavía no se emite) y nunca los datos de Aduana; si una de sus líneas parece mercadería (un equipo, cartuchos, el flete, una unidad como KN), avisos te lo dice, sin bloquear. Si no mandas naturaleza y viene indServicio, se asume "servicios" (así siguen funcionando las integraciones anteriores); sin ninguno de los dos, 400.
El tipo de cambio de la 110 lo fija FacturaLibre, y desde el 18-10-2026 también el de sus notas: el valor oficial del Banco Central para la fecha de emisión de cada documento (si ese día no tuvo valor —fin de semana o feriado bancario—, el último publicado antes); la nota que anula (código 1) lleva el de lo que anula —la 112, el de su 110—, así rebaja exactamente los pesos que sumó. No hace falta mandarlo; si lo mandas, se ignora y aviso te dice cuál se usó. La excepción es lo que emitiste con tu software anterior, porque el SII no nos informa su tipo de cambio: ver «Lo que emitiste con tu software anterior», abajo. Sin valor oficial no se emite: 422 con reintentable: true. En la respuesta, exportacion.tipoCambio es el usado, con tipoCambioFecha (de qué día es) y tipoCambioFuente. El receptor extranjero lleva el RUT genérico 55555555-5 y, en la 110, direccion y ciudad obligatorias (las de tu cliente en el extranjero); su identificación real va en exportacion.extranjero, donde nacionalidad es el código de país de la tabla de Aduana (3 dígitos: 216 México, 405 Nueva Zelandia…; en la 110, uno que no es el país de un cliente extranjero en esa tabla se rechaza con 400). En la respuesta, montos trae el equivalente en pesos (es lo que declara tu F29) y exportacion los montos en la moneda. Una nota de exportación referencia siempre su 110, con su código: la 112 la anula (1, por el total exacto) o la rebaja (3, con un tope que se mide en la moneda); la 111 cobra más sobre ella (3) o le corrige un texto (2, en cero), y nunca la anula: eso lo hace la 112. La nota repite lo que exportó su 110 —naturaleza, indServicio, moneda y, si lleva datos de Aduana, la modalidad y la cláusula—: si no, 422 antes de tomar folio (una 110 con la naturaleza equivocada se anula con una 112 que la repita, y se emite de nuevo). Una nota nacional (61 o 56) no corrige un documento de exportación: 422. Sin descuentos por línea ni globales por ahora.
Cómo califica Aduana el servicio (tipo de servicio 3): exportacion.calificacion es { "por": "listado", "codigos": ["00160501"] } si el servicio está en el listado de servicios calificados como exportación de Aduana (de 1 a 3 códigos de 8 dígitos, como texto: los ceros cuentan), o { "por": "resolucion", "numero": "…", "fecha": "AAAA-MM-DD" } (con codigos, si la resolución los da) si Aduana te lo calificó con una resolución, que no puede ser posterior al documento (no es retroactiva). Con ella armamos la referencia 812 al final de las referencias: con el listado cita la Res. Ex. N° 1.931 de 16-05-2024 de Aduana —la que reemplazó el Apéndice III que califica el listado— con el código en la razón; con una resolución, su número y su fecha. Es nuestra lectura de la norma: ninguna fuente del SII dice qué citar en la 812 cuando el servicio está en el listado. Si además mandas una 812 que cita otra resolución, 400; si ya van 40 referencias, 400. La calificación va solo con el tipo 3 (con 4 o 5, o en mercadería, 400). Sin la calificación ni la 812, avisos te lo recuerda: la 111 o la 112 de un servicio que corrige montos (código 3) sale con reparo (REF-2-826). La nota que corrige montos de una 110 tuya sin la 812 la hereda de ella (avisos lo dice). Un código que no está en nuestra copia del listado (al 05-12-2025) solo se avisa: Aduana lo amplía con cada resolución.
Lo que emitiste con tu software anterior: el SII no nos informa la moneda ni el tipo de cambio de esas facturas de exportación, así que la nota que corrige una la declara en exportacion.facturaAnterior, { "total": "10000", "tipoCambio": "900" }: su total en la moneda de la nota y su tipo de cambio, como texto decimal con punto, tal como dice su PDF. Lo cruzamos con lo que registró el SII (total × tipo de cambio, redondeado, tiene que dar sus pesos, a un peso) y desde ahí la nota se mide en la moneda. Es obligatorio en la primera 112 que le corrige montos (código 3): sin él, 422 con codigo: "falta_factura_anterior". Si ya cargamos el XML de esa factura, se mide con lo que dice su XML y no hace falta declararla (si la declaras, tiene que decir lo mismo). La 112 que la anula (código 1) puede mandar solo tipoCambio, el de esa factura, o el objeto (si van los dos, tienen que decir lo mismo); en la 111 y con código 2 es opcional, pero si viene se valida. Se declara una vez: las notas siguientes sobre esa factura lo heredan (si lo repiten, igual; si dicen otra cosa, 422), la respuesta lo devuelve en exportacion.facturaAnterior y avisos dice de dónde salió. Sobre una 110 emitida con FacturaLibre no se usa: sus datos ya los tenemos. Una nota que anula o corrige montos de más de una de esas facturas va una por cada una (cada una tiene su total y su tipo de cambio), salvo la que solo las anula, sin declarar ninguna, con un tipo de cambio común, como siempre. En producción, una nota que anula o corrige montos de una factura de exportación que no está ni en FacturaLibre ni en lo que el SII registró de tu software anterior se rechaza (422): si la emitiste hace poco, el SII todavía no nos la informa.
{
"tipoDte": 110,
"receptor": {
"rut": "55555555-5",
"razonSocial": "Overseas Diagnostics Ltd.",
"direccion": "12 Harbour Road",
"ciudad": "Auckland",
"email": "ap@overseas.example"
},
"lineas": [
{ "nombre": "Análisis PCR (lote 2026-09)", "cantidad": 3, "precioUnitario": 1250.5 },
{ "nombre": "Informe técnico", "cantidad": 1, "precioUnitario": 300 }
],
"exportacion": {
"naturaleza": "servicios",
"moneda": "DOLAR USA",
"indServicio": 3,
"extranjero": { "numId": "NZBN-9429041234567", "nacionalidad": "405" },
"calificacion": { "por": "listado", "codigos": ["00160501"] }
},
"formaPago": 2
}La exportación de mercadería (naturaleza: "bienes") va sin indServicio y con el bloque exportacion.aduana, con los códigos (números) de las tablas del Anexo 51 de Aduana: modalidadVenta (1 A FIRME · 2 BAJO CONDICION · 3 EN CONSIGNACION LIBRE · 4 EN CONSIGNACION CON UN MINIMO A FIRME), clausulaVenta (1 CIF, 2 CFR, 3 EXW, 4 FAS, 5 FOB, 6 S/CL, 7 FCA, 8 OTRA, 9 DDP; con la 8 «OTRA», también incotermOtra: CPT, CIP, DPU o DAP), viaTransporte (1 MARÍTIMA, FLUVIAL Y LACUSTRE · 4 AÉREO · 5 POSTAL · 6 FERROVIARIO · 7 CARRETERO / TERRESTRE · 8 OLEODUCTOS, GASODUCTOS · 9 TENDIDO ELÉCTRICO (Aéreo, Subterráneo) · 10 OTRA · 11 COURIER/AEREO), puertoEmbarque (el puerto, aeropuerto o paso fronterizo de Chile por donde sale) y puertoDesembarque (donde llega, fuera de Chile), de la tabla 51-11; paisDestino (tabla 51-9) y bultos (hasta 10 tipos de la tabla 51-23, cada uno con su cantidad y sus marcas, que el SII exige: si no tienen, «Sin marca»). Además, la 110 de mercadería exige formaPagoExportacion (tabla 51-22; con pago anticipado, también fechaCancelacion, la fecha en que te pagaron. La forma de pago de la factura sale de ella si no mandas formaPago: la 32 pagada el día de la emisión o antes, al contado, y todo lo demás —cobranza, acreditivo, las mixtas—, a crédito, con su fechaVencimiento si la mandas. Es así desde el 19-10-2026; antes, sin formaPago salía al contado. Si mandas otra, se respeta y avisos te lo dice), la nacionalidad del cliente (es también su país ante Aduana), cada línea con cantidad y unidad —la sigla de la tabla 51-24: KN (kilogramo), U (piezas o ítems), LT (litro), MT (metro); «UN» y «KG» no existen— y salidaFisicaConfirmada: true: confirmas que la mercadería sale físicamente de Chile con su DUS, DUSSI o courier (no va al XML). Con CIF van flete y seguro; con CFR, el flete; en las demás cláusulas son opcionales. Si se los cobras al cliente, van además como líneas del documento (es lo que paga el importador). totalClausulaVenta es opcional: si no va, es el total del documento con 2 decimales. Con EXW, FAS, FOB o FCA el flete y el seguro internacionales los paga el comprador aparte y no van en el valor de la cláusula: si los cobras en el documento, manda totalClausulaVenta sin ellos (si no va, es el total del documento, con el flete adentro) y POST /documentos/validar te lo avisa en avisos. El flete interno —el traslado en Chile hasta el puerto o aeropuerto de embarque— sí es parte del valor FCA, FAS o FOB, y flete y seguro son solo el tramo internacional (el flete del DUS va desde el puerto de embarque: Anexo 35 del Compendio, 13.6 y 13.7); con EXW tu cliente paga todo el transporte, y cobrar el interno se avisa. El tramo de cada línea no viaja en la API: una que dice «interno» (o «pre-carriage») se lee como el interno, salvo «en destino»; «internacional», «marítimo», «aéreo», «ocean», «sea» o «marine», como el internacional; si no lo dice, o dice los dos, con FCA, FAS o FOB vale totalClausulaVenta con ella o sin ella (con EXW, sin ella; con las demás, con ella). «Transporte internacional», «courier» y «shipping» también son flete; el portal pregunta el tramo de cada línea. Los pesos (pesoBruto, pesoNeto) son opcionales y van con su unidad (unidadPesoBruto, unidadPesoNeto), y fechaEmbarque (no va al XML) sirve para avisarte si la factura va después del embarque o en otro mes. Lo que falte o esté mal es un 400 con el campo, antes de tomar folio; lo que conviene revisar y no bloquea lo devuelven POST /documentos/validar y POST /documentos (junto al documento emitido) en avisos. Una nota de una 110 de mercadería lleva naturaleza: "bienes"; sus datos de Aduana son opcionales, pero lo que mande tiene que ser válido, y si ajusta el valor de una venta «a firme» escribe la causa en la razon de su referencia. Todavía no se emiten las muestras sin carácter comercial (forma de pago 21 o modalidad 9, «sin pago»: 400). En la respuesta, exportacion.aduana trae cada código con su glosa ({ codigo, glosa, sigla }) y totalBultos, y exportacion.indServicio es 0 en mercadería.
{
"tipoDte": 110,
"receptor": {
"rut": "55555555-5",
"razonSocial": "Acuícola del Pacífico S.A. de C.V.",
"direccion": "Av. del Puerto 450",
"ciudad": "Manzanillo",
"email": "compras@acuicola.example"
},
"lineas": [
{ "nombre": "Kit de diagnóstico PCR", "cantidad": 60, "unidad": "U", "precioUnitario": 85.5 },
{ "nombre": "Flete marítimo", "cantidad": 1, "unidad": "U", "precioUnitario": 420 },
{ "nombre": "Seguro de la carga", "cantidad": 1, "unidad": "U", "precioUnitario": 35 }
],
"exportacion": {
"naturaleza": "bienes",
"moneda": "DOLAR USA",
"extranjero": { "numId": "APA990101AB1", "nacionalidad": "216" },
"formaPagoExportacion": 1,
"aduana": {
"modalidadVenta": 1,
"clausulaVenta": 1,
"viaTransporte": 1,
"nombreTransporte": "MSC ANNA",
"puertoEmbarque": 906,
"puertoDesembarque": 217,
"paisDestino": 216,
"bultos": [{ "tipo": 22, "cantidad": 6, "marcas": "APA-2026-10" }],
"pesoBruto": "184.50",
"unidadPesoBruto": 6,
"pesoNeto": "150",
"unidadPesoNeto": 6,
"flete": "420",
"seguro": "35",
"fechaEmbarque": "2026-10-20",
"salidaFisicaConfirmada": true
}
}
}Ceder una factura a un factoring: POST /documentos/{id}/ceder con cesionario (rut, razonSocial, direccion de 5 a 80 caracteres y email — los tres los exige el SII), montoCesion (opcional, por defecto el total), ultimoVencimiento (AAAA-MM-DD, por defecto el vencimiento pactado o emisión + 30 días), emailDeudor y otrasCondiciones. Solo facturas (33/34/43) a crédito, ya aceptadas por el SII, sin notas de crédito que las anulen o rebajen y no marcadas como pagadas, una cesión por documento (si no, 409 con el porqué). Responde 201 con la cesión en curso: un Track ID no es una cesión anotada — espera el webhook dte.cedido o consulta GET /documentos/{id}/ceder. Es irreversible: no hay DELETE (revertirla es un trámite presencial ante el SII).
Una factura (33/34/46) exige el receptor completo: RUT, razón social, giro, dirección y comuna. Si falta alguno, la emisión —y /validar— la rechazan con el campo señalado, antes de tomar folio. Una boleta (39/41) no necesita receptor. El rut se acepta con o sin puntos y con dígito verificador K mayúscula o minúscula (76543210-3, 78.459.548-K); lo normalizamos.
Largos máximos por campo (del esquema del SII). Si te pasas, el error te dice cuál — con su ruta, p. ej. campo: “lineas → línea 1 → nombre”:
| Campo | Límite |
|---|---|
| lineas | máximo 60 líneas por documento |
| lineas[].nombre | 80 caracteres. En una boleta (39/41) un nombre que no cabe NO rebota —se cuenta también como llega al SII, donde «…» son tres puntos—: queda como nombre hasta la última palabra entera que cabe (o hasta donde cabe, si no hay un espacio desde el carácter 40) y el resto pasa al comienzo de la descripción del ítem; lo que pase de los 1.000 de la descripción se corta. En facturas, notas y guías sigue rebotando |
| lineas[].descripcion | 1.000 caracteres (opcional): va al SII (DscItem) y se imprime bajo el nombre, en letra más chica |
| lineas[].codigo | 35 caracteres (opcional) |
| lineas[].unidad | 4 caracteres (opcional; en la exportación de mercadería, obligatoria en la 110 y siempre la sigla de la tabla 51-24 de Aduana: KN, U, LT…) |
| receptor.razonSocial | 100 caracteres |
| receptor.giro | 40 caracteres — se TRUNCA a 40, no rebota |
| receptor.direccion | 70 caracteres; en la factura de exportación (110), la dirección del cliente en el extranjero, obligatoria |
| receptor.comuna | 20 caracteres |
| receptor.ciudad | 20 caracteres (opcional; en la factura de exportación (110), la ciudad del cliente en el extranjero, obligatoria) |
| receptor.email | 80 caracteres (opcional): la PERSONA que recibe el PDF |
| receptor.telefono | 40 caracteres (opcional): solo una boleta (39/41) lo lleva al XML, como TelefonoRecep |
| receptor.casillaIntercambio | 80 caracteres (opcional): la casilla de intercambio del SOFTWARE del receptor (la que su área de pagos declara para recibir facturas electrónicas, p. ej. …@custodium.com). Ahí va el sobre EnvioDTE en un correo aparte, y es lo que se escribe en CorreoRecep del XML. Si no viene, se toma de tu libreta de clientes para ese RUT; si tampoco está ahí y el receptor también usa FacturaLibre, su casilla se conoce sola y el documento entra a sus compras aunque mandes enviarEmail: false (con una casilla de otro dominio, en el request o en la libreta, se usa esa y enviarEmail: false la apaga). Solo en 33/34/52/56/61 |
| observaciones | 500 caracteres (opcional) |
| lineas[].precioUnitario | hasta 6 decimales en facturas, guías, notas y exportación (el monto de la línea se redondea a peso, mitad hacia arriba); entero en boletas |
| lineas[].cantidad | mayor que cero y hasta 999.999.999; se redondea a 6 decimales (los que admite el SII) y el monto de la línea se calcula con esa cantidad. cantidad × precio no puede pasar de $999.999.999.999 |
| lineas[].descuentoPct | 0 a 99,99 (opcional); se redondea a 2 decimales |
| sucursal | El código de una sucursal registrada (opcional; hasta 20 caracteres, sin importar mayúsculas): el documento sale con su domicilio y su código del SII. Una que no existe o está desactivada se rechaza antes del folio. Sin ella, la casa matriz |
| patente | La patente del vehículo que carga (opcional; hasta 8 letras y números): en facturas (33, 34) y guías (52), como pide la Res. Ex. SII 52/2015 a quien vende combustible. En una guía con traslado, es la del transporte (si mandas las dos, iguales) |
| lineas[].impuestoEspecifico | { codigo: 35 (gasolina) | 28 (diésel), base, variable? } (opcional): el impuesto específico a los combustibles de la línea, en pesos enteros de la línea; base desde 0 y variable (MEPCO) con signo. El precioUnitario nunca lo incluye. Solo en 33, 39, 52, 56 y 61, y en una línea no exenta (en otro caso, 400) |
| descuentoGlobal.valor | en % se redondea a 2 decimales; en pesos, a entero (si queda en cero, se rechaza). Un descuento no puede superar el monto sobre el que se aplica; un recargo sí. En una exenta (34/41) se aplica siempre sobre lo exento |
| fechaVencimiento | AAAA-MM-DD (opcional): en 33/34/110 a crédito (formaPago 2) y en boletas (39/41) de servicios periódicos, no antes de la emisión; va en el XML como FchVenc |
| boleta | objeto opcional, solo en boletas (39/41): medio de pago, caja, quien atendió, período, código de cliente y datos del rubro. Cada campo y su límite, en «Boletas por rubro» |
| monedaPrecios | { moneda: "UF" | "UTM" | "USD" | "EUR", tipoCambio?: "969.70" } (opcional): los precios de las líneas vienen en esa unidad y se convierten a pesos; el documento ante el SII es en pesos y cada línea conserva su precio en la unidad, el valor usado y su origen (otraMoneda). UF (diaria) y UTM (mensual): siempre el valor oficial del SII. USD y EUR: el tipo de cambio oficial del Banco Central de Chile (el dólar observado y el euro) de la fecha de emisión; si ese día no tuvo valor —fin de semana o feriado bancario—, el último publicado antes. tipoCambio (pesos por 1 USD o 1 EUR, texto con punto decimal y hasta 4 decimales) solo se usa si no hay valor oficial para esa fecha (el Banco Central aún no lo publica o no respondió), y el documento dice que lo ingresó el emisor; si hay valor oficial, el que mandes se ignora. Solo en 33/34/39/41/56/61 (en otro tipo, 400) y si el negocio tiene la unidad activa (422 si no, si no hay valor oficial y no viene tipoCambio, o si hace falta tipoCambio y está fuera de 100-10.000) |
| referencias | máximo 40; folio hasta 18 caracteres (el de un documento tributario, numérico y distinto de 0); fecha entre el 01-08-2002 y el 31-12-2050; razon hasta 90 caracteres; las comerciales (801, HES…) sin codigo. En una boleta, la caja y quien atendió (una referencia) y cada dato del rubro que va al SII (una cada uno) cuentan dentro de esas 40; en una exportación, también la 812 que arma el servidor desde exportacion.calificacion |
| exportacion.aduana: códigos | números enteros de las tablas del Anexo 51 de Aduana, solo los vigentes: modalidadVenta, clausulaVenta, viaTransporte, puertoEmbarque, puertoDesembarque, paisDestino, bultos[].tipo, unidadPesoBruto y unidadPesoNeto |
| exportacion.aduana: textos | nombreTransporte y nombreCiaTransporte 40 caracteres; booking y operador 20; rutCiaTransporte, un RUT chileno válido |
| exportacion.aduana.bultos | hasta 10 tipos; cantidad entera desde 1 y hasta 10 dígitos; marcas OBLIGATORIAS en cada tipo (las de los bultos, o «Sin marca»; hasta 255 caracteres), idContainer 25, sello 20, emisorSello 70 |
| exportacion.aduana.totalClausulaVenta | texto decimal con punto, mayor que cero y con hasta 2 decimales (opcional: si no va, el total del documento con 2 decimales) |
| exportacion.aduana.flete / seguro | texto decimal con punto, mayor que cero y con hasta 4 decimales, en la moneda del documento |
| exportacion.aduana.pesoBruto / pesoNeto | texto decimal con punto, mayor que cero, hasta 2 decimales y 10 dígitos en total; con su unidad |
| exportacion.fechaCancelacion / aduana.fechaEmbarque | AAAA-MM-DD, entre 2000 y 2050 |
| exportacion.calificacion | solo con indServicio 3: { por: "listado", codigos } (de 1 a 3 códigos de 8 dígitos, como texto) o { por: "resolucion", numero (hasta 18 caracteres), fecha (no posterior al documento), codigos? }; arma la referencia 812 |
| exportacion.facturaAnterior | solo en 111/112: { total, tipoCambio } de la factura de tu software anterior que corrige la nota, como texto decimal con punto: total mayor que cero con hasta 4 decimales, en la moneda de la nota; tipoCambio entre 100 y 10.000, con hasta 4 decimales |
| Idempotency-Key | 8 a 80 caracteres |
Boletas por rubro
Una boleta (39/41) puede llevar, además de sus líneas, lo propio de cada rubro: el medio de pago, la caja y quién atendió, el período de un servicio mensual, tu código del cliente y los datos que revisa un tercero —el paciente y el profesional de una consulta, la mascota, la patente—. Van en el objeto boleta y en receptor.telefono. Todo es opcional: una integración que no los manda emite exactamente igual que antes. Ni la API ni la pantalla de FacturaLibre exigen los datos del rubro; lo único obligatorio es lo que exige la ley sobre 135 UF, más abajo. boleta va solo en boletas: en otro tipo de documento responde 400. Un campo que mandas vacío ("") cuenta como no enviado.
curl -X POST https://app.facturalibre.cl/api/v1/documentos \
-H "Authorization: Bearer fl_live_su_clave" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: cita-5512" \
-d '{
"tipoDte": 41,
"receptor": {
"rut": "18456789-K",
"razonSocial": "Josefa Martínez Rojas",
"email": "josefa@correo.cl",
"telefono": "+56 9 8765 4321"
},
"lineas": [
{ "nombre": "Sesión de kinesiología", "cantidad": 1, "precioUnitario": 28000 }
],
"boleta": {
"rubro": "salud",
"medioPago": "debito",
"vendedor": "TV01",
"vendedorNombre": "Tomás Vera Lagos",
"datos": {
"profesional": "Tomás Vera Lagos, RUT 15.234.567-4, kinesiólogo",
"prevision": "Isapre"
}
}
}'Lo que un tercero revisa queda timbrado, no solo impreso: cada dato del rubro que va al SII viaja en su propia <Referencia> con CodRef (el código del dato) y RazonRef (su valor, hasta 90 caracteres), los campos que el formato de boletas del SII define para informarle un dato al cliente. La caja y quien atendió van juntos en una referencia, después de las que citan documentos. Esa boleta lleva en su XML:
<IdDoc> … <IndServicio>3</IndServicio><MedioPago>2</MedioPago></IdDoc>
<Receptor><RUTRecep>18456789-K</RUTRecep><RznSocRecep>Josefa Martínez Rojas</RznSocRecep>
<CorreoRecep>josefa@correo.cl</CorreoRecep><TelefonoRecep>+56 9 8765 4321</TelefonoRecep></Receptor>
…
<Referencia><NroLinRef>1</NroLinRef><CodVndor>TV01</CodVndor></Referencia>
<Referencia><NroLinRef>2</NroLinRef><CodRef>PROFESIONAL</CodRef>
<RazonRef>Tomás Vera Lagos, RUT 15.234.567-4, kinesiólogo</RazonRef></Referencia>
<Referencia><NroLinRef>3</NroLinRef><CodRef>PREVISION</CodRef><RazonRef>Isapre</RazonRef></Referencia>| Campo | Límite y a dónde va |
|---|---|
| boleta.rubro | uno de los rubros de abajo (14). Ordena los datos en el XML y en el impreso; si no viene, se usa el rubro de tu negocio |
| boleta.medioPago | efectivo · debito · credito · transferencia · cheque · otro → IdDoc/MedioPago (tabla de abajo). Obligatorio sobre 135 UF |
| boleta.caja | 8 caracteres (latin-1): el código de la caja → Referencia/CodCaja |
| boleta.cajaNombre | 40 caracteres: el nombre de la caja, solo en el impreso |
| boleta.vendedor | 8 caracteres (latin-1): el código de quien atendió (vendedor, garzón, profesional) → Referencia/CodVndor |
| boleta.vendedorNombre | 60 caracteres: su nombre, solo en el impreso |
| boleta.codigoCliente | 20 caracteres (latin-1): tu código del cliente, socio o alumno → Receptor/CdgIntRecep |
| boleta.periodoDesde | AAAA-MM-DD: inicio del período de un servicio periódico → IdDoc/PeriodoDesde. Va con periodoHasta (los dos o ninguno) |
| boleta.periodoHasta | AAAA-MM-DD, no antes de periodoDesde: fin del período → IdDoc/PeriodoHasta |
| boleta.saldoAnterior | pesos enteros, negativo si es un saldo a favor: lo que arrastra de períodos anteriores → Totales/TotalPeriodo (lo de este período), SaldoAnterior y VlrPagar (la suma). No cambia el total del documento |
| boleta.datos | { clave: texto }: los datos del rubro (tabla de abajo), cada uno hasta su largo. Los que van al SII, una Referencia con CodRef y RazonRef cada uno; los demás, solo el impreso |
| boleta.efectivoRecibido | pesos enteros, 0 o más: con cuánto pagó en efectivo; solo el impreso (calcula el vuelto) |
| boleta.propina | pesos enteros, 0 o más: la propina pagada, solo el impreso y FUERA del total (no es venta ni lleva IVA) |
| boleta.profesionalTratante | { nombre, rut?, profesion?, registro? }: salud. El profesional tratante en casillas: nombre (60, obligatorio si mandas el objeto), RUT con su dígito verificador, profesión (40) y N° de registro de la Superintendencia de Salud (20). Si no mandas datos.profesional, de aquí sale el texto que va al SII (Referencia con CodRef PROFESIONAL, 90); el impreso lo usa completo |
| boleta.paciente | { nombre, rut? }: salud. El paciente cuando NO es quien paga: nombre (60) y RUT. Si no mandas datos.paciente, de aquí sale el texto de la Referencia PACIENTE. Sin él, el paciente es el receptor |
| receptor.telefono | 40 caracteres: el teléfono de quien paga → Receptor/TelefonoRecep. Se acepta en cualquier documento, pero solo la boleta lo lleva al XML y lo guarda |
| fechaVencimiento | AAAA-MM-DD: en una boleta, el vencimiento de un servicio periódico → IdDoc/FchVenc |
Medio de pago. El formato del SII tiene cinco; débito y crédito son los dos «pago electrónico».
| medioPago | En el XML |
|---|---|
| efectivo | MedioPago 1 (Efectivo) |
| debito | MedioPago 2 (Pago electrónico) |
| credito | MedioPago 2 (Pago electrónico) |
| transferencia | MedioPago 3 (Transferencia electrónica) |
| cheque | MedioPago 4 (Cheque) |
| otro | MedioPago 5 (Otro medio) |
Datos del rubro (boleta.datos). Las claves son estas: una que no está en la tabla responde 400 con la lista de las válidas, y un valor más largo que su tope también. Puedes mandar datos de otro rubro (una veterinaria que también vende): van igual, en el orden del catálogo. Los que dicen «solo el impreso» (la mesa, el próximo control) no viajan al SII; los que van al SII tienen que poder escribirse en latin-1, como todo el XML (sin emojis).
| Clave | Rótulo · destino · largo |
|---|---|
| paciente | Paciente · al SII: CodRef «PACIENTE» · hasta 90 caracteres · ej.: Josefa Martínez Rojas, RUT 18.456.789-K |
| profesional | Profesional tratante · al SII: CodRef «PROFESIONAL» · hasta 90 caracteres · ej.: Tomás Vera Lagos, RUT 15.234.567-4, kinesiólogo |
| prevision | Previsión · al SII: CodRef «PREVISION» · hasta 40 caracteres · ej.: Isapre |
| mascota | Mascota · al SII: CodRef «MASCOTA» · hasta 90 caracteres · ej.: Toby, canino, ficha 2231 |
| proximoControl | Próximo control · solo el impreso · hasta 40 caracteres · ej.: 14-11-2026 |
| mesa | Mesa · solo el impreso · hasta 20 caracteres · ej.: 12 |
| comensales | Personas · solo el impreso · hasta 10 caracteres · ej.: 3 |
| vehiculo | Vehículo · al SII: CodRef «VEHICULO» · hasta 90 caracteres · ej.: HJKL-32, Toyota Yaris 2019 |
| kilometraje | Kilometraje · al SII: CodRef «KILOMETRAJE» · hasta 20 caracteres · ej.: 84.210 km |
| ordenTrabajo | Orden de trabajo · al SII: CodRef «ORDEN TRABAJO» · hasta 30 caracteres · ej.: 3312 |
| patente | Patente · al SII: CodRef «PATENTE» · hasta 12 caracteres · ej.: GHTR-45 |
| entrada | Entrada · al SII: CodRef «ENTRADA» · hasta 20 caracteres · ej.: 14-10-2026 14:02 |
| salida | Salida · al SII: CodRef «SALIDA» · hasta 20 caracteres · ej.: 14-10-2026 16:39 |
| alumno | Alumno · al SII: CodRef «ALUMNO» · hasta 90 caracteres · ej.: Tomás Rivas Muñoz, Nivel Medio Mayor |
| origen | Origen · al SII: CodRef «ORIGEN» · hasta 90 caracteres · ej.: Los Militares 5620, Las Condes |
| destino | Destino · al SII: CodRef «DESTINO» · hasta 90 caracteres · ej.: 5 Norte 845, Viña del Mar |
| conductor | Conductor · al SII: CodRef «CONDUCTOR» · hasta 90 caracteres · ej.: Luis Paredes |
| ordenServicio | Orden de servicio · al SII: CodRef «ORDEN SERVICIO» · hasta 30 caracteres · ej.: 588 |
| huesped | Huésped · al SII: CodRef «HUESPED» · hasta 90 caracteres · ej.: Andrea Soto Pino |
| habitacion | Habitación · al SII: CodRef «HABITACION» · hasta 20 caracteres · ej.: 204 |
| evento | Evento · al SII: CodRef «EVENTO» · hasta 90 caracteres · ej.: Concierto de primavera |
| fechaEvento | Fecha del evento · al SII: CodRef «FECHA EVENTO» · hasta 20 caracteres · ej.: 20-11-2026 21:00 |
| lugar | Lugar · al SII: CodRef «LUGAR» · hasta 90 caracteres · ej.: Teatro Municipal de Viña del Mar |
| ubicacion | Ubicación · al SII: CodRef «UBICACION» · hasta 60 caracteres · ej.: Platea, fila F, asiento 12 |
Los rubros y los datos que usa cada uno. El rubro de tu negocio lo confirmamos contigo y lo ajustas en Configuración → «Tu boleta»; con boleta.rubro lo eliges en cada boleta. El asterisco marca lo que pide la pantalla de FacturaLibre: la API no lo exige.
| rubro | Qué es y qué datos usa |
|---|---|
| general | General (Servicios profesionales, consultorías, publicidad y todo lo demás): sin datos propios |
| salud | Salud (Consultas, kinesiología, dental, psicología, nutrición, laboratorio): profesional, paciente, prevision |
| veterinaria | Veterinaria (Clínicas veterinarias, laboratorios veterinarios, peluquería de mascotas): mascota, profesional, proximoControl |
| tienda | Tienda (Vestuario, calzado, ferretería, librería, tecnología, repuestos): sin datos propios |
| almacen | Almacén (Almacenes, minimarkets, botillerías, panaderías): sin datos propios |
| restaurante | Restaurante (Restaurantes, cafeterías, bares, comida rápida): mesa, comensales |
| belleza | Belleza (Peluquerías, barberías, estética, spa, manicure): sin datos propios |
| taller | Taller (Mecánica, desabolladura, servicio técnico, reparación de equipos): vehiculo, kilometraje, ordenTrabajo |
| estacionamiento | Estacionamiento (Estacionamientos de superficie y subterráneos): patente, entrada, salida |
| mensual | Servicio mensual (Gimnasios, suscripciones, internet, condominios, arriendo de equipos, software): período, codigoCliente, saldoAnterior |
| educacion | Educación (Jardines infantiles, preuniversitarios, academias, capacitación): alumno, período, codigoCliente |
| transporte | Transporte (Fletes, mudanzas, carga, transporte de pasajeros, turismo): origen, destino, vehiculo, conductor, ordenServicio |
| hoteleria | Hotelería (Hoteles, hostales, cabañas, apart hotel): habitacion, entrada, salida |
| eventos | Eventos (Conciertos, teatro, deportes, ferias, cursos de un día): evento, fechaEvento, lugar, ubicacion |
Servicios periódicos (un gimnasio, una suscripción, un jardín infantil): el período va en periodoDesde/periodoHasta, el vencimiento en fechaVencimiento y lo que se arrastra en saldoAnterior. Con período y sin indServicio, el rubro mensual y el de educación van con IndServicio 1 (servicios periódicos); los demás, con el 3 de siempre. Con saldo anterior, el XML lleva TotalPeriodo (lo de este período, igual al total), SaldoAnterior y VlrPagar (la suma); el total del documento no cambia. En el ejemplo: TotalPeriodo $23.990, SaldoAnterior $4.500 y VlrPagar $28.490.
{
"tipoDte": 39,
"receptor": {
"rut": "16789012-1",
"razonSocial": "Andrés Soto Pino",
"email": "andres@correo.cl"
},
"lineas": [
{ "nombre": "Plan Pro, octubre 2026", "cantidad": 1, "precioUnitario": 23990 }
],
"fechaVencimiento": "2026-11-10",
"boleta": {
"rubro": "mensual",
"medioPago": "transferencia",
"codigoCliente": "SOC-0042",
"periodoDesde": "2026-10-01",
"periodoHasta": "2026-10-31",
"saldoAnterior": 4500
}
}Sobre 135 UF la ley exige identificar a quien paga (Ley 21.713 y Res. Ex. SII 44/2025, para lo emitido desde el 1 de septiembre de 2025). Una boleta cuyo total pasa de $5.363.275 —el umbral de 2026: 135 × la UF del 31 de diciembre de 2025— necesita el RUT de quien paga (no el genérico 66666666-6), sus nombres y apellidos en receptor.razonSocial y boleta.medioPago; el teléfono y el correo siguen siendo opcionales. Si falta algo, la rechazamos antes de tomar folio con 400 (lo mismo responde POST /documentos/validar): error dice qué falta y campo dónde (receptor, o boleta → medioPago si solo falta el medio de pago).
HTTP/1.1 400 Bad Request
{
"error": "Esta boleta es de $6.000.000: sobre $5.363.275 (135 UF) la ley exige identificar a quien paga (Ley 21.713). Falta el RUT de quien paga, sus nombres y apellidos y el medio de pago. (receptor)",
"campo": "receptor"
}Con los precios en otra unidad (monedaPrecios) el total en pesos se conoce al convertirlos, en la emisión: ahí el mismo rechazo llega como 422, también antes de tomar folio.
En la respuesta, en el webhook, en GET /documentos/{id} y en el listado, el documento trae boleta con lo que se guardó (cada campo siempre presente, null si no vino) y receptor.telefono. Los dos son null en facturas, notas y guías, y en una boleta que no los trajo:
"receptor": { "rut": "18456789-K", "razonSocial": "Josefa Martínez Rojas", …, "telefono": "+56 9 8765 4321" },
"boleta": {
"rubro": "salud", "medioPago": "debito",
"caja": null, "cajaNombre": null, "vendedor": "TV01", "vendedorNombre": "Tomás Vera Lagos",
"codigoCliente": null, "periodoDesde": null, "periodoHasta": null, "saldoAnterior": null,
"efectivoRecibido": null, "propina": null,
"datos": { "profesional": "Tomás Vera Lagos, RUT 15.234.567-4, kinesiólogo", "prevision": "Isapre" }
}Eventos: emitir sin saber de DTE
POST /eventos es la puerta para sistemas que no hablan tributario: un ecommerce, un POS, un Zapier. Le cuentas la venta — los ítems al precio final que pagó el cliente (con IVA) y quién compró — y nosotros decidimos el documento: factura si el cliente trae RUT, razón social, giro, dirección y comuna; boleta en cualquier otro caso (y la variante exenta si todos los ítems lo son). La decisión tomada viaja en la respuesta, en decision, para tu propio registro.
curl -X POST https://app.facturalibre.cl/api/v1/eventos \
-H "Authorization: Bearer fl_live_su_clave" \
-H "Content-Type: application/json" \
-d '{
"tipo": "venta",
"origen": "mi-sistema",
"referencia": "orden-1042",
"cliente": { "nombre": "Juana Pérez", "email": "juana@correo.cl" },
"items": [
{ "nombre": "Suscripción mensual", "cantidad": 1, "precioUnitario": 12990 }
]
}'HTTP/1.1 201 Created
{
"documento": { "id": "8a1b…", "tipoDte": 39, "folio": 35012, "estado": "firmado", … },
"decision": {
"tipoDte": 39,
"motivo": "cliente sin datos tributarios completos → boleta"
},
"enviado": false
}- La idempotencia es del evento:
(origen, referencia)emite UNA vez, reintentes lo que reintentes. La referencia es tu número de orden. - Puedes forzar con
documento: "boleta"o"factura"(esta última exige los datos tributarios del cliente). - Si al convertir precios con IVA a netos de factura el redondeo mueve el total en algún peso, te lo decimos en
aviso— nunca en silencio. - Una boleta nueva se envía al SII como en
POST /documentos: dentro de la petición, con el mismo plazo, y la respuesta trae el documento como quedó (enviadosi el SII ya la recibió). El reintento del mismo evento responde al tiro con su folio. - Nuestro plugin de WooCommerce usa exactamente este endpoint: cualquier integración puede hacer lo mismo con una llamada.
Folios: nos encargamos nosotros
No tienes que gestionar folios. Los folios (los CAF que autoriza el SII) los solicitamos, cargamos y reabastecemos nosotros, de forma 100% automática, por cada tipo de documento. No pides folios, no cargas CAF, no vigilas el stock: tu sistema solo emite.
- Reabastecimiento automático: cuando el stock de un tipo baja, pedimos el siguiente CAF al SII solos, antes de que se agote. Es un proceso continuo de nuestro lado, invisible para ti y para tu cliente.
- Si en un instante puntual una factura no encuentra folio, no falla: queda en estado
en_esperay la emitimos solas en cuanto hay folios (típicamente minutos). TuPOSTresponde 201 con ese estado; el veredicto final llega por webhook. No reintentes: ya está encolada. - El único límite es la cantidad de timbraje que el SII te tenga autorizada —algo que depende de tu situación ante el SII, no de esta API—. Si alguna vez hay que gestionarlo, lo vemos nosotros contigo; tu integración no necesita hacer nada.
Idempotencia
Manda Idempotency-Key (8–80 caracteres, p. ej. el id de tu pedido) en cada emisión. Reintentar con la misma clave jamás emite dos veces ni consume otro folio. La garantía es un índice único en la base, no una caché — sobrevive a instancias paralelas.
Cuándo es seguro reintentar con la misma clave: casi siempre. Ante cualquier duda —un 500, un timeout, una respuesta que no llegó— repite el request con la misma Idempotency-Key. Si el documento ya avanzó, te devolvemos ese mismo documento (200) en vez de crear otro. Si otra petición con esa clave lo está emitiendo en ese momento, te decimos que está en curso (reintentable: true, codigo: "en_curso" y Retry-After: 3): repite con la misma clave. Y si un intento anterior se cortó después de tomar el folio y antes de firmarlo, el reintento del mismo día lo retoma con ese mismo folio: te devolvemos el documento firmado.
Hay dos casos en que debes usar una clave nueva, y te lo decimos explícitamente con un 422, siempre con reintentable: false. codigo: "clave_agotada": el intento de esa clave tomó un folio y se cortó antes de firmar en otro día (una boleta solo se firma con la fecha de hoy); ese folio se anula ante el SII y te devolvemos ese documento en el error. Emite con una clave nueva: no se duplica, porque ese documento nunca llegó al SII. Y sin código, cuando un intento anterior tomó el folio y falló de forma irreversible (por ejemplo, el certificado vencido al firmar): ese folio queda registrado y no se reutiliza; corrige la causa antes de usar una clave nueva, o volvería a fallar igual. Nunca tienes que adivinar: o te devolvemos el documento, o te decimos que vuelvas en segundos, o te pedimos la clave nueva.
| Estado del intento previo | Qué pasa al reintentar con la misma clave |
|---|---|
| enviado / aceptado / rechazado | Te devolvemos ese documento (200). No dupliques. |
| firmado | Emitido, esperando al SII. Te devolvemos ese documento (200). |
| en_espera | Sin folios, se emitirá solo. Te devolvemos ese documento (200). |
| error sin folio (p. ej. sin_folios) | No consumió nada: se emite de nuevo al instante con esa misma clave. |
| borrador en curso | Otra petición con la misma clave lo está emitiendo ahora: `reintentable: true`, `codigo: "en_curso"` y `Retry-After: 3`, con el documento. Sin folio todavía, 200 (sin folio); con el folio ya tomado, 422. Repite con la MISMA clave. |
| borrador cortado, hoy | Se cortó entre el folio y la firma: se retoma con EL MISMO folio y te devolvemos el documento firmado (200). |
| borrador cortado, otro día | 422 `codigo: "clave_agotada"`, `reintentable: false`, con el documento quemado: usa una clave nueva. |
| error con folio tomado | La firma o el SII lo rechazó: 422 sin código, `reintentable: false`. Corrige la causa y usa una clave nueva (ese folio no se reutiliza). |
Consultar y listar
GET /documentos/{id} devuelve el documento; GET /documentos lista con filtros (estado, tipoDte, folio, receptorRut, desde/hasta, limit hasta 100) y paginación por cursor: usa el siguienteCursor de cada respuesta hasta que venga null.
Para reconciliar cuando perdiste la respuesta de un POST, filtra por tu clave: GET /documentos?idempotencyKey=pedido-8841 devuelve el documento de esa clave (o una lista vacía si nunca se emitió). Cada documento incluye su idempotencyKey en la respuesta.
La clave es por ambiente: la misma Idempotency-Key con tu fl_test_ y con tu fl_live_ son dos documentos, y cada clave encuentra solo los de su ambiente. Una clave no puede empezar con sandbox: ni con prop: (están reservados).
| Estado | Qué significa |
|---|---|
| borrador | Borrador programado (`borrador: true`): sin folio todavía, se emite solo en `autoAdvanceAt` |
| firmado | Folio y timbre asignados; el envío al SII está en curso. Una boleta (39/41) firmada ya es válida y se entrega (`entregable: true`): si el SII no la recibe (caído, lento, 403, 429, certificado), sigue firmada y se reintenta sola; no pasa a `error` |
| enviado | El SII lo recibió (hay trackId); espera veredicto. Una boleta con «envío repetido» (RPT) del SII se queda aquí, entregable, hasta que la confirmamos con el envío original (nunca `rechazado` ni `dte.rechazado` por eso); si el SII confirma que no encuentra su envío (lo repite en una segunda consulta, 10 minutos o más después), vuelve a `firmado` y se sube de nuevo el mismo documento con otro trackId, a lo más 3 veces. Una exportación (110, 111, 112) que se subió de nuevo porque la primera subida quedó en duda también se queda aquí si el SII rechaza esa nueva subida, sin `dte.rechazado`, hasta que confirmamos con el SII cuál de los envíos vale; y una factura, nota, guía o exportación cuyo envío el SII procesa sin contarla como aceptada nunca se da por aceptada |
| aceptado | Aceptado por el SII — terminal |
| aceptado_reparos | Aceptado con reparos — terminal, revisa siiGlosa |
| rechazado | Rechazado por el SII — terminal, el folio quedó consumido |
| en_espera | Sin folios disponibles; se emitirá solo (solo facturas) |
| error | No se pudo completar la emisión; revisa siiGlosa. Una boleta ya firmada nunca llega aquí por un problema al enviarla al SII |
| anulado | Anulado por una nota de crédito posterior |
| respuestaReceptor | Aparte del estado ante el SII: lo que el SOFTWARE DE TU CLIENTE respondió por la casilla de intercambio, si respondió. `estado`: recibido (acuse técnico) · aceptado · aceptado_discrepancias · reclamado (Ley 19.983) · recibo_mercaderias (la aceptación que da mérito ejecutivo), con la `fecha` de la respuesta. null mientras no responda. Es lo que él dijo, con su firma; la autoridad sobre lo aceptado sigue siendo el SII |
PDF y XML
GET /documentos/{id}/pdf entrega la representación impresa (con timbre PDF417) y GET /documentos/{id}/xml el DTE firmado (?sobre=1 para el sobre de envío completo). El PDF responde 409 solo mientras el documento no tiene folio (borrador o en_espera), y el XML mientras no está firmado (eso, o un documento que falló al firmarse y quedó en error); desde firmado los dos existen. El PDF de una boleta (39/41) firmada o enviada es la boleta del cliente y se entrega al emitirse, sin marca de agua —es lo que dice entregable: true—: la Res. Ex. SII 74/2020 pide entregarla en el momento de la venta, y su envío al SII lo hace nuestra cola, con reintentos. El de una factura, nota o guía firmada sale con la marca «PENDIENTE DE ENVÍO AL SII» hasta que el SII la recibe; para entregarla, espera el webhook dte.aceptado o vuelve a consultar. Uno rechazado, con error o anulado lo dice en su propia marca de agua («RECHAZADO POR EL SII», «CON ERROR», «ANULADO»). El PDF también le llega solo por correo al receptor si la emisión trae su email. Si prefieres entregarlo tú, manda "enviarEmail": false en cada emisión: el documento se emite igual y no sale ningún correo de nuestra parte, ni a la persona ni a la casilla de intercambio del software de tu cliente. La excepción: si tu cliente también usa FacturaLibre y no indicas otra casilla (ni la hay en tu libreta para ese RUT), su casilla es nuestra y el documento entra igual a sus compras al aceptarlo el SII (la Res. Ex. SII 45/2003 pide entregarle el ejemplar electrónico al receptor electrónico, y nadie más puede dejarlo ahí).
Para no depender de recordar el flag en cada request, puedes apagar el envío a nivel de toda la empresa desde Integraciones → API → Correo al receptor. Con eso, ninguna emisión de la empresa manda correo a la persona ni a la casilla externa del receptor, aunque el request pida enviarEmail: true — defensa en profundidad para cuando eres tú quien entrega los documentos. Lo emitido a un cliente que también usa FacturaLibre entra igual a sus compras, salvo que indiques otra casilla (o la haya en tu libreta para ese RUT).
El XML se entrega como archivo binario: Content-Type: application/octet-stream con Content-Disposition: attachment y el nombre del archivo terminado en .xml. Los bytes son el XML tal como se firmó, en ISO-8859-1 (lo declara su primera línea): una «ñ» o una tilde es un byte, y la firma verifica sobre esos mismos bytes. Léelo como bytes, no como texto UTF-8; si lo conviertes, conviértelo desde ISO-8859-1. Hasta el 24-10-2026 la respuesta decía application/xml e inline; el contenido no cambió, solo la cabecera, para que ningún intermediario lo recodifique en el camino.
Cotizaciones
Tu sistema puede crear y actualizar cotizaciones en FacturaLibre, y tu cliente (la persona del negocio) las factura después desde el portal con un clic. Una cotización no es un documento tributario: no toca al SII ni consume folios. La numeración es la de siempre de tu empresa, y los montos los calcula el servidor con la misma aritmética de una factura, así que lo cotizado y lo facturado cuadran peso a peso.
curl -X POST https://app.facturalibre.cl/api/v1/cotizaciones \
-H "Authorization: Bearer fl_live_su_clave" \
-H "Content-Type: application/json" \
-d '{ "origen": "mi-tienda", "referencia": "cotizacion-8841", "tipoDte": 33,
"receptor": { "rut": "76.086.428-5", "razonSocial": "Constructora Andes SpA" },
"lineas": [{ "nombre": "Casco de seguridad", "cantidad": 10, "precioUnitario": 10000 }],
"validezDias": 15 }'
# → 201 Created (la primera vez; 200 OK si ya existía y se actualizó)
{
"cotizacion": {
"id": "f3b1…", "numero": 12, "origen": "mi-tienda", "referencia": "cotizacion-8841",
"estado": "enviada", "tipoDte": 33,
"fechaEmision": "2026-10-18", "validaHasta": "2026-11-02",
"receptor": { "rut": "76086428-5", "razonSocial": "Constructora Andes SpA" },
"montos": { "neto": 100000, "exento": 0, "iva": 19000, "total": 119000 },
"documento": null,
"urlEmitir": "https://app.facturalibre.cl/emitir?cotizacion=f3b1…",
"urlPortal": "https://app.facturalibre.cl/cotizaciones?q=12"
}
}origen(tu sistema: 2 a 30 caracteres, minúsculas, números y guiones) yreferencia(tu id: hasta 80 caracteres, letras, números y. _ : -) son la llave de idempotencia: el mismo par es siempre la misma cotización, aunque dos peticiones lleguen a la vez (la base deja pasar una sola).- El resto del cuerpo es el de una cotización del portal:
tipoDte(33 o 34, obligatorio),receptor(razonSocialobligatoria; el RUT es opcional, se exige al facturar),lineas,descuentoGlobal,observacionesyvalidezDias(1 a 120; por omisión 30). Mismos largos máximos que en los límites.enviarEmailse rechaza (422): FacturaLibre no le envía nada al cliente final de tu negocio (ni el link público de la cotización, que la respuesta tampoco trae). La cotización que tu cliente ve es la tuya: tu propia página o tu propio PDF. - 201 si era nueva. Si ya existía, estaba
enviada(tambiénvencida) y no tiene factura, el POST la actualiza (receptor, líneas, descuento, observaciones, tipo y montos; lo que no mandes del receptor se borra) y responde 200; conserva su número, su estado y su fecha de emisión, y la validez solo cambia si mandasvalidezDias(así renuevas una vencida). Repetir el mismo cuerpo es seguro. - Dos casos no se tocan y responden 409 con la cotización tal como está:
codigo: "cotizacion_facturada"si ya tiene una factura viva (o se está facturando en ese instante; una factura rechazada por el SII o con error no cuenta), ycodigo: "cotizacion_respondida"si el cliente ya la aceptó o rechazó (o la marcaron a mano). En los dos, crea otra con otrareferencia. estado:enviada,aceptada,rechazada(lo que respondió el cliente desde su link),vencida(unaenviadacuya validez ya pasó; se calcula al leer) yfacturada(con sudocumento). La respuesta no trae el token del link público del cliente final.urlEmitirlleva a la persona al formulario de emisión con la cotización cargada;urlPortala la cotización en su panel. Piden iniciar sesión en el portal.- Alcance de la clave: no hay permisos por clave ni por
origen. Cualquier clave de la empresa puede leer y reescribir las cotizaciones de cualquierorigen(y las que nacieron en el portal no, porque no tienen origen). Cada llamada queda auditada con el id de la clave. - Reintentos: un 5xx o un 503 (
reintentable: true, conRetry-After) se repite con el mismo origen y referencia, que es la llave de idempotencia de este endpoint;Idempotency-Keyno se usa aquí.
HTTP/1.1 409 Conflict
{
"error": "Esta cotización ya se factura (o se está facturando): no se puede modificar. Crea otra con otra referencia.",
"codigo": "cotizacion_facturada",
"cotizacion": { "id": "f3b1…", "estado": "facturada", "documento": { "id": "9c41…", "tipoDte": 33, "folio": 4321, "estado": "aceptado" }, … }
}GET /cotizaciones?origen=…&referencia=… devuelve { "cotizacion": … }, o 404 si no existe para tu clave (empresa y ambiente: una clave de pruebas no ve las reales). Un parámetro mal escrito es 400; un cuerpo del POST inválido (un campo mal escrito o desconocido, un monto que no cuadra, enviarEmail), 422 con el campo que falló (en este endpoint, a diferencia de /documentos, que responde 400). El POST es una escritura: consume el límite por minuto de la clave, como la emisión (los GET, no).
Receptores: autocompletar
Para que quien factura desde tu sistema escriba solo el RUT del cliente: GET /receptores/{rut} devuelve lo que el SII registra de ese RUT, que es lo mismo con que el portal llena el receptor al emitir: la razón social, los giros con su código de actividad, las direcciones inscritas y si es un contribuyente vigente. Son datos públicos del SII: la respuesta es la misma para cualquier empresa que pregunte y no trae nada de la tuya.
curl https://app.facturalibre.cl/api/v1/receptores/76.086.428-5 \
-H "Authorization: Bearer fl_live_su_clave"
# → 200 OK
{
"receptor": {
"rut": "76086428-5",
"razonSocial": "CONSTRUCTORA ANDES SPA",
"vigente": true,
"giro": "CONSTRUCCION DE EDIFICIOS PARA USO RESIDENCIAL",
"giros": [
{ "codigo": 410010, "glosa": "CONSTRUCCION DE EDIFICIOS PARA USO RESIDENCIAL", "afectaIva": true },
{ "codigo": 410020, "glosa": "CONSTRUCCION DE EDIFICIOS PARA USO NO RESIDENCIAL", "afectaIva": true }
],
"direcciones": {
"matriz": { "direccion": "AV APOQUINDO 4500 OF 1201", "comuna": "Las Condes" },
"sucursales": [{ "direccion": "CAMINO A MELIPILLA 9800", "comuna": "Maipú" }],
"fechaNomina": "2026-08-03"
},
"consultadoAt": "2026-10-24T13:05:12.000Z"
}
}- El RUT va en la ruta con o sin puntos, con guion o sin él, y el dígito verificador K en mayúscula o minúscula. Uno con el dígito verificador malo responde 400 con
codigo: "rut_invalido"ycampo: "rut". girosva en el orden del SII ygiroes el primero (null si no registra ninguno). Al emitir, el giro del receptor se trunca a 40 caracteres.direccionessale de la nómina pública de direcciones del SII: la casa matriz y las sucursales vigentes, con la fecha de corte de la nómina enfechaNomina. La nómina trae solo personas jurídicas: para una persona natural, o un RUT que no está en ella, vienenully la dirección se escribe a mano.vigentees la misma regla que aplica la emisión antes de tomar folio: el SII registra datos para ese RUT. Si no los registra, la respuesta es 404 concodigo: "receptor_sin_datos"yvigente: false: con tu clave de producción, una factura a ese RUT se rechaza antes de tomar folio conreceptor_no_vigente(abajo).- Una persona natural sin inicio de actividades está registrada en el SII, pero el registro público no muestra su nombre. Para ella la respuesta es 404 con el mismo
codigoydatosPublicos: false, sinvigente. Sí se le puede facturar: escribe su nombre, giro y dirección. El SII contesta lo mismo para un RUT mal escrito, así que si esperabas una empresa, revísalo. - Guardamos la respuesta del SII: lo que registra se reutiliza 7 días y lo que no registra, 1 día.
consultadoAtdice cuándo la guardamos. Si el registro del SII no responde, devolvemos lo último que registraba de ese RUT, si lo guardamos en los últimos 30 días; si no, 503 concodigo: "sii_no_disponible",reintentable: trueyRetry-After: 60: reintenta después o deja escribir los datos a mano. - Límite: 30 consultas por minuto por clave y 1.000 por día por empresa (y un techo del servicio de 20.000 al día entre todas); pasado eso, 429 con
codigo: "limite_receptores"yRetry-After. No consume el límite por minuto de la emisión. - Responde igual con
fl_live_y confl_test_: en el ambiente de pruebas también son los datos reales del SII, así que pruebas tu autocompletado con los RUT de tus clientes.
HTTP/1.1 404 Not Found
{
"error": "El SII no registra datos para el RUT 77.000.001-7: no es un contribuyente vigente y una factura a ese RUT se rechazaría (receptor_no_vigente). Revisa el RUT.",
"codigo": "receptor_sin_datos",
"rut": "77000001-7",
"vigente": false
}HTTP/1.1 404 Not Found
{
"error": "El SII no publica datos para el RUT 12.345.678-5. Suele ser una persona sin inicio de actividades: se le puede facturar escribiendo su nombre, giro y dirección. Si esperabas una empresa, revisa el RUT.",
"codigo": "receptor_sin_datos",
"rut": "12345678-5",
"datosPublicos": false
}Sucursales y patente
Si emites desde varios locales con el mismo RUT, registra cada uno en el portal (Datos maestros → Sucursales) y, si lo tienes, el código de sucursal que te dio el SII. Cada una tiene un codigo que se arma solo con el nombre («Estación Colina» → ESTACION-COLINA); lo ves y lo cambias en «Código para integraciones (API)», y GET /sucursales los lista. Al emitir mandas sucursal con ese código y el documento sale con el domicilio del local: en el XML, Sucursal, CdgSIISucur y DirOrigen/CmnaOrigen (la boleta no tiene nombre de sucursal en su formato: lleva el código y el domicilio), y en el impreso, el domicilio del local. En una guía, el origen del traslado es ese local. Sin sucursal, la casa matriz, como siempre. La respuesta trae sucursal (código, nombre y código del SII) y patente.
GET /sucursales lista las registradas, con activa: false en las desactivadas (desde esas no se emite). Una sucursal que no existe o está desactivada se rechaza antes de tomar folio, también en /documentos/validar.
patente: quien vende combustible pone en sus facturas y guías la patente del vehículo que carga (Res. Ex. SII 52/2015, en el campo Patente del área Transporte). En una factura que no ampara traslado va sola en Transporte, sin volverla una factura de traslado; en una guía, es la del transporte. Sale también impresa.
curl https://app.facturalibre.cl/api/v1/sucursales -H "Authorization: Bearer fl_test_…"
→ { "sucursales": [ { "codigo": "CHICUREO", "nombre": "Chicureo", "codigoSii": 81234567,
"direccion": "Av. Chicureo 1234", "comuna": "Colina", "ciudad": "Santiago", "activa": true } ] }
POST https://app.facturalibre.cl/api/v1/documentos
{ "tipoDte": 33, "sucursal": "CHICUREO", "patente": "ABCD12", "receptor": { … }, "lineas": [ … ] }Webhooks
Registramos hasta 3 endpoints https por empresa. Cada evento llega firmado con tu secreto whsec_ (se muestra una vez al crear el endpoint):
POST https://tu-sistema.cl/webhooks/facturalibre
FacturaLibre-Firma: t=1754920000,v1=ab12…
FacturaLibre-Evento: dte.aceptado
FacturaLibre-Entrega: 9c41… ← dedupe: procesa cada id una sola vez
{
"id": "9c41…",
"evento": "dte.aceptado",
"creadoEn": "2026-08-11T14:05:10.000Z",
"datos": {
"documento": {
"id": "5f0c…",
"tipoDte": 33,
"folio": 124,
"estado": "aceptado",
"ambiente": "produccion",
"fechaEmision": "2026-08-11",
"receptor": { "rut": "76543210-3", "razonSocial": "Cliente SpA", "giro": "Comercio", "direccion": "Providencia 1234", "comuna": "Providencia", "email": "facturas@cliente.cl" },
"montos": { "neto": 100000, "exento": 0, "iva": 19000, "total": 119000 },
"respuestaReceptor": { "estado": "recibido", "fecha": "2026-08-12T15:22:52.000Z" },
"trackId": "12355834916",
"siiGlosa": null,
"idempotencyKey": "pedido-8841",
"createdAt": "2026-08-11T14:03:22.000Z"
}
}
}| Evento | Cuándo llega |
|---|---|
| dte.en_espera | Sin folios en el instante: quedó en cola y se emitirá solo — espera el dte.aceptado, no reintentes |
| dte.enviado | El SII recibió el documento (trae trackId). Si la boleta subió dentro de su propio POST (en el ambiente de pruebas, cualquier documento), este aviso sale después por nuestra cola (en segundos o pocos minutos): la respuesta del POST ya traía `enviado` con su trackId. En una boleta puede llegar otra vez, con otro trackId, si el SII confirmó que no encuentra el envío anterior y se subió de nuevo (a lo más 3 veces) |
| dte.aceptado | Veredicto: aceptado |
| dte.aceptado_reparos | Veredicto: aceptado con reparos |
| dte.rechazado | Veredicto: rechazado (en una boleta, solo por un rechazo del documento mismo: nunca por un «envío repetido» (RPT) ni por un error del canal con el SII: 403, 429, token o certificado; en una exportación, el rechazo de una nueva subida solo después de confirmarlo con el SII) |
| dte.error | La emisión no se pudo completar (nunca por un problema al enviar al SII una boleta ya firmada: esa sigue firmada y se reintenta) |
| dte.cedido | La cesión de la factura quedó anotada en el Registro de Cesiones del SII (POST /documentos/{id}/ceder) |
El cuerpo es el mismo para todos los eventos: { id, evento, creadoEn, datos: { documento } }. Lo único que cambia es el string evento. El documento es el mismo objeto que devuelve GET /documentos/{id}. En dte.rechazado y dte.aceptado_reparos, el motivo del SII viene como texto en datos.documento.siiGlosa (es null cuando no hay glosa):
{
"id": "9c41…",
"evento": "dte.rechazado",
"creadoEn": "2026-08-11T14:07:02.000Z",
"datos": { "documento": {
"id": "5f0c…", "folio": 124, "estado": "rechazado",
"siiGlosa": "DTE con folio fuera de rango autorizado", // ← el motivo del SII, texto
…
} }
}Verifica SIEMPRE la firma antes de procesar — sobre el body crudo, tal como llegó (re-serializar el JSON cambia los bytes y rompe la verificación):
import { createHmac, timingSafeEqual } from "node:crypto"
export function verificarFirma(req: { headers: Headers; bodyCrudo: string }): boolean {
const firma = req.headers.get("facturalibre-firma") ?? "" // "t=1754920000,v1=ab12…"
const partes = Object.fromEntries(firma.split(",").map((p) => p.split("=", 2)))
const t = Number(partes["t"])
if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false // tolerancia 5 min
const esperado = createHmac("sha256", process.env.FACTURALIBRE_WHSEC!)
.update(`${t}.${req.bodyCrudo}`) // el body CRUDO, sin re-serializar
.digest("hex")
const a = Buffer.from(esperado)
const b = Buffer.from(partes["v1"] ?? "")
return a.length === b.length && timingSafeEqual(a, b)
}- Prueba tu verificación sin emitir nada: en Integraciones → Webhooks, «Enviar una prueba» manda un evento
pruebafirmado con el secreto de ese endpoint, con el mismo sobre ({ id, evento: "prueba", creadoEn, datos }, dondedatostrae tu empresa y una nota, sin documento). Es de una sola vez: si no responde 2xx no se reintenta ni cuenta como fallo del endpoint. Tratapruebacomo un evento más: verifica la firma y responde 2xx. - Responde 2xx rápido (antes de 5 segundos) y procesa después; otra respuesta cuenta como fallo.
- Reintentamos con backoff durante ~44 horas. Deduplica por
FacturaLibre-Entrega: el mismo id puede llegar más de una vez. - Tras demasiados fallos seguidos el endpoint se desactiva solo y avisamos por correo a los dueños de la empresa. Puedes reactivarlo desde el panel cuando tu servicio vuelva a estar arriba.
Desde Integraciones → API gestionas los webhooks a mano: ves el log de últimas entregas con su estado, código HTTP y error; reintentas una entrega puntual (para depurar «¿me llegó y lo perdí, o nunca salió?»); rotas el secreto whsec_ sin recrear el endpoint (el nuevo se muestra una vez; actualízalo en tu servidor); y reactivas un endpoint caído.
Boletas de honorarios (BHE)
Para cuentas de persona natural (plan Honorarios). La BHE no es un DTE: la emite el SII a nombre del titular, con la retención vigente calculada por el propio SII, y no tiene ambiente de prueba — solo aceptan claves fl_live_ y cada POST crea un documento tributario real. El contrato es síncrono: la respuesta ya trae el número y el código de barras.
POST /v1/boletas-honorarios
{
"receptorRut": "76543210-K",
"receptorNombre": "Empresa Cliente SpA",
"receptorDomicilio": "Av. Providencia 1234",
"comunaCodigo": 15103,
"lineas": [{ "glosa": "Asesoría agosto 2026", "monto": 500000 }],
"fecha": { "dia": 18, "mes": 8, "anio": 2026 },
"retiene": "receptor",
"emailReceptor": "pagos@cliente.cl"
}retiene:receptor(la empresa que paga retiene — lo normal) oemisor. Los montos son brutos en CLP enteros; la retención y el líquido los calcula el SII y vuelven en la respuesta.GET /v1/boletas-honorarios?anio=&mes=lista lo emitido;GET /v1/boletas-honorarios/:id/pdfbaja el PDF oficial del SII.GET /v1/boletas-honorarios/emisiones/:llavedice qué pasó con unaIdempotency-Keysin repetir el POST ni tocar al SII:estadoesemitida(con la boleta),en_curso,en_revision(respetaRetry-After),no_emitida(repite el POST conconfirmarReemision, salvoyaHayUnaIgual) ofallida(conreintentable). 404 si la llave nunca se usó en la cuenta.Idempotency-Key(header o campo del cuerpo) es obligatoria: el mismo valor nunca emite una segunda boleta. La misma llave con otros datos responde 422 e indica qué pasó con la original (original.estado).- Un 502 con
ambigua: true— o un timeout/504, trátalo igual — significa que el SII no confirmó la emisión. Nosotros guardamos la intención y la verificamos con el SII. Reintenta con la MISMA Idempotency-Key (no con una nueva): te devolvemos la boleta si salió, o un 409 conenRevision: truemientras todavía no se sabe (respetaRetry-After). - Un 409 con
noEmitida: truesignifica que verificamos con el SII que esa boleta no salió. Si todavía la necesitas, repite la petición con la misma llave y"confirmarReemision": true(siempre, sin importar cuánto tiempo pasó). Si además traeyaHayUnaIgual, después se emitió otra boleta idéntica (mismo receptor, monto y fecha) y esa llave ya no emite: si de verdad necesitas otra igual, usa una llave nueva. - Un 409 con
igualEnRevision: truesignifica que OTRA emisión con el mismo receptor, monto y fecha todavía se está verificando con el SII y pudo haber salido: la tuya no se emitió. EsperaRetry-Aftery repite. - Un 429 con
pausado: truesignifica que nosotros pausamos los ingresos al SII con la clave de esa cuenta (varios intentos seguidos sin éxito; seguir podría bloquearla en el SII). La boleta no se emitió: reintenta con la misma llave después deRetry-After. - Un 409 con
enCurso: truesignifica que hay otra emisión corriendo para la misma cuenta; un 503, que el SII no está disponible ahora y la boleta no se emitió. En ambos, reintenta con la misma llave después deRetry-After. Un 422 son datos que el SII no acepta: reintentar igual no sirve. - Un 409 con
claveInvalida: truesignifica que el SII rechazó la clave tributaria guardada (el titular la cambió o su cuenta está bloqueada): se repone desde el portal y no se vuelve a probar la anterior.
Canal integrador (plataformas)
Para plataformas que emiten por muchos titulares (una agenda de profesionales, un marketplace): una credencial fl_canal_… con alcance a las cuentas que el canal crea, y un webhook único para todas. La credencial y el secreto del webhook se entregan a mano al integrar (no hay autoservicio). Cada cuenta persona la autoriza su titular: firma un mandato e ingresa su clave del SII en una página de FacturaLibre a la que llega por un enlace de un solo uso; el dueño del negocio nunca ve ni teclea claves.
POST /v1/canal/cuentas
Authorization: Bearer fl_canal_…
{ "refExterna": "emisor-123", "tipo": "persona",
"rut": "12.345.678-9", "email": "titular@correo.cl", "nombre": "Nombre Del Titular",
"mandato": { "nombre": "Nombre Del Titular", "rut": "12.345.678-9", "version": "2026-09-v1" } }
→ 201 { "cuenta": { "id": "…", "estado": "invitada", "clave": "sin_cargar", "puedeEmitir": false, … } }
POST /v1/canal/cuentas/{id}/enlace-clave → 201 { "url": "https://app.facturalibre.cl/canal/clave/…", "token": "…",
"enviarA": "https://app.facturalibre.cl/api/canal/clave", "venceAt": "…" }
GET /v1/canal/cuentas/{id}/mandato → { "version": "2026-09-v1", "texto": "MANDATO PARA…", "titular": { … }, "firmadoAt": null }
GET /v1/canal/cuentas/{id} → { "cuenta": { "estado", "clave", "puedeEmitir", "mandato": { "firmadoAt" }, … } }
POST /v1/canal/cuentas/{id}/revocar → { "cuenta": { "estado": "revocada", … } }El titular puede autorizar en la página de FacturaLibre (url) o en la página del propio canal: el canal muestra el texto de GET …/mandato (solo lectura, no gasta enlaces) y el navegador del titular envía { "token", "clave", "aceptaMandato": true } directo a enviarA. La clave nunca pasa por los servidores del canal. Ese endpoint no usa cookies y responde CORS solo al origen del webhook del canal (y sus hermanos www. y app.); los errores traen error en palabras y una marca (claveIncorrecta, vencido, siiCaido, pausado). Hay un tope de tres intentos por cuenta y por hora: una clave errada suma al bloqueo del titular en el SII.
Con la cuenta activa, el canal emite por ella con la misma credencial y el header X-Cuenta. En modo diferido la intención se encola y responde 202: la emite la cola y el resultado llega por webhook (o por GET /emisiones/{id}). La Idempotency-Key es obligatoria (usa el id del pago): repetirla devuelve 200 con el estado actual y jamás una segunda boleta. Una emisión fallida es la excepción útil: el mismo POST la vuelve a encolar (202) porque nada llegó al SII —una transitoria que agotó sus reintentos, una clave que ya se cargó de nuevo—; si FacturaLibre comprobó que NO se emitió (errorTipo: no_emitida), responde 409 noEmitida hasta que el POST traiga confirmarReemision: true, y se niega igual (409 con yaHayUnaIgual) si después salió una boleta idéntica por otra llave.
POST /v1/boletas-honorarios
Authorization: Bearer fl_canal_…
X-Cuenta: {cuentaId}
Idempotency-Key: pago-123
{ "modo": "diferido", "refExterna": "pago-123",
"receptorRut": "12.345.678-9", "receptorNombre": "Nombre Del Cliente", "receptorDomicilio": "Calle 1 234", "comunaCodigo": 13101,
"lineas": [{ "glosa": "Corte de pelo", "monto": 15000 }], "fecha": { "dia": 18, "mes": 9, "anio": 2026 }, "retiene": "emisor" }
→ 202 { "emision": { "id": "…", "estado": "en_curso", "refExterna": "pago-123", "boleta": null } }
→ 200 la misma emisión si la llave ya existe (en curso, en revisión o emitida)
→ 202 la misma emisión de nuevo en_curso si estaba fallida (se reencola)
→ 409 { "noEmitida": true, "emisionId": "…" } si estaba fallida no_emitida y no viene "confirmarReemision": true
GET /v1/boletas-honorarios/emisiones/{id} → { "emision": { "estado": "emitida", "boleta": { "numero", "codigoBarras", "liquido", … } } }
estado: en_curso · en_revision · emitida · fallida (errorTipo, errorDetalle, reintentable)
GET /v1/boletas-honorarios/{boletaId}/pdf → el PDF oficial del SII (archivado)refExternaes el id del emisor en tu plataforma y es única por canal: repetir el alta devuelve la misma cuenta (200). Un RUT que ya tiene cuenta en FacturaLibre responde 409rut_en_uso. Los errores traencodigolegible por máquina; un 4xx no se reintenta.- La cuenta emite cuando
puedeEmitires true: clave validada con UN login de prueba en el SII y mandato firmado. Mientras tanto el titular puede pedir otro enlace (invalida el anterior; duran 48 h). - Webhooks al canal, con el mismo sobre y firma que los de empresa:
cuenta.activa,cuenta.rechazada(con el texto del SII),cuenta.clave_invalida(una clave que servía dejó de servir) ycuenta.revocada. Y de cada emisión diferida:bhe.emitida(con la boleta),bhe.ambigua(el SII no confirmó: la concilia el cron, no la reintentes),bhe.fallida(conerrorTipo; las fallas transitorias no avisan porque la cola reintenta sola) ybhe.anulada(la conciliación la vio anulada en el SII). EndatosviajanemisionId,cuentaIdyemision(la misma forma del GET). Un mismo evento no se manda dos veces por la misma emisión. - Una cuenta ajena al canal responde 404, nunca 403: la API no confirma qué cuentas existen fuera de tu alcance.
Errores y límites
Todos los errores responden { "error": "…" } (y campo cuando la validación sabe señalarlo). La emisión (POST /documentos y /eventos) tiene un límite por minuto por clave; su estado viaja en los headers X-RateLimit-Limit / -Remaining / -Reset en la respuesta de emisión y en todo 429 (que además trae Retry-After). Los GET (consultas, PDF, XML) no consumen esa cuota, así que no llevan esos headers.
| Código | Qué significa |
|---|---|
| 400 | Cuerpo o parámetros inválidos; `campo` indica dónde. También una boleta sobre 135 UF que no identifica a quien paga (RUT, nombre y medio de pago): `error` dice qué falta, antes de tomar folio |
| 401 | Clave ausente, no válida o revocada. Una clave recién revocada (o una empresa recién suspendida) puede seguir respondiendo hasta 30 segundos: lo que tarda en enterarse cada servidor |
| 402 | La suscripción de la empresa no está al día |
| 403 | La clave no calza con el ambiente de la empresa, o la empresa no puede emitir (salvo durante una ventana de certificación de boletas: 503, abajo) |
| 404 | El documento (o la cotización) no existe para esta clave (empresa y ambiente). En `/receptores`, que el SII no registra el RUT (`codigo: "receptor_sin_datos"`, `vigente: false`) o que lo registra sin datos públicos, como una persona sin inicio de actividades (el mismo `codigo`, `datosPublicos: false`) |
| 409 | El recurso aún no está disponible o ya no admite la operación (p. ej. PDF de un documento que todavía no tiene folio o XML de uno que todavía no está firmado, un borrador que ya se emitió, una factura que no se puede ceder, una cotización que ya se factura, `codigo: "cotizacion_facturada"`, o que el cliente ya respondió, `codigo: "cotizacion_respondida"`; ambas con la `cotizacion`) |
| 422 | El SII o el motor rechazó la emisión; `error` trae el motivo, `reintentable` dice si vale la pena repetirlo con la MISMA Idempotency-Key, y `codigo` lo nombra: `sin_folios` (una boleta que sale sola en unos minutos), `original_en_proceso` (una nota sobre un documento que todavía no tiene veredicto del SII —firmado, en cola, esperando folios o enviado sin respuesta; una exportación, también mientras confirmamos con el SII una nueva subida, lo que puede tardar horas—: repítela cuando esté aceptado, con el webhook `dte.aceptado` o `dte.aceptado_reparos`) y `nota_en_curso` (otra nota sobre el mismo documento se está emitiendo: repítela en unos segundos), las tres con `reintentable: true`; `en_curso` (otra petición con tu misma Idempotency-Key ya tomó el folio y lo está firmando: repítela con la MISMA clave en los segundos que diga `Retry-After`, trae el `documento`) también con `reintentable: true`; y `clave_agotada` (el intento de esa clave tomó un folio y se cortó antes de firmar en otro día: ese folio se anula y con esa clave ya no sale; emite con una clave NUEVA, no se duplica; trae el `documento` quemado) con `reintentable: false`; `idempotencia_conflicto` (esa Idempotency-Key ya la usó OTRO documento —otro tipo o a otro receptor—: no se devuelve el anterior como si fuera este; emite con una clave nueva) con `reintentable: false`; también `falta_factura_anterior` (una 112 que corrige montos de una factura de exportación de tu software anterior cuyo total y tipo de cambio todavía no conocemos —ninguna nota los declaró y no tenemos su XML—, sin `exportacion.facturaAnterior`: manda los dos, como dice su PDF) con `reintentable: false`. Una nota que choca con el documento que corrige por lo que ya tiene (ya anulado, sin crédito que acreditar…) llega sin `codigo` y con `reintentable: false`: el porqué, con los montos, va en `error`. Lo mismo responden `POST /documentos/validar` y `PATCH /documentos/{id}`; `POST /eventos` responde los mismos campos, `receptor_no_vigente` (el registro público del SII dice que no registra el RUT del receptor: se rechaza ANTES de tomar folio, no es reintentable; corrige el RUT o pide a tu cliente que regularice su situación. Una persona sin inicio de actividades no se rechaza: el SII sí le acepta facturas); y `identificar_135_uf` (una boleta sobre 135 UF que solo la emisión pudo medir —precios en UF o un año nuevo— y no identifica a quien paga: completa el RUT, el nombre y `boleta.medioPago`), con `reintentable: false`. `POST /cotizaciones` responde 422 con `campo` en toda validación de su cuerpo (incluido `enviarEmail`) y `reintentable: false` en un monto que no cuadra |
| 429 | Límite de peticiones; respeta `Retry-After`. En `/receptores`, `codigo: "limite_receptores"` (30 por minuto por clave y 1.000 por día por empresa; y un techo del servicio de 20.000 al día entre todos, que el uso normal no toca) |
| 500 | Error nuestro; reintenta con la misma Idempotency-Key |
| 503 | No disponible por un momento, y no por tu documento: nuestra base no respondió (al verificar la clave, contar el límite o revisar la suscripción) o la empresa está en una ventana de certificación de boletas ante el SII (`codigo: "ventana_certificacion"`; la emisión se reanuda sola al terminar). Siempre JSON con `reintentable: true` y `Retry-After` (5 segundos la base, 300 la ventana): repite con la MISMA Idempotency-Key (en `/cotizaciones`, con el mismo `origen` y `referencia`; allí también es un 503 cualquier fallo al guardar). En `/receptores`, también cuando el registro público del SII no respondió (`codigo: "sii_no_disponible"`, `Retry-After: 60`) |
Conecta tu IA (MCP)
FacturaLibre tiene un servidor MCP (Model Context Protocol): conectas tu asistente de IA a tus negocios y le preguntas en tus palabras cuánto vendiste, quiénes son tus mejores clientes, quién te debe o cómo viene tu F29, o le pides la factura que le emitiste el jueves a un cliente. Si le pides una boleta o una factura nueva, te la deja lista y tú la emites con un toque en FacturaLibre; o, si al conectarlo dejas marcada «Puede emitir documentos» (el Permiso para emitir), la emite él después de que se lo confirmas en el chat, con los límites que tú fijes. Probado con Claude.
Dirección del servidor
https://mcp.facturalibre.cl/mcp
Es la misma para cualquier asistente y no es una clave: sin tu autorización no abre nada. Le habla a tu asistente, no al navegador: abierta en una pestaña responde un error (405), y es lo esperado.
En Claude (web, escritorio y teléfono)
- En Claude, abre Configuración → Conectores. Hazlo una vez desde claude.ai o la app de escritorio; después lo tienes también en el teléfono.
- Toca Agregar conector personalizado.
- En nombre escribe FacturaLibre y en URL pega la dirección de arriba. Toca Agregar.
- Toca Conectar. Se abre FacturaLibre: eliges qué negocios puede ver y confirmas con el código de tu app de autenticación.
- En un chat, activa FacturaLibre en los conectores y pregúntale lo que necesites.
Si tu Claude está en inglés: Settings → Connectors → Add custom connector. En los planes Team o Enterprise lo agrega primero quien administra la organización.
En Claude Code
claude mcp add --transport http facturalibre https://mcp.facturalibre.cl/mcpDespués escribe /mcp en Claude Code, elige facturalibre y entra con tu cuenta.
Otros asistentes compatibles con MCP remoto y OAuth pueden funcionar; escríbenos a soporte@facturalibre.cl si el tuyo no conecta.
Qué puede hacer
Cada herramienta usa el mismo cálculo que las pantallas de FacturaLibre. Al conectar concedes uno o los dos permisos:
facturalibre:leer · Para ver. Se concede siempre al conectar:
listar_empresas· Listar mis negociosLos negocios que esta conexión puede consultar, con el RUT que piden las demás herramientas, tu rol en cada uno y si ya emite documentos reales.
resumen_ventas· Resumen de ventasLo vendido por mes (total, neto y exento), con el mismo criterio de la pantalla Resumen: un documento anulado sigue contando y su nota de crédito resta; la guía de despacho y la factura de compra no son venta. Incluye las ventas emitidas fuera de FacturaLibre que registró el SII. El IVA a pagar sale de f29_del_periodo.
mejores_clientes· Mejores clientesLos clientes que más le compraron al negocio en un período, por monto o por cantidad de documentos, con el mismo criterio de ventas de la pantalla Reportes: un documento anulado sigue contando y su nota de crédito resta; la guía de despacho y la factura de compra no son venta. Incluye las ventas emitidas fuera de FacturaLibre que registró el SII.
cuentas_por_cobrar· Cuentas por cobrarQuién le debe al negocio y desde cuándo: facturas a crédito ya recibidas por el SII y no marcadas como pagadas, por cliente y por antigüedad. Descuenta las notas de crédito parciales y excluye las facturas cedidas. Las exportaciones que se cobran en su moneda van sumadas en pesos al tipo de cambio de su factura, y lo que se debe en la moneda va aparte («monedas»).
f29_del_periodo· F29 del períodoEl F29 pre-armado de un mes (IVA débito y crédito, PPM, retenciones y total) y su estado: mes en curso, cuadra o no con el registro de ventas del SII, ya declarado (con lo que quedó por pagar o el pago anotado), con compras sin sincronizar o con ventas emitidas fuera de FacturaLibre que este cálculo aún no suma. Es un borrador para revisar, no la declaración.
gastos_del_exterior· Gastos del exteriorLas facturas de proveedores extranjeros (Google, Meta, AWS…) que llegaron al negocio, la factura de compra (46) que se emite por cada una y las facturas de compra emitidas en el mes.
buscar_clientes· Buscar clientesBusca en los clientes del negocio (libreta, historial y cotizaciones) por nombre o RUT. El correo y la dirección solo se devuelven si los pides.
buscar_documentos· Buscar documentosBusca en los documentos emitidos por el negocio por cliente (nombre o RUT) o número (folio), tipo, estado y fechas, del último emitido al primero, como la pantalla Documentos: cada uno con su total, su estado ante el SII y, si es una factura a crédito, si está pagada. No suma montos: lo vendido sale de resumen_ventas.
ver_documento· Ver un documentoEl detalle de un documento emitido (cliente, líneas, montos, referencias, estado ante el SII y si está pagado) o de uno preparado por el asistente. Se busca por su id, por tipo y número (folio) o por el id de la propuesta.
descargar_documento· Descargar un documentoUn enlace para descargar el PDF o el XML firmado de un documento emitido, buscado por su id o por tipo y número (folio). El enlace vence en 10 minutos y deja de servir si se desconecta el asistente.
entregar_documento· Entregar un documentoEncuentra un documento emitido por lo que la persona recuerda —cliente (nombre o RUT), tipo, número, día o semana, monto exacto o aproximado— y, si calza uno solo, lo entrega con sus datos y un enlace de descarga que vence en 10 minutos; si calzan varios, los lista para elegir. Las fechas se calculan en hora de Chile.
ver_planilla· Ver una planillaCómo va una planilla: cuántas facturas se emitieron, cuántas aceptó o rechazó el SII, cuántas esperan y cerca de qué hora termina.
facturalibre:preparar · Para preparar y, si el dueño deja marcada «Puede emitir documentos» al conectar (el Permiso para emitir), emitir. Es opcional al conectar y solo vale en los negocios donde tu rol permite emitir; nunca en una demostración:
preparar_documento· Preparar un documento para emitirArma una boleta o factura con los montos calculados por FacturaLibre. No emite nada ni usa folio. Si la persona le dio a este asistente el Permiso para emitir y el documento cabe en sus límites, trae la ficha y la línea para confirmarlo en el chat; si no, un enlace de aprobación que vence (la boleta al terminar el día; la factura en 24 horas). Una factura va a un cliente de la libreta o a uno nuevo: al nuevo lo verifica FacturaLibre en el SII, que pone su razón social, y necesita su dirección y comuna. Una boleta sobre 135 UF necesita el RUT de quien paga y el medio de pago. Indica siempre si los precios incluyen IVA.
emitir_propuesta· Emitir un documento preparadoEmite la boleta, factura o nota de crédito que dejó lista preparar_documento o preparar_anulacion, si la persona le dio a este asistente el Permiso para emitir en FacturaLibre y el documento cabe en sus límites; si no, no emite y devuelve el enlace para emitirla con un toque. Lleva la línea de confirmación que vino con el documento. Un documento emitido llega al SII y no se borra: se corrige con una nota de crédito.
preparar_anulacion· Preparar una anulaciónDeja lista la nota de crédito que anula por completo una factura (33) o factura exenta (34) ya aceptada por el SII, con sus mismos ítems, cliente y total. No emite nada. No anula boletas, facturas de compra ni de exportación, ni facturas cedidas o con notas de crédito previas.
cargar_planilla· Cargar una planillaRecibe en partes de hasta 50 las facturas (33 y 34) de una planilla, por ejemplo un Excel, y las revisa todas: clientes —los de la libreta y los nuevos, que FacturaLibre verifica en el SII y que necesitan dirección y comuna—, montos, IVA y tipos. Con la última parte devuelve el resumen —cuántas, por cuánto, cuáles tienen problemas y cuánto tardarían— con su línea de confirmación. No emite nada.
emitir_planilla· Emitir una planillaEmite en segundo plano las facturas válidas de una planilla ya revisada, con la línea de confirmación de su resumen, si la persona dio el Permiso para emitir planillas y cabe en sus límites; si no, devuelve un enlace para confirmarla con un toque en FacturaLibre. Durante la ventana de arrepentimiento (10 minutos por omisión) se pueden cancelar sin costo.
cancelar_planilla· Cancelar una planillaCancela las facturas de una planilla que todavía no se emiten: no cuestan nada. Las ya emitidas se anulan con anular_planilla.
anular_planilla· Anular una planillaDeja lista la anulación, con notas de crédito, de las facturas que el asistente emitió desde una planilla y que el SII ya aceptó este mes. No emite nada: se confirma con emitir_planilla.
Permiso para emitir
Sin este permiso, el asistente te deja cada documento listo y tú lo emites con un toque en FacturaLibre. Con él, lo emite después de que le dices que sí en el chat, sin abrir enlaces: queda emitido y enviado al SII.
- Se da al conectar: en la pantalla donde autorizas a tu asistente, la casilla «Puede emitir documentos (te pregunta en el chat antes de cada uno)» viene marcada, y el mismo código con que confirmas la conexión la cubre: el de tu app de autenticación o, si no la tienes, uno que te mandamos por correo. Solo la ve el dueño del negocio; quien no es dueño se conecta igual y emite con un toque. Para un asistente que ya conectaste, toca «Permitir que emita documentos» en su conexión, en Integraciones → Asistente de IA: un paso, con tu código. Cada asistente se permite uno por uno. Vence a los 90 días, y te avisamos por correo cuando vence.
- Cada documento se confirma en el chat (una planilla, una vez). El asistente te muestra el cliente, el detalle y el total calculados por FacturaLibre y te pregunta si lo emite. FacturaLibre lo emite solo con la línea de confirmación de ese documento, pedida por la misma conexión que lo preparó, hace menos de 60 minutos y el mismo día; lo que respondes en el chat no lo ve. En Claude, esa línea se ve también en el aviso de permiso de «Emitir un documento preparado», si no lo dejas en «Permitir siempre»: ese aviso es la única pausa que no depende del asistente.
- Los límites los fijas tú, en Integraciones → Asistente de IA → Permiso para emitir: qué puede emitir (facturas, boletas, planillas y anular lo que emitió) y, si quieres, un tope de documentos y de monto por día, en hora de Chile. Por omisión no hay topes diarios, y no hay tope por documento. Lo que pase un límite te lo deja listo para que lo emitas tú. Ahí también lo ves, lo pausas y lo apagas.
- A tus clientes y a clientes nuevos: antes de emitir, FacturaLibre verifica cada RUT nuevo en el registro público del SII y usa la razón social que el SII tiene registrada. Un RUT que el SII no reconoce no se emite.
- Las boletas salen con fecha de hoy, hasta las 23:40 (hora de Chile). Después, te la deja lista para que la emitas tú.
- Te avisamos por correo cada documento que emite tu asistente, y cada planilla al programarla y al terminar, con un botón «Pausar el asistente». Pausar o revocar el permiso no pide código y rige desde la pregunta siguiente; reanudarlo o ampliarlo, sí: el de tu app o uno que te mandamos por correo.
- Si intenta repetir una venta que ya se emitió hace menos de 10 minutos, no la emite sin que confirmes que es otra; si lo intenta 3 veces en una hora, el permiso se pausa solo y te avisamos.
Planillas
Si le pasas un Excel con las facturas del mes, tu asistente se las manda a FacturaLibre en partes de hasta 50, y FacturaLibre las revisa todas: clientes (los de tu libreta y los nuevos, verificados en el SII, que necesitan dirección y comuna), montos, IVA y tipos. Te devuelve un resumen con cuántas son, por cuánto, cuáles tienen problemas y cuánto tardarían.
- Hasta 200 facturas por planilla; más, en varias planillas. Solo facturas y facturas exentas: las boletas se piden una a una.
- Se confirman una vez y se emiten en segundo plano: no hace falta dejar el chat abierto. Con el permiso de planillas se confirman en el chat; si no, con un toque en FacturaLibre.
- Confirmadas en el chat, esperan 10 minutos (por omisión) antes de empezar a emitirse: en ese rato las cancelas sin costo. Te llega un correo cuando terminan.
- La misma planilla confirmada dos veces en una semana no se emite dos veces.
Anular
Con el permiso, tu asistente anula por chat, con una nota de crédito por el total, solo lo que él mismo emitió en el mes, también una planilla entera. Para cualquier otra factura aceptada por el SII te deja la nota de crédito lista, y la emites tú en FacturaLibre. No anula boletas, facturas de compra ni de exportación, ni facturas cedidas o con notas de crédito previas.
Qué no hace
- No emite sin tu permiso: solo emite si se lo permitiste (al conectarlo o desde Integraciones → Asistente de IA), dentro de tus límites y después de que le digas que sí en el chat. Los montos los calcula FacturaLibre, no el asistente.
- No anula lo que no emitió él este mes, y nunca cede facturas.
- No ve tu certificado digital, tus claves del SII ni tu suscripción.
Seguridad
- Autorización OAuth 2.1 con PKCE: el asistente nunca ve tu contraseña, y recibe un acceso que dura una hora y se renueva solo. De cada acceso guardamos su huella (hash), nunca el valor.
- Al conectar eliges qué negocios puede ver y confirmas con el código de 6 dígitos de tu app de autenticación o, si no la tienes (o lo prefieres), con uno que te mandamos por correo: vale 10 minutos, sirve una sola vez y solo para esa conexión.
- Cada vez que conectas uno, te avisamos por correo.
- El Permiso para emitir queda guardado con la fecha, la dirección IP, el texto exacto que aceptaste y cómo confirmaste que eras tú. Cada cambio te llega por correo, a ti y a los demás dueños del negocio.
- La conexión dura hasta 90 días; después te pide permiso de nuevo. La desconectas cuando quieras en Integraciones → Asistente de IA, y deja de ver tus negocios desde su consulta siguiente.
- Cuando le pides el PDF o el XML de un documento, te entrega un enlace que vence en 10 minutos y deja de servir si lo desconectas. Quien lo tenga lo puede abrir: no lo compartas.
Límites
- 60 consultas por minuto por conexión; después responde 429 con
Retry-After. - 20 documentos preparados por hora por negocio (100 con el Permiso para emitir), y 100 al día por conexión.
- 10 emisiones por minuto por conexión.
- Planillas de hasta 200 facturas, en partes de hasta 50 y con hasta 20 líneas por factura.
- 30 descargas cada 10 minutos por conexión.
- Hasta 20 negocios por conexión y 20 asistentes conectados por persona.
- Solo se conectan negocios que ya emiten documentos reales con FacturaLibre. En una demostración, el asistente lee los datos de muestra y no prepara documentos.
Para desarrolladores
- Transporte HTTP de MCP sin sesión y solo JSON:
POST https://mcp.facturalibre.cl/mcp. UnGETresponde 405 conAllow: POST. - Metadatos del recurso protegido (RFC 9728):
https://mcp.facturalibre.cl/.well-known/oauth-protected-resource/mcp - Metadatos del servidor de autorización (RFC 8414):
https://app.facturalibre.cl/.well-known/oauth-authorization-server - Registro dinámico de clientes (RFC 7591) sin secreto: cliente público con PKCE S256 y
resource(RFC 8707). Solo se aceptan las redirecciones de Claude y de ChatGPT, y la de un programa local:http://localhost:<puerto>/callbackohttp://127.0.0.1:<puerto>/callback. - Alcances:
facturalibre:leeryfacturalibre:preparar. El token va enAuthorization: Bearer; en la URL se rechaza con 400.
Un POST sin token responde 401 con el desafío que lleva al descubrimiento:
curl -i -X POST https://mcp.facturalibre.cl/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.facturalibre.cl/.well-known/oauth-protected-resource/mcp", scope="facturalibre:leer facturalibre:preparar"¿Listo para integrar?
Si ya tienes cuenta, crea tu clave fl_test_ en Integraciones → API y prueba el ciclo completo contra el SII simulado, sin consumir folios. Si todavía no, entra a la demo con tu empresa: ahí mismo creas la clave y emites.