Consultar boletas de honorarios del SII
Lee las boletas de honorarios electrónicas (BHE) ya sincronizadas para esta conexión, filtradas por período y/o perspectiva (emitidas = las que emitió esta empresa; recibidas = las que le emitieron, donde esta empresa es el agente retenedor).
| Tool ID | sii.boletas_honorarios.consultar |
| Nombre MCP | sii__boletas_honorarios__consultar |
| Conector | sii |
| Plano | action |
| Lee el alcance | boletas_honorarios (debe estar habilitado en la conexión) |
| Scope (permiso) | sii:read |
| Auth | none |
| Versión | 2 |
| Sensible | sí |
| Deprecado | no |
| Comportamiento | readOnly=true, destructive=false, idempotent=true, openWorld=false |
Requiere conexión. Indica cuál en cada llamada: header
X-Connect-Connectionen REST, campoconnectionIden elexecutede MCP y en las opciones del SDK. No hay resolución implícita, ni siquiera con una sola conexión activa: la conexión es la empresa. El id sale deconexiones.estado.consultar.
Qué hace
Lectura pura: NO dispara una sincronización nueva ni contacta al SII. Si el período nunca se sincronizó, devuelve una lista vacía y 'sincronizacion: null'. Para traer datos nuevos, usa 'sii.conexion.sincronizar' primero. El filtro tributario canónico es 'estado' distinto de 'S' sobre el código crudo: 'V' (anulación pendiente), 'R' y 'U' (observadas) siguen VIGENTES; solo 'S' está anulada: nunca filtres por 'estadoNormalizado' igual a 'vigente'. El 'estado' es el observado en la última sincronización del período, no el estado final: una BHE puede anularse, o revertir de anulación pendiente a vigente, hasta el 1 de marzo del año siguiente, y por petición administrativa sin plazo después. Resincroniza el período para refrescarlo; 'ultimaLecturaEn' dice cuándo se observó cada fila. La suma de 'retencion_receptor' es el insumo para cuadrar el F29 código 151, no el código 151: ese además incluye las retenciones por BTE y se imputa al mes del pago. Pagina con 'cursor': cuando la respuesta trae 'cursor' distinto de null, hay más filas. reenvía ese valor tal cual en 'cursor' para pedir la página siguiente; nunca lo construyas a mano.
Entrada
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
periodo | string ^\d{4}-\d{2}$ | no | Un mes, en formato AAAA-MM y en calendario chileno (por ejemplo '2026-07'). Cada sitio de uso afina qué significa ahí: en una sincronización es el mes que se va a traer, y en una consulta a la caché es el filtro. Esta descripción base existe para que el campo nunca llegue pelado a quien lee el contrato. |
perspectiva | "emitidas" · "recibidas" | no | emitidas = las que emitió esta empresa; recibidas = las que le emitieron, donde esta empresa es el agente retenedor. Sin este filtro vienen las dos. |
cursor | string | no | Paginación: el valor que devolvió la respuesta anterior, tal cual. |
limit | entero 1-500 | no · default 100 | Filas por página. |
JSON Schema de entrada
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"periodo": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}$",
"description": "Un mes, en formato AAAA-MM y en calendario chileno (por ejemplo '2026-07'). Cada sitio de uso afina qué significa ahí: en una sincronización es el mes que se va a traer, y en una consulta a la caché es el filtro. Esta descripción base existe para que el campo nunca llegue pelado a quien lee el contrato."
},
"perspectiva": {
"description": "emitidas = las que emitió esta empresa; recibidas = las que le emitieron, donde esta empresa es el agente retenedor. Sin este filtro vienen las dos.",
"type": "string",
"enum": [
"emitidas",
"recibidas"
]
},
"cursor": {
"description": "Paginación: el valor que devolvió la respuesta anterior, tal cual.",
"type": "string"
},
"limit": {
"default": 100,
"description": "Filas por página.",
"type": "integer",
"minimum": 1,
"maximum": 500
}
}
}Ejemplo
curl -X POST https://connect.emisso.ai/api/v1/tools/sii.boletas_honorarios.consultar/execute \
-H "Authorization: Bearer connect_sk_…" \
-H "X-Connect-Connection: conn_9tKfR2mQx4Vb" \
-H "Content-Type: application/json" \
-d '{"input":{"periodo":"2026-07","perspectiva":"recibidas"}}'const data = await connect.tools.sii.boletas_honorarios.consultar({ periodo: "2026-07", perspectiva: "recibidas" }, { connectionId: "conn_9tKfR2mQx4Vb" });{
"tool": "sii.boletas_honorarios.consultar",
"params": {
"periodo": "2026-07",
"perspectiva": "recibidas"
},
"connectionId": "conn_9tKfR2mQx4Vb"
}Salida esperada (200):
{
"data": {
"documentos": [
{
"folio": "153",
"perspectiva": "recibidas",
"periodo": "2026-07",
"fechaBoleta": "15/07/2026",
"fechaBoletaDate": "2026-07-15",
"rutContraparte": "12345678-5",
"razonSocialContraparte": "María José Riquelme Fuentes",
"codigoBarras": "108452276390415387",
"honorariosBrutos": 500000,
"retencionEmisor": 0,
"retencionReceptor": 76250,
"honorariosLiquidos": 423750,
"estado": "N",
"estadoNormalizado": "vigente",
"esSocProfesional": "NO",
"fechaEventoEstado": null,
"fechaEventoEstadoDate": null,
"ultimaLecturaEn": "2026-08-06T03:15:42.000Z"
}
],
"cursor": null,
"sincronizacion": {
"sincronizadoEn": "2026-08-06T03:15:42.000Z",
"completo": true,
"incompletos": 0,
"fueraDeVentana": null,
"perspectivasFallidas": []
}
},
"meta": {
"request_id": "req_…",
"tool_id": "sii.boletas_honorarios.consultar",
"plane": "action",
"latency_ms": 24,
"audit_status": "recorded"
}
}Recortado a una boleta. En 'recibidas' esta empresa es el agente retenedor: 'retencionReceptor' se descuenta de 'honorariosBrutos' y 'honorariosLiquidos' es lo que recibe el profesional.
Salida
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
documentos | lista de objeto | sí | Las boletas de honorarios que calzan con el filtro, una por fila. Sale de la caché ya sincronizada, nunca de una consulta en vivo al SII. |
documentos[].folio | string | sí | El número de la boleta, tal cual lo manda el SII y como texto: puede traer ceros a la izquierda o no ser numérico, y no se normaliza. |
documentos[].perspectiva | "emitidas" · "recibidas" | sí | emitidas = las boletas que emitió esta empresa; recibidas = las que le emitieron, donde esta empresa es el agente retenedor. |
documentos[].periodo | string | sí | El período tributario de la boleta, en formato AAAA-MM. |
documentos[].fechaBoleta | string | sí | La fecha de la boleta tal cual la manda el SII, en formato DD/MM/AAAA. Para ordenar o comparar usa 'fechaBoletaDate'. |
documentos[].fechaBoletaDate | string | null | sí |
documentos[].razonSocialContraparte | string | sí | El nombre o razón social del otro lado: en 'recibidas' es el profesional que emitió, en 'emitidas' es el receptor. |
documentos[].codigoBarras | string | sí | El código de barras con que el SII identifica la boleta. Es único por boleta dentro del informe. |
documentos[].honorariosBrutos | entero | sí | El honorario bruto en pesos chilenos: lo facturado antes de descontar la retención. |
documentos[].retencionEmisor | entero | sí | La retención declarada por el propio emisor, en pesos chilenos. En 'recibidas' llega siempre en 0 porque ese informe no expone el campo: ahí la retención que importa es 'retencionReceptor'. |
documentos[].retencionReceptor | entero | sí | La retención que hizo el receptor como agente retenedor, en pesos chilenos. Su suma es el insumo para cuadrar el código 151 del F29, no el código 151 en sí. |
documentos[].honorariosLiquidos | entero | sí | Lo que recibe el profesional: el bruto menos la retención, en pesos chilenos. |
documentos[].estado | string | sí | El código de estado tal cual lo manda el SII: 'N' vigente, 'S' anulada, 'V' anulación pendiente, 'R' y 'U' observadas. El filtro tributario correcto es 'estado' distinto de 'S', porque 'V', 'R' y 'U' siguen vigentes. |
documentos[].estadoNormalizado | "vigente" · "anulada" · "vigente_anulacion_pendiente" · "observada_receptor" · "observada_unidad" · "desconocido" | sí | El mismo estado traducido a un enum estable. No lo uses para filtrar lo vigente: 'vigente_anulacion_pendiente', 'observada_receptor' y 'observada_unidad' también lo están. Un código que no reconocemos sale 'desconocido' y nunca se omite de un cómputo. |
documentos[].esSocProfesional | string | null | sí |
documentos[].fechaEventoEstado | string | null | sí |
documentos[].fechaEventoEstadoDate | string | null | sí |
documentos[].rutContraparte | string | null | sí |
documentos[].ultimaLecturaEn | string | sí | Cuándo se observó esta fila por última vez, en ISO 8601 UTC. Una boleta de honorarios es mutable hasta el 1 de marzo del año siguiente: si esta marca es vieja, resincroniza el período antes de decidir sobre su estado. |
cursor | string | null | sí |
sincronizacion | objeto | null | sí |
sincronizacion.sincronizadoEn | string | sí | Cuándo terminó la última sincronización de este período, en ISO 8601 UTC. Es la frescura del dato que estás leyendo. |
sincronizacion.completo | booleano | null | sí |
sincronizacion.incompletos | entero | null | sí |
sincronizacion.fueraDeVentana | entero | null | sí |
sincronizacion.perspectivasFallidas | lista de objeto | sí | Qué direcciones fallaron enteras en esa sincronización, con su código de error. Hoy sólo la puebla el alcance de boletas de honorarios; para los demás llega vacía. |
sincronizacion.perspectivasFallidas[].perspectiva | "emitidas" · "recibidas" | sí | Qué lado falló: 'emitidas' son las que emitió esta empresa y 'recibidas' las que le emitieron. |
sincronizacion.perspectivasFallidas[].code | string | sí | El código del catálogo de errores que explica por qué falló ese lado. Decide por el código, nunca por el texto. |
JSON Schema de salida
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"documentos": {
"type": "array",
"items": {
"type": "object",
"properties": {
"folio": {
"type": "string",
"description": "El número de la boleta, tal cual lo manda el SII y como texto: puede traer ceros a la izquierda o no ser numérico, y no se normaliza."
},
"perspectiva": {
"type": "string",
"enum": [
"emitidas",
"recibidas"
],
"description": "emitidas = las boletas que emitió esta empresa; recibidas = las que le emitieron, donde esta empresa es el agente retenedor."
},
"periodo": {
"type": "string",
"description": "El período tributario de la boleta, en formato AAAA-MM."
},
"fechaBoleta": {
"type": "string",
"description": "La fecha de la boleta tal cual la manda el SII, en formato DD/MM/AAAA. Para ordenar o comparar usa 'fechaBoletaDate'."
},
"fechaBoletaDate": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "La misma fecha en formato AAAA-MM-DD, o 'null' si no se pudo parsear."
},
"razonSocialContraparte": {
"type": "string",
"description": "El nombre o razón social del otro lado: en 'recibidas' es el profesional que emitió, en 'emitidas' es el receptor."
},
"codigoBarras": {
"type": "string",
"description": "El código de barras con que el SII identifica la boleta. Es único por boleta dentro del informe."
},
"honorariosBrutos": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "El honorario bruto en pesos chilenos: lo facturado antes de descontar la retención."
},
"retencionEmisor": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "La retención declarada por el propio emisor, en pesos chilenos. En 'recibidas' llega siempre en 0 porque ese informe no expone el campo: ahí la retención que importa es 'retencionReceptor'."
},
"retencionReceptor": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "La retención que hizo el receptor como agente retenedor, en pesos chilenos. Su suma es el insumo para cuadrar el código 151 del F29, no el código 151 en sí."
},
"honorariosLiquidos": {
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991,
"description": "Lo que recibe el profesional: el bruto menos la retención, en pesos chilenos."
},
"estado": {
"type": "string",
"description": "El código de estado tal cual lo manda el SII: 'N' vigente, 'S' anulada, 'V' anulación pendiente, 'R' y 'U' observadas. El filtro tributario correcto es 'estado' distinto de 'S', porque 'V', 'R' y 'U' siguen vigentes."
},
"estadoNormalizado": {
"type": "string",
"enum": [
"vigente",
"anulada",
"vigente_anulacion_pendiente",
"observada_receptor",
"observada_unidad",
"desconocido"
],
"description": "El mismo estado traducido a un enum estable. No lo uses para filtrar lo vigente: 'vigente_anulacion_pendiente', 'observada_receptor' y 'observada_unidad' también lo están. Un código que no reconocemos sale 'desconocido' y nunca se omite de un cómputo."
},
"esSocProfesional": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Si el emisor es una sociedad de profesionales, tal cual lo manda el SII. Es texto crudo, no un booleano, y puede venir 'null'."
},
"fechaEventoEstado": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Cuándo el SII registró el evento que dejó la boleta en su estado actual. Cubre anulación, solicitud de anulación y observación, no sólo la anulación. 'null' mientras no hubo evento."
},
"fechaEventoEstadoDate": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "La misma fecha en formato AAAA-MM-DD, o 'null' si no vino o no se pudo parsear."
},
"rutContraparte": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "El RUT del otro lado: en 'recibidas' es el profesional que emitió y en 'emitidas' es el receptor. 'null' cuando la boleta se emitió sin receptor, que el SII permite."
},
"ultimaLecturaEn": {
"type": "string",
"description": "Cuándo se observó esta fila por última vez, en ISO 8601 UTC. Una boleta de honorarios es mutable hasta el 1 de marzo del año siguiente: si esta marca es vieja, resincroniza el período antes de decidir sobre su estado."
}
},
"required": [
"folio",
"perspectiva",
"periodo",
"fechaBoleta",
"fechaBoletaDate",
"razonSocialContraparte",
"codigoBarras",
"honorariosBrutos",
"retencionEmisor",
"retencionReceptor",
"honorariosLiquidos",
"estado",
"estadoNormalizado",
"esSocProfesional",
"fechaEventoEstado",
"fechaEventoEstadoDate",
"rutContraparte",
"ultimaLecturaEn"
],
"additionalProperties": false
},
"description": "Las boletas de honorarios que calzan con el filtro, una por fila. Sale de la caché ya sincronizada, nunca de una consulta en vivo al SII."
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "El cursor de la página siguiente, opaco. 'null' significa que no hay más filas; cualquier otro valor se reenvía tal cual en 'cursor' de la próxima llamada y nunca se construye a mano."
},
"sincronizacion": {
"anyOf": [
{
"type": "object",
"properties": {
"sincronizadoEn": {
"type": "string",
"description": "Cuándo terminó la última sincronización de este período, en ISO 8601 UTC. Es la frescura del dato que estás leyendo."
},
"completo": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"description": "'true' = el período se sincronizó entero. 'false' = quedaron casillas sin traer, así que puede faltar información. 'null' = no se puede saber, porque no hay registro de ese intento."
},
"incompletos": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "Cuántas casillas quedaron sin traer en esa sincronización. 'null' cuando no se puede saber."
},
"fueraDeVentana": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "Sólo aplica a guías: cuántas direcciones cayeron fuera de la ventana de 6 meses que el SII conserva. Un 0 dice que se verificó y no aplicó; 'null', que no aplica o no se conoce."
},
"perspectivasFallidas": {
"type": "array",
"items": {
"type": "object",
"properties": {
"perspectiva": {
"type": "string",
"enum": [
"emitidas",
"recibidas"
],
"description": "Qué lado falló: 'emitidas' son las que emitió esta empresa y 'recibidas' las que le emitieron."
},
"code": {
"type": "string",
"description": "El código del catálogo de errores que explica por qué falló ese lado. Decide por el código, nunca por el texto."
}
},
"required": [
"perspectiva",
"code"
],
"additionalProperties": false
},
"description": "Qué direcciones fallaron enteras en esa sincronización, con su código de error. Hoy sólo la puebla el alcance de boletas de honorarios; para los demás llega vacía."
}
},
"required": [
"sincronizadoEn",
"completo",
"incompletos",
"fueraDeVentana",
"perspectivasFallidas"
],
"additionalProperties": false
},
{
"type": "null"
}
],
"description": "Completitud del último sync del período consultado. Es 'null' por DOS motivos distintos, y ninguno significa que las filas devueltas sean inválidas: (a) la consulta no filtró por 'periodo', así que no hay un sync único al que mirar (pide un 'periodo' concreto para obtener el bloque); o (b) ese período nunca se sincronizó. Un 'null' junto a una lista CON documentos es siempre el caso (a)."
}
},
"required": [
"documentos",
"cursor",
"sincronizacion"
],
"additionalProperties": false
}Errores de esta tool
| Código | HTTP | Reintentable | Qué hacer |
|---|---|---|---|
connection_disabled | 403 | no | Reactívala en /connections o usa otra conexión del mismo sistema. |
alcance_not_enabled | 403 | no | Habilita el alcance en /connections o quítalo del input de la sincronización. |
Toda llamada puede devolver además los códigos transversales (validation_error, unauthorized, scope_not_granted, rate_limited, entre otros): el detalle vive en el catálogo de errores.
Próximos pasos
sii.conexion.sincronizar: la tool que escribe los datos que esta lectura devuelve.- Sincronizar y consultar: por qué leer datos reales son dos pasos.