HappyHorse 1.1 API
HappyHorse video: from a prompt, from a picture, from reference pictures, or an edit of a finished clip.
For AI assistants:Download .mdAll documentation .mdOpen as text
Connect in three steps
- Get a keyCreate a key in the dashboard after you confirm your email. One key opens every model.
- Check the pricePOST /v1/price shows the cost of a run in advance, without charging you.
- Run a task and collect the resultPOST /v1/tasks starts a task, GET /v1/tasks/{id} shows its status and files.
Ready-to-use code
Replace YOUR_API_KEY with your key. The code starts a task and waits for the result. In cURL, repeat the second request with the id from the first response instead of TASK_ID until status becomes succeeded.
curl -X POST "https://api.cyhub.ai/v1/tasks" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
--data '{
"model": "happyhorse",
"settings": {
"mode": "text_to_video",
"prompt": "Лошадь скачет по полю на закате, камера движется рядом",
"resolution": "720p",
"aspect_ratio": "16:9",
"duration": 5
}
}'
curl "https://api.cyhub.ai/v1/tasks/TASK_ID" \
-H "Authorization: Bearer YOUR_API_KEY"import time
import requests
API = "https://api.cyhub.ai/v1"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}
body = {
"model": "happyhorse",
"settings": {
"mode": "text_to_video",
"prompt": "Лошадь скачет по полю на закате, камера движется рядом",
"resolution": "720p",
"aspect_ratio": "16:9",
"duration": 5,
},
}
response = requests.post(f"{API}/tasks", json=body, headers=HEADERS, timeout=60)
response.raise_for_status()
task = response.json()
while task["status"] in ("queued", "running"):
time.sleep(5)
task = requests.get(f"{API}/tasks/{task['id']}", headers=HEADERS, timeout=30).json()
print(task["status"], task["result"])const API = "https://api.cyhub.ai/v1";
const HEADERS = { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" };
const body = {
"model": "happyhorse",
"settings": {
"mode": "text_to_video",
"prompt": "Лошадь скачет по полю на закате, камера движется рядом",
"resolution": "720p",
"aspect_ratio": "16:9",
"duration": 5
}
};
async function main() {
let response = await fetch(`${API}/tasks`, { method: "POST", headers: HEADERS, body: JSON.stringify(body) });
if (!response.ok) throw new Error(await response.text());
let task = await response.json();
while (task.status === "queued" || task.status === "running") {
await new Promise((resolve) => setTimeout(resolve, 5000));
response = await fetch(`${API}/tasks/${task.id}`, { headers: HEADERS });
task = await response.json();
}
console.log(task.status, task.result);
}
main();Price before the run
Prices as of 15.10.2026: from 49 ₽. POST /v1/price shows the exact price of your settings.
| Mode | Price |
|---|---|
| From a prompt | from 49 ₽ |
| From a picture | from 49 ₽ |
| From references | from 49 ₽ |
| Video editing with a 3 s file | from 121 ₽ |
Send the same settings to POST /v1/price: the response shows the price of the run without charging you.
curl -X POST "https://api.cyhub.ai/v1/price" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
--data '{
"model": "happyhorse",
"settings": {
"mode": "text_to_video",
"prompt": "Лошадь скачет по полю на закате, камера движется рядом",
"resolution": "720p",
"aspect_ratio": "16:9",
"duration": 5
}
}'amount_minor: the price of the run in minor units (kopecks for rubles)currency: the wallet currencyavailable_minor: how much your balance has for new tasks right now
Modes
Each mode has its own parameters and examples. The mode is set by the mode field.
- From a prompt
mode = text_to_video - From a picture
mode = image_to_video - From references
mode = reference_to_video - Video editing
mode = video_edit
From a prompt
Video from text alone, no pictures are sent.
Value of the mode field: text_to_video
Price in this mode from 49 ₽.
Parameters
Model parameters go inside settings. Omitted optional fields take their default values.
promptRequiredWhat happens in the video. Any language works, Chinese text is limited to 2,500 characters.
Type: StringMinimum characters: 1Maximum characters: 5000resolutionOptionalResolution of the finished video; the price depends on it.
Type: StringAllowed values:720p1080pDefault:"720p"aspect_ratioOptionalFrame shape: landscape, portrait, square or the classic 4:3 and 3:4.
Type: StringAllowed values:16:99:161:14:33:4Default:"9:16"durationOptionalVideo length in seconds, 3 to 15. The price is per second.
Type: IntegerMinimum: 3Maximum: 15Default:5
Parameters not listed here are not accepted: the response is 422 unknown_setting.
Input
Request example
Send this JSON to POST /v1/tasks with your API key. To check the price first, send the same JSON to POST /v1/price.
Video from a prompt
{
"model": "happyhorse",
"settings": {
"mode": "text_to_video",
"prompt": "Лошадь скачет по полю на закате, камера движется рядом",
"resolution": "720p",
"aspect_ratio": "16:9",
"duration": 5
}
}The price is calculated when the task is accepted, currency RUB.
Output
- One MP4 video.
- Generation takes 3 to 15 minutes, longer for long clips.
| Kind | Formats | How many | Note |
|---|---|---|---|
video | mp4 | 1 |
A finished task as GET /v1/tasks/{id} returns it (some fields left out). The caption may sit on the task or on a single file and may be empty; the model picks the file name.
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"status": "succeeded",
"finished_at": "2026-10-01T12:03:41+00:00",
"result": {
"caption": "Caption of the result: the model and its settings",
"texts": [],
"files_expire_at": "2026-10-08T12:03:41+00:00",
"files_expired": false,
"artifacts": [
{
"index": 0,
"kind": "video",
"filename": "video.mp4",
"size": 12582912,
"caption": "",
"download_path": "/v1/tasks/7c9e6679-7425-40de-944b-e07fc1f90ae7/artifacts/0"
}
]
}
}From a picture
The picture becomes the first frame, the model animates it by the prompt. The video takes the shape of the picture.
Value of the mode field: image_to_video
Price in this mode from 49 ₽.
Parameters
Model parameters go inside settings. Omitted optional fields take their default values.
promptRequiredWhat happens in the video. Any language works, Chinese text is limited to 2,500 characters.
Type: StringMinimum characters: 1Maximum characters: 5000resolutionOptionalResolution of the finished video; the price depends on it.
Type: StringAllowed values:720p1080pDefault:"720p"image_urlsRequiredOne URL of the picture for the first frame.
Type: List (String, uri)Maximum items: 1durationOptionalVideo length in seconds, 3 to 15. The price is per second.
Type: IntegerMinimum: 3Maximum: 15Default:5
Parameters not listed here are not accepted: the response is 422 unknown_setting.
Input
- The picture is a URL of a JPEG, PNG or WebP file up to 20 MB, each side at least 300 pixels, shape from 1:2.5 to 2.5:1.
| Field | Accepts | Formats | Files | File size up to |
|---|---|---|---|---|
image_urls | Images | jpeg, jpg, png, webp | 1 | 20 MB |
Request example
Send this JSON to POST /v1/tasks with your API key. To check the price first, send the same JSON to POST /v1/price.
Animate a picture
{
"model": "happyhorse",
"settings": {
"mode": "image_to_video",
"prompt": "Камера медленно наезжает, волосы героини развеваются на ветру",
"image_urls": [
"https://example.com/first-frame.jpg"
],
"duration": 5
}
}The price is calculated when the task is accepted, currency RUB.
Output
- One MP4 video.
- Generation takes 3 to 15 minutes, longer for long clips.
| Kind | Formats | How many | Note |
|---|---|---|---|
video | mp4 | 1 |
A finished task as GET /v1/tasks/{id} returns it (some fields left out). The caption may sit on the task or on a single file and may be empty; the model picks the file name.
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"status": "succeeded",
"finished_at": "2026-10-01T12:03:41+00:00",
"result": {
"caption": "Caption of the result: the model and its settings",
"texts": [],
"files_expire_at": "2026-10-08T12:03:41+00:00",
"files_expired": false,
"artifacts": [
{
"index": 0,
"kind": "video",
"filename": "video.mp4",
"size": 12582912,
"caption": "",
"download_path": "/v1/tasks/7c9e6679-7425-40de-944b-e07fc1f90ae7/artifacts/0"
}
]
}
}From references
Characters, objects and settings from your pictures in a new video.
Value of the mode field: reference_to_video
Price in this mode from 49 ₽.
Parameters
Model parameters go inside settings. Omitted optional fields take their default values.
promptRequiredWhat happens in the video. Any language works, Chinese text is limited to 2,500 characters.
Type: StringMinimum characters: 1Maximum characters: 5000resolutionOptionalResolution of the finished video; the price depends on it.
Type: StringAllowed values:720p1080pDefault:"720p"reference_image_urlsRequired1 to 9 URLs of pictures with the characters, objects or setting.
Type: List (String, uri)Maximum items: 9aspect_ratioOptionalFrame shape: landscape, portrait, square or the classic 4:3 and 3:4.
Type: StringAllowed values:16:99:161:14:33:4Default:"9:16"durationOptionalVideo length in seconds, 3 to 15. The price is per second.
Type: IntegerMinimum: 3Maximum: 15Default:5
Parameters not listed here are not accepted: the response is 422 unknown_setting.
Input
- Pictures are URLs of JPEG, PNG or WebP files up to 20 MB each, the short side at least 400 pixels.
- The prompt can refer to the pictures in the order of the URLs: [Image 1], [Image 2] and so on.
| Field | Accepts | Formats | Files | File size up to |
|---|---|---|---|---|
reference_image_urls | Images | jpeg, jpg, png, webp | 9 | 20 MB |
Request example
Send this JSON to POST /v1/tasks with your API key. To check the price first, send the same JSON to POST /v1/price.
A character from a picture
{
"model": "happyhorse",
"settings": {
"mode": "reference_to_video",
"prompt": "Женщина с [Image 1] идёт по ночному городу под дождём",
"reference_image_urls": [
"https://example.com/woman.png"
],
"aspect_ratio": "9:16",
"duration": 5
}
}The price is calculated when the task is accepted, currency RUB.
Output
- One MP4 video.
- Generation takes 3 to 15 minutes, longer for long clips.
| Kind | Formats | How many | Note |
|---|---|---|---|
video | mp4 | 1 |
A finished task as GET /v1/tasks/{id} returns it (some fields left out). The caption may sit on the task or on a single file and may be empty; the model picks the file name.
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"status": "succeeded",
"finished_at": "2026-10-01T12:03:41+00:00",
"result": {
"caption": "Caption of the result: the model and its settings",
"texts": [],
"files_expire_at": "2026-10-08T12:03:41+00:00",
"files_expired": false,
"artifacts": [
{
"index": 0,
"kind": "video",
"filename": "video.mp4",
"size": 12582912,
"caption": "",
"download_path": "/v1/tasks/7c9e6679-7425-40de-944b-e07fc1f90ae7/artifacts/0"
}
]
}
}Video editing
A finished clip is changed by the prompt: other clothes, style, objects. Runs on version 1.0, so a second costs more here.
Value of the mode field: video_edit
Price in this mode from 121 ₽, with a 3 s file.
Parameters
Model parameters go inside settings. Omitted optional fields take their default values.
promptRequiredWhat to change in the clip, for example "dress the hero in the sweater from the picture". Any language works, Chinese text is limited to 2,500 characters.
Type: StringMinimum characters: 1Maximum characters: 5000resolutionOptionalResolution of the finished video; the price depends on it.
Type: StringAllowed values:720p1080pDefault:"720p"video_urlRequiredOne URL of the clip to change.
Type: List (String, uri)Maximum items: 1reference_image_urlsOptionalUp to 5 URLs of pictures with what to add to the clip. Optional.
Type: List (String, uri)Maximum items: 5audio_settingOptionalSound of the result: new sound matched to the changed video, or the sound of the source clip.
Type: StringAllowed values:autooriginDefault:"auto"
Parameters not listed here are not accepted: the response is 422 unknown_setting.
Input
- The video is a URL of an MP4 or MOV file up to 100 MB, 3 to 60 seconds long, sides from 320 to 2160 pixels, shape from 1:2.5 to 2.5:1, more than 8 frames per second.
- The whole clip goes to the model. The price follows its length: the seconds of the source and as many again for the result, a part of a second counts as a whole one.
- Pictures are URLs of JPEG, PNG or WebP files up to 10 MB each, each side at least 300 pixels, shape from 1:2.5 to 2.5:1.
| Field | Accepts | Formats | Files | File size up to |
|---|---|---|---|---|
video_url | Video | mp4, mov | 1 | 100 MB |
reference_image_urls | Images | jpeg, jpg, png, webp | 5 | 10 MB |
Request example
Send this JSON to POST /v1/tasks with your API key. To check the price first, send the same JSON to POST /v1/price.
Change the hero's clothes
{
"model": "happyhorse",
"settings": {
"mode": "video_edit",
"prompt": "Надень на героя полосатый свитер с картинки",
"video_url": [
"https://example.com/clip.mp4"
],
"reference_image_urls": [
"https://example.com/sweater.png"
],
"audio_setting": "origin"
}
}The price is calculated when the task is accepted, currency RUB.
Output
- One MP4 video.
- Generation takes 3 to 15 minutes, longer for long clips.
| Kind | Formats | How many | Note |
|---|---|---|---|
video | mp4 | 1 |
A finished task as GET /v1/tasks/{id} returns it (some fields left out). The caption may sit on the task or on a single file and may be empty; the model picks the file name.
{
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"status": "succeeded",
"finished_at": "2026-10-01T12:03:41+00:00",
"result": {
"caption": "Caption of the result: the model and its settings",
"texts": [],
"files_expire_at": "2026-10-08T12:03:41+00:00",
"files_expired": false,
"artifacts": [
{
"index": 0,
"kind": "video",
"filename": "video.mp4",
"size": 12582912,
"caption": "",
"download_path": "/v1/tasks/7c9e6679-7425-40de-944b-e07fc1f90ae7/artifacts/0"
}
]
}
}See also
Try HappyHorse 1.1 through the API
One key opens every CyHUB model. Payment in rubles, and you see the price before the run.
Get an API key