Errores
Códigos de estado HTTP y cuerpo de error que devuelve la API de javinfo.
Las solicitudes fallidas no se facturan. Solo pagas los 200.
Códigos de estado
| Estado | Significado |
|---|---|
400 | Solicitud incorrecta. Validación fallida (falta un parámetro, valor fuera de rango, enum incorrecto), una solicitud a /query o /idols sin q ni filtro, o un id de proveedor desconocido. |
401 | Clave API ausente o inválida. |
402 | Crédito insuficiente. Retry-After es una hora, una pista para clientes automatizados; una recarga te desbloquea al instante. Consulta facturación. |
404 | Sin resultado. Lo devuelven /movie, /random, /idols/{id}, /discover/similar, las consultas de /analytics/idols/*, y /resolve, /resolve/provenance y /resolve/streams. |
422 | Solo /query: ningún proveedor admite esa combinación de filtro y orden, el fijado no la admite, o paginaste más allá de 50 sin q. Consulta Filtrado. |
429 | Demasiadas solicitudes: el tope por minuto de tu cuenta, o el presupuesto por hora de los proveedores en vivo. Espera Retry-After. |
503 | Un proveedor fijado (providers=) superó su presupuesto por hora. Quita la fijación o espera Retry-After. |
499 | El cliente cerró la solicitud antes de que respondiera un proveedor. |
/query nunca devuelve 404. Sin coincidencias es un 200 con count: 0 y results vacío,
y no cuesta nada: comprueba count. Las búsquedas por nombre (/idols/{id},
/discover/similar, resolve) devuelven 404 si falta el código o el intérprete.
Cuerpo del error
Los errores de los manejadores usan el sobre de oRPC: defined, code, status y message.
{
"defined": false,
"code": "NOT_FOUND",
"status": 404,
"message": "no title found for \"ZZZZ-99999\""
}Un 400 añade data.issues, una entrada por regla fallida:
{
"defined": false,
"code": "BAD_REQUEST",
"status": 400,
"message": "Input validation failed",
"data": {
"issues": [
{
"expected": "string",
"code": "invalid_type",
"path": ["q"],
"message": "Invalid input: expected string, received undefined"
}
]
}
}422: mismo sobre, status: 422, code: "BAD_REQUEST":
{
"defined": false,
"code": "BAD_REQUEST",
"status": 422,
"message": "does not support sort \"rating\""
}Los rechazos en la puerta, antes del manejador, son más cortos:
{ "error": "invalid api key" }Sin clave, la solicitud pasa la puerta y el manejador la rechaza con el cuerpo UNAUTHORIZED:
{
"defined": false,
"code": "UNAUTHORIZED",
"status": 401,
"message": "Unauthorized"
}El limitador por minuto también usa la forma corta: { "error": "rate limit exceeded" }.
No des por hecho code: decide por el estado y lee el cuerpo.
Esperar antes de reintentar
429, 402 y 503 llevan Retry-After en segundos. Respétalo:
if ([429, 402, 503].includes(res.status)) {
const wait = Number(res.headers.get('Retry-After') ?? 1);
await new Promise((r) => setTimeout(r, wait * 1000));
}En 402, esa hora es orientativa. Si hay una persona delante, recarga y reintenta ya.