Guías
Errores
Todos los códigos de error y estados HTTP de la API de CheaperGen (400, 401, 402, 404, 409, 429, 502 y 503), con sus causas y cómo gestionar o reintentar cada uno.
La API usa los códigos de estado HTTP habituales: 2xx indica éxito, 4xx que debes modificar la solicitud y 5xx que se produjo un error en nuestro sistema o en un servicio externo. Todas las respuestas de error tienen el mismo formato JSON, así que puedes gestionarlas en un solo lugar.
Formato de error#
{
"error": {
"code": "invalid_request",
"message": "\"resolution\" must be one of: 480p, 720p",
"param": "resolution"
}
}code: una cadena estable y legible por máquinas. Usa este valor para tomar decisiones en el código, no el mensaje.message: una explicación legible por personas y segura para incluir en los registros. La redacción puede cambiar.param: aparece cuando un campo específico de la solicitud causó el error.
Códigos de error#
| HTTP | código | Significado | Qué hacer | ¿Reintentar? |
|---|---|---|---|---|
| 400 | invalid_request | El cuerpo no es JSON válido, falta un campo obligatorio, un valor está fuera del rango o no está permitido, el cuerpo contiene un parámetro desconocido, una mención del prompt no apunta a nada o un archivo de video o audio de referencia no se puede leer o supera los límites del modelo (duración, tamaño, resolución o frecuencia de fotogramas). param indica el campo que causa el error. | Corrige la solicitud. El mensaje indica exactamente qué está mal. | Después de corregirlo |
| 401 | unauthorized | Falta la clave de API, está mal formada o fue revocada. | Comprueba el encabezado Authorization: Bearer y que la clave esté activa. | Después de corregirlo |
| 402 | insufficient_balance | Tu saldo no alcanza para cubrir el precio de esta generación. No se te cobró nada. | Añade créditos o activa la recarga automática en Panel → Facturación. Consulta Facturación. | Después de corregirlo |
| 404 | not_found | El ID del endpoint, el modelo o la generación no existe, o la generación pertenece a otra cuenta. | Comprueba el ID en la lista de modelos. | No |
| 409 | conflict | La solicitud entra en conflicto con el estado del recurso; por lo general, se debe a que se intenta cancelar una generación que ya está en curso o terminó. | Consulta la generación para ver su estado actual. | No |
| 410 | model_delisted | El modelo ya no está disponible. No se envió ni cobró nada; puedes seguir consultando las generaciones anteriores. | Elige otro modelo en la lista de modelos. | No |
| 429 | rate_limited | Se enviaron demasiadas solicitudes por segundo o tu cola de generaciones en espera está llena. | Espera y vuelve a intentarlo. Consulta Límites de solicitudes. | Con espera incremental |
| 500 | internal_error | Se produjo un error de nuestro lado. | Vuelve a intentarlo con una espera incremental. Si el problema persiste, contacta con soporte e indica la hora de la solicitud. | Con espera incremental |
| 501 | direct_upload_unavailable | La carga directa con URL prefirmada no está disponible en esta implementación. | Vuelve a cargarlo con multipart/form-data. Consulta Cargas. | No |
| 502 | — | Un error de red o de una puerta de enlace ocurrió antes de que la solicitud llegara a nuestra API (poco frecuente). Los fallos del modelo en el servicio externo no aparecen como errores HTTP: la generación falla con un motivo de error. | Vuelve a intentarlo con una espera incremental. No se te cobró nada. | Con espera incremental |
| 503 | model_unavailable | El modelo no acepta generaciones nuevas temporalmente. | Vuelve a intentarlo más tarde o cambia de modelo. Comprueba página de estado. | Con espera incremental |
| 503 | pricing_unavailable | No se pudieron consultar los precios temporalmente, así que no se calculó el precio de la solicitud. No se envió ni se cobró nada. | Vuelve a intentar la misma solicitud en unos segundos (la respuesta incluye una cabecera Retry-After), con el mismo Idempotency-Key. | Con espera incremental |
| 503 | fallback_price_declined | La capacidad habitual no está disponible; ahora solo se ofrece el precio de emergencia (como máximo, el precio oficial) y enviaste allow_fallback_price: false. No se te cobró nada; el mensaje muestra ambos precios. | Vuelve a intentarlo más tarde para obtener el precio estándar o envía allow_fallback_price: true (el valor predeterminado) para aceptar el precio de emergencia. | Con espera incremental |
| 400 | max_cost_exceeded | El precio, incluido el de emergencia, supera tu max_cost_usd. No se te cobró nada. | Reduce la resolución o la duración, o confirma el precio y aumenta max_cost_usd. | Después de corregirlo |
Errores durante una generación#
Un error HTTP significa que se rechazó la solicitud y no se cobró nada. Es distinto de una generación aceptada que falla más tarde: la llamada a la API se realizó correctamente (incluso POST /run devuelve 202 si una tarea falla de inmediato) y el status de la generación pasa a ser failed, con un objeto error. El importe reservado se reembolsa automáticamente. El mismo objeto aparece en GET /generations, en la carga webhook y en los resultados de las herramientas MCP.
{
"status": "failed",
"error": {
"code": "generation_failed",
"message": "ByteDance's safety review for Seedance 2.0 Fast rejected this request (the prompt or an input file).",
"reason": "content_blocked",
"hint": "Describe the character's look instead of naming a copyrighted character or real person, keep it non-explicit, or try another model.",
"retryable": false,
"refunded": true,
"detail": "Tu solicitud no superó la revisión de seguridad del contenido. Ajusta el prompt y vuelve a intentarlo."
}
}code es la categoría general (los cuatro valores documentados desde el lanzamiento). reason explica exactamente el motivo; úsalo en el código y muestra message y hint a tus usuarios. retryable indica si se puede volver a enviar la misma solicitud; param especifica qué campo cambiar, si se puede determinar, y detail contiene el texto del proveedor del modelo.
| error.reason | error.code | Qué ocurrió | Qué hacer | ¿Reenviar sin cambios? |
|---|---|---|---|---|
content_blocked | generation_failed | El filtro de seguridad del proveedor del modelo rechazó el prompt, un archivo de entrada o el resultado generado (por ejemplo, por un personaje con derechos de autor, una persona real o contenido explícito). El mensaje indica de quién era el filtro. | Reformula el prompt (describe el aspecto en vez de mencionar a un personaje, una marca o una persona real), usa otros archivos de entrada o prueba un modelo de otro proveedor. Si lo envías sin cambios, volverá a fallar por el mismo motivo. | No; primero haz un cambio |
invalid_input | generation_failed | El modelo no pudo aceptar una de las entradas o los ajustes: un archivo demasiado grande, en un formato no admitido, con dimensiones o relación de aspecto incorrectas, demasiado largo o con un valor no compatible. param indica el campo cuando podemos identificarlo. | Corrige el campo indicado (consulta los límites del modelo en su página de API) y vuelve a enviar la solicitud, o prueba otro modelo. | No; primero haz un cambio |
input_unreachable | generation_failed | No se pudo descargar una URL de entrada: requiere iniciar sesión, el enlace firmado ha caducado, no apunta directamente al archivo o el servidor de origen rechazó la solicitud. Cuando el proveedor del modelo no puede descargar un archivo, normalmente lo descargamos nosotros y volvemos a intentarlo con nuestra copia; por eso, este mensaje suele significar que no se pudo descargar el archivo en absoluto. | Usa una URL pública y directa al archivo (o súbelo con POST /api/v1/uploads) y vuelve a enviar la solicitud. | No; primero haz un cambio |
upstream_unavailable | upstream_error | El proveedor del modelo estaba caído, sobrecargado o sin capacidad, y probamos todas las rutas disponibles. | Vuelve a intentarlo en uno o dos minutos o usa otro modelo. | Sí |
upstream_error | upstream_error | El proveedor encontró un error interno durante la generación, después de que probáramos todas las rutas disponibles. | Vuelve a intentarlo; estos errores suelen ser temporales. Si sigue fallando, prueba otro modelo. | Sí |
timeout | timeout | La generación no terminó a tiempo (por el límite del proveedor o por nuestro límite de 40 minutos). | Vuelve a intentarlo. Los clips más cortos o de menor resolución terminan antes. | Sí |
output_unavailable | upstream_error | El modelo terminó, pero no devolvió ningún archivo utilizable o no se pudo descargar y guardar el resultado. | Retry. | Sí |
model_unavailable | model_unavailable | El modelo o esta modalidad dejó de estar disponible mientras se procesaba la generación. | Elige otro modelo o vuelve a intentarlo más tarde. | No; primero haz un cambio |
canceled | upstream_error | El proveedor canceló la tarea o hizo que caducara antes de terminar. (Si cancelas tú la generación, su estado es canceled y no se informa de ningún error.) | Retry. | Sí |
generation_failed | generation_failed | El modelo se detuvo sin generar un resultado ni indicar el motivo. | Vuelve a intentarlo una vez; si vuelve a fallar, simplifica el prompt o las entradas, o prueba otro modelo. | Sí |
Los fallos causados por tu solicitud —content_blocked, un archivo rechazado en invalid_input o input_unreachable— no se reintentan en otros proveedores, porque volverían a rechazarse. Primero se reintentan los cortes del servicio y los errores del proveedor en todas las rutas compatibles, al mismo precio. Consulta Fallos y reembolsos.
Cuando un proveedor indica que no puede descargar uno de tus archivos de entrada, normalmente intentamos descargarlo nosotros. Si podemos, volvemos a intentar el trabajo con una copia alojada por nosotros, al mismo precio y sin que tengas que cambiar nada; la generación sigue mostrando las URL que enviaste y la copia se elimina junto con la generación según su retención. Por eso, input_unreachable suele significar que no se pudo descargar el archivo en absoluto: requiere iniciar sesión, el enlace firmado ha caducado, no apunta directamente al archivo o el servidor de origen rechazó la solicitud. Copiamos imágenes de hasta 30 MB, videos de hasta 200 MB y audio de hasta 50 MB; los archivos más grandes o ilegibles fallan con invalid_input.
Reintentar de forma segura#
Reintenta los errores 429, 500, 502 y 503 con retroceso exponencial y fluctuación aleatoria. No reintentes sin cambios otros errores 4xx; volverán a fallar por el mismo motivo.
Las solicitudes de envío no son idempotentes
Cada envío correcto con POST /run/{endpoint} crea y factura una nueva generación. Si se agota el tiempo de espera de la red al enviar y no sabes si se aceptó, consulta tus generaciones recientes antes de volver a enviarla.
const RETRYABLE = new Set([429, 500, 502, 503]);
export async function postWithRetry(url, headers, body, attempts = 5) {
let resp;
for (let attempt = 0; attempt < attempts; attempt++) {
resp = await fetch(url, { method: "POST", headers, body: JSON.stringify(body) });
if (!RETRYABLE.has(resp.status)) break;
// exponential backoff with jitter: ~1s, 2s, 4s, 8s…
await new Promise((r) => setTimeout(r, Math.min(2 ** attempt, 30) * 1000 + Math.random() * 1000));
}
const data = await resp.json();
if (!resp.ok) throw new Error(`${resp.status} ${data.error.code}: ${data.error.message}`);
return data;
}Ejemplos de validación#
Los mensajes de validación indican el campo y los valores permitidos, así que puedes mostrárselos directamente a los desarrolladores:
[
{
"error": {
"code": "invalid_request",
"message": "\"prompt\" is required",
"param": "prompt"
}
},
{
"error": {
"code": "invalid_request",
"message": "Unknown parameter \"resoluton\"",
"param": "resoluton"
}
},
{
"error": {
"code": "not_found",
"message": "Unknown endpoint \"bytedance/seedance-2.0-fast/text-to-gif\". See GET /api/v1/models."
}
}
]También puedes consultar el precio sin ejecutar la solicitud: POST /api/v1/quote/{endpoint} valida los campos que afectan al precio y devuelve el coste. Consulta referencia de la API.
¿Algo no está claro o falta información? Escribe a support@cheapergen.com; leemos todos los mensajes.