Documentation API HappyHorse

Guide complet pour intégrer l’API de génération vidéo HappyHorse 1.0 dans vos applications.

API v1.0 Base URL: https://happyhorse.app

Démarrage rapide

bash
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"
  }'

Authentification

Toutes les requêtes API nécessitent un jeton Bearer dans l’en-tête Authorization.

Obtenir votre clé API: Vous pouvez obtenir votre clé API sur la page API Keys du tableau de bord. → Obtenir votre clé API

http
Authorization: Bearer YOUR_API_KEY

Fonctionnement de Generate et Status

Les tâches vidéo HappyHorse sont asynchrones : créez une tâche avec POST /api/generate, conservez la task_id retournée, puis appelez GET /api/status jusqu'à un état final.

1

Créer une tâche

Envoyez le prompt, le modèle, le mode, la durée et les images optionnelles à /api/generate. Une réponse réussie renvoie immédiatement task_id.

2

Interroger le statut

Utilisez task_id avec /api/status. Tant que le statut est IN_PROGRESS, la vidéo est encore générée et response reste null.

3

Lire le résultat

Quand le statut devient SUCCESS, data.response.resultUrls[0] est l'URL vidéo. En cas de FAILED, affichez error_message et arrêtez le polling.

Modèles disponibles

HappyHorse 1.0

HappyHorse 1.0

Génération vidéo IA de haute qualité avec HappyHorse

TypeDescriptionDuréeCrédits
pro (text-to-video)Texte vers vidéo qualité Pro3-15s54/s (no audio) · 80/s (with audio)
pro (image-to-video)Image vers vidéo qualité Pro3-15s54/s (no audio) · 80/s (with audio)
std (text-to-video)Texte vers vidéo qualité standard3-15s40/s (no audio) · 60/s (with audio)
std (image-to-video)Image vers vidéo qualité standard3-15s40/s (no audio) · 60/s (with audio)

Points de terminaison API

Crée une tâche de génération vidéo. Le champ model doit être 'happyhorse-1.0/video'.

Corps de la requête

Paramètres du corpsJSON
model:string

Nom du modèle, doit être 'happyhorse-1.0/video'

prompt:optional string

Description textuelle de la vidéo (max. 2500 caractères). Non requis si multi_shots est true.

mode:optional string

Mode qualité : 'pro' ou 'std' (défaut : std) Defaults to std.

duration:optional number

Durée en secondes (3–15). En mode multi-plans, la durée finale est déduite de multi_prompt ; si vous envoyez duration explicitement, elle doit correspondre à la somme des durées des plans. Defaults to 5 / sum(multi_prompt).

aspect_ratio:optional string

Format de sortie (16:9, 9:16, 1:1) Defaults to 16:9.

image_urls:optional string[]

Tableau d’URLs d’images pour l’image vers vidéo

sound:optional boolean

Activer l’audio natif (défaut : true). Pour les requêtes multi-plans, envoyez explicitement ce champ avec true ou false. Defaults to true.

cfg_scale:optional number

Adhérence au prompt (0-1, défaut : 0.5). Les valeurs élevées suivent le prompt plus fidèlement. Defaults to 0.5.

multi_shots:optional boolean

Mode multi-plans avec plusieurs prompts Defaults to false.

multi_prompt:optional array

Tableau d’objets 'prompt, duration' pour le mode multi-plans

happyhorse_elements:optional array

Tableau d'objets décrivant chaque élément. Dans le prompt, écrivez @ suivi de la valeur du champ name (ex. : name 'element_dog' → @element_dog). Chaque élément : name, description, element_input_urls (2-4 URLs). Max. 3 éléments par tâche.

Texte vers vidéo

json
{
  "model": "happyhorse-1.0/video",
  "prompt": "A majestic eagle soaring through clouds at sunset",
  "mode": "pro",
  "duration": 5,
  "aspect_ratio": "16:9",
  "sound": true
}

Image vers vidéo

json
{
  "model": "happyhorse-1.0/video",
  "prompt": "The character slowly turns and smiles",
  "mode": "pro",
  "image_urls": ["https://example.com/my-image.jpg"],
  "duration": 5
}

Vidéo multi-plans

json
{
  "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"
}

Réponses

Task created successfully

{
  "code": 200,
  "message": "success",
  "data": {
    "task_id": "n92abc123hh10",
    "status": "IN_PROGRESS"
  }
}

Vérifie le statut d’une génération vidéo avec le task_id renvoyé par l’endpoint generate.

Paramètres de requête

Paramètres de requête
task_id:string

Identifiant unique renvoyé par generate (préfixe n92)

Exemple de requête

bash
curl -X GET 'https://happyhorse.app/api/status?task_id=n92abc123hh10' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Astuce: Le champ response contient un tableau resultUrls. Utilisez data.response.resultUrls[0] pour l’URL de la vidéo.

javascript
// Extract video URL after the task is complete
const task = payload.data;
const videoUrl = task.status === "SUCCESS"
  ? task.response?.resultUrls?.[0]
  : null;

Réponses

{
  "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
  }
}

Bonnes pratiques de polling

La génération vidéo peut prendre un peu de temps : traitez les vérifications de statut comme une tâche de fond calme, pas comme une boucle serrée.

Commencer avec un court délai

Attendez environ 8-10 secondes avant le premier contrôle, puis interrogez toutes les 10-20 secondes. Des requêtes plus fréquentes n'accélèrent pas la génération.

S'arrêter aux états finaux

SUCCESS et FAILED sont finaux. Arrêtez le polling dès que l'un apparaît, et conservez task_id pour le support ou une recherche ultérieure.

Utiliser un timeout client

Après 10-15 minutes, arrêtez l'attente active et laissez l'utilisateur relancer manuellement la vérification. Ne laissez pas un onglet interroger sans fin.

Ralentir en cas d'erreur

Si vous recevez 429 ou une erreur réseau temporaire, ralentissez avant la prochaine requête. Pour 401 ou 402, demandez à l'utilisateur de corriger la clé API ou les crédits.

javascript
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.");
}

Bac à sable API

Testez l’API directement dans le navigateur. Remplacez YOUR_API_KEY par votre clé réelle.

Bac à sable APIPOST

Codes d’erreur

Statut HTTPCodeDescription
400 Requête incorrecteINVALID_PROMPTLe prompt est invalide ou vide
400 Requête incorrecteINVALID_DURATIONDurée hors plage prise en charge (3–15 s)
400 Requête incorrecteINVALID_MODELLe modèle doit être 'happyhorse-1.0/video'
401 Non autoriséINVALID_API_KEYClé API manquante ou invalide
402 Paiement requisINSUFFICIENT_CREDITSCrédits insuffisants pour cette opération
429 Trop de requêtesRATE_LIMITEDTrop de requêtes, veuillez ralentir
500 Erreur interne du serveurINTERNAL_ERRORErreur serveur, réessayez plus tard