Códigos de error
Estado documental: Contrato propuesto. Los códigos y mensajes pasan a estado implementado o verificado únicamente cuando estén disponibles en la API correspondiente.
Objetivo
Esta página define el formato común de error, el significado de los códigos iniciales y la acción recomendada para cada familia.
Formato común
{
"error": {
"code": "validation_error",
"message": "La solicitud contiene datos inválidos.",
"fields": {
"amount": "required"
},
"retryable": false,
"request_id": "req_01JXYZ"
}
}
Campos del error
| Campo | Significado |
|---|---|
code |
Código estable y procesable por el sistema. |
message |
Descripción legible para diagnóstico. No debe utilizarse como clave lógica. |
fields |
Detalle opcional de campos inválidos. |
details |
Contexto adicional permitido para el cliente. |
retryable |
Indica si la misma intención puede reintentarse bajo las reglas del endpoint. |
request_id |
Identificador para trazabilidad y soporte. |
Los mensajes pueden mejorar sin cambiar el código. La integración debe tomar decisiones a partir de code, el HTTP status y retryable.
Semántica HTTP
| HTTP | Uso general | Regla |
|---|---|---|
400 |
Solicitud mal formada. | Corregir antes de repetir. |
401 |
Autenticación ausente, inválida o vencida. | Renovar o corregir credenciales. |
403 |
La identidad existe, pero no tiene acceso. | No insistir sin cambiar permisos o ambiente. |
404 |
El recurso no existe o no es visible para la integración. | Revisar el identificador y el ambiente. |
409 |
Conflicto de idempotencia, duplicidad o estado. | No crear otra operación a ciegas. |
410 |
El recurso temporal ya venció. | Crear un recurso nuevo cuando corresponda. |
413 |
El archivo excede el límite. | Reducirlo. |
415 |
Formato no admitido. | Utilizar un formato permitido. |
422 |
La estructura es válida, pero los datos no cumplen el contrato. | Corregir los datos. |
429 |
Límite de solicitudes superado. | Esperar y aplicar reintento progresivo. |
500 |
Error inesperado. | Reintentar solo cuando sea seguro. |
503 |
Servicio temporalmente no disponible. | Reintentar con espera y la misma idempotencia. |
Algunas consultas asíncronas pueden devolver 202 junto con report_not_ready. Ese resultado indica procesamiento en curso, no un fallo irreversible.
Autenticación, ambiente y permisos
| HTTP | Código | Significado | Reintento | Acción |
|---|---|---|---|---|
| 401 | invalid_credentials |
Las credenciales no son válidas. | No | Revisar client_id, secreto y ambiente. |
| 401 | credential_revoked |
La credencial fue revocada. | No | Generar o solicitar otra credencial. |
| 401 | access_token_expired |
El token de acceso venció. | Sí | Obtener otro token y repetir de forma segura. |
| 403 | environment_not_allowed |
La credencial no corresponde al ambiente. | No | Usar las credenciales y base URL correctas. |
| 403 | permission_denied |
La identidad no tiene el permiso requerido. | No | Revisar roles y permisos. |
| 403 | user_not_authorized |
El usuario no está autorizado para la acción. | No | Asignar un usuario autorizado. |
| 409 | credential_rotation_in_progress |
Ya existe una rotación de credencial activa. | No | Completar o cancelar el proceso existente. |
Validación y configuración
| HTTP | Código | Significado | Acción |
|---|---|---|---|
| 422 | validation_error |
Uno o más campos no cumplen el contrato. | Corregir los campos indicados. |
| 422 | invalid_amount |
El monto es inválido. | Enviar una cadena decimal válida y permitida. |
| 422 | unsupported_currency |
La moneda no está habilitada. | Utilizar una moneda admitida por la integración. |
Idempotencia y duplicados
| HTTP | Código | Significado | Acción |
|---|---|---|---|
| 409 | idempotency_conflict |
La clave ya fue utilizada con otro contenido. | No cambiar solo la clave para forzar otra creación; revisar la intención original. |
| 409 | external_transaction_conflict |
El ID externo ya existe con datos diferentes. | Consultar la operación existente y corregir la integración. |
| 409 | possible_duplicate_transaction |
Existe una operación reciente con características equivalentes. | Revisar antes de crear otra. |
Órdenes y sesiones de checkout
| HTTP | Código | Significado | Acción |
|---|---|---|---|
| 404 | payment_order_not_found |
La orden no existe o no es visible. | Revisar ID y ambiente. |
| 409 | invalid_state_transition |
La acción no corresponde al estado actual. | Consultar el recurso y decidir según su estado. |
| 404 | checkout_session_not_found |
La sesión no existe. | Revisar el identificador. |
| 410 | checkout_session_expired |
La sesión venció. | Crear otra sesión cuando la orden lo permita. |
| 401 | checkout_token_invalid |
El token temporal no es válido. | No reutilizarlo; obtener una sesión válida. |
Turnos, usuarios, dispositivos y entregas
| HTTP | Código | Significado | Acción |
|---|---|---|---|
| 404 | shift_not_available |
El turno no existe o no está disponible. | Consultar o abrir un turno válido. |
| 409 | shift_closed |
El turno ya fue cerrado. | No crear nuevas operaciones en ese turno. |
| 409 | shift_device_mismatch |
El dispositivo no corresponde al turno. | Corregir el dispositivo o turno. |
| 404 | device_not_available |
El dispositivo no está disponible. | Revisar su estado o utilizar otro autorizado. |
| 404 | delivery_not_found |
La entrega no existe. | Revisar el identificador. |
| 409 | delivery_retry_not_allowed |
La entrega no admite otro reintento. | Crear una nueva acción solo cuando el flujo lo permita. |
Evidencias, OCR y casos pendientes
| HTTP | Código | Significado | Acción |
|---|---|---|---|
| 415 | evidence_not_supported |
El formato no está admitido. | Enviar un formato permitido. |
| 413 | evidence_too_large |
El archivo excede el límite. | Reducirlo antes de repetir. |
| 422 | evidence_unreadable |
La imagen no puede interpretarse. | Enviar otra evidencia más legible. |
| 500 | ocr_failed |
El procesamiento OCR falló. | Reintentar solo cuando retryable sea verdadero o solicitar revisión. |
| 404 | pending_case_not_found |
El caso pendiente no existe. | Revisar el ID y el ambiente. |
| 409 | pending_case_already_resolved |
El caso ya fue resuelto. | Consultar su resolución; no repetir la acción. |
| 409 | resolution_not_allowed |
La resolución solicitada no es compatible con el caso. | Elegir una acción permitida. |
Devoluciones
| HTTP | Código | Significado | Acción |
|---|---|---|---|
| 404 | refund_case_not_found |
El caso de devolución no existe. | Revisar el identificador. |
| 422 | refund_amount_exceeds_received |
El monto supera el importe recibido o disponible. | Corregir el monto. |
| 422 | refund_execution_evidence_required |
Falta evidencia de ejecución. | Adjuntar la evidencia requerida. |
| 409 | refund_already_completed |
La devolución ya fue registrada como completada. | No repetir el efecto. |
Reportes
| HTTP | Código | Significado | Acción |
|---|---|---|---|
| 422 | report_type_not_supported |
El tipo de reporte no está disponible. | Utilizar un tipo admitido. |
| 202 | report_not_ready |
El trabajo todavía está en proceso. | Consultar nuevamente después. |
| 410 | report_expired |
La descarga temporal venció. | Solicitar otro trabajo. |
| 500 | report_generation_failed |
El reporte no pudo generarse. | Reintentar según retryable. |
| 422 | invalid_report_filter |
El filtro no aplica al reporte solicitado. | Corregir los filtros. |
Webhooks
| HTTP | Código | Significado | Acción |
|---|---|---|---|
| 404 | webhook_endpoint_not_found |
El receptor no existe. | Revisar el ID o registrar otro endpoint. |
| 401 | webhook_signature_invalid |
La firma no es válida. | Rechazar el evento o corregir el secreto de prueba. |
| 401 | webhook_timestamp_invalid |
El timestamp está fuera de la tolerancia aplicable. | Rechazar y revisar sincronización de tiempo. |
| 404 | webhook_delivery_not_found |
El intento de entrega no existe. | Revisar el identificador. |
| 409 | webhook_retry_not_allowed |
El intento no puede repetirse. | Consultar el evento y la política de reentrega. |
| 422 | webhook_url_invalid |
La URL no es válida o no está autorizada. | Registrar una URL HTTPS permitida. |
Disponibilidad y límites
| HTTP | Código | Significado | Acción |
|---|---|---|---|
| 429 | rate_limit_exceeded |
La integración superó el límite aplicable. | Esperar; respetar Retry-After cuando esté disponible. |
| 503 | service_unavailable |
El servicio no está disponible temporalmente. | Aplicar espera progresiva y conservar idempotencia. |
| 500 | internal_error |
Ocurrió un error inesperado. | Conservar request_id y reintentar solo cuando sea seguro. |
Reglas de reintento
401 access_token_expired
→ obtener otro token
409 idempotency_conflict
→ no crear otra operación a ciegas
422 validation_error
→ corregir antes de repetir
429 rate_limit_exceeded
→ esperar
503 service_unavailable
→ reintento progresivo con la misma Idempotency-Key
- Un reintento de la misma intención conserva el mismo
external_transaction_id, la mismaIdempotency-Keyy el mismo payload. - Si una conexión termina sin respuesta, la empresa debe consultar por ID externo antes de crear otra operación.
- Los errores de validación no se reintentan sin corregir los datos.
- Un conflicto 409 requiere consultar el recurso y resolver la causa.
- Los reintentos deben tener un límite y espera progresiva.
Errores desconocidos
Ante un código no reconocido, la empresa debe:
- no asumir éxito;
- conservar HTTP status,
codeyrequest_id; - seguir
retryablecuando esté presente; - evitar mostrar detalles técnicos sensibles al comprador;
- consultar el changelog y la versión del contrato.
Seguridad de los mensajes
Las respuestas no deben publicar secretos, credenciales, stack traces, consultas internas ni detalles privados de infraestructura.
Criterios de aceptación documental
- Existe un sobre común de error.
- El código, y no el mensaje, guía la lógica de la integración.
request_idpermite trazabilidad.retryableinforma la posibilidad de reintento.- Los 409 no se reintentan a ciegas.
- Los 422 se corrigen antes de repetir.
- Los 429 y 503 utilizan espera progresiva.
- Los reintentos conservan idempotencia.
- Los errores desconocidos no se tratan como éxito.
- Las respuestas no exponen información interna.
Payment Orders, Counters y capacidad
Payment Order / API Engine v1.0 separa los errores públicos de la intención de cobro de los conflictos internos que ocurren durante la resolución o adquisición de un Counter.
counter_busy
| HTTP | Código | Ámbito | Significado | Acción |
|---|---|---|---|---|
| 409 | counter_busy |
Interno / Adapter | El Counter concreto ya mantiene una Payment Order abierta y no puede adquirirse para otra. | No elegir otro instrumento arbitrariamente. En orígenes con pool, el Allocator puede intentar otro Counter disponible. |
counter_busy describe el conflicto de adquisición de un Counter específico. En Web Checkout el integrador no selecciona Counters ni conoce un pool: YUPY administra internamente la capacidad runtime del Counter virtual Web canónico.
no_counter_available
| HTTP | Código | Ámbito | Significado | Acción |
|---|---|---|---|---|
| Por definir | no_counter_available |
Público / capacidad | No existe en ese momento un Counter elegible disponible dentro del pool aplicable. | Tratarlo como falta de capacidad. Reintentar únicamente según retryable y la política del endpoint, conservando la misma intención e idempotencia cuando corresponda. |
Importante: el HTTP status público definitivo de no_counter_available todavía no está cerrado. No debe documentarse 409 ni 503 como contrato final hasta que el API Engine defina esa decisión.
Relación con el medio de pago
El error histórico payment_profile_invalid deja de formar parte del contrato activo de selección del instrumento. El caller solicita payment_method; YUPY resuelve internamente el Counter, la policy y el instrumento concreto habilitado para ese contexto.
Idempotencia en errores de capacidad
Un error de capacidad no autoriza a crear otra intención comercial a ciegas. Si el endpoint permite reintento, debe preservarse external_transaction_id, la intención original y la Idempotency-Key mientras se esté reintentando la misma operación técnica.
Changelog — Payment Order / API Engine
2026-08-09 — Payment Order / API Engine v1.0: se retiró payment_profile_invalid del contrato activo de selección de instrumento; se incorporó 409 counter_busy como conflicto interno de adquisición de un Counter; se añadió no_counter_available como error público de capacidad del pool sin fijar todavía su HTTP status final; y se aclaró que los reintentos de capacidad deben conservar la intención e idempotencia cuando el endpoint los permita.