> ## Documentation Index
> Fetch the complete documentation index at: https://docs.linkmodel.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Seedance video generation with the Volcengine API

> Create and query Seedance video tasks through LinkModel's Volcengine-compatible API, including reference inputs, 1080p output, and Seedance 2.5 Draft workflows.

Use LinkModel's Volcengine-compatible task API with `seedance-2-0`, `seedance-2-0-fast`, `seedance-2-0-mini`, and `seedance-2-5`. Video generation is asynchronous: create a task, save its ID, then query its status and download the result.

This guide describes the interface as of **October 29, 2026 (Asia/Shanghai)**.

## Choose the interface

Choose the guide that matches the request format you want to use:

| Your integration | Use |
| - | - |
| Adapting an existing Volcengine-style video request with typed `content` blocks | This guide: `/volcengine/api/v3/contents/generations/tasks`. Adjust the request to the supported fields below. |
| Using LinkModel's unified video-generation interface | The [Seedance unified API reference](https://docs.linkmodel.ai/api-reference/bytedance/seedance-2-0.md): `/v1/videos/generations`. |

This guide uses **LinkModel API keys** and the base URL `https://api.linkmodel.ai`. It covers LinkModel's supported fields, not every upstream Volcengine feature. Create and query a task through the same interface; follow that interface's request and response formats.

| Operation | Method | URL |
| - | - | - |
| Create a video task | POST | `https://api.linkmodel.ai/volcengine/api/v3/contents/generations/tasks` |
| Query a video task | GET | `https://api.linkmodel.ai/volcengine/api/v3/contents/generations/tasks/{task_id}` |

All requests require `Authorization: Bearer YOUR_API_KEY`. POST requests also require `Content-Type: application/json`. Your account must have access to the selected model and features. Keep the key on your server, out of public pages, client-side code, and logs. Query tasks with credentials from the account that created them; missing tasks and tasks belonging to another account return `404`.

## Generate your first video

Set `LINKMODEL_API_KEY` in your local environment. Examples use placeholder keys, task IDs, and media URLs; replace them before use. Creating a task generates billable usage at your account's applicable price.

### 1. Create a task

Only `model` and `content` are required. This example also selects a 5-second, `480p` video without generated audio or a watermark so the initial result does not depend on those defaults.

```bash theme={null}
curl 'https://api.linkmodel.ai/volcengine/api/v3/contents/generations/tasks' \
  -H "Authorization: Bearer ${LINKMODEL_API_KEY}" \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "seedance-2-0",
    "content": [
      {"type": "text", "text": "A white ceramic cup on a wooden table in soft daylight. Slow camera movement, no text."}
    ],
    "duration": 5,
    "resolution": "480p",
    "generate_audio": false,
    "watermark": false
  }'
```

A successful creation returns HTTP `200`:

```json theme={null}
{
  "id": "example-task-id"
}
```

Save the top-level `id`. There is no `code` or `data.task_id` wrapper. Acceptance does **not** mean the video has finished generating. You can use the same request structure with `seedance-2-0-fast`.

### 2. Query the task

```bash theme={null}
curl 'https://api.linkmodel.ai/volcengine/api/v3/contents/generations/tasks/YOUR_TASK_ID' \
  -H "Authorization: Bearer ${LINKMODEL_API_KEY}"
```

Use the complete `id` from creation, at most 50 characters long, in the path. Do not use a media URL or another platform's task ID.

Process each query in this order:

1. **No response or non-200 HTTP status:** handle a request error using [errors and retries](#errors-and-retries). A query error does not establish that generation failed.
2. **HTTP `200`:** inspect the top-level `status` below. HTTP success means the query succeeded, not necessarily the video generation.
3. **Terminal task status:** stop polling. Save the video for `succeeded`, or record the failure details for `failed`.

| Status | Meaning | Action |
| - | - | - |
| `queued` | Waiting to start | Wait and query again. |
| `running` | Processing | Wait and query again. |
| `succeeded` | Generation completed | Read `content.video_url` and stop polling. |
| `failed` | Generation failed | Stop polling and record `error.code` and `error.message`. |
| `cancelled` | Task cancelled | Stop polling. This guide does not expose a cancellation endpoint. |

Start with a 3–5 second polling interval and increase the interval as needed. This is a suggested client strategy, not a completion-time guarantee. If your local wait limit expires, retain the ID and query later; a local timeout does not fail or cancel the task.

### 3. Save the result

A successful query returns HTTP `200`. For a completed task, download the URL in `content.video_url` and save the video promptly. Output URLs do not have a guaranteed fixed lifetime in this guide.

```json theme={null}
{
  "id": "example-task-id",
  "model": "seedance-2-0",
  "status": "succeeded",
  "created_at": 1793274351,
  "updated_at": 1793274582,
  "draft": false,
  "content": {
    "video_url": "https://example.com/output.mp4"
  },
  "usage": {
    "completion_tokens": 50638,
    "total_tokens": 50638
  }
}
```

The timestamps, usage, ID, and URL above illustrate the response format only. See [query response fields](#query-response-fields) for optional metadata and failure responses.

## Model support

Availability depends on your account's enabled features.

| Model | Regular output resolutions | `duration` | Maximum reference images / videos / audio inputs | Draft |
| - | - | - | - | - |
| `seedance-2-0` | `480p`, `720p`, `1080p` | `-1` or an integer from 4–15 seconds | 9 / 3 / 3 | No |
| `seedance-2-0-fast` | `480p`, `720p` | `-1` or an integer from 4–15 seconds | 9 / 3 / 3 | No |
| `seedance-2-0-mini` | `480p`, `720p` | `-1` or an integer from 4–15 seconds | 9 / 3 / 3 | No |
| `seedance-2-5` | `480p`, `720p`, `1080p` (requires account access) | `-1` or an integer from 4–30 seconds | 30 / 10 / 10 | Yes, `480p` only |

`duration: -1` selects intelligent duration. Under the current default configuration, omitted duration means 5 seconds for 2.0, Fast, and Mini, and intelligent duration for 2.5. Account policies may affect effective parameters; specify a fixed duration and resolution during initial integration.

Reference limits are counted separately and exclude dedicated first and last frames. These are request-validation limits, not guarantees that every combination of formats, file sizes, and media durations will succeed.

`4k` is not supported. Seedance 2.5 requires the corresponding account permission for `1080p`.

### Resolution tiers and observed dimensions

`resolution` selects a tier; it does not necessarily equal the file's height. These are observed output examples for `16:9`, not fixed dimensions guaranteed for every task:

| Model and request | Observed video dimensions |
| - | - |
| `seedance-2-0`, `480p` | 864 × 496 |
| `seedance-2-0-fast`, `480p` | 864 × 496 |
| `seedance-2-5`, `480p` Draft | 854 × 480 |
| `seedance-2-5`, `1080p` text-to-video / reference-video generation | 1920 × 1080 |
| `seedance-2-0-mini`, `720p` | 1280 × 720 |

Do not reject a 2.0 `480p` result solely because its height is not 480 pixels. Inspect the video file for actual dimensions, including other aspect ratios.

## Request fields

### Top-level fields

| Field | Type | Required | Description |
| - | - | - | - |
| `model` | string | Yes | An exact model name from the support table. |
| `content` | object\[] | Yes | At least one content block, as described below. |
| `duration` | integer | No | Seconds or `-1`; see model ranges and defaults above. `0` is invalid. |
| `resolution` | string | No | Lowercase `480p`, `720p`, or `1080p`, within the model's available range. Regular output defaults to `720p`; Draft uses `480p`. |
| `ratio` | string | No | `16:9`, `4:3`, `1:1`, `3:4`, `9:16`, `21:9`, or `adaptive`. See the 2.5 frame-input restriction below. |
| `seed` | integer | No | From `-1` to `2147483647`, inclusive; `0` is valid. Reproducibility across models or parameter changes is not guaranteed. |
| `generate_audio` | boolean | No | Whether to generate audio. Set explicitly when possible; omitted for Draft means `false`. |
| `watermark` | boolean | No | Whether to add a watermark. Set explicitly when possible. |
| `draft` | boolean | No | Defaults to `false`. Only `seedance-2-5` accepts `true` to create a `480p` sample. |

Use boolean `false`, not the string `"false"`. Omit optional fields you do not need.

Unknown JSON fields return `400`. Do not send `omni_reference_task_type`, `callback_url`, `service_tier`, `tools`, `extends`, or `idempotency_key`. Top-level `prompt`, `images`, `videos`, `audio`, and `draft_task_id` are also unsupported by this interface.

### Content blocks

Every block needs `type` and only the corresponding content field. Media values must be objects, such as `"image_url": {"url": "https://example.com/input.jpg"}`, rather than URL strings.

| `type` | Content field | `role` | Description |
| - | - | - | - |
| `text` | `text`: string | Omit | Prompt; at most one text block. |
| `image_url` | `image_url`: `{"url":"..."}` | `first_frame`, `last_frame`, or `reference_image` | An omitted role means first frame. Reference images require explicit `reference_image`. |
| `video_url` | `video_url`: `{"url":"..."}` | `reference_video` or omit | Reference video. |
| `audio_url` | `audio_url`: `{"url":"..."}` | `reference_audio` or omit | Reference audio input, separate from the output-audio switch. |
| `draft_task` | `draft_task`: `{"id":"..."}` | Omit | A Draft reference, subject to the conversion conditions below. |

URLs must be nonempty. Use HTTPS media URLs that the server can download directly. Login-protected, expired, or private-network URLs are unsuitable. Supply media using the URL structure shown here.

### Choose one input mode

Build `content` for one of these modes. Do not combine frame input, reference-media input, and Draft conversion in the same request.

| Mode | What goes in `content` | Rules to check before submitting |
| - | - | - |
| Text to video | One nonempty `text` block | No media input is needed. |
| First frame or first + last frames | One `first_frame`, optionally one `last_frame` and one text block | A last frame requires a first frame. No reference images, videos, or audio. For **2.5**, omit `ratio` or use `adaptive`; fixed ratios are rejected. |
| Reference media | Reference image, video, and/or audio blocks, optionally one text block | Follow each model's count limits. **2.0 / Fast / Mini:** audio requires a reference image or video. **2.5:** audio-only reference input is allowed. No first/last-frame blocks. |
| Draft conversion | Exactly one `draft_task` block | No other content blocks. Use the [Draft conversion request](#convert-an-eligible-sample) and omit inherited fields. |

Across ordinary generation modes, provide valid text or media; empty text alone is invalid. At most one text block, one first frame, and one last frame are allowed. For images, always specify the intended `role`: omission means first frame, not reference image.

## Generation examples

The following JSON bodies all use the same POST creation endpoint. Replace media URLs with accessible inputs and select parameters your account can use.

### First and last frames

This example uses 2.0. For 2.5, omit `ratio` or change it to `adaptive`. To use only a first frame, remove the last-frame block.

```json theme={null}
{
  "model": "seedance-2-0",
  "content": [
    {"type": "text", "text": "Transition naturally from morning to dusk while keeping the scene consistent."},
    {"type": "image_url", "image_url": {"url": "https://example.com/first.jpg"}, "role": "first_frame"},
    {"type": "image_url", "image_url": {"url": "https://example.com/last.jpg"}, "role": "last_frame"}
  ],
  "duration": 5,
  "resolution": "720p",
  "ratio": "16:9",
  "generate_audio": false,
  "watermark": false
}
```

### Reference video with Mini

```json theme={null}
{
  "model": "seedance-2-0-mini",
  "content": [
    {"type": "text", "text": "Follow the reference camera movement to show a white ceramic cup in soft daylight."},
    {"type": "video_url", "video_url": {"url": "https://example.com/reference.mp4"}, "role": "reference_video"}
  ],
  "duration": 5,
  "resolution": "720p",
  "ratio": "16:9",
  "seed": 0,
  "generate_audio": false,
  "watermark": false
}
```

For reference images and audio, add blocks like these to `content`, respecting the model limits and combination rules. This is a content fragment, not a complete request:

```json theme={null}
[
  {"type": "image_url", "image_url": {"url": "https://example.com/reference.jpg"}, "role": "reference_image"},
  {"type": "audio_url", "audio_url": {"url": "https://example.com/reference.mp3"}, "role": "reference_audio"}
]
```

### Seedance 2.5 at 1080p

Your account needs Seedance 2.5 `1080p` access. These are regular generation requests: omit `draft`; creating a sample first is not required. A reference video can have a different resolution from the output, such as a 480p input for 1080p output.

**Text to video**

```json theme={null}
{
  "model": "seedance-2-5",
  "content": [
    {"type": "text", "text": "A white ceramic cup on a wooden table in soft daylight. Slow camera movement, no text."}
  ],
  "duration": 5,
  "resolution": "1080p",
  "ratio": "16:9",
  "seed": 0,
  "generate_audio": false,
  "watermark": false
}
```

**Reference video**

```json theme={null}
{
  "model": "seedance-2-5",
  "content": [
    {"type": "text", "text": "A white ceramic cup on a wooden table in soft daylight. Slow camera movement, no text."},
    {"type": "video_url", "video_url": {"url": "https://example.com/reference-video.mp4"}, "role": "reference_video"}
  ],
  "duration": 5,
  "resolution": "1080p",
  "ratio": "16:9",
  "seed": 0,
  "generate_audio": false,
  "watermark": false
}
```

These requests use the applicable “without reference video” and “with reference video” price tiers, respectively, based on actual output usage and your account's effective prices. Do not add a top-level `videos` billing field.

## Seedance 2.5 Draft workflow

Draft samples require the corresponding account access and use `480p`. A successful result with `draft: true` is still a sample.

### Create a sample

```json theme={null}
{
  "model": "seedance-2-5",
  "content": [
    {"type": "text", "text": "A white ceramic cup on a wooden table in soft daylight. Slow camera movement, no text."}
  ],
  "draft": true,
  "duration": 5,
  "resolution": "480p",
  "ratio": "16:9",
  "seed": 0,
  "generate_audio": false,
  "watermark": false
}
```

Query the returned task ID using the same query endpoint until the sample succeeds.

### Convert an eligible sample

Contact support to confirm that your account and sample are eligible before attempting conversion. Regular `1080p` generation access does not make every sample convertible. Conversion requires `resolution: "1080p"`; substituting `720p` returns `400`.

After support confirms eligibility and the sample reaches `succeeded`, POST this **complete request body** to the same creation endpoint. Replace the ID with the successful sample's LinkModel `id`:

```json theme={null}
{
  "model": "seedance-2-5",
  "resolution": "1080p",
  "content": [
    {"type": "draft_task", "draft_task": {"id": "YOUR_COMPLETED_DRAFT_TASK_ID"}}
  ],
  "watermark": false
}
```

The intentionally omitted generation settings are inherited from the sample. Do not copy the sample-creation request and simply add `draft_task`.

Conversion follows these rules:

* The sample must belong to your account, match the request model, and have completed successfully. Reference the LinkModel `id` returned when creating the sample.
* `content` must contain only one `draft_task`, without text, images, video, or audio. Do not send top-level `draft_task_id`.
* `duration`, `ratio`, `seed`, and `generate_audio` are inherited and **must be omitted entirely**. Passing the same values or explicit `null` is rejected.
* Do not set `draft: true`. You may specify `watermark`; it is not one of the inherited fields above.

The sample must have all necessary information. Intelligent-duration samples without actual-duration metadata may be rejected. Do not substitute another model's 1080p tier.

## Query response fields

Clients should tolerate absent optional fields and newly added response fields.

| Field | Type | Description |
| - | - | - |
| `id` | string | LinkModel task ID. |
| `model` | string | Model name. |
| `status` | string | Lowercase task status, listed above. |
| `created_at` | integer | Creation time in Unix seconds. |
| `updated_at` | integer, optional | Update time in Unix seconds. |
| `draft` | boolean | Whether the result is a Draft sample. |
| `content` | object, optional | Available after success; do not depend on it during processing. |
| `content.video_url` | string | Output URL; a string, not a `{"url":"..."}` object. |
| `content.last_frame_url` | string, optional | Returned only when the corresponding result metadata is available. |
| `usage` | object, optional | Returned for terminal tasks when valid usage data exists. Absence does not mean zero usage. |
| `usage.completion_tokens` | integer | Output token usage. |
| `usage.total_tokens` | integer | Total token usage; do not assume it always equals output usage. |
| `error` | object, optional | Failure details when `status` is `failed`. |

Metadata such as `seed`, `generate_audio`, `resolution`, `ratio`, `duration`, `frames`, `framespersecond`, and `output_format` is returned only when reliable result information is available. The response is not guaranteed to echo the full request. Inspect the video file for actual dimensions, duration, and audio tracks; missing `resolution` metadata does not mean a 1080p request produced a lower-resolution video.

## Errors and retries

There are two separate failure paths: a rejected HTTP request and a failed generation reported by a successful query.

### HTTP request errors

Rejected requests use an error envelope. For example, querying a nonexistent task returns HTTP `404`:

```json theme={null}
{
  "error": {
    "code": "NotFound",
    "type": "NotFound",
    "message": "Task not found",
    "param": ""
  }
}
```

| HTTP status | Common `error.code` / `error.type` | Action |
| - | - | - |
| `400` | `InvalidParameter` / `BadRequest` | Correct JSON, unknown fields, types, enum values, or input combinations before resubmitting. |
| `401` | `AuthenticationError` / `Unauthorized` | Check the Bearer API key. |
| `403` | `AccessDenied` / `Forbidden` | Confirm account/model access and billing conditions, including available balance. |
| `404` | `NotFound` / `NotFound` | Check the task ID and account; the task is missing or not accessible to this account. |
| `429` | `TooManyRequests` / `TooManyRequests` | Distinguish rate limiting from exhausted key quota using the response details. Quota exhaustion may return `KEY_QUOTA_EXHAUSTED`. |
| `5xx` | `InternalServiceError` / `InternalServerError` | Creation or querying is temporarily unavailable. Preserve tracing information; query existing tasks before considering new submissions. |

### Generation failure

A successful HTTP `200` query can report a failed task. Handle this separately from an HTTP request error:

```json theme={null}
{
  "id": "example-task-id",
  "model": "seedance-2-0",
  "status": "failed",
  "draft": false,
  "error": {
    "code": "GenerationFailed",
    "message": "Example generation failure reason"
  }
}
```

Do not base application logic solely on fixed `message` text. Request errors and HTTP `200` responses with `status: "failed"` are different failure paths.

### When to retry

If a POST times out, disconnects, or has an ambiguous result, do not immediately resubmit automatically: the task may already have been accepted. This interface has no public request-idempotency field. Preserve the request time and tracing information, and verify the task outcome to avoid duplicate generation.

For query network errors or temporary service errors, retry the **same task ID** after a delay. When contacting support, provide the task ID, request time, response `X-Request-ID` header if present, and redacted request parameters. Never include your API key.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.