Skip to content
API Reference

HappyHorse

HappyHorse is a video generation model series covering four capabilities — text-to-video, image-to-video, reference-to-video, and video editing. Unlike model families where the mode is inferred from the materials you attach, HappyHorse names the capability in the model code itself: -t2v, -i2v, -r2v, -video-edit.

POST https://llm.siraya.ai/v1/videos/generations
GET https://llm.siraya.ai/v1/videos/{video_id}

Synchronous by default, asynchronous on request

By default the request waits for the render and returns the finished video URL. A HappyHorse render can take minutes, so async: true is recommended: you get an id back immediately and poll GET /v1/videos/{video_id} every ~15 seconds until status is completed or failed. Pass a callbackUrl to be notified instead of polling. See Asynchronous generation.

Supported Models

Model ID Capability Resolutions
happyhorse-1.0-t2v Text-to-video 720P, 1080P
happyhorse-1.0-i2v Image-to-video (first frame) 720P, 1080P
happyhorse-1.0-r2v Reference-to-video (1–9 reference images) 720P, 1080P
happyhorse-1.0-video-edit Video editing (source video + up to 5 reference images) 720P, 1080P
happyhorse-1.1-t2v Text-to-video 480P, 720P, 1080P
happyhorse-1.1-i2v Image-to-video (first frame) 480P, 720P, 1080P
happyhorse-1.1-r2v Reference-to-video (1–9 reference images) 480P, 720P, 1080P

1.0 vs 1.1

The two versions differ in exactly two ways:

  • 1.1 adds a 480P tier. 1.0 offers 720P and 1080P only.
  • Video editing exists only in 1.0. There is no 1.1 video-edit model.

Everything else — seconds, aspect_ratio, seed, watermark, and the media containers — is identical between versions for the same capability.

Capabilities by model

✅ supported · — not accepted.

Capability seconds resolution aspect_ratio seed watermark frame_images input_references audio_setting
Text-to-video (-t2v) ✅ ✅ ✅ ✅ ✅ — — —
Image-to-video (-i2v) ✅ ✅ — ✅ ✅ ✅ first frame only — —
Reference-to-video (-r2v) ✅ ✅ ✅ ✅ ✅ — ✅ 1–9 images —
Video editing (-video-edit) — ✅ 720P/1080P — ✅ ✅ — ✅ 1 video + ≤5 images ✅

aspect_ratio is accepted on image-to-video and video editing but has no effect — the source material sets the frame. seconds is likewise not accepted on video editing.

Authorization string Required
Your API Key (e.g., Bearer <API_KEY>).

Body

All HappyHorse parameters are sent flat, at the top level of the request body. There is no extra_body passthrough for this family — every supported parameter has a top-level field.

model string Required
The model ID — one of the codes in Supported Models, e.g. happyhorse-1.0-t2v.
prompt string Required
A text description of the video content. Up to 5000 characters (2500 for Chinese text). On reference-to-video, use [Image 1], [Image 2] … to refer to entries in input_references — see Reference-to-video.
seconds integer Default: 5
Video length in seconds, 3–15; a value outside the range returns a 400 at submit. duration is not a supported field — use seconds. Not accepted on video editing — the output length follows the source video instead.
resolution string Default: 1080P
480P, 720P, or 1080P. 480P is available on 1.1 models only; video editing is 720P/1080P. Values are case-sensitive — 480p is rejected with a 400.
aspect_ratio string Default: 16:9
One of 16:9, 9:16, 1:1, 4:3, 3:4, 4:5, 5:4, 9:21, 21:9. Applies to text-to-video and reference-to-video only — on image-to-video and video editing the source material sets the frame and this field has no effect.
seed integer
Random seed for reproducibility, 0–2147483647. When omitted, a random seed is generated.
watermark boolean Default: true
Whether the output carries a generated-content watermark. HappyHorse watermarks by default — send "watermark": false explicitly if you don't want one. See Behavior worth knowing.
frame_images array
Image-to-video only. A single entry with frame_type: "first_frame" — HappyHorse has no last_frame support. See frame_images.
input_references array
Reference-to-video and video editing only. Typed entries carrying a role and a url — see input_references.
audio_setting string Default: auto
Video editing only. auto — the model decides the soundtrack from the prompt — or origin to keep the source video's audio.
async boolean Default: false
When false, the request waits for generation to finish and returns the completed video URL. When true, it returns immediately with a video id you poll for status — recommended here, since HappyHorse renders can take minutes. See Asynchronous generation.
callbackUrl string
Only used when async is true. An http(s) URL the router will POST to once generation completes (or fails), so you don't have to poll.
curl https://llm.siraya.ai/v1/videos/generations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <API_KEY>" \
  -d '{
    "model": "happyhorse-1.0-t2v",
    "prompt": "A lighthouse on a cliff at sunset",
    "seconds": 5,
    "resolution": "720P",
    "aspect_ratio": "16:9",
    "watermark": false,
    "seed": 42
  }'
import requests

url = "https://llm.siraya.ai/v1/videos/generations"
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer <API_KEY>"
}
data = {
    "model": "happyhorse-1.0-t2v",
    "prompt": "A lighthouse on a cliff at sunset",
    "seconds": 5,
    "resolution": "720P",
    "aspect_ratio": "16:9",
    "watermark": False,
    "seed": 42
}

response = requests.post(url, headers=headers, json=data)
print(response.json())

Example Response

