API Reference

HppyHorse 1.1 API

Integrate HppyHorse 1.1 text-to-video, image-to-video, and reference-to-video workflows with the public HppyHorse API.

HppyHorse 1.1 Base URL: https://hppyhorse.com

Quick Start

bash
curl -X POST 'https://hppyhorse.com/api/happyhorse-1-1/generate' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "happyhorse-1-1/text-to-video",
    "prompt": "A cinematic sunrise over a glass city, slow drone camera",
    "duration": 5,
    "resolution": "1080p",
    "aspect_ratio": "16:9"
  }'

Authentication

Send your dashboard API key as a Bearer token in the Authorization header.

http
Authorization: Bearer YOUR_API_KEY

1.1 Models

ModelUse CaseRequired Inputs
happyhorse-1-1/text-to-videoGenerate a video from a text prompt.prompt
happyhorse-1-1/image-to-videoAnimate one or more source images.image_urls
happyhorse-1-1/reference-to-videoUse reference imagery to guide the generated video.prompt, reference_image

API Endpoints

Create an asynchronous 1.1 generation task. The stable /api/generate endpoint also accepts the same 1.1 request body.

Body parametersJSON
model:string

happyhorse-1-1/text-to-video, happyhorse-1-1/image-to-video, or happyhorse-1-1/reference-to-video.

prompt:optional string

Text prompt. Required for text-to-video and reference-to-video. Optional for image-to-video.

image_urls:optional string[]

Source image URLs for image-to-video.

reference_image:optional string[]

Reference image URLs for reference-to-video. In the prompt, refer to them as [Image 1], [Image 2], and so on.

duration:optional number

Video duration in seconds. Supported range is 3-15. Defaults to 5.

resolution:optional string

Output resolution: 720p or 1080p. Defaults to 1080p.

aspect_ratio:optional string

Aspect ratio for text-to-video and reference-to-video: 16:9, 9:16, 1:1, 4:3, 3:4, 4:5, 5:4, 9:21, or 21:9. Defaults to 16:9.

Text to Video

json
{
  "model": "happyhorse-1-1/text-to-video",
  "prompt": "A cinematic sunrise over a glass city, slow drone camera",
  "duration": 5,
  "resolution": "1080p",
  "aspect_ratio": "16:9"
}

Image to Video

json
{
  "model": "happyhorse-1-1/image-to-video",
  "image_urls": ["https://example.com/source-image.jpg"],
  "prompt": "Subtle camera push-in with natural motion",
  "duration": 5,
  "resolution": "1080p"
}

Reference to Video

json
{
  "model": "happyhorse-1-1/reference-to-video",
  "prompt": "[Image 1] is the product reference. Show it on a reflective studio table with smooth camera motion.",
  "reference_image": ["https://example.com/product-reference.jpg"],
  "duration": 5,
  "resolution": "1080p",
  "aspect_ratio": "16:9"
}
{
  "code": 200,
  "message": "success",
  "data": {
    "task_id": "n92abc123hh10",
    "status": "IN_PROGRESS"
  }
}

Poll by task_id until the task reaches SUCCESS or FAILED. The stable /api/status endpoint also works for 1.1 task IDs.

Query parameters
task_id:string

The task ID returned by the generate endpoint.

bash
curl -X GET 'https://hppyhorse.com/api/happyhorse-1-1/status?task_id=n92abc123hh10' \
  -H 'Authorization: Bearer YOUR_API_KEY'
{
  "code": 200,
  "message": "success",
  "data": {
    "task_id": "n92abc123hh10",
    "status": "SUCCESS",
    "model": "happyhorse-1-1/text-to-video",
    "response": {
      "resultUrls": [
        "https://cdn.example.com/videos/result.mp4"
      ]
    },
    "error_message": null
  }
}

Polling Pattern

Wait a few seconds before the first status check, then poll every 10-20 seconds. Stop as soon as you see SUCCESS or FAILED.

javascript
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function waitForHappyHorse11(taskId) {
  const deadline = Date.now() + 15 * 60 * 1000;
  let delayMs = 10000;

  while (Date.now() < deadline) {
    const res = await fetch(
      `${BASE_URL}/api/happyhorse-1-1/status?task_id=${encodeURIComponent(taskId)}`,
      { headers: { Authorization: `Bearer ${API_KEY}` } }
    );
    const payload = await res.json();
    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.");
}