Emisso Connect
Sistemas

Banco de Chile Empresas

Saldos, movimientos y cartolas mensuales del Portal Empresas de Banco de Chile, sincronizados a la caché de Connect. El login es HTTP puro: no hay desafío de navegador que resolver.

Con la clave del portal, bch_empresas sincroniza saldos, movimientos y cartolas mensuales del Portal Empresas de Banco de Chile hacia el plano persistido de Connect, y tres tools de consulta los leen de esa caché sin esperar al banco. El conn_… de la conexión dice qué empresa lees y viaja en toda llamada (en REST, el header X-Connect-Connection).

A diferencia de BICE Empresas, el login de Banco de Chile no exige resolver ningún desafío de navegador: todo el camino, desde el login hasta el logout, corre por HTTP puro. Es el conector bancario más simple de los cuatro que ofrece Connect, no el más caro.

Qué necesitas para conectar

En el enlace de conexión la persona entrega la Clave de banca en línea del portal, en tres campos:

CampoQué es
RUT de accesoEl RUT de la persona que inicia sesión en el portal.
ClaveSu clave de banca en línea de Banco de Chile.
RUT de la empresaLa empresa que esta conexión va a leer.

El acceso solo lee, y desde el dashboard se revoca en el acto. La clave no pasa por tu código: la entrega quien la tiene, en un enlace que sirve una sola vez. Si el acceso ve más de una empresa en el portal, la conexión no se puede crear: Connect todavía no tiene un selector para elegir cuál, así que la clave que uses tiene que ver una sola empresa.

Los alcances

AlcanceQué traeTool que lo lee
saldosEl saldo disponible y la línea de crédito de cada cuenta, como una foto por díabch_empresas.saldos.consultar
movimientosLos movimientos del período, con descripción, canal y saldo arrastradobch_empresas.movimientos.consultar
cartolasEl extracto mensual ya emitido por el banco, con su número de cartola y los saldos de apertura y cierrebch_empresas.cartolas.consultar

Qué alcances quedan habilitados se decide por conexión, desde el dashboard. El gate de alcances rechaza la llamada entera si uno solo de los alcances pedidos no está habilitado: pedir ["saldos","movimientos","cartolas"] sobre una conexión que no habilitó cartolas no sincroniza ni saldos ni movimientos, devuelve 403 alcance_not_enabled completo. Una conexión creada antes del 2026-08-11 puede no tener cartolas habilitado, porque hasta esa fecha el alta no lo pre-marcaba: su parser MT940 todavía no se había corrido contra el banco real. Se habilita desde /ajustes como cualquier otro alcance.

Sincronizar

curl -X POST https://connect.emisso.ai/api/v1/tools/bch_empresas.conexion.sincronizar/execute \
  -H "Authorization: Bearer connect_sk_..." \
  -H "X-Connect-Connection: conn_9tKfR2mQx4Vb" \
  -H "Content-Type: application/json" \
  -d '{"input":{"periodo":"2026-08","alcances":["saldos","movimientos"]}}'

Respuesta (recortada):

{
  "data": {
    "periodo": "2026-08",
    "results": [
      { "alcance": "saldos", "status": "ok", "recordsSynced": 2 },
      { "alcance": "movimientos", "status": "ok", "recordsSynced": 41 }
    ]
  },
  "meta": { "request_id": "req_...", "tool_id": "bch_empresas.conexion.sincronizar", "plane": "read" }
}

Un solo login del Portal Empresas cubre los alcances pedidos, y el logout corre al terminar. Como en los demás bancos, saldos es una foto del momento: en un período que no es el corriente devuelve cero con su explicación en detalle. Y el login no exige esperarlo en línea: el trabajo se encola por la API de control. Para incluir cartolas en la misma llamada, habilítalo antes en la conexión (dashboard → alcances); de lo contrario pedirlo tumba la sincronización entera, no solo ese alcance.

Verdades operativas

La ventana es de 45 días por consulta, y el rechazo es HTTP 300

Cada consulta de movimientos al banco acepta como máximo 45 días de rango. Una ventana más ancha no vuelve con un código 4xx habitual: vuelve con HTTP 300, un estado de redirección que un cliente HTTP común seguiría en silencio como si fuera un enlace válido. Connect intercepta ese 300 antes de seguirlo y lo traduce a upstream_unexpected_response (502, no reintentable): reintentar la misma ventana da el mismo resultado, así que no vale la pena. bch_empresas.conexion.sincronizar pide siempre un mes calendario (máximo 31 días), así que tu sync nunca choca con este límite por sí solo; importa si ves ese código en la bitácora y necesitas saber por qué no es transitorio.

La retención es de ~6 años

El banco acepta consultas de hasta aproximadamente 6 años atrás: una ventana de 30 días ubicada 1, 3 o 5 años atrás responde HTTP 200, aunque en la medición volvió sin movimientos, así que ese 200 vacío no distingue "no hubo movimientos en esa ventana" de "la cuenta no existía todavía". La misma ventana ubicada 7 años atrás el banco la rechaza con el mismo HTTP 300 que usa para una ventana demasiado ancha: recién ahí queda claro que la fecha cayó fuera de lo que el banco conserva. Si necesitas historia más allá de esos ~6 años, no hay forma de conseguirla: el corte lo pone el banco, no Connect.

El x-xsrf-token rota a mitad de sesión

El header x-xsrf-token que protege cada POST del portal no queda fijo durante todo el login: el banco lo reemite en ciertas respuestas, y el valor cambia. Connect relee la cookie del jar inmediatamente antes de cada POST, nunca cachea el valor del login. Un cliente que lo cachee del primer login funciona en las primeras llamadas y después empieza a fallar de forma intermitente, justo cuando el banco rota el token, un patrón difícil de reproducir porque depende del momento exacto de la rotación.

El flag de paginación es "Y"/"N", no "S"

El indicador de "hay más páginas" que devuelve el banco (pagina[].masPaginas) usa las letras en inglés, "Y" o "N", nunca la "S" de "sí" que uno esperaría en un portal en castellano. Un cliente que compare contra "S" nunca la encuentra, corta después de la primera página y trunca en silencio: parece que la cuenta tiene pocos movimientos cuando en realidad hay más sin traer. Connect no usa ese flag para decidir si sigue paginando: el corte real es que el índice de término llegue al total de registros, el mismo criterio sin importar qué letra mande el banco.

La cartola emitida es mensual y llega en MT940

El extracto que el banco emite una vez al mes (la cartola) no es el mismo feed que movimientos: es un objeto propio, con su propio saldo de apertura y de cierre. El único formato en que el banco la entrega con esos dos datos es MT940, el estándar SWIFT de mensajería bancaria: trae el número de cartola (tag 28C) y los saldos de apertura y cierre (tags 60/62), que ningún otro formato del portal declara en su encabezado. El único formato alternativo medido, el XLS, no tiene esos dos campos y sus columnas para identificar cada línea (número de documento, transacción, caja) vienen en cero en toda la muestra medida; el PDF y el TXT no se llegaron a inspeccionar. bch_empresas.cartolas.consultar ya devuelve el número de cartola y los saldos parseados desde MT940: no hace falta interpretarlo por tu cuenta.

El logout no invalida la sesión del lado del banco

Está medido, más de una vez: guardando la cookie de sesión antes de que Connect cierre la conexión con el banco y reinyectándola después, el banco sigue respondiendo autenticado con HTTP 200. Connect igual llama al logout en cada sincronización (son tres peticiones baratas y es lo que hace el propio portal), pero eso limpia el estado del lado de Connect, no el del banco: ninguna integración debería asumir que, tras un logout, la sesión anterior quedó inutilizable. Como Connect nunca persiste esa sesión entre sincronizaciones, el residual queda enteramente del lado del banco, que la expira sola pasado un tiempo de inactividad.

Errores que vas a ver

CódigoQué significaQué hacer
428 connection_credential_requiredLa conexión no tiene una credencial viva: nunca se vinculó, venció o fue revocada.Emite un enlace de reconexión y pide la clave de nuevo. No reintentes con la credencial anterior.
409 connection_busyOtra operación tiene tomado el candado de esta conexión.Espera unos segundos y reintenta: el candado se suelta solo.
409 connection_sync_in_progressYa corre una sincronización de esa conexión para ese período.Espera a que termine, o consulta directamente: puede que ya haya datos.
403 alcance_not_enabledLa conexión no tiene habilitado el alcance que la tool pide.Habilítalo en la conexión desde el dashboard, o quítalo del input de la sincronización.
409 connection_identity_mismatchLa empresa que ve el banco no coincide con la que declara la conexión: la credencial ve más de una empresa en el portal (detectado al verificar), o una fila sincronizada trajo el RUT de otra empresa.No reintentes sin revisar: puede ser una credencial multiempresa o una rotación que cambió de empresa. Repórtalo con el request_id.
502 upstream_unexpected_responseEl banco rechazó la ventana de fechas consultada (HTTP 300). No es un problema transitorio.Repórtalo con el request_id si el mismo período sigue fallando tras reintentar.
502 upstream_errorEl banco (o el camino hasta él) falló de forma transitoria.Reintenta más tarde. Si persiste, el problema está del lado del banco.

El envelope de cada código está en el catálogo de errores.

Próximos pasos

On this page