Saltar al contenido principal

Primeros pasos

1. Obtener un token​

El gateway emite un JWT de 15 minutos con OAuth 2.0 client_credentials. La credencial puede ir en Authorization: Basic o en el cuerpo, en formulario o JSON.

curl -s -X POST https://gateway.banco.example/v1/oauth/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=client_credentials \
-d scope="clients:read deposits:read"
{
"access_token": "<JWT>",
"token_type": "Bearer",
"expires_in": 900,
"scope": "clients:read deposits:read",
"tenant": "banco-demo",
"environment": "sandbox"
}
  • scope es opcional: pide un subconjunto de los alcances de tu cliente. Si pides uno que no tienes, 400 con error: invalid_scope.
  • El token queda atado al inquilino y al entorno de tu credencial: una credencial de pruebas solo obtiene tokens de pruebas.
  • Tras varios intentos fallidos seguidos, la credencial (o la dirección de origen) queda bloqueada temporalmente: 429.
  • Si el banco rotó tu secreto y entras con el anterior, la respuesta trae X-Finora-Secret-Expires con la fecha en que deja de valer.
Sin pedir token

Para pruebas puntuales, el gateway acepta también la cabecera apiKey: <clientId>.<secreto>. En producción usa el token: el secreto viaja una vez cada 15 minutos y no en cada petición.

2. Hacer la primera llamada​

curl -s "https://gateway.banco.example/v1/deposit-products?paginationDetails=ON" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/vnd.finora.v1+json" \
-i

Cabeceras de la petición​

CabeceraObligatoriaUso
Authorization: Bearer <JWT>síToken del paso 1.
Acceptnoapplication/json o application/vnd.finora.v1+json. Pedir otra versión (v2…) responde 406 VERSION_NO_SOPORTADA.
X-Finora-TenantnoInquilino. Si el banco usa subdominios por inquilino, se deduce del host; si la envías, debe coincidir con el de tu credencial.
X-Finora-Environmentnosandbox o production. Debe coincidir con el entorno de tu credencial.
Idempotency-Keyen escriturasUUID. Ver más abajo.
X-Request-IdnoTu identificador de traza ([A-Za-z0-9._-], de 8 a 64 caracteres); el gateway lo devuelve. Si no lo envías o no cumple el formato, genera uno.

Cabeceras de la respuesta​

CabeceraContenido
X-Request-IdIdentificador de la petición; cítalo al pedir soporte.
X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-ResetLímite de tu cliente, lo que queda y los segundos hasta reiniciarse. Al excederlo, 429 LIMITE_EXCEDIDO con Retry-After.
Items-Total, Items-Offset, Items-LimitSolo con ?paginationDetails=ON.
Items-Next-CursorEn los movimientos de una cuenta, que se paginan por cursor.

3. Paginar​

Las listas devuelven un arreglo JSON y se paginan con offset (desde 0) y limit (50 por defecto, hasta 1000). Con paginationDetails=ON recibes el total en las cabeceras Items-*.

Los movimientos de una cuenta (GET /v1/deposits/{id}/transactions) se paginan por cursor: usa el valor de Items-Next-Cursor en ?cursor=; offset no aplica y limit va de 1 a 100.

4. Escribir con idempotencia​

Toda escritura exige Idempotency-Key con un UUID (v4 recomendado). El gateway guarda el resultado 6 horas.

Las respuestas 4xx y 5xx no se guardan: puedes corregir y reintentar con la misma clave.

ErrorHTTPCuándo
IDEMPOTENCY_KEY_REQUERIDA400Falta la cabecera en una escritura.
IDEMPOTENCY_KEY_INVALIDA400La clave no es un UUID.

5. Interpretar errores​

Los errores siguen RFC 7807 (application/problem+json) con type del espacio urn:finora:core-gateway: y siempre traen codigo, requestId y timestamp. Por compatibilidad con otros cores, incluyen además errorCode (el estado HTTP), errorReason (categoría) y, cuando se conoce, errorSource (el campo culpable).

{
"type": "urn:finora:core-gateway:no-soportado-por-core",
"title": "Operación no disponible en el core",
"status": 501,
"detail": "El core no expone la modificación de créditos por API.",
"instance": "/v1/loans/215",
"codigo": "CORE_NO_SOPORTA",
"requestId": "4f1c9a2b7e8d4c6a9b0e1f2a3b4c5d6e",
"timestamp": "2026-10-20T14:05:11.204-04:00",
"errorCode": 501,
"errorReason": "METHOD_NOT_IMPLEMENTED",
"operacion": "PATCH /v1/loans/{loanId}",
"alternativa": "…"
}

Decide siempre por codigo.

HTTPerrorReasonEjemplos de codigo
400INVALID_PARAMETERSIDEMPOTENCY_KEY_REQUERIDA, PAGINACION_POR_CURSOR, DETAILS_LEVEL_INVALIDO
401INVALID_CREDENTIALSGW_CREDENCIAL_INVALIDA
403PERMISSION_DENIEDTENANT_CRUZADO, ENTORNO_CRUZADO
406INVALID_API_OPERATIONVERSION_NO_SOPORTADA
409CONFLICTIDEMPOTENCIA_EN_CURSO
422BUSINESS_RULE_VIOLATIONIDEMPOTENCIA_CUERPO_DISTINTO, reglas de negocio del core
423TENANT_SUSPENDEDTENANT_SUSPENDIDO
429TOO_MANY_REQUESTSLIMITE_EXCEDIDO, GW_LOGIN_BLOQUEADO
501METHOD_NOT_IMPLEMENTEDCORE_NO_SOPORTA

6. Nivel de detalle​

Algunas consultas aceptan ?detailsLevel=FULL para incluir datos de consultas adicionales al core: el saldo por fases en GET /v1/deposits/{id}, el plan de pagos en GET /v1/loans/{id} o el estado de la ficha en GET /v1/clients/{id}. El valor por defecto es BASIC.