Autenticación y permisos
La API externa del core acepta dos credenciales. Las dos las emite el banco durante la incorporación; no hay alta de autoservicio.
| Credencial | Cómo se envía | Qué concede |
|---|---|---|
| Clave API | Cabecera X-Api-Key: <clave> | Los alcances (scopes) registrados para la clave, por ejemplo account:read o payment:write. |
| Token OAuth 2.0 | Authorization: Bearer <token>, obtenido en POST /oauth2/token con grant_type=client_credentials | Los roles del cliente OAuth configurados por el banco. |
Para integraciones de sistema a sistema, pide una clave API con los alcances exactos que necesitas. Las rutas de pagos (/api/v1/payments/*) y de clientes (/api/v1/ext/customers) solo aceptan alcances de clave API.
Obtener un token OAuth 2.0
curl -s -X POST https://api.banco.example/oauth2/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=client_credentials
{
"access_token": "<token opaco>",
"token_type": "Bearer",
"expires_in": 899
}
El token es opaco y dura 15 minutos por defecto (la instalación puede cambiarlo). Renueva el token antes de que venza; no hay refresh token en este flujo.
Llamar con clave API
curl -s https://api.banco.example/api/v1/ext/account-products \
-H "X-Api-Key: $FINORA_API_KEY"
Permisos por operación
Cada operación exige un permiso. Una clave API lo obtiene por su alcance; un token OAuth, por los roles del cliente.
| Alcance | Qué permite |
|---|---|
customer:read / customer:write | Consultar y registrar clientes. |
account:read | Productos de cuenta, cuentas, saldos, movimientos y bloqueos. |
account:write | Abrir una cuenta a un cliente existente (con KYC y verificación en listas). |
account:status | Registrar y liberar bloqueos; cerrar una cuenta. Crítico. |
account:authorize | Aprobar o rechazar un bloqueo registrado por otra identidad. Crítico. |
credit:read | Productos de crédito, simulación, créditos, plan de pagos y cotización de cancelación. |
credit:write | Crear la solicitud de crédito. |
credit:approve | Aprobar o rechazar la solicitud. Crítico. |
credit:disburse | Desembolsar un crédito aprobado. Crítico. |
credit:payment | Cobrar cuotas, adelantos y la cancelación anticipada. Crítico. |
payment:write | Transferencias internas, depósitos y retiros. |
gl:read / gl:write | Consultar el plan de cuentas y los asientos; registrar y reversar asientos manuales (crítico). |
events:read | Leer el flujo de eventos y gestionar suscripciones de consumidor. Crítico. |
webhook:read / webhook:write | Consultar y gestionar webhooks salientes (crítico en escritura). |
Crítico significa que el permiso no lo concede ningún rol genérico de acceso total: hay que otorgarlo de forma expresa. Cuando falta, la API responde 403.
Cuatro ojos
Las operaciones de dos pasos exigen identidades distintas en cada paso:
- Un bloqueo de cuenta lo registra una identidad y lo aprueba otra.
- Un crédito lo solicita una identidad, lo aprueba otra y lo desembolsa una tercera, distinta de la que aprobó.
Si la misma credencial intenta los dos pasos, la API responde 422 con type terminado en four-eyes-violation. En la práctica necesitas una credencial por rol (por ejemplo, una para originar y otra para aprobar).
Idempotencia
Toda escritura exige Idempotency-Key (UUID v4 recomendado, hasta 200 caracteres en las rutas /api/v1/ext/**).
| Situación | Respuesta |
|---|---|
| Primera vez | 201 (o 202 en un bloqueo) con el recurso creado. |
| Misma clave y misma petición | 200 con el resultado original; no se vuelve a ejecutar. |
| Misma clave y petición distinta | 409, type terminado en idempotency-key-reused. |
| Falta la cabecera | 400. |
Genera la clave una vez por operación de negocio y guárdala junto a tu registro; reutilízala en cada reintento tras un corte de red.
Errores
Los errores siguen RFC 7807 con Content-Type: application/problem+json:
{
"type": "https://finora.dcgeeks.com/problems/missing-header",
"title": "Header requerido ausente",
"status": 400,
"detail": "El header 'Idempotency-Key' es obligatorio para este endpoint.",
"instance": "/api/v1/ext/accounts",
"timestamp": "2026-10-13T10:15:30-04:00"
}
Decide por status y por el sufijo de type, nunca por el texto de detail.
| HTTP | Sufijos de type frecuentes | Qué hacer |
|---|---|---|
| 400 | validation-error, missing-header, invalid-idempotency-key, malformed-body | Corregir la petición. |
| 401 | — | Revisar la credencial. |
| 403 | access-denied | Pedir al banco el alcance que falta. |
| 404 | not-found, *-not-found | Corregir el identificador. |
| 409 | idempotency-key-reused, *-state-conflict | No reintentar con otra clave: consultar el estado. |
| 422 | four-eyes-violation, business-rule-violation, insufficient-funds | Regla de negocio: revisar detail. |