Documentación de la API HappyHorse
Guía completa para integrar la API de generación de vídeo HappyHorse 1.0 en tus aplicaciones.
Inicio rápido
curl -X POST 'https://happyhorse.app/api/generate' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"model": "happyhorse-1.0/video",
"prompt": "A cinematic shot of mountains at sunrise",
"mode": "pro",
"duration": 5,
"aspect_ratio": "16:9"
}'Autenticación
Todas las solicitudes requieren un token Bearer en el encabezado Authorization.
Obtener tu clave API: Puedes obtener tu clave en la página API Keys del panel. → Obtener tu clave API
Authorization: Bearer YOUR_API_KEYCómo funcionan Generate y Status
Las tareas de vídeo de HappyHorse son asíncronas: crea una tarea con POST /api/generate, guarda el task_id devuelto y consulta GET /api/status hasta llegar a un estado final.
Crear una tarea
Envía prompt, model, mode, duration e imágenes opcionales a /api/generate. Una respuesta correcta devuelve task_id de inmediato.
Consultar el estado
Usa task_id con /api/status. Mientras status sea IN_PROGRESS, el vídeo sigue renderizándose y response permanece null.
Leer el resultado
Cuando status sea SUCCESS, data.response.resultUrls[0] es la URL del vídeo. Si pasa a FAILED, muestra error_message y detén el polling.
Modelos disponibles
HappyHorse 1.0
Generación de vídeo con IA de alta calidad con HappyHorse
| Tipo | Descripción | Duración | Créditos |
|---|---|---|---|
pro (text-to-video) | Texto a vídeo calidad Pro | 3-15s | 54/s (no audio) · 80/s (with audio) |
pro (image-to-video) | Imagen a vídeo calidad Pro | 3-15s | 54/s (no audio) · 80/s (with audio) |
std (text-to-video) | Texto a vídeo calidad estándar | 3-15s | 40/s (no audio) · 60/s (with audio) |
std (image-to-video) | Imagen a vídeo calidad estándar | 3-15s | 40/s (no audio) · 60/s (with audio) |
Endpoints de la API
Crea una tarea de generación de vídeo. El campo model debe ser 'happyhorse-1.0/video'.
Cuerpo de la solicitud
Nombre del modelo; debe ser 'happyhorse-1.0/video'
Descripción en texto del vídeo (máx. 2500 caracteres). No es obligatorio si multi_shots es true.
Modo de calidad: 'pro' o 'std' (predeterminado: std) Defaults to std.
Duración en segundos (3–15). En modo multi-plano, la duración final se deriva de multi_prompt; si envías duration explícitamente, debe coincidir con la suma de las duraciones de los planos. Defaults to 5 / sum(multi_prompt).
Relación de aspecto de salida (16:9, 9:16, 1:1) Defaults to 16:9.
Array de URLs de imagen para imagen a vídeo
Activar audio nativo (predeterminado: true). En solicitudes multi-plano, envía este campo explícitamente como true o false. Defaults to true.
Adherencia al prompt (0-1, predeterminado: 0.5). Valores más altos siguen el prompt con más fidelidad. Defaults to 0.5.
Modo multi-plano con varios prompts Defaults to false.
Array de objetos 'prompt, duration' para multi-plano
Array de objetos de elemento. En el prompt, escribe @ seguido del valor de name (p. ej. name 'element_dog' → @element_dog). Cada elemento: name, description, element_input_urls (2-4 URLs de imagen). Max 3 por tarea.
Texto a vídeo
{
"model": "happyhorse-1.0/video",
"prompt": "A majestic eagle soaring through clouds at sunset",
"mode": "pro",
"duration": 5,
"aspect_ratio": "16:9",
"sound": true
}Imagen a vídeo
{
"model": "happyhorse-1.0/video",
"prompt": "The character slowly turns and smiles",
"mode": "pro",
"image_urls": ["https://example.com/my-image.jpg"],
"duration": 5
}Vídeo multi-plano
{
"model": "happyhorse-1.0/video",
"mode": "pro",
"multi_shots": true,
"sound": true,
"duration": 10,
"multi_prompt": [
{ "prompt": "A woman walks into a coffee shop", "duration": 3 },
{ "prompt": "She orders a latte and sits by the window", "duration": 4 },
{ "prompt": "She looks outside and smiles", "duration": 3 }
],
"aspect_ratio": "16:9"
}Respuestas
Task created successfully
{
"code": 200,
"message": "success",
"data": {
"task_id": "n92abc123hh10",
"status": "IN_PROGRESS"
}
}Comprueba el estado con el task_id devuelto por el endpoint generate.
Parámetros de consulta
ID único devuelto por generate (prefijo n92)
Ejemplo de solicitud
curl -X GET 'https://happyhorse.app/api/status?task_id=n92abc123hh10' \
-H 'Authorization: Bearer YOUR_API_KEY'Consejo: El campo response contiene el array resultUrls. Usa data.response.resultUrls[0] para la URL del vídeo.
// Extract video URL after the task is complete
const task = payload.data;
const videoUrl = task.status === "SUCCESS"
? task.response?.resultUrls?.[0]
: null;Respuestas
{
"code": 200,
"message": "success",
"data": {
"task_id": "n92abc123hh10",
"status": "SUCCESS",
"consumed_credits": 400,
"created_at": "2026-04-08T10:30:00Z",
"type": "text-to-video",
"request": {
"model": "happyhorse-1.0/video",
"prompt": "A majestic eagle soaring through clouds at sunset",
"mode": "pro",
"duration": 5,
"aspect_ratio": "16:9"
},
"response": {
"resultUrls": [
"https://cdn.example.com/videos/abc123.mp4"
]
},
"error_message": null
}
}Buenas prácticas de polling
La generación de vídeo puede tardar un poco, así que trata las consultas de estado como una tarea de fondo tranquila, no como un bucle apretado.
Empieza con una breve espera
Espera unos 8-10 segundos antes de la primera consulta y luego consulta cada 10-20 segundos. Consultar más rápido no hará que el vídeo termine antes.
Detente en estados finales
SUCCESS y FAILED son finales. Detén el polling en cuanto veas cualquiera de ellos y guarda el task_id para soporte o consultas posteriores.
Usa un timeout del cliente
Después de 10-15 minutos, detén la espera activa y permite que el usuario vuelva a consultar el estado manualmente. No dejes una pestaña del navegador consultando para siempre.
Reduce el ritmo ante errores
Si recibes 429 o un error temporal de red, espera más antes de la siguiente solicitud. Para 401 o 402, pide al usuario que corrija la clave API o los créditos.
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
async function waitForHappyHorseVideo(taskId) {
const deadline = Date.now() + 15 * 60 * 1000;
let delayMs = 8000;
while (Date.now() < deadline) {
const res = await fetch(
`${BASE_URL}/api/status?task_id=${encodeURIComponent(taskId)}`,
{ headers: { Authorization: `Bearer ${API_KEY}` } }
);
if (res.status === 429) {
await sleep(Math.min(delayMs * 2, 30000));
continue;
}
const payload = await res.json();
if (!res.ok) {
throw new Error(payload.message || `Status request failed: ${res.status}`);
}
const task = payload.data;
if (task.status === "SUCCESS") {
return task.response?.resultUrls?.[0];
}
if (task.status === "FAILED") {
throw new Error(task.error_message || "Generation failed");
}
await sleep(delayMs);
delayMs = Math.min(delayMs + 2000, 20000);
}
throw new Error("Timed out. Keep the task_id and check again later.");
}Zona de pruebas API
Prueba la API en el navegador. Sustituye YOUR_API_KEY por tu clave real.
Códigos de error
| Estado HTTP | Código | Descripción |
|---|---|---|
| 400 Solicitud incorrecta | INVALID_PROMPT | El prompt no es válido o está vacío |
| 400 Solicitud incorrecta | INVALID_DURATION | Duración fuera del rango admitido (3–15 s) |
| 400 Solicitud incorrecta | INVALID_MODEL | El modelo debe ser 'happyhorse-1.0/video' |
| 401 No autorizado | INVALID_API_KEY | Falta la clave API o no es válida |
| 402 Pago requerido | INSUFFICIENT_CREDITS | Créditos insuficientes para esta operación |
| 429 Demasiadas solicitudes | RATE_LIMITED | Demasiadas solicitudes; reduce la frecuencia |
| 500 Error interno del servidor | INTERNAL_ERROR | Error del servidor; inténtalo más tarde |