Transcrita del código del gateway (main, la versión desplegada). Todo error es application/problem+json con:
| Propiedad | Qué es |
|---|
type | urn:finora:core-gateway:<tipo> |
title, status, detail | Lo de RFC 7807 |
codigo | El código estable de esta página: es el que tu programa debe leer |
requestId | El mismo valor de la cabecera X-Request-Id |
timestamp | Momento del error |
errorCode | El estado HTTP, para clientes que esperan ese campo |
errorReason | Categoría: INVALID_PARAMETERS (400), INVALID_CREDENTIALS (401), PERMISSION_DENIED (403), NOT_FOUND (404), INVALID_API_OPERATION (405, 406, 415), CONFLICT (409), BUSINESS_RULE_VIOLATION (422), TENANT_SUSPENDED (423), TOO_MANY_REQUESTS (429), METHOD_NOT_IMPLEMENTED (501), SERVICE_UNAVAILABLE (503), INTERNAL_ERROR (otros 5xx) |
errorSource | El campo, parámetro o cabecera culpable, cuando se conoce (limit, Idempotency-Key, filterCriteria[0], Content-Type…) |
Lee siempre codigo, nunca el texto de detail: el texto puede cambiar, el código no.
| Estado | codigo | Tipo | Cuándo | Qué hacer |
|---|
| 400 | GW_GRANT_NO_SOPORTADO | grant-no-soportado | grant_type distinto de client_credentials | Usa client_credentials |
| 400 | GW_CREDENCIAL_AMBIGUA | solicitud-invalida | El client_id del cuerpo no coincide con el de Authorization: Basic | Manda la credencial por una sola vía |
| 400 | GW_ALCANCE_INVALIDO | alcance-invalido | Pediste en scope un alcance que tu credencial no tiene | Pide un subconjunto de los tuyos, o ninguno |
| 401 | GW_CREDENCIAL_INVALIDA | credencial-invalida | Cliente o secreto incorrectos | Revisa el par; cada fallo suma al bloqueo |
| 401 | GW_NO_AUTENTICADO | no-autenticado | Petición sin token ni apiKey, o token vencido o alterado | Pide un token nuevo |
| 429 | GW_LOGIN_BLOQUEADO | demasiados-intentos | Demasiados fallos seguidos de esa credencial | Espera el tiempo de bloqueo y corrige el secreto |
| 429 | GW_IP_BLOQUEADA | demasiados-intentos | Demasiadas credenciales inválidas desde tu dirección | Espera; el bloqueo vale incluso con una credencial válida |
En /v1/oauth/token el error trae además la propiedad error de OAuth 2.0: invalid_client, invalid_request,
invalid_scope, unsupported_grant_type o unauthorized_client.
| Estado | codigo | Tipo | Cuándo |
|---|
| 400 | TENANT_INVALIDO | solicitud-invalida | El nombre de institución no tiene un formato válido |
| 400 | TENANT_AMBIGUO | solicitud-invalida | El subdominio y X-Finora-Tenant nombran instituciones distintas |
| 400 | ENTORNO_AMBIGUO | solicitud-invalida | El subdominio y X-Finora-Environment se contradicen |
| 400 | ENTORNO_INVALIDO | solicitud-invalida | X-Finora-Environment no es production ni sandbox |
| 403 | GW_ALCANCE_INSUFICIENTE | alcance-insuficiente | Tu credencial no tiene el alcance de ese dominio y método |
| 403 | TENANT_CRUZADO | tenant-cruzado | Pediste una institución distinta de la de tu credencial |
| 403 | ENTORNO_CRUZADO | entorno-cruzado | Token de producción contra el sandbox, o al revés |
| 403 | TENANT_DESCONOCIDO | tenant-desconocido | La institución no está en el registro del gateway |
| 403 | SANDBOX_NO_DISPONIBLE | sandbox-no-disponible | La institución no tiene sandbox declarado |
| 403 | MODULO_NO_HABILITADO | modulo-no-habilitado | El dominio no está en el plan de la institución |
| 423 | TENANT_SUSPENDIDO | tenant-suspendido | La institución está suspendida |
| Estado | codigo | Cuándo |
|---|
| 400 | PAGINACION_INVALIDA | offset negativo o limit fuera de rango (1–1000; 1–100 en movimientos de cuenta) |
| 400 | PAGINATION_DETAILS_INVALIDO | paginationDetails no es ON ni OFF |
| 400 | PAGINACION_POR_CURSOR | Pediste movimientos de cuenta con offset: se paginan con cursor |
| 400 | DETAILS_LEVEL_INVALIDO | detailsLevel no es BASIC ni FULL |
| 400 | ID_INVALIDO | Un identificador de la ruta con formato inválido (también un GET sobre una acción :verbo) |
| 400 | FECHA_INVALIDA | Una fecha que no es yyyy-MM-dd |
| 400 | MONEDA_INVALIDA | Moneda que no es un código ISO 4217 de tres letras |
| 400 | TIPO_INVALIDO | type de cuenta contable fuera de la lista |
| 400 | ESTADO_INVALIDO | accountState de crédito fuera de la lista |
| 400 | RANGO_DE_FECHAS_REQUERIDO | Búsqueda de asientos sin bookingDate BETWEEN con value y secondValue |
| 400 | CUERPO_INVALIDO, GW_CUERPO_INVALIDO | El cuerpo no es un objeto JSON legible |
| 400 | CUENTA_INCONSISTENTE | La cuenta del cuerpo no coincide con la de la ruta (depósitos, retiros, transferencias) |
| 400 | GW_SOLICITUD_INVALIDA | Falta un parámetro o tiene un tipo inválido |
| 400 | IDEMPOTENCY_KEY_REQUERIDA | Escritura sin Idempotency-Key |
| 400 | IDEMPOTENCY_KEY_INVALIDA | Idempotency-Key no es un UUID |
| 400 | CURSOR_INVALIDO | El cursor de eventos no tiene el formato que entregó el core |
| 400 | CURSOR_NO_ADMITIDO | Mandaste cursor al leer una suscripción: esa lee desde su cursor confirmado |
| 400 | TIPOS_DE_EVENTO_INVALIDOS | eventTypes con un tipo inválido o más de 50 |
| 400 | YAML_REQUERIDO | PUT de configuración con el cuerpo vacío |
| 404 | GW_RUTA_INEXISTENTE | La ruta no existe en /v1 |
| 404 | PRODUCTO_NO_ENCONTRADO | El producto de captación o de crédito no existe en el core de la institución |
| 405 | GW_METODO_NO_PERMITIDO | El método no aplica a esa ruta |
| 406 | VERSION_NO_SOPORTADA | Accept pide una versión distinta de application/vnd.finora.v1+json |
| 406 | GW_NO_ACEPTABLE | Accept pide un formato que la ruta no produce |
| 413 | YAML_DEMASIADO_GRANDE | El documento de configuración supera 2 MiB |
| 415 | GW_TIPO_NO_SOPORTADO | Content-Type no admitido (JSON en general; YAML en la configuración) |
| Estado | codigo | Cuándo | Qué hacer |
|---|
| 409 | IDEMPOTENCIA_EN_CURSO | Otra petición con la misma clave aún no termina | Espera y reintenta con la misma clave |
| 422 | IDEMPOTENCIA_CUERPO_DISTINTO | Reusaste la clave con otro cuerpo | Una operación nueva lleva una clave nueva |
| 429 | LIMITE_EXCEDIDO | Agotaste el límite; alcanceLimite dice si fue el tuyo (CLIENTE) o el de la institución (TENANT) | Espera lo que dice Retry-After |
| Estado | codigo | Cuándo |
|---|
| 501 | CORE_NO_SOPORTA | La ruta es parte de la superficie /v1 pero el core no la ofrece por API. El error trae operacion y alternativa (por ejemplo, reversar en lugar de borrar un asiento) |
El gateway no inventa rechazos de negocio: los toma del core y los reexpone.
| Estado | codigo | Cuándo |
|---|
| 4xx del core | CORE_<TIPO> | El core rechazó la operación con un tipo propio: unbalanced-entry llega como CORE_UNBALANCED_ENTRY, con su mismo estado y sus datos de negocio (blockingRuleCodes, existingCustomerId, operationalDate…) y estadoCore |
| 400 / 404 / 409 / 422 | CORE_SOLICITUD_INVALIDA, CORE_NO_ENCONTRADO, CORE_CONFLICTO, CORE_REGLA_DE_NEGOCIO, CORE_RECHAZO | El core rechazó sin un tipo propio |
| 403 | CORE_ACCESO_DENEGADO | La credencial del gateway ante el core no tiene el permiso de esa operación |
| 403 | CORE_MODULE_DISABLED | El módulo no está licenciado en el core de la institución (propiedad modulo) |
| 404 | CORE_RUTA_NO_DISPONIBLE | El core de esa institución todavía no tiene esa ruta (una versión anterior) |
| 422 | CORE_FOUR_EYES_VIOLATION | Quien aprueba es la misma identidad que quien solicitó (cuatro ojos) |
| 502 | CORE_ERROR_INTERNO | Error interno del core, sin detalle publicable |
| 502 | CORE_RESPUESTA_NO_JSON | El core respondió algo que no es JSON |
| 502 | CORE_CREDENCIAL_RECHAZADA | El core no aceptó la credencial del gateway: lo corrige el operador, no tú |
| 503 | CORE_NO_DISPONIBLE | El core no responde (red o tiempo agotado) |
| 503 | CORE_CIRCUITO_ABIERTO | El circuit breaker de esa institución está abierto tras varios fallos del core |
| 503 | CORE_SIN_CREDENCIAL | El gateway no tiene configurada la credencial de esa institución |
| 500 | GW_ERROR_INTERNO | Error inesperado del gateway; nunca trae trazas |
Los tipos de la API contable están en la referencia de la API contable.
| Situación | ¿Reintentas? |
|---|
5xx, CORE_NO_DISPONIBLE, CORE_CIRCUITO_ABIERTO | Sí, con espera creciente y la misma Idempotency-Key |
409 IDEMPOTENCIA_EN_CURSO | Sí, con la misma clave, después de unos segundos |
| 429 | Sí, después de Retry-After |
| Cualquier otro 4xx | No: corrige la petición primero |