{
    "created": 1760347750,
    "data": [
        {
            "url": "https://resources.siraya.ai/v1/videos/video_8fK2mQxR7pLnVwZ3tYbC.../content"
        }
    ],
    "error": {}
}

With "async": true, the job is accepted immediately instead:

{
  "id": "video_8fK2mQxR7pLnVwZ3tYbC...",
  "object": "video",
  "status": "processing",
  "model": "happyhorse-1.0-t2v",
  "seconds": 5,
  "usage": { "completion_tokens": 0, "total_tokens": 0 }
}

Poll GET /v1/videos/{video_id} with that id until status is completed — see Poll for status.

Media inputs

HappyHorse uses two different containers depending on whether the material is a hard constraint on the frame or soft guidance for the content.

frame_images

Pins the opening frame of an image-to-video render. Exactly one entry, and first_frame is the only supported type — there is no last-frame control in this family.

Field Type Description
frame_type string first_frame only.
image_url string Public URL or a data:image/jpeg;base64,... data URL.
{
  "model": "happyhorse-1.1-i2v",
  "prompt": "The scene comes to life",
  "frame_images": [
    { "frame_type": "first_frame", "image_url": "https://your-domain.com/cat.jpg" }
  ],
  "seconds": 5,
  "resolution": "720P"
}

aspect_ratio is ignored here — the frame you supply determines the output shape. Choose a first frame already cropped to the ratio you want.

input_references

Soft-guidance material for reference-to-video and video editing. Each entry carries a role and a url:

role Used by Count
reference_image reference-to-video 1–9
video video editing — the source clip being edited exactly 1, required
reference_image video editing — extra style/subject material 0–5, optional

Reference image requirements: JPEG/JPG/PNG/WEBP, shortest side ≥ 400px, ≤ 20MB. Source video requirements (video editing): MP4 or MOV, 3–60 seconds, ≤ 100MB.

Reference-to-video

-r2v models build a video from 1–9 reference images. The prompt addresses them positionally with [Image 1], [Image 2] … matching the order of the input_references array.

{
  "model": "happyhorse-1.1-r2v",
  "prompt": "[Image 1] stands in a sunny meadow holding the object from [Image 2]",
  "input_references": [
    { "role": "reference_image", "url": "https://your-domain.com/character.jpg" },
    { "role": "reference_image", "url": "https://your-domain.com/prop.jpg" }
  ],
  "resolution": "720P",
  "aspect_ratio": "16:9"
}

Video editing

happyhorse-1.0-video-edit restyles or edits an existing clip. It takes one required video entry and optionally up to five reference_image entries for style or subject guidance.

{
  "model": "happyhorse-1.0-video-edit",
  "prompt": "Change the style to a watercolor painting",
  "input_references": [
    { "role": "video", "url": "https://your-domain.com/input.mp4" }
  ],
  "audio_setting": "origin",
  "resolution": "720P",
  "watermark": false
}
  • seconds is not accepted. The output length follows the source video — kept as-is up to 15 seconds, truncated to the first 15 seconds if the source is longer. The seconds field in the status response reports the real output length.
  • aspect_ratio has no effect — the source video sets the frame.
  • audio_setting decides the soundtrack: auto lets the model score the clip from your prompt, origin keeps the source audio.

Poll for status

GET https://llm.siraya.ai/v1/videos/{video_id}
curl https://llm.siraya.ai/v1/videos/<video_id> \
  -H "Authorization: Bearer <API_KEY>"

When you submit with async: true, call the status endpoint with the returned id until status reads completed or failed. Poll roughly every 15 seconds and back off on 429. Passing a callbackUrl at submit time removes the need to poll at all.

{
  "id": "video_8fK2mQxR7pLnVwZ3tYbC...",
  "object": "video",
  "status": "completed",
  "model": "happyhorse-1.0-t2v",
  "seconds": 5,
  "resolution": "720p",
  "ratio": "16:9",
  "output_url": "https://.../out.mp4?Expires=...&Signature=..."
}

Response object

Field Type Present Meaning
id string always Opaque — pass it straight to GET /v1/videos/{video_id}; don't parse it
object string always Always video
status string always processing · completed · failed
error object on failure { code, message }
seconds integer completed Output duration, rounded to the nearest second
resolution, ratio string completed Reported for the finished video; resolution is lowercase <height>p (e.g. 720p) even though requests use 720P
output_url string completed Signed and expires after 24 hours — download promptly, don't cache it as a stable link

Once status is completed you can also stream the raw bytes from GET /v1/videos/{video_id}/content.

Behavior worth knowing

Watermarking is on by default. HappyHorse is the exception among the video families on this platform: watermark defaults to true, so an output you never configured comes back watermarked. Send "watermark": false on every request where that matters.

Resolution values are case-sensitive. 720P and 1080P are accepted; 720p and 480p return a 400 (Input should be '1080P' or '720P'). This differs from the lowercase 720p used by most other video models on the platform.

Results expire in 24 hours. Both the video id and the output_url stop working after a day. Download and re-host anything you need to keep.

Errors

A request-time refusal is final — it means the parameters can't work together, not that the service is unavailable. Retrying the same body won't help.

{
  "error": {
    "code": "invalid_request_error",
    "message": "Input should be '1080P' or '720P'",
    "type": "invalid_request_error"
  }
}
Status Meaning
400 An invalid value or unsupported combination — a lowercase resolution, 480P on a 1.0 model, a seconds outside 3–15, or a reference image below the size floor
404 Unrecognized model code
200 with status: "processing" Accepted — keep polling