Códigos de error y estados HTTP
Todo fallo devuelve un código estable y legible por máquina junto al estado HTTP. Ramifique según el código, nunca según el texto del mensaje: los mensajes están escritos para personas y pueden reescribirse, mientras que los códigos forman parte del contrato.
Los 42 códigos que puede devolver la API para revendedores, agrupados según qué salió mal. Cada entrada indica el estado HTTP con el que llega y el cambio que lo resuelve.
Autenticación (401)
| Código | HTTP | Qué significa | Cómo resolverlo |
|---|---|---|---|
| MISSING_API_KEY | 401 | La clave de API es obligatoriaNo se envió el encabezado Authorization o su formato no es correcto. | Incluye el encabezado: Authorization: Bearer <keyId>.<secret>action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_API_KEY | 401 | Clave de API no válidaLa clave de API enviada no coincide con ninguna clave activa del sistema. | Revisa que el ID de la clave y el secreto sean correctos. Si hace falta, genera una clave nueva desde el panel Acceso a la API.action: FIX_INPUT · retryable: false · retry_after: null |
Autorización (403)
| Código | HTTP | Qué significa | Cómo resolverlo |
|---|---|---|---|
| ACCOUNT_DISABLED | 403 | La cuenta está desactivadaYa no se devuelve. Una cuenta que no puede hacer pedidos responde ACCOUNT_FROZEN (HTTP 403). | Maneja ACCOUNT_FROZEN en su lugar.Ya no se devuelve. Lo reemplaza ACCOUNT_FROZEN |
| ACCOUNT_FROZEN | 403 | La cuenta está congeladaTu cuenta se congeló temporalmente, por lo general por actividad sospechosa. | Contacta a soporte para descongelar tu cuenta.action: CONTACT_SUPPORT · retryable: false · retry_after: null |
| IP_NOT_ALLOWED | 403 | La dirección IP no está en la lista de permitidasLa solicitud vino de una dirección IP que no está en la lista de IP permitidas de tu clave de API. | Agrega la IP de tu servidor a la lista de permitidas en el panel Acceso a la API o quita las restricciones de IP.action: FIX_INPUT · retryable: false · retry_after: null |
Validación de la solicitud (400)
| Código | HTTP | Qué significa | Cómo resolverlo |
|---|---|---|---|
| MISSING_REQUIRED_FIELD | 400 | Falta un campo obligatorioFalta un campo obligatorio en el cuerpo de la solicitud. En los requisitos del jugador, details.field indica qué campo falta. | Revisa la documentación del endpoint y, para los campos del jugador, GET /catalog/category/:categoryId/requirements. Luego envía todos los campos obligatorios.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_PARAMETER_FORMAT | 400 | Un parámetro tiene un formato no válidoUn campo de los requisitos tiene un formato no válido (por ejemplo, texto en un campo numérico). El campo afectado se indica en details.field. | Vuelve a revisar los requisitos de la categoría y envía el campo en el formato que esperan su data_type y sus reglas de validación.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_PARAMETER_VALUE | 400 | Un parámetro tiene un valor no válidoUn campo de los requisitos tiene un valor no permitido: está por debajo del mínimo, por encima del máximo o no coincide con ninguna de sus select_options. El campo afectado se indica en details.field. | Envía un valor que los requisitos de la categoría permitan para ese campo.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_PARAMETER_LENGTH | 400 | Un parámetro tiene una longitud no válidaUn campo de los requisitos es más corto o más largo de lo permitido. El campo afectado se indica en details.field. | Revisa min_length / max_length en los requisitos de la categoría.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_UUID_FORMAT | 400 | Formato de UUID no válidoEl order_id no tiene un formato de UUID válido. | Usa cualquier formato de UUID válido (v1, v4, v7, etc.). Formato: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_QUANTITY | 400 | Cantidad no válidaLa cantidad debe ser un número entero positivo. | Indica una cantidad entera >= 1.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_CATEGORY_ID | 400 | ID de categoría no válidoEl categoryId enviado no es un número válido. | Usa el Explorador del catálogo o GET /catalog/categories para encontrar IDs de categoría válidos.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_BIG_CATEGORY_ID | 400 | ID de categoría principal no válidoEl bigCategoryId enviado no es un número válido. | Consulta el Explorador del catálogo o GET /catalog/big-categories para ver los IDs de categoría principal válidos.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_ITEM_ID | 400 | ID de artículo no válidoEl ID de artículo enviado no es válido. | Busca IDs de artículo válidos en el Explorador del catálogo o con GET /catalog/subcategories.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_SUBCATEGORY | 400 | Subcategoría no válidaEl ID de subcategoría no existe. | Verifica el sub_category_id con los endpoints del catálogo.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_PRODUCT_CONFIG | 400 | Configuración de producto no válidaYa no se devuelve. Si falta un campo de requisito, ahora se responde MISSING_REQUIRED_FIELD; si el producto no se puede vender en este momento, se responde PRODUCT_UNAVAILABLE. | Maneja MISSING_REQUIRED_FIELD y PRODUCT_UNAVAILABLE en su lugar.Ya no se devuelve. Lo reemplaza MISSING_REQUIRED_FIELD |
| INVALID_PAGINATION | 400 | Parámetros de paginación no válidosLos valores de page o limit están fuera de rango. | Usa page >= 1 y un limit entre 1 y 100.action: FIX_INPUT · retryable: false · retry_after: null |
| INVALID_DATE_FORMAT | 400 | Formato de fecha no válidoEl parámetro created_after o created_before no es una fecha ISO 8601 válida. | Usa el formato ISO 8601: 2024-01-01T00:00:00Z.action: FIX_INPUT · retryable: false · retry_after: null |
Validación del jugador (400 / 429 / 503)
| Código | HTTP | Qué significa | Cómo resolverlo |
|---|---|---|---|
| PLAYER_NOT_FOUND | 400 | Jugador no encontradoEl juego confirmó que este ID de jugador no existe. Este código solo aparece con una respuesta confirmada; si el ID no se puede verificar, recibes PLAYER_CHECK_UNAVAILABLE. | Revisa que el ID del jugador sea correcto. Comprueba si el juego necesita un zone_id.action: FIX_INPUT · retryable: false · retry_after: null |
| PLAYER_CHECK_UNAVAILABLE | 503 | Por ahora no se pueden verificar los IDs de jugador de este juegoEn este momento no es posible comprobar los IDs de jugador de este juego. El ID del jugador NO fue rechazado. | Repite la misma solicitud pasados retry_after segundos. No le digas a tu cliente que el ID es incorrecto.action: RETRY_LATER · retryable: true · retry_after: 60 |
| PLAYER_BUSY | 429 | Este ID de jugador ya se está verificandoOtra solicitud con el mismo ID de jugador sigue en verificación. | Vuelve a enviar la solicitud después de retry_after segundos.action: RETRY_SOON · retryable: true · retry_after: 5 |
| PLAYER_VALIDATION_FAILED | 400 | Falló la validación del jugadorYa no se devuelve. Si un ID de jugador no se puede comprobar en ese momento, la respuesta es PLAYER_CHECK_UNAVAILABLE (HTTP 503). | Maneja PLAYER_CHECK_UNAVAILABLE en su lugar.Ya no se devuelve. Lo reemplaza PLAYER_CHECK_UNAVAILABLE |
| REGION_MISMATCH | 400 | La región de este jugador no puede recibir este productoEl jugador pertenece a una región donde este producto no se puede entregar. El error incluye player_region y player_name. | Elige el producto que corresponde a la región del jugador.action: CHOOSE_OTHER · retryable: false · retry_after: null |
Reglas de negocio (400 / 409)
| Código | HTTP | Qué significa | Cómo resolverlo |
|---|---|---|---|
| INSUFFICIENT_BALANCE | 400 | Saldo insuficiente en la billeteraTu billetera no tiene fondos suficientes para completar este pedido. | Recarga tu billetera desde la página de recargas antes de hacer el pedido.action: TOP_UP · retryable: false · retry_after: null |
| OUT_OF_STOCK | 400 | Producto agotadoEl producto solicitado está agotado en este momento. | Inténtalo más tarde o elige otro producto.action: RETRY_LATER · retryable: true · retry_after: null |
| INSUFFICIENT_STOCK | 400 | Hay menos unidades disponibles de las solicitadasHay menos unidades disponibles de las que pide tu pedido. A diferencia de OUT_OF_STOCK, aquí sí puedes hacer algo: error.max_quantity indica cuántas unidades se pueden pedir ahora mismo. No se cobró nada. | Envía de nuevo el pedido con una cantidad igual o menor a error.max_quantity.action: FIX_INPUT · retryable: false · retry_after: null |
| PRODUCT_UNAVAILABLE | 409 | Este producto no está disponible temporalmenteEl producto existe, pero ahora mismo no se puede vender. | Vuelve a intentarlo más tarde o elige otro producto.action: RETRY_LATER · retryable: true · retry_after: null |
| PRICING_UPDATING | 409 | Se está actualizando el precio del productoEstamos actualizando el precio de este producto. | Repite la misma solicitud después de retry_after segundos y luego vuelve a revisar el precio.action: RETRY_SOON · retryable: true · retry_after: 30 |
| OFFER_NOT_FOUND | 400 | Esta oferta no está disponible para la cuenta de este jugadorUna oferta de un solo uso (por ejemplo, un bono de primera recarga) no está disponible para la cuenta de este jugador. Es posible que ya se haya usado. | Elige otro producto para este jugador.action: CHOOSE_OTHER · retryable: false · retry_after: null |
| DUPLICATE_ORDER | 409 | ID de pedido duplicadoYa existe un pedido con este UUID. Es una protección de idempotencia. | Usa un UUID nuevo cuando crees un pedido nuevo. Si te aparece al reintentar, el primer intento sí se procesó: consulta ese pedido con GET /orders/{orderId} en lugar de crear otro.action: CHECK_ORDER · retryable: false · retry_after: null |
| PRICE_INCREASED | 400 | El precio subió más de lo esperadoEl precio unitario actual es mayor que el expected_unit_price que enviaste. | Consulta el precio más reciente con GET /catalog/subcategory/:id/price y actualiza expected_unit_price.action: FIX_INPUT · retryable: false · retry_after: null |
| SUBCATEGORY_DISABLED | 400 | La subcategoría está desactivadaYa no se devuelve. Si un producto no se puede vender en ese momento, la respuesta es PRODUCT_UNAVAILABLE (HTTP 409). | Maneja PRODUCT_UNAVAILABLE en su lugar.Ya no se devuelve. Lo reemplaza PRODUCT_UNAVAILABLE |
No encontrado (404)
| Código | HTTP | Qué significa | Cómo resolverlo |
|---|---|---|---|
| ORDER_NOT_FOUND | 404 | Pedido no encontradoNo existe ningún pedido con ese ID. | Comprueba que el ID del pedido sea correcto.action: FIX_INPUT · retryable: false · retry_after: null |
| ITEM_NOT_FOUND | 404 | Artículo no encontradoEl artículo del catálogo que solicitaste no existe. | Usa los endpoints del catálogo para encontrar IDs de artículos válidos.action: FIX_INPUT · retryable: false · retry_after: null |
| NO_REQUIREMENTS_FOUND | 404 | No se encontraron requisitos para esta categoríaPor ahora, esta categoría no tiene requisitos de jugador que devolver. | Prueba más tarde o elige otra categoría.action: RETRY_LATER · retryable: true · retry_after: null |
| ITEM_NOT_AVAILABLE | 404 | Artículo no disponibleYa no se devuelve. Si un artículo existe pero no se puede vender en ese momento, la respuesta es PRODUCT_UNAVAILABLE (HTTP 409). | Maneja PRODUCT_UNAVAILABLE en su lugar.Ya no se devuelve. Lo reemplaza PRODUCT_UNAVAILABLE |
Validación de solicitudes por lote (400)
| Código | HTTP | Qué significa | Cómo resolverlo |
|---|---|---|---|
| INVALID_ORDER_IDS_FORMAT | 400 | Formato de order_ids no válidoEl campo order_ids debe ser un array de cadenas. | Envía order_ids así: { "order_ids": ["uuid1", "uuid2"] }.action: FIX_INPUT · retryable: false · retry_after: null |
| EMPTY_ORDER_IDS | 400 | Array order_ids vacíoEl array order_ids no puede estar vacío. | Incluye al menos un ID de pedido en el array.action: FIX_INPUT · retryable: false · retry_after: null |
| TOO_MANY_ORDER_IDS | 400 | Demasiados IDs de pedidoPuedes consultar hasta 50 IDs de pedido a la vez. | Divide la solicitud en lotes de 50 o menos.action: FIX_INPUT · retryable: false · retry_after: null |
Límite de solicitudes (429)
| Código | HTTP | Qué significa | Cómo resolverlo |
|---|---|---|---|
| RATE_LIMIT_EXCEEDED | 429 | Límite de solicitudes superadoSuperaste el límite de este endpoint. Los límites por minuto (catálogo, pedidos y cuenta) envían X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset en cada respuesta, y details repite limit, remaining (0), retry_after y window_seconds. POST /player/validate, en cambio, se mide con tu cuota diaria de verificaciones de jugador: no envía encabezados X-RateLimit y su 429 trae limit, current, remaining, reset_at y reset_in_seconds dentro de error. En ambos casos, error.retry_after y el encabezado Retry-After indican los segundos que debes esperar. | Antes de reintentar, espera los segundos que indica retry_after o el encabezado Retry-After. En los endpoints con límite por minuto, vigila X-RateLimit-Remaining para no llegar nunca al límite.action: RETRY_LATER · retryable: true · retry_after: segundos hasta el reinicio |
Errores del servidor (5xx)
| Código | HTTP | Qué significa | Cómo resolverlo |
|---|---|---|---|
| INTERNAL_ERROR | 500 | Error interno del servidorOcurrió un error inesperado en el servidor. | Vuelve a enviar la solicitud pasados retry_after segundos. En POST /orders/create usa el mismo order_id, así el pedido nunca se crea dos veces. Si el error continúa, contacta a soporte.action: RETRY_LATER · retryable: true · retry_after: 30 |
| SERVICE_UNAVAILABLE | 503 | Servicio no disponible temporalmenteYa no se devuelve. Un fallo del servidor responde con INTERNAL_ERROR (HTTP 500). El único 503 es PLAYER_CHECK_UNAVAILABLE, cuando un ID de jugador no se puede comprobar en ese momento. | Gestiona INTERNAL_ERROR y PLAYER_CHECK_UNAVAILABLE en su lugar.Ya no se devuelve. Lo reemplaza INTERNAL_ERROR |
¿Recién llega a la plataforma? Empiece por la presentación de la API de recargas de juegos para revendedores, o lea la presentación del programa de revendedores de SHOP2TOPUP para ver cómo funciona la cuenta de socio.