HappyHorse Video Generation
HappyHorse is a video generation model family from Alibaba Cloud Bailian, featuring physically realistic visuals and smooth motion. AutoRouter wraps the upstrea
HappyHorse Video Generation
HappyHorse is a video generation model family from Alibaba Cloud Bailian, featuring physically realistic visuals and smooth motion. AutoRouter wraps the upstream DashScope async task API as a unified /v1/video/generations async task endpoint, covering four capabilities: text-to-video, image-to-video, reference-to-video, and video editing.
HappyHorse uses an async task-based API: submit a request, receive a task_id, poll for status, then download the video from data.result_url.
1. Supported Models
| Model | Capability | Required Media Input | Description |
|---|---|---|---|
happyhorse-1.0-t2v | Text-to-Video | — | Generate video from pure text prompt |
happyhorse-1.0-i2v | Image-to-Video | 1 first-frame image | Generate video starting from a first-frame image |
happyhorse-1.0-r2v | Reference-to-Video | 1–9 reference images | Multi-image reference generation, prompt uses [Image N] to reference |
happyhorse-1.0-video-edit | Video Editing | 1 video + 0–5 reference images | Style transfer, local replacement on existing videos |
All 4 models share the same endpoint /v1/video/generations, distinguished only by the model field. Response structures are identical across models.
2. Common Endpoints
2.1 Submit Task
POST /v1/video/generationsRequest Headers
| Header | Required | Description |
|---|---|---|
Authorization | ✓ | Bearer sk-YourApiKey |
Content-Type | ✓ | application/json |
Request Body Fields
| Field | Type | Required | Description |
|---|---|---|---|
model | string | ✓ | HappyHorse model name (see table above) |
prompt | string | ✓ | Text prompt. Max 5000 non-Chinese chars or 2500 Chinese chars; excess is auto-truncated |
size | string | — | Resolution tier. 720P / 1080P (default 1080P) |
duration | int | — | Video duration in seconds, range 3~15, default 5. Ignored by video-edit (duration follows input video, max 15s) |
input_reference | string | model-dependent | i2v only: first-frame image URL (publicly accessible) |
metadata | object | model-dependent | HappyHorse-specific parameters container, see Section 3 |
Response
{
"id": "task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o",
"task_id": "task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o",
"object": "video",
"model": "happyhorse-1.0-t2v",
"status": "queued",
"progress": 0,
"created_at": 1778250615
}id / task_id is the AutoRouter public ID (with task_ prefix), used for subsequent queries. It is not the upstream DashScope task_id — always use the value returned here.
2.2 Query Task Status
GET /v1/video/generations/{task_id}The response uses AutoRouter's unified {code, message, data} wrapper format. data contains full task details, billing info, channel info, and the raw upstream response.
Response (Queued / NOT_START)
{
"code": "success",
"message": "",
"data": {
"id": 23,
"task_id": "task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o",
"platform": "17",
"user_id": 3,
"group": "default",
"channel_id": 18,
"quota": 178500,
"action": "textGenerate",
"status": "NOT_START",
"fail_reason": "",
"submit_time": 1778250615,
"start_time": 0,
"finish_time": 0,
"created_at": 1778250615,
"updated_at": 1778250615,
"progress": "0%",
"properties": {
"input": "",
"upstream_model_name": "happyhorse-1.0-t2v",
"origin_model_name": "happyhorse-1.0-t2v"
},
"data": {
"output": {
"task_id": "89c3124e-c1eb-4017-a4db-8b81536dfd22",
"task_status": "PENDING"
},
"request_id": "85a9f836-4bbe-9b95-bbfd-f3ee1309cebb"
}
}
}Response (In Progress / IN_PROGRESS)
{
"code": "success",
"message": "",
"data": {
"id": 23,
"task_id": "task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o",
"status": "IN_PROGRESS",
"progress": "30%",
"submit_time": 1778250615,
"start_time": 1778250620,
"finish_time": 0,
"properties": {
"upstream_model_name": "happyhorse-1.0-t2v",
"origin_model_name": "happyhorse-1.0-t2v"
},
"data": {
"output": { "task_status": "RUNNING" }
}
}
}Response (Completed / SUCCESS)
{
"code": "success",
"message": "",
"data": {
"id": 18,
"task_id": "task_SEf9uAzULfIdexfoVEcrpuhNNmQvJVfZ",
"platform": "17",
"user_id": 3,
"group": "default",
"channel_id": 18,
"quota": 297500,
"action": "textGenerate",
"status": "SUCCESS",
"fail_reason": "",
"result_url": "https://dashscope-463f.oss-accelerate.aliyuncs.com/.../xxx.mp4?Expires=...&Signature=...",
"submit_time": 1778249722,
"start_time": 1778249737,
"finish_time": 1778249834,
"created_at": 1778249722,
"updated_at": 1778249834,
"progress": "100%",
"properties": {
"input": "",
"upstream_model_name": "happyhorse-1.0-r2v",
"origin_model_name": "happyhorse-1.0-r2v"
},
"data": {
"output": {
"task_id": "54b32dcb-6887-4839-bd1b-3bf73efef38c",
"end_time": "2026-05-08 22:16:57.506",
"video_url": "https://dashscope-463f.oss-accelerate.aliyuncs.com/.../xxx.mp4",
"orig_prompt": "...",
"submit_time": "2026-05-08 22:15:22.401",
"task_status": "SUCCEEDED"
},
"usage": {
"SR": 720,
"ratio": "16:9",
"duration": 5,
"video_count": 1,
"input_video_duration": 0,
"output_video_duration": 5
},
"request_id": "9f888f70-8519-90b7-a540-a69a31e03181"
}
}
}Response (Failed / FAILURE)
{
"code": "success",
"message": "",
"data": {
"id": 25,
"task_id": "task_xxx",
"status": "FAILURE",
"fail_reason": "InvalidParameter: ...",
"progress": "100%",
"data": {
"output": { "task_status": "FAILED" }
}
}
}Key Fields
| Field | Type | Description |
|---|---|---|
code | string | Response code, "success" on success |
message | string | Response message |
data.id | int | Internal auto-increment task ID |
data.task_id | string | AutoRouter public task ID (with task_ prefix) |
data.status | string | Task status: NOT_START / QUEUED / IN_PROGRESS / SUCCESS / FAILURE |
data.result_url | string | Video URL (non-empty on SUCCESS, upstream OSS signed link) |
data.fail_reason | string | Failure reason (non-empty only on FAILURE) |
data.quota | int | Raw quota value billed for this task |
data.progress | string | Progress string, e.g. "30%" / "100%" |
data.submit_time / start_time / finish_time | int64 | Submit / start / finish Unix timestamps (seconds) |
data.created_at / updated_at | int64 | Record create / last update time |
data.properties.upstream_model_name | string | Actual model name sent to upstream DashScope |
data.properties.origin_model_name | string | Model name requested by the client |
data.data | object | Raw upstream DashScope response (output.video_url, usage, request_id) |
Status Enum
| Status | DashScope Equivalent | Description |
|---|---|---|
NOT_START | PENDING | Created, not yet processing (at submission moment) |
QUEUED | PENDING | Queued upstream |
IN_PROGRESS | RUNNING | Generating |
SUCCESS | SUCCEEDED | Completed, result_url is the video URL |
FAILURE | FAILED / CANCELED / UNKNOWN | Generation failed, fail_reason contains the reason |
The video URL (data.result_url) is an upstream OSS signed link. The Expires= parameter is typically valid for 24 hours — download or persist it to your own storage promptly.
3. HappyHorse-Specific Parameters (metadata)
These fields are passed via the metadata object in the request body. AutoRouter forwards them to upstream DashScope.
3.1 Video Control
| Field | Type | Applicable Models | Description | Default |
|---|---|---|---|---|
ratio | string | t2v / r2v | Aspect ratio: 16:9 / 9:16 / 1:1 / 4:3 / 3:4 | 16:9 |
watermark | bool | All | Whether to add watermark ("Happy Horse" in bottom-right) | true |
seed | int | All | Random seed, range 0 ~ 2147483647, auto-generated if not specified | — |
audio_setting | string | video-edit | Audio control: auto (model-decided) / origin (preserve original) | auto |
i2v does not support ratio: the output aspect ratio automatically follows the input first-frame image.
3.2 Multi-Media Input (input.media)
r2v and video-edit require media input via the metadata.input.media array:
{
"metadata": {
"input": {
"media": [
{ "type": "reference_image", "url": "https://.../img1.jpg" },
{ "type": "reference_image", "url": "https://.../img2.jpg" },
{ "type": "video", "url": "https://.../video.mp4" }
]
}
}
}type | Purpose | Quantity Limit |
|---|---|---|
reference_image | Reference image (r2v and video-edit) | r2v: 1–9; video-edit: 0–5 |
video | Source video (video-edit only) | video-edit: exactly 1 |
first_frame | First-frame image (i2v only, alternative to the top-level input_reference) | i2v: exactly 1 |
r2v prompt convention: In the prompt, reference images using [Image 1], [Image 2] in array order. Example: "The woman in [Image 1] wearing red qipao raises her hand to unfold the fan in [Image 2]."
3.3 Media Asset Limits
| Type | Format | Resolution | File Size | Other |
|---|---|---|---|---|
| Image (i2v first frame) | JPEG / JPG / PNG / WEBP | W & H ≥ 300 px | ≤ 10 MB | Aspect ratio 1:2.5 ~ 2.5:1 |
| Image (r2v reference) | JPEG / JPG / PNG / WEBP | Short edge ≥ 400 px (720P+ recommended) | ≤ 10 MB | Avoid blurry / heavily compressed images |
| Image (video-edit reference) | JPEG / JPG / PNG / WEBP | W & H ≥ 300 px | ≤ 10 MB | Aspect ratio 1:2.5 ~ 2.5:1 |
| Video (video-edit input) | MP4 / MOV (H.264 recommended) | Long edge ≤ 2160, short ≥ 320 | ≤ 100 MB | 3–60s, >8 fps, aspect ratio 1:2.5 ~ 2.5:1 |
video-edit output duration rule: If input video ≤15s, output duration matches input. If input >15s, the system auto-crops the first 15s, so output is max 15s.
4. Full Examples
# Step 1: Submit task
curl -X POST https://autorouter.top/v1/video/generations \
-H "Authorization: Bearer sk-YourApiKey" \
-H "Content-Type: application/json" \
-d '{
"model": "happyhorse-1.0-t2v",
"prompt": "A cat napping in sunlight, fur gently swaying in the breeze",
"size": "720P",
"duration": 5,
"metadata": {
"ratio": "16:9",
"seed": 42,
"watermark": false
}
}'
# Response (OpenAI flat format):
# {
# "id": "task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o",
# "task_id": "task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o",
# "status": "queued", ...
# }
# Step 2: Poll (recommended interval: 10–15s)
curl https://autorouter.top/v1/video/generations/task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o \
-H "Authorization: Bearer sk-YourApiKey"
# Step 3: Once data.status == "SUCCESS", download from data.result_url
curl -o cat.mp4 "https://dashscope-463f.oss-accelerate.aliyuncs.com/.../xxx.mp4?Expires=..."# i2v: pass first-frame image via input_reference
curl -X POST https://autorouter.top/v1/video/generations \
-H "Authorization: Bearer sk-YourApiKey" \
-H "Content-Type: application/json" \
-d '{
"model": "happyhorse-1.0-i2v",
"prompt": "Camera slowly pushes in, the scene comes alive",
"size": "720P",
"duration": 5,
"input_reference": "https://example.com/girl.jpg"
}'i2v's aspect ratio follows input_reference; metadata.ratio is not supported.
# r2v: up to 9 reference images, use [Image 1], [Image 2] in prompt
curl -X POST https://autorouter.top/v1/video/generations \
-H "Authorization: Bearer sk-YourApiKey" \
-H "Content-Type: application/json" \
-d '{
"model": "happyhorse-1.0-r2v",
"prompt": "The woman in [Image 1] wearing red qipao raises her hand to unfold the fan in [Image 2], while the tassel earrings from [Image 3] sway gently with her head movement",
"size": "720P",
"duration": 5,
"metadata": {
"ratio": "16:9",
"input": {
"media": [
{ "type": "reference_image", "url": "https://example.com/girl.jpg" },
{ "type": "reference_image", "url": "https://example.com/folding-fan.jpg" },
{ "type": "reference_image", "url": "https://example.com/earrings.jpg" }
]
}
}
}'# video-edit: 1 video + up to 5 reference images
curl -X POST https://autorouter.top/v1/video/generations \
-H "Authorization: Bearer sk-YourApiKey" \
-H "Content-Type: application/json" \
-d '{
"model": "happyhorse-1.0-video-edit",
"prompt": "Make the horse-headed character in the video wear the striped sweater from the image",
"size": "720P",
"metadata": {
"audio_setting": "origin",
"input": {
"media": [
{ "type": "video", "url": "https://example.com/source.mp4" },
{ "type": "reference_image", "url": "https://example.com/sweater.webp" }
]
}
}
}'video-edit ignores duration; output follows input video length (max 15s).
5. Polling Guidelines
| Item | Recommendation |
|---|---|
| Polling interval | 10–15 seconds, never under 5s to avoid rate limiting |
| Terminal states | data.status == "SUCCESS" or data.status == "FAILURE" |
| Total timeout | 5 minutes for t2v/i2v/r2v; 8–10 minutes for video-edit |
| Typical duration | t2v/i2v/r2v: 100–150s; video-edit: 180–250s |
| Video URL validity | Approx. 24 hours; download or persist immediately |
Simple Polling Script (Bash)
#!/bin/bash
TID="task_9dxfuz8h5gxBvdIqvyoVnZr3DVJxzI1o"
KEY="sk-YourApiKey"
while true; do
RESP=$(curl -sS "https://autorouter.top/v1/video/generations/$TID" -H "Authorization: Bearer $KEY")
echo "$RESP"
STATUS=$(echo "$RESP" | python3 -c "import sys,json;print(json.load(sys.stdin)['data'].get('status',''))")
case "$STATUS" in
SUCCESS|FAILURE) break ;;
esac
sleep 15
done6. Error Handling
6.1 HTTP 400 Parameter Errors (pre-submit validation, no billing)
AutoRouter validates required fields before submitting to upstream:
| Scenario | Response |
|---|---|
Missing prompt | {"code":"invalid_request","message":"prompt is required","data":null} |
| Unknown model | {"code":"invalid_request","message":"unknown model: ..."} |
6.2 HTTP 401 / 403 Auth Errors
401 Unauthorized: API Key invalid or expired403 Forbidden: API Key has no access to this model (check token's model allowlist)
6.3 HTTP 402 Insufficient Balance
Returns insufficient user quota. Top up at the AutoRouter console.
6.4 Task FAILURE Status
Task was accepted but upstream generation failed (data.status == "FAILURE"). Check data.fail_reason:
| Reason | Suggested Action |
|---|---|
| Content moderation | Adjust prompt to avoid sensitive content |
i2v missing input_reference | Image-to-video requires a first-frame image |
| r2v with 0 reference images | Provide at least 1 reference_image |
| video-edit missing video | media must contain exactly 1 type: video element |
| Media URL unreachable | Ensure URL is publicly accessible and not expired |
| Media file violates specs | See Section 3.3 for asset limits |
| Illegal parameter combo (unsupported resolution, etc.) | Follow Section 3 for valid parameters |
When a task enters FAILURE, AutoRouter automatically refunds the billed quota. Check refund records in the logs page.
7. OpenAI-Compatible Endpoints (Optional)
In addition to the primary /v1/video/generations endpoint, HappyHorse is also compatible with the OpenAI-style /v1/videos endpoint, making it easy to integrate with OpenAI SDKs / clients. The two endpoint sets are fully equivalent (same backend task); choose based on your client integration approach.
7.1 Submit (OpenAI-Compatible)
POST /v1/videosRequest body fields are identical to /v1/video/generations. Response is also the OpenAI flat format.
7.2 Query (OpenAI-Compatible)
GET /v1/videos/{task_id}Returns the OpenAI standard flat structure:
{
"id": "task_hI0pZ1xklxOsDWK2wYyK30DT3QQUjM7A",
"object": "video",
"model": "happyhorse-1.0-t2v",
"status": "completed",
"progress": 100,
"created_at": 1778249702,
"completed_at": 1778249795,
"metadata": {
"url": "https://dashscope-463f.oss-accelerate.aliyuncs.com/.../xxx.mp4?Expires=...&Signature=..."
}
}OpenAI Status Mapping
| OpenAI Status | Unified Format Status |
|---|---|
queued | NOT_START / QUEUED |
in_progress | IN_PROGRESS |
completed | SUCCESS |
failed | FAILURE |
You can mix the two endpoints: submitting via POST /v1/video/generations and querying via GET /v1/videos/{id} works fine — both share the same task_id. But we recommend staying consistent within a single business flow for easier debugging.
8. FAQ
Do all 4 HappyHorse models share the same endpoint?
Yes. All use POST /v1/video/generations, distinguished only by the model field. Response structure is identical, so no per-model client-side adaptation is needed.
What's the difference between /v1/video/generations and /v1/videos?
They are dual-endpoint coexistence for HappyHorse in AutoRouter:
/v1/video/generations(recommended): AutoRouter unified format. Query returns{code, message, data}wrapper with billing, channel, and raw upstream data. Consistent with other video models like Seedance./v1/videos(OpenAI-compatible): Query returns the OpenAI standard flat structure, convenient for direct use with OpenAI SDKs / compatible clients.
Both point to the same backend task, and the same task_id can be queried across both endpoint sets.
Should I use 720P or 720p for size?
Uppercase 720P / 1080P is recommended. Lowercase also works, but using uppercase consistently is preferred.
What values does duration support?
Integer range 3~15, default 5. Notes:
video-editignoresduration; output follows input video (max 15s).- Different resolution tiers may have different pricing; refer to console pricing.
How does [Image N] in the r2v prompt map to images?
Strictly by metadata.input.media array order. The 1st reference_image maps to [Image 1], the 2nd to [Image 2], and so on. For best results, be explicit, e.g. "the woman in [Image 1] wearing red qipao".
Can I disable the watermark?
Yes. Set metadata.watermark: false. Default is watermarked with "Happy Horse" in the bottom-right corner.
When do video URLs expire?
The upstream OSS signed URL's Expires= parameter is typically set to 24 hours after generation. After expiry, you can re-query the task (as long as the task record isn't cleaned up) to get a fresh URL. Upstream retains tasks for 24 hours; after that, status becomes UNKNOWN. Best practice: download and persist to your own storage as soon as the task completes.
What aspect ratios does i2v support?
i2v does not support manual aspect ratio selection; the output follows the input_reference image's aspect ratio. If you need a specific aspect, crop / resize the input image beforehand.
Can video-edit preserve the original audio?
Yes. Set metadata.audio_setting: "origin" to preserve the input video's audio. Default is auto (model decides).
Does the same seed produce identical results?
Not entirely. Fixing seed improves reproducibility, but due to the model's probabilistic nature, even identical seeds don't guarantee identical outputs.
How to pick the right model?
By input type:
- Only text description →
happyhorse-1.0-t2v - One starting-frame image →
happyhorse-1.0-i2v - Multiple reference images (people, props, accessories) to combine →
happyhorse-1.0-r2v - Style transfer or local replacement on an existing video →
happyhorse-1.0-video-edit