AI Video
Generate short AI videos asynchronously across Seedance, HappyHorse, and PixVerse models from text, image, video, and audio inputs.
AI Video creates short videos asynchronously. Submit a generation request, then poll the task until it reaches success or failed.
Seedance and HappyHorse share one endpoint — POST /v1/video-generation/generate — and you pick a model with the model field. PixVerse runs on its own endpoint with a different request shape. Tasks from all three families are read back through the same task, list, and detail endpoints.
All endpoints on this page use the OpenAPI base URL
https://api.marswave.ai/openapi and authenticate with your API key via the
Authorization: Bearer $LISTENHUB_API_KEY header. Create keys at
listenhub.ai/settings/api-keys.
Choose a model
Four models span three families. Use this table to pick one, then open the model's page for its exact limits and pricing notes.
| Model | Family | Generate endpoint | Best for | Resolution | Duration |
|---|---|---|---|---|---|
doubao-seedance-2-fast (default) | Seedance | /v1/video-generation/generate | Fast text / image / video generation | 480p, 720p | 4-15s |
doubao-seedance-2-pro | Seedance | /v1/video-generation/generate | Higher-quality Seedance generation, up to 1080p | 480p, 720p, 1080p | 4-15s |
happyhorse | HappyHorse | /v1/video-generation/generate | Reference-video editing, portrait ratios, longer reference clips | 720p, 1080p | 3-15s |
pixverse | PixVerse | /v1/video-generation/pixverse/generate | Nine capability modes: transitions, fusion, restyle, mimic, lip sync, marketing agents | 360p, 540p, 720p, 1080p | 1-60s |
doubao-seedance-2-fast is the default when model is omitted on the shared endpoint. PixVerse has no model default of its own on the shared endpoint — you reach it through its dedicated pixverse/generate path and select a version (pixverse, v6, v5, v4.5) with that endpoint's own model field.
| Model | Aspect ratios | Rate limit |
|---|---|---|
doubao-seedance-2-fast | 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 | 5 RPM |
doubao-seedance-2-pro | 16:9, 4:3, 1:1, 3:4, 9:16, 21:9 | 5 RPM |
happyhorse | 16:9, 4:3, 1:1, 3:4, 9:16, 21:9, 4:5, 5:4 | 5 RPM |
pixverse | 9:16, 16:9, 1:1, 4:3, 3:4 | 5 RPM |
Model limits differ. doubao-seedance-2-fast does not support 1080p.
Seedance models do not support 4:5 or 5:4. happyhorse does not support
480p, last_frame, or audio_url. Requests that combine an unsupported
model, ratio, resolution, or duration return 400.
Seedance
doubao-seedance-2-pro and doubao-seedance-2-fast: limits and pricing notes.
HappyHorse
happyhorse: portrait ratios, reference-video editing, and longer input windows.
PixVerse
Nine capability modes on a dedicated endpoint, from lip sync to marketing agents.
Workflow
The shared endpoint covers Seedance and HappyHorse. PixVerse follows the same three-step flow on its own generate and estimate paths; see the PixVerse page.
Estimate Credits
Call POST /v1/video-generation/estimate-credits (or POST /v1/video-generation/pixverse/estimate-credits for PixVerse) before generation when you need to show a cost confirmation.
Create a Task
Call POST /v1/video-generation/generate (or POST /v1/video-generation/pixverse/generate). The response returns a taskId and episodeId.
Poll for Result
Poll GET /v1/video-generation/tasks/{taskId} until status is success or failed. This endpoint is shared across all model families.
Content Items
The content array accepts 1-16 items. It can include at most one text prompt, up to nine images, up to three videos, and up to three audio files. This array applies to the shared Seedance / HappyHorse endpoint; PixVerse uses top-level images, videos, and audios fields instead.
| Type | Required fields | Role | Notes |
|---|---|---|---|
text | text | None | Max 2500 characters. Seedance models accept up to 500 characters. |
image_url | image_url.url | first_frame, last_frame, reference_image | last_frame requires a first_frame. Frame roles cannot be mixed with reference roles. |
video_url | video_url.url | reference_video | Requires inputVideoDuration. Seedance accepts 2-15s input; HappyHorse accepts 3-60s input. |
audio_url | audio_url.url | reference_audio | Requires at least one image or video item. Not supported by happyhorse. |
Use frame roles (first_frame, optionally last_frame) for image-to-video.
Use reference roles (reference_image, reference_video, reference_audio)
for multimodal reference generation. Do not mix frame roles and reference
roles in one request.
Create Video Task
POST /v1/video-generation/generate
Create an asynchronous video generation task on the shared Seedance / HappyHorse endpoint. Credits are charged when the task is created and refunded automatically if generation fails. For PixVerse, use POST /v1/video-generation/pixverse/generate.
Text to Video
curl -X POST "https://api.marswave.ai/openapi/v1/video-generation/generate" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seedance-2-fast",
"content": [
{
"type": "text",
"text": "A cinematic aerial shot of a quiet coastal city at sunrise"
}
],
"resolution": "720p",
"ratio": "16:9",
"duration": 5,
"generateAudio": true
}'const response = await fetch(
'https://api.marswave.ai/openapi/v1/video-generation/generate',
{
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.LISTENHUB_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'doubao-seedance-2-fast',
content: [
{
type: 'text',
text: 'A cinematic aerial shot of a quiet coastal city at sunrise',
},
],
resolution: '720p',
ratio: '16:9',
duration: 5,
generateAudio: true,
}),
},
)
const data = await response.json()
console.log('Task ID:', data.data.taskId)import os
import requests
response = requests.post(
'https://api.marswave.ai/openapi/v1/video-generation/generate',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
json={
'model': 'doubao-seedance-2-fast',
'content': [
{
'type': 'text',
'text': 'A cinematic aerial shot of a quiet coastal city at sunrise',
}
],
'resolution': '720p',
'ratio': '16:9',
'duration': 5,
'generateAudio': True,
},
)
data = response.json()
print('Task ID:', data['data']['taskId'])Response:
{
"code": 0,
"message": "",
"data": {
"taskId": "665f1d4e8b3a3f001234abcd",
"episodeId": "665f1d4e8b3a3f001234abce",
"status": "generating"
}
}Image to Video
Use first_frame to start from one image. Add last_frame only when you want to control the ending frame.
curl -X POST "https://api.marswave.ai/openapi/v1/video-generation/generate" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seedance-2-pro",
"content": [
{
"type": "text",
"text": "The camera slowly pushes in while mist moves through the scene"
},
{
"type": "image_url",
"role": "first_frame",
"image_url": {
"url": "https://example.com/start-frame.jpg"
}
}
],
"resolution": "1080p",
"ratio": "16:9",
"duration": 5
}'Video Reference
When content contains video_url, set inputVideoDuration to the reference video's duration in seconds.
curl -X POST "https://api.marswave.ai/openapi/v1/video-generation/generate" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "happyhorse",
"content": [
{
"type": "text",
"text": "Restyle the subject as a polished product launch clip"
},
{
"type": "video_url",
"role": "reference_video",
"video_url": {
"url": "https://example.com/reference.mp4"
}
},
{
"type": "image_url",
"role": "reference_image",
"image_url": {
"url": "https://example.com/style-reference.jpg"
}
}
],
"resolution": "720p",
"ratio": "9:16",
"duration": 5,
"inputVideoDuration": 8,
"audioSetting": "auto"
}'Request Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
model | string | No | doubao-seedance-2-fast | doubao-seedance-2-pro, doubao-seedance-2-fast, or happyhorse. |
content | array | Yes | - | Input items. See Content Items. |
resolution | string | No | 720p | 480p, 720p, or 1080p, subject to model limits. |
ratio | string | No | 16:9 | 16:9, 4:3, 1:1, 3:4, 9:16, 21:9, 4:5, or 5:4, subject to model limits. |
duration | integer | No | 5 | Output duration in seconds. Seedance requires 4-15; HappyHorse accepts 3-15. |
generateAudio | boolean | No | true | Whether to generate audio with the video. |
seed | integer | No | -1 | Random seed, -1 to 4294967295. Use -1 for random generation. |
inputVideoDuration | integer | No | 0 | Required when using video_url. Seedance accepts 2-15; HappyHorse accepts 3-60. |
audioSetting | string | No | auto | For video-edit workflows. auto generates audio; origin keeps original video audio. |
Resolution, ratio, duration, and inputVideoDuration limits vary by model.
See Seedance and
HappyHorse for the
per-model rules.
Get Task
GET /v1/video-generation/tasks/{taskId}
Poll the task detail endpoint until the task reaches a terminal state. This endpoint returns tasks from every model family, including PixVerse.
curl "https://api.marswave.ai/openapi/v1/video-generation/tasks/{taskId}" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"Task statuses:
| Status | Meaning |
|---|---|
pending | Task created and waiting to be submitted. |
generating | Provider generation is in progress. |
uploading | Provider output is ready and ListenHub is storing it. |
success | Video is ready. Use videoUrl for the stored output. |
failed | Generation failed. Credits are refunded automatically when applicable. |
Response:
{
"code": 0,
"message": "",
"data": {
"id": "665f1d4e8b3a3f001234abcd",
"taskId": "665f1d4e8b3a3f001234abcd",
"episodeId": "665f1d4e8b3a3f001234abce",
"status": "success",
"model": "doubao-seedance-2-fast",
"params": {
"content": [
{
"type": "text",
"text": "A cinematic aerial shot of a quiet coastal city at sunrise"
}
],
"resolution": "720p",
"ratio": "16:9",
"duration": 5,
"generateAudio": true,
"seed": -1
},
"videoUrl": "https://assets.listenhub.ai/video-generation/output.mp4",
"coverUrl": "https://assets.listenhub.ai/video-generation/cover.jpg",
"providerVideoUrl": "https://provider.example/video.mp4",
"duration": 5,
"resolution": "720p",
"ratio": "16:9",
"seed": 123456,
"creditCharged": 12,
"enabledShare": false,
"createdAt": 1700000000000,
"updatedAt": 1700000300000
}
}List Tasks
GET /v1/video-generation/tasks
List the current API user's video generation tasks in reverse chronological order. Tasks from all model families appear in the same list.
curl "https://api.marswave.ai/openapi/v1/video-generation/tasks?page=1&pageSize=20&status=success" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"Query Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
page | integer | No | 1 | Page number. |
pageSize | integer | No | 20 | Items per page, max 100. |
status | string | No | - | Optional filter: pending, generating, uploading, success, or failed. |
Response:
{
"code": 0,
"message": "",
"data": {
"items": [
{
"id": "665f1d4e8b3a3f001234abcd",
"episodeId": "665f1d4e8b3a3f001234abce",
"status": "success",
"model": "doubao-seedance-2-fast",
"title": "A cinematic aerial shot of a quiet coastal city at sunrise",
"prompt": "A cinematic aerial shot of a quiet coastal city at sunrise",
"params": {
"content": [],
"resolution": "720p",
"ratio": "16:9",
"duration": 5,
"generateAudio": true,
"seed": -1
},
"videoUrl": "https://assets.listenhub.ai/video-generation/output.mp4",
"coverUrl": "https://assets.listenhub.ai/video-generation/cover.jpg",
"providerVideoUrl": "https://provider.example/video.mp4",
"seed": 123456,
"creditCharged": 12,
"createdAt": 1700000000000
}
],
"page": 1,
"pageSize": 20,
"total": 1
}
}Estimate Credits
POST /v1/video-generation/estimate-credits
Estimate the credit cost before creating a task on the shared Seedance / HappyHorse endpoint. PixVerse has its own estimate at POST /v1/video-generation/pixverse/estimate-credits. Credit cost is never fixed — always call the matching estimate endpoint to read the exact value for your parameters.
curl -X POST "https://api.marswave.ai/openapi/v1/video-generation/estimate-credits" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "doubao-seedance-2-fast",
"resolution": "720p",
"duration": 5,
"hasVideoInput": false,
"ratio": "16:9"
}'Request Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
model | string | Yes | - | doubao-seedance-2-pro, doubao-seedance-2-fast, or happyhorse. |
resolution | string | Yes | - | 480p, 720p, or 1080p, subject to model limits. |
duration | integer | Yes | - | Output duration in seconds. |
hasVideoInput | boolean | No | false | Set to true when the generation request includes video_url. |
inputVideoDuration | integer | No | 0 | Required when hasVideoInput is true. |
ratio | string | No | 16:9 | Aspect ratio. |
Response:
{
"code": 0,
"message": "",
"data": {
"tokens": 155520,
"credits": 12
}
}Errors
| HTTP status | Meaning |
|---|---|
400 | Invalid parameters, unsupported model/ratio/resolution combination, or missing required media duration. |
402 | Not enough credits. |
403 | The task exists but does not belong to the current API user. |
404 | Task not found. |
429 | Rate limit exceeded (5 RPM per user on the generate endpoints). |
PixVerse returns its own numeric code values alongside these HTTP statuses — see PixVerse error codes.