> For the complete documentation index, see [llms.txt](https://docs.apismart.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apismart.ai/api-guides/video-generation-api.md).

# Video Generation API

Learn how to generate videos with ApiSmart using HappyHorse and Seedance, including text, image, video, audio, multimodal inputs, task polling, and resolution settings.

Use the Video Generation API to create videos with supported ApiSmart video models.

Depending on the selected model, you can generate videos from **text, images, videos, audio, and multimodal references**.

Video generation is asynchronous. After creating a task, use the returned task ID to check its status until generation completes.

### 🎬 Endpoints

#### Create a Video Task

**Method:** `POST`

**Endpoint:** `/v1/video/tasks`

**Full URL:**

`https://gw.apismart.ai/v1/video/tasks`

#### Query a Video Task

**Method:** `GET`

**Endpoint:** `/v1/video/tasks/{id}`

#### Retrieve Video Content

**Method:** `GET`

**Endpoint:** `/v1/videos/{id}/content`

### 🔑 Authentication

Include your ApiSmart API Key in the `Authorization` header:

```http
Authorization: Bearer <your-api-key>
```

For JSON requests, also include:

```http
Content-Type: application/json
```

### 🧩 Supported Video Models

ApiSmart currently supports two video model families.

#### HappyHorse

* `happyhorse-1.0`
* `happyhorse-1.1`

#### Seedance

* `doubao-seedance-2.0`
* `doubao-seedance-2-0-fast`
* `doubao-seedance-2-0-mini`
* `doubao-seedance-2-5`

Capabilities, supported resolutions, inputs, and billing rules vary by model.

For pricing information, see [**Model Pricing and Billing**](/models-and-pricing/model-pricing-and-billing.md).

***

## HappyHorse

HappyHorse supports several generation workflows. The API automatically determines the workflow based on the inputs included in the request.

| Input           | Workflow           |
| --------------- | ------------------ |
| Prompt only     | Text-to-video      |
| One image       | Image-to-video     |
| Multiple images | Reference-to-video |
| Video input     | Video editing      |

When multiple input types are present, workflow detection follows this priority:

**Video editing → Reference-to-video → Image-to-video → Text-to-video**

### ✨ Text-to-Video

```bash
curl https://gw.apismart.ai/v1/video/tasks \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "happyhorse-1.0",
    "prompt": "A miniature city at night, lights glowing while a train moves through the streets",
    "duration": 5,
    "size": "720P",
    "metadata": {
      "ratio": "16:9"
    }
  }'
```

### 🖼️ Image-to-Video

Provide a single image URL using `image`:

```bash
curl https://gw.apismart.ai/v1/video/tasks \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "happyhorse-1.0",
    "prompt": "Make the person smile naturally and slowly turn toward the camera",
    "image": "https://example.com/input.png",
    "duration": 5,
    "size": "1080P"
  }'
```

### 🧩 Multiple Reference Images

Use `images` when your request needs multiple reference images:

```bash
curl https://gw.apismart.ai/v1/video/tasks \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "happyhorse-1.0",
    "prompt": "Use the person from the first reference image and the fan from the second reference image",
    "images": [
      "https://example.com/person.png",
      "https://example.com/fan.png"
    ],
    "duration": 5,
    "size": "720P",
    "metadata": {
      "mode": "r2v",
      "ratio": "16:9"
    }
  }'
```

When referencing multiple HappyHorse images in a prompt, follow the reference order used by the model.

### 🎞️ Video Editing

HappyHorse also supports video input.

```bash
curl https://gw.apismart.ai/v1/video/tasks \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "happyhorse-1.0",
    "prompt": "Transform the video into a cyberpunk visual style while preserving the subject motion",
    "input_reference": "https://example.com/input.mp4",
    "size": "720P"
  }'
```

For video editing, you can provide `duration` to specify the generated video length. If it is omitted, the service can use the source video duration.

### ⚠️ HappyHorse Resolution and Duration

Always explicitly specify the resolution and duration when creating standard HappyHorse generation requests.

If resolution is omitted, HappyHorse billing defaults to:

**1080p**

If duration is omitted, billing defaults to:

**5 seconds**

For example, with `happyhorse-1.0`:

**Default billing**

`1080p × 5 seconds = $1.35`

Explicitly requesting:

```json
{
  "resolution": "720p",
  "duration": 5
}
```

results in:

`720p × 5 seconds = $0.725`

Explicitly setting these parameters helps prevent unexpected charges.

> HappyHorse request formats may use `resolution` or `size` for resolution-related configuration. Follow the format shown for the workflow you are implementing.

***

## Seedance

Seedance uses the `content` array to combine text and multimodal references.

Supported content types include:

* `text`
* `image_url`
* `video_url`
* `audio_url`

### ✨ Text-to-Video

```bash
curl https://gw.apismart.ai/v1/video/tasks \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2.0",
    "content": [
      {
        "type": "text",
        "text": "A cat running along the beach at sunset, cinematic lighting and high visual detail"
      }
    ],
    "ratio": "16:9",
    "duration": 4,
    "resolution": "720p",
    "watermark": false
  }'
```

### 🖼️ Reference Image

Use `reference_image` when an image should guide the generated video.

```bash
curl https://gw.apismart.ai/v1/video/tasks \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2.0",
    "content": [
      {
        "type": "text",
        "text": "Make the character in the image perform a natural dance"
      },
      {
        "type": "image_url",
        "image_url": {
          "url": "https://example.com/input.jpg"
        },
        "role": "reference_image"
      }
    ],
    "duration": 4,
    "resolution": "720p"
  }'
```

### 🎞️ First and Last Frame Generation

Seedance can generate the transition between a specified first frame and last frame.

Use:

* `role: "first_frame"`
* `role: "last_frame"`

Example:

```bash
curl https://gw.apismart.ai/v1/video/tasks \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2.0",
    "content": [
      {
        "type": "text",
        "text": "Keep the camera fixed and smoothly transition from morning to sunset"
      },
      {
        "type": "image_url",
        "image_url": {
          "url": "https://example.com/start.jpg"
        },
        "role": "first_frame"
      },
      {
        "type": "image_url",
        "image_url": {
          "url": "https://example.com/end.jpg"
        },
        "role": "last_frame"
      }
    ],
    "duration": 4,
    "ratio": "16:9",
    "resolution": "720p"
  }'
```

You can also provide only a `first_frame` if you want the generated video to begin with a specific image.

Image references can use public HTTP/HTTPS URLs or Base64 Data URIs.

### 🎥 Reference Video

Use `reference_video` when an existing video should guide generation:

```bash
curl https://gw.apismart.ai/v1/video/tasks \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2.0",
    "content": [
      {
        "type": "text",
        "text": "Add cinematic lighting and atmosphere to the video"
      },
      {
        "type": "video_url",
        "video_url": {
          "url": "https://example.com/input.mp4"
        },
        "role": "reference_video"
      }
    ],
    "duration": 4,
    "resolution": "720p"
  }'
```

Requests that contain video input can use a different Seedance pricing tier.

See [**Model Pricing and Billing**](/models-and-pricing/model-pricing-and-billing.md) for current pricing details.

### 🎵 Images, Video, and Audio

Seedance also supports multimodal reference combinations.

Available roles include:

| Role              | Purpose                            |
| ----------------- | ---------------------------------- |
| `reference_image` | Reference image                    |
| `first_frame`     | First frame of the generated video |
| `last_frame`      | Last frame of the generated video  |
| `reference_video` | Reference video                    |
| `reference_audio` | Reference audio                    |

`reference_audio` cannot be used by itself. It must be combined with a supported image or video reference.

A multimodal request can look like:

```json
{
  "model": "doubao-seedance-2.0",
  "content": [
    {
      "type": "text",
      "text": "图片1中的角色在舞台上跳舞，动作参考视频1，并配合音频1"
    },
    {
      "type": "image_url",
      "image_url": {
        "url": "https://example.com/character.jpg"
      },
      "role": "reference_image"
    },
    {
      "type": "video_url",
      "video_url": {
        "url": "https://example.com/dance.mp4"
      },
      "role": "reference_video"
    },
    {
      "type": "audio_url",
      "audio_url": {
        "url": "https://example.com/music.mp3"
      },
      "role": "reference_audio"
    }
  ],
  "generate_audio": false,
  "ratio": "9:16",
  "duration": 5,
  "resolution": "720p"
}
```

#### Referencing Multiple Assets in Prompts

When multiple non-text assets are included, use:

* `图片1`, `图片2`, ...
* `视频1`, `视频2`, ...
* `音频1`, `音频2`, ...

Numbering starts from `1` and follows the order of non-text items in the `content` array.

Do not add spaces between the Chinese asset type and its number.

### 📦 Seedance Input Limits

Seedance supports up to **12 reference assets in total**, including:

* Up to 9 images
* Up to 3 videos
* Up to 3 audio files

The combined total must not exceed 12.

### 📎 Base64 Image Input

In addition to public URLs, `image_url.url` can contain a Base64 Data URI:

```json
{
  "type": "image_url",
  "image_url": {
    "url": "data:image/jpeg;base64,/9j/4AAQSkZJRg..."
  },
  "role": "reference_image"
}
```

The `data:image/...;base64,` prefix is required.

***

### ⚙️ Request Parameters

| Parameter                 | Models     | Type           | Description                           |
| ------------------------- | ---------- | -------------- | ------------------------------------- |
| `model`                   | All        | string         | Video model ID                        |
| `prompt`                  | All        | string         | Text generation instruction           |
| `duration`                | All        | integer        | Video duration in seconds             |
| `resolution` / `size`     | All        | string         | Requested resolution                  |
| `content`                 | All        | array          | Multimodal content array              |
| `image` / `images`        | HappyHorse | string / array | Image URL or multiple image URLs      |
| `input_reference`         | HappyHorse | string         | Source video URL for video editing    |
| `metadata`                | HappyHorse | object         | Additional HappyHorse configuration   |
| `ratio`                   | Seedance   | string         | Aspect ratio such as `16:9` or `9:16` |
| `callback_url`            | Seedance   | string         | Optional callback URL                 |
| `return_last_frame`       | Seedance   | boolean        | Return the generated final frame      |
| `generate_audio`          | Seedance   | boolean        | Generate synchronized audio           |
| `draft`                   | Seedance   | boolean        | Enable draft mode                     |
| `tools`                   | Seedance   | array / object | Optional tool configuration           |
| `seed`                    | All        | integer        | Random seed                           |
| `watermark`               | Seedance   | boolean        | Enable or disable watermark           |
| `execution_expires_after` | Seedance   | integer        | Task expiration time in seconds       |

Supported parameters can vary by model and workflow.

***

### 📐 Resolution and Duration

Resolution and duration can directly affect video billing.

#### Default Values

| Model Family | Resolution When Omitted | Duration When Omitted   |
| ------------ | ----------------------- | ----------------------- |
| HappyHorse   | Billed as **1080p**     | **5 seconds**           |
| Seedance     | Billed as **720p**      | Determined by the model |

#### Supported Resolutions

| Model ID                   | Supported Resolutions   |
| -------------------------- | ----------------------- |
| `happyhorse-1.0`           | `720p`, `1080p`         |
| `happyhorse-1.1`           | `720p`, `1080p`         |
| `doubao-seedance-2.0`      | `480p`, `720p`, `1080p` |
| `doubao-seedance-2-0-fast` | `480p`, `720p`, `1080p` |
| `doubao-seedance-2-0-mini` | `480p`, `720p`, `1080p` |
| `doubao-seedance-2-5`      | `480p`, `720p`          |

Seedance does not support `4k`.

If an unsupported resolution is requested, the API can return:

`400 unsupported_resolution`

Requests rejected by this validation do not incur a generation charge.

#### Seedance Output Resolution

For Seedance, the requested `resolution` determines the billing tier, but the actual output resolution is determined by the model service.

After generation completes, use the `resolution` field in the task response when you need the actual output resolution.

***

### 🔄 Query Task Status

After creating a video task, use the returned task ID:

```bash
curl https://gw.apismart.ai/v1/video/tasks/<task_id> \
  -H "Authorization: Bearer <your-api-key>"
```

#### Task Statuses

| Status      | Meaning                           |
| ----------- | --------------------------------- |
| `queued`    | Waiting in queue                  |
| `running`   | Generation in progress            |
| `succeeded` | Generation completed successfully |
| `failed`    | Generation failed                 |
| `cancelled` | Task was cancelled                |
| `expired`   | Task expired                      |

Continue polling while the task is `queued` or `running`.

### 📦 Successful Task Response

A successful response can look like:

```json
{
  "id": "task_xxxxxx",
  "status": "succeeded",
  "model": "happyhorse-1.0",
  "content": {
    "video_url": "https://cdn.example.com/result.mp4"
  },
  "resolution": "720p",
  "ratio": "16:9",
  "duration": 5
}
```

Use `content.video_url` to access the generated result when it is returned.

### ❌ Failed Task Response

A failed task can look like:

```json
{
  "id": "task_xxxxxx",
  "status": "failed",
  "model": "happyhorse-1.0",
  "error": {
    "code": "InvalidParameter",
    "message": "The parameter is invalid."
  }
}
```

For complete error handling guidance, see [**HTTP Status Codes and API Errors**](/troubleshooting/http-status-codes-and-api-errors.md).

***

### 🕘 View Recent Generated Videos

Use:

`GET /v1/videos`

to retrieve recently generated successful videos.

Example:

```bash
curl "https://gw.apismart.ai/v1/videos?page=1&page_size=20" \
  -H "Authorization: Bearer <your-api-key>"
```

#### Query Parameters

| Parameter   | Default | Description                 |
| ----------- | ------: | --------------------------- |
| `page`      |     `1` | Page number                 |
| `page_size` |    `20` | Records per page, up to 100 |

Video history records can include:

* Generation ID
* Task ID
* Model ID
* Video URL
* Duration
* Resolution
* Cost
* Creation time
* Storage status

Only videos generated successfully are included.

Video history can currently be queried for the most recent **7 days**.

Save important generated videos to your own storage rather than relying only on history availability.

***

### 👤 Verified Real-Person Assets

Seedance also supports a verified real-person asset workflow for authorized real-person video generation.

This advanced workflow uses:

`POST /seedance-gateway`

A typical process is:

1. Create a verification session.
2. Complete the mobile verification process.
3. Retrieve the resulting `GroupId`.
4. Create a verified asset.
5. Wait until the asset status becomes `Active`.
6. Reference the asset using `asset://asset_id` in a Seedance video request.

Example:

```json
{
  "model": "doubao-seedance-2.0",
  "content": [
    {
      "type": "text",
      "text": "图片1中的人物介绍图片2中的产品，近景镜头"
    },
    {
      "type": "image_url",
      "image_url": {
        "url": "asset://asset-2026xxxxxx"
      },
      "role": "reference_image"
    },
    {
      "type": "image_url",
      "image_url": {
        "url": "https://example.com/product.jpg"
      },
      "role": "reference_image"
    }
  ],
  "duration": 8,
  "resolution": "720p",
  "generate_audio": true
}
```

Verified assets are account-specific. An `asset://` reference must belong to the account making the video request.

Because real-person asset management involves a separate verification and asset lifecycle, consider documenting the complete workflow separately if you use this feature extensively.

***

### ⚠️ Common Issues

#### Invalid API Key

`401 invalid_api_key`

Verify:

```http
Authorization: Bearer <your-api-key>
```

#### Insufficient Balance

`402 insufficient_quota`

Add funds before retrying the request.

#### Model Not Available

`403 model_not_allowed`

The selected video model is not enabled for your account or API Key.

#### Unsupported Video Model

`403 model_not_video_capable`

The selected model cannot be used with the Video Generation API.

#### Unsupported Resolution

`400 unsupported_resolution`

The requested resolution is not supported by the selected model.

#### Temporary Service Errors

`502`, `503`, and `504` can indicate temporary provider, gateway, or dependent-service problems.

Use an appropriate retry strategy for temporary failures.

***

### ✅ Before Creating a Video Task

Verify that:

* Your API Key is valid and enabled
* Your account has sufficient balance
* The model ID is correct
* The selected model supports your input type
* `resolution` is supported by the model
* `duration` is explicitly set when appropriate
* Seedance reference assets stay within the supported limits
* `reference_audio` is not used by itself
* Your application is prepared to poll asynchronous task status
* You understand the billing method of the selected video model

### ➡️ Next Steps

Continue with:

* [**Models and Model IDs**](/models-and-pricing/models-and-model-ids.md) — Find valid video model IDs
* [**Model Pricing and Billing**](/models-and-pricing/model-pricing-and-billing.md) — Understand video pricing and billing rules
* [**Response Modes**](/api-guides/response-modes.md) — Understand asynchronous video requests
* [**Usage Logs and Costs**](/api-usage/usage-logs-and-costs.md) — Review request-level usage and costs
* [**HTTP Status Codes and API Errors**](/troubleshooting/http-status-codes-and-api-errors.md) — Troubleshoot failed video requests
