Boufin API v2
Referencia de la API v2 de Boufin: autenticación, inicio de tareas con composición de acciones y notificación vía webhook. Para detalles operativos (límites, catálogo de entidades, schemas completos), consulta la referencia OpenAPI.
Autenticación
El endpoint de autenticación se mantiene en /api/v1/auth/login y es el único endpoint de auth oficial, compatible tanto con clientes v1 como con clientes v2. Con tu API Key obtienes un token de sesión:
curl -X POST "https://${URL}/api/v1/auth/login" \
-H "X-API-Key: ${API_KEY}" \
-H "Content-Type: application/json" \
--data '{"expire": 60}'
| Campo | Descripción |
|---|---|
X-API-Key | Tu API Key entregada por Boufin |
expire | (Opcional) Minutos de validez del token. Por defecto 60. Ver límites y validaciones en la referencia de la API |
Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Usa el token en el header Authorization: Bearer ${TOKEN} para todas las siguientes peticiones.
Iniciar proceso de extracción
Endpoint: POST /api/v2/tasks
La v2 mantiene el mismo concepto de tarea e incorpora cuatro mejoras principales respecto a v1:
- Entidad como campo independiente: en v1, entidad y acción iban combinadas en un único string (
banco-xx:movement). En v2 la entidad se especifica en el campo top-levelentityy las acciones quedan limpias ({ "id": "movement" }). - Nuevo formato de credenciales: se pasan como objeto con modo
encrypted,persistedoraw, en lugar de campos sueltos. - Composición de acciones: una sola tarea puede ejecutar múltiples acciones (
movement,product-balance,tef) sobre la misma entidad. - Webhook configurable: en lugar de un booleano, el webhook es un objeto que permite habilitarlo y ajustar el número de reintentos.
curl --request POST \
'https://${URL}/api/v2/tasks' \
-H 'Authorization: Bearer ${TOKEN}' \
-H 'Content-Type: application/json' \
-d '{
"entity": "banco-chile",
"credentials": {
"mode": "encrypted",
"value": "czuqliRO1DKMj4bbPIzMEIYyj4+GqFLBXXc/TM7d3x0==-Qlih4F8+I6kZv8xCuSAc2A=="
},
"actions": [
{ "id": "movement" }
]
}'
Response:
{ "taskId": "5cbae0b5e1b5d035d99469f42c653ff4bb8aecdf9dbdb8e10f45a31677683369" }
Referencia de campos
Request
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
entity | string | Sí | Slug de la entidad bancaria (ej. banco-chile). Ver listado en la referencia OpenAPI |
credentials | object | Sí | Credenciales del usuario. Ver tabla de modos |
actions | array | Sí | Lista de acciones a ejecutar. Mínimo una |
webhook | object | No | Notificación al finalizar |
Modos de credentials
mode | Campos | Descripción |
|---|---|---|
encrypted | value: string — formato ${CIPHER_TEXT}-${IV} | Cifrado temporal con el token de sesión como llave (máx. 60 min) |
persisted | value: string — ciphertext obtenido del servicio de cifrado persistente | Cifrado persistente, reutilizable entre requests |
raw | username: string, password: string | Texto plano, protegido por TLS |
Campos de actions[]
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
id | string | Sí | Acción a ejecutar: movement, product-balance, tef |
params | object | No | Parámetros opcionales según la acción |
Campos de webhook
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
enable | boolean | Sí | Activa la notificación al finalizar el proceso. Si es false, no se envía aunque el objeto webhook esté presente |
retries | integer | No | Cantidad total de intentos de entrega (incluye el intento inicial). Rango 1–5. Default 3 |
Credenciales
El campo credentials define cómo se envían las credenciales del usuario. Soporta tres modos:
- Opción 1 — Cifrado temporal (
encrypted): Las credenciales se cifran en cada request usando tu token de sesión como llave (AES-256-CBC; la llave se deriva aplicando SHA-256 sobre el token antes de usarla). El cifrado tiene una duración máxima de 60 minutos, por lo que es ideal para integraciones en tiempo real. Consulta la guía de cifrado temporal. - Opción 2 — Cifrado persistente (
persisted): Las credenciales se cifran una sola vez a través del servicio de cifrado de Boufin y el resultado se reutiliza en múltiples requests. Ideal para extracciones periódicas sin requerir la interacción del usuario. Consulta la guía de cifrado persistente. - Opción 3 — Texto plano (
raw): Las credenciales se envían en "texto plano", protegidas en todo momento por TLS, tanto en la conexión externa como en la comunicación interna.
Opción 1 — Cifrado temporal
{
"entity": "banco-chile",
"credentials": {
"mode": "encrypted",
"value": "czuqliRO1DKMj4bbPIzMEIYyj4+GqFLBXXc/TM7d3x0==-Qlih4F8+I6kZv8xCuSAc2A=="
},
"actions": [{ "id": "movement" }]
}
Opción 2 — Cifrado persistente
{
"entity": "banco-chile",
"credentials": {
"mode": "persisted",
"value": "sdfAgNUFdLoF7eDGAcB3BB17gEhWG+3Q6Q5Z6Q=="
},
"actions": [{ "id": "movement" }]
}
Opción 3 — Texto plano
{
"entity": "banco-chile",
"credentials": {
"mode": "raw",
"username": "11.111.111-1",
"password": "123456789"
},
"actions": [{ "id": "movement" }]
}
Acciones
Una tarea puede ejecutar múltiples acciones en secuencia sobre la misma entidad. Cada acción puede incluir parámetros opcionales para filtrar la extracción.
Acción simple
{
"entity": "banco-chile",
"credentials": {
"mode": "persisted",
"value": "sdfAgNUFdLoF7eDGAcB3BB17gEhWG+3Q6Q5Z6Q=="
},
"actions": [{ "id": "movement" }]
}
Con filtros
La acción movement acepta parámetros opcionales para acotar la extracción:
{
"entity": "banco-chile",
"credentials": {
"mode": "persisted",
"value": "sdfAgNUFdLoF7eDGAcB3BB17gEhWG+3Q6Q5Z6Q=="
},
"actions": [
{
"id": "movement",
"params": { "date_range": { "from": "2025-01-01", "to": "2025-01-31" } }
}
]
}
El historial disponible varía según la entidad. Si from es anterior al registro más antiguo disponible o to es posterior a la fecha más reciente, la fecha fuera de rango se ajusta internamente al límite disponible — la solicitud no falla por estar fuera de rango. El formato YYYY-MM-DD sí es obligatorio.
Composición
Se pueden combinar múltiples acciones. Se ejecutan en orden sobre la misma sesión bancaria:
{
"entity": "banco-chile",
"credentials": {
"mode": "persisted",
"value": "sdfAgNUFdLoF7eDGAcB3BB17gEhWG+3Q6Q5Z6Q=="
},
"actions": [
{ "id": "product-balance" },
{
"id": "movement",
"params": { "date_range": { "from": "2025-01-01", "to": "2025-01-31" } }
}
]
}
| Acción | Descripción | Parámetros opcionales |
|---|---|---|
movement | Movimientos de cuenta | date_range |
product-balance | Saldo de productos | — |
tef | Destinatarios TEF (Transferencia Electrónica de Fondos) | — |
Configuración del webhook
Para utilizar el webhook debes solicitar la activación con el equipo de soporte. La URL de destino y la llave compartida para descifrar el payload se configuran en esa misma instancia.
Si se omite el objeto webhook, la API no enviará notificaciones — el cliente debe consultar el estado vía GET /api/v2/tasks/{taskId}.
Habilitado
{
"entity": "banco-chile",
"credentials": {
"mode": "persisted",
"value": "sdfAgNUFdLoF7eDGAcB3BB17gEhWG+3Q6Q5Z6Q=="
},
"actions": [{ "id": "movement" }],
"webhook": { "enable": true }
}
Con reintentos configurados
{
"entity": "banco-chile",
"credentials": {
"mode": "persisted",
"value": "sdfAgNUFdLoF7eDGAcB3BB17gEhWG+3Q6Q5Z6Q=="
},
"actions": [{ "id": "product-balance" }, { "id": "movement" }],
"webhook": { "enable": true, "retries": 3 }
}
Recepción de la notificación
Cuando el proceso finaliza, Boufin enviará una notificación HTTP POST a la URL configurada con el equipo de soporte.
Payload
El cuerpo de la notificación es un JSON con un único campo data que contiene el payload completamente cifrado como string:
{
"data": "<cifrado>"
}
Al descifrar data obtienes un JSON con los campos del resultado:
{
"taskId": "5cbae0b5e1b5d035d99469f42c653ff4bb8aecdf9dbdb8e10f45a31677683369",
"taskStatus": "success",
"taskStatusCode": 200
}
| Campo | Descripción |
|---|---|
taskId | ID de la tarea que finalizó |
taskStatus | Estado final del proceso (ver tabla de estados) |
taskStatusCode | Código numérico del estado |
El webhook solo se dispara cuando el proceso termina definitivamente. Los posibles valores son:
taskStatusCode | taskStatus | Descripción |
|---|---|---|
200 | success | Todas las acciones completadas exitosamente |
206 | partial | Al menos una acción completó, otra(s) fallaron |
401 | wrong_login | Credenciales incorrectas |
401 | locked | La cuenta del usuario está bloqueada en la entidad |
500 | error | Error general — ninguna acción pudo ejecutarse |
taskStatusCode: 401 aplica a las credenciales de la entidad bancaria (sea wrong_login o locked), no al Bearer token. Una falla del Bearer se devuelve como HTTP 401 en la respuesta de la propia llamada, sin envolver en taskStatus.
Por el momento los estados se mantienen igual que en la v1. Puedes ver la referencia completa en la documentación del endpoint de estado de tarea.
Cifrado del payload
El campo data está cifrado con el mismo algoritmo descrito en Credenciales (AES-256-CBC). La llave compartida es acordada previamente con el equipo de soporte.
El formato del string cifrado es el mismo que en el cifrado temporal:
${CIPHER_TEXT}-${IV}
La llave se deriva aplicando SHA-256 sobre la llave compartida antes de usarla para descifrar.
Poder descifrar el campo data con tu llave compartida es prueba de origen: una petición que no provenga de Boufin no podrá producir un ciphertext válido bajo esa llave.
Ejemplo de request entrante
Así se verá la solicitud POST que llegará a tu servidor:
POST /tu-endpoint HTTP/1.1
Content-Type: application/json
{
"data": "2iHTdihWU9zAcb+ixoavm6xcmk3xq8+3NMIBd5gpleTHnWT41EoPltpcllnRdiJb7V6EK/2mz3ccxozaZ79Wcw==-0s8j3MAEU7bBEYHjVIK6aQ=="
}
Al descifrar el campo data con la llave compartida obtienes:
{
"taskId": "5cbae0b5e1b5d035d99469f42c653ff4bb8aecdf9dbdb8e10f45a31677683369",
"taskStatus": "success",
"taskStatusCode": 200
}
Cifrar el body completo como un único bloque es más seguro y simple que cifrar campo por campo: no expone la estructura del mensaje y se descifra en un solo paso.
Reintentos
Si tu servidor no responde con 200 o 204, Boufin reintentará la entrega. La cantidad total de intentos se controla con webhook.retries (default 3, rango 1–5). Intervalo de 30 segundos entre intentos. Cada intento espera un máximo de 5 segundos antes de marcarlo como fallido.
| Intento | Momento |
|---|---|
| 1° | Al finalizar el proceso |
| 2° | +30 segundos |
| 3° | +60 segundos |
| … | (continúa hasta retries) |
Si todos los intentos fallan, el evento queda registrado internamente. Puedes consultar el estado final de la tarea directamente usando GET /api/v2/tasks/{taskId}.
Para ejemplos de implementación del descifrado puedes referirte a la guía de cifrado temporal, ya que usa el mismo algoritmo.
Respuestas
Esta es la estructura base de la API v2 y todavía está en proceso de trabajo. Puede evolucionar — especialmente por la variabilidad en las respuestas de las entidades financieras durante extracciones compuestas.
Una vez finalizado el proceso, consulta los datos extraídos usando el taskId obtenido al crear la tarea:
curl "https://${URL}/api/v2/tasks/${TASK_ID}" \
-H "Authorization: Bearer ${TOKEN}"
No basta con tener un token válido — debe ser el mismo cliente que inició el proceso de extracción, como indica la documentación oficial. Esto aplica tanto al polling como a la consulta del resultado final.
Estados de la tarea
El taskStatus y taskStatusCode reflejan el resultado consolidado de todas las acciones ejecutadas:
taskStatusCode | taskStatus | Descripción |
|---|---|---|
202 | pending | Extracción encolada, aún no comenzó |
202 | running | Extracción en ejecución |
200 | success | Todas las acciones completadas exitosamente |
206 | partial | Al menos una acción completó, otra(s) fallaron |
401 | wrong_login | Credenciales incorrectas |
401 | locked | La cuenta del usuario está bloqueada en la entidad |
500 | error | Error general — ninguna acción pudo ejecutarse |
taskStatusCode: 401 aplica a las credenciales de la entidad bancaria (sea wrong_login o locked), no al Bearer token. Una falla del Bearer se devuelve como HTTP 401 en la respuesta de la propia llamada, sin envolver en taskStatus.
La tabla del webhook (Recepción de la notificación) es un subconjunto: solo lista los estados terminales.
Escenarios de respuesta
Cada acción retorna su propia respuesta dentro de results.actions, con su propio status, data y, en caso de fallo, reason y errorCode.
Éxito completo
Todas las acciones completaron sin problemas:
{
"taskStatus": "success",
"taskStatusCode": 200,
"results": {
"username": "11111111-1",
"entityId": "banco-estado",
"actions": [
{
"id": "product-balance",
"status": "success",
"data": [
/* productos */
]
},
{
"id": "movement",
"status": "success",
"data": [
/* movimientos */
]
}
]
}
}
Resultado parcial
Al menos una acción completó y otra falló. Cada acción indica su propio estado:
{
"taskStatus": "partial",
"taskStatusCode": 206,
"results": {
"username": "11111111-1",
"entityId": "banco-estado",
"actions": [
{
"id": "product-balance",
"status": "success",
"data": [
/* productos */
]
},
{
"id": "movement",
"status": "error",
"data": null,
"reason": "Entity did not respond during extraction",
"errorCode": "ENTITY_UNAVAILABLE"
}
]
}
}
Credenciales incorrectas
{
"taskStatus": "wrong_login",
"taskStatusCode": 401,
"results": null
}
Credenciales bloqueadas
La cuenta del usuario está bloqueada en la entidad bancaria (típicamente tras múltiples intentos fallidos). Las credenciales podrían ser correctas, pero la entidad rechaza el acceso:
{
"taskStatus": "locked",
"taskStatusCode": 401,
"results": null
}
Error general
La entidad no estuvo disponible y ninguna acción pudo ejecutarse:
{
"taskStatus": "error",
"taskStatusCode": 500,
"results": null
}
Referencia de campos
Campos de results
| Campo | Tipo | Descripción |
|---|---|---|
username | string | Identificador del usuario consultado (formato según la entidad) |
entityId | string | Slug de la entidad bancaria. Ver listado en la referencia de la API |
actions | array | Resultados por acción. Ver tabla siguiente |
Campos de results.actions[]
| Campo | Tipo | Descripción |
|---|---|---|
id | string | Identificador de la acción ejecutada |
status | "success" | "error" | Estado de esta acción en particular |
data | array | null | Datos extraídos. null si status = error |
reason | string | Descripción del problema en inglés, pensada para uso interno/debugging. Presente si status = error |
errorCode | string | Código de error en UPPER_SNAKE_CASE. Es el identificador estándar para manejo programático. Presente si status = error |
Códigos de error
errorCode | Descripción |
|---|---|
WRONG_LOGIN | Credenciales de la entidad bancaria incorrectas |
LOCKED_CREDENTIALS | Credenciales válidas pero la cuenta está bloqueada en la entidad bancaria |
ENTITY_UNAVAILABLE | La entidad no respondió durante la extracción |
EXTRACTION_TIMEOUT | La extracción excedió el tiempo máximo permitido |
INVALID_PARAMS | Parámetros del request inválidos para la acción solicitada |
Estamos consolidando la lista completa de códigos. Esta tabla cubre los casos más frecuentes hoy.