Ir al contenido

Errores

Toda respuesta de error tiene la misma forma:

422 Unprocessable Entity
{ "error": {
"type": "invalid_request_error", "code": "limit_exceeded",
"message": "Supera el límite por operación de pago móvil",
"request_id": "req_8a0312ba896772bc441134cd",
"meta": { "limit": "per_tx_max", "max": "10000000", "scope": "platform" } } }
Campo Qué es
code Código estable. Programa contra esto
type Familia del error: te dice si tiene sentido reintentar
message Texto legible. Puede cambiar o traducirse: no lo parsees
request_id También viaja en la cabecera x-request-id. Inclúyelo al abrir un ticket
meta Contexto estructurado cuando lo hay: qué límite se superó, qué campo es inválido, cuánto saldo había. Ausente en errores internos

Tu switch sobre error.code necesita un default para códigos desconocidos.

type HTTP Significa ¿Reintentar?
invalid_request_error 400 · 404 · 409 · 422 Algo de la petición está mal No sin corregir
authentication_error 401 · 403 Credenciales o permisos No
rate_limit_error 429 Vas demasiado rápido Sí, más despacio
provider_error 502 · 503 Fallo de un riel Sí, con la misma Idempotency-Key
api_error ≥ 500 Fallo nuestro Sí
Código HTTP Qué hacer
api_key_missing 401 Falta el header x-api-key
api_key_invalid 401 Revisar credenciales
api_key_revoked 401 Esa clave se revocó
api_key_expired 401 Pedir una nueva
tenant_suspended 403 Contactar a soporte
insufficient_scope 403 Usar una clave con el scope de meta.required
Código HTTP Qué hacer
validation_failed 400 Corregir el cuerpo o la query. El message dice qué campo; a veces también meta.field
invalid_amount 400 Monto ≤ 0, fuera de rango, o tan pequeño que la comisión se lo comería
unsupported_asset 400 Activo o par no soportado
Código HTTP Qué hacer
idempotency_key_reused 409 Clave nueva: el cuerpo cambió
idempotency_request_in_flight 409 La original sigue en curso; reintentar en segundos
Código HTTP Qué hacer
quote_not_found 404 No existe, o es de otro programa
quote_expired 422 Pedir una cotización nueva
quote_already_consumed 409 Esa cotización ya la usó otra dispersión
Código HTTP Qué hacer
beneficiary_not_found 404 El beneficiaryId no es tuyo o no existe
beneficiary_blocked 422 Está bloqueado: ni se lee ni se le dispersa
beneficiary_instrument_missing 422 Sin teléfono para pago móvil, o sin cuenta para transferencia. meta trae beneficiaryId e instrument
Código HTTP Qué hacer
insufficient_tenant_funds 422 Tu saldo no alcanza. Sólo si operas prefondeado
credit_limit_exceeded 422 Agotaste la línea del cierre diario
limit_exceeded 422 meta dice qué límite (per_tx_max, daily_max, monthly_max, daily_count_max), el tope y el consumo
invalid_state_transition 409 La operación no aplica al estado actual del pago

payment_not_found, quote_not_found, beneficiary_not_found y event_not_found → 404, igual que un recurso de otro programa.

Código HTTP Qué hacer
no_provider_available 503 No hay riel para ese banco/instrumento ahora mismo. Reintentar más tarde
provider_error 502 Fallo del proveedor. Reintentar con la misma Idempotency-Key
rate_limited 429 Bajar el ritmo. Respetar Retry-After
internal_error 500 Fallo nuestro. Reintentable; manda el request_id si persiste

Un error que no encaje en los códigos anteriores llega con un código genérico por familia: not_found (404), conflict (409), unprocessable (422) o invalid_request (400). Trátalos como el resto de su familia.


Los motivos de rechazo del riel no son error.code

Sección titulada «Los motivos de rechazo del riel no son error.code»
201 Created — la dispersión se procesó y el riel la rechazó
{ "id": "89920401-26da-4f69-b57d-bc20e0366ce2", "status": "failed",
"reason": "beneficiary_missing_phone",
"asset": "BS", "amount": "5000000", "feeAmount": "0" }
reason Qué pasó
beneficiary_missing_phone Falta el móvil del beneficiario. Ocurre también en transferencia
beneficiary_missing_account Falta el número de cuenta para transferencia
beneficiary_mismatch Nombre o cédula no coinciden con el titular de esa cuenta o teléfono
invalid_destination_account La cuenta destino no existe o está mal formada
sender_required No había remitente por ninguno de los tres caminos
amount_below_rail_minimum Por debajo del piso del riel
amount_above_rail_limit Por encima del techo del riel
amount_not_positive Importe ≤ 0
amount_precision_loss El importe no se puede representar sin perder céntimos
bank_unreachable Ese riel no cubre el banco destino
instrument_unsupported Ese riel no ofrece ese instrumento
rail_insufficient_balance El riel no tiene liquidez de dispersión ahora mismo
rail_rejected Rechazo genérico del riel
provider_timeout No sabemos si pagó → el pago queda en unknown, no en failed
no_route Ningún riel candidato para esa combinación

El mismo valor queda en status_reason del pago y en el reason de la transición dentro de events[]. Qué hacer con cada uno: cuando algo falla.

Un pago con status: "unknown" responde 200/201, no un error: el riel no confirmó, y el pago está en duda. Ver estados de un pago.