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

# Create Video

> Creates a video generation task

## Overview

For coding agents, discover the current recommended video shortlist first with `GET /v1/models?recommended_for=video`, then send the selected `model` explicitly to this endpoint.

Video generation is asynchronous. You submit a request, receive a canonical async task ID and `poll_url`, then poll for the result.

### Polling behavior

For the most reliable polling behavior, follow the exact `poll_url` returned by the create request.

If a create response returns `poll_url`, call that exact URL. When it points to `/v1/tasks/{id}`, treat that as the canonical fixed status endpoint.

The async task identifier may surface as `id` or `task_id`. Treat them as the same task identity.

### Model and media behavior

Audio output is model-dependent. In TokenLab, Veo 3 and Seedance requests default to audio-on when `output_audio` is omitted. When a model supports audio control, use `output_audio` to explicitly toggle it. The aliases `outputAudio` and `generate_audio` are accepted for compatibility and must match `output_audio` when more than one is provided.

For production integrations, prefer publicly reachable `https` URLs for images, videos, and audio. Inline `data:` URLs remain supported for compatible models, but large base64 payloads are harder to retry, inspect, and debug.

## Request Body

<ParamField body="model" type="string" default="veo3.1">
  Video model ID. Use the model IDs shown by TokenLab such as `veo3.1`, `wan-2.7`, `happyhorse-1.0`, `viduq3`, `pixverse-v6`, or `kling-3.0-video`; choose text-to-video, image-to-video, reference-to-video, or other variants with `operation`. See the [Video Generation Guide](/guides/video-generation) and [Models API](/api-reference/models/list-models) for current public video model capabilities.
</ParamField>

<Note>
  **PixVerse**

  * Model: `pixverse-c1`, `pixverse-v6`, `pixverse-v5.6`
  * Operations: `text-to-video`, `image-to-video`, `start-end-to-video`, `reference-to-video`
  * Audio selector: `output_audio`, default `false`

  On TokenLab, the PixVerse models above do not accept `operation=video-extension`.

  **HappyHorse**

  * Model: `happyhorse-1.0`
  * Operations: `text-to-video`, `image-to-video`, `reference-to-video`, `video-to-video`
  * Audio selector: Do not send `output_audio`
</Note>

<ParamField body="prompt" type="string" required>
  Text description of the video to generate. Required for most public video models.
</ParamField>

<ParamField body="operation" type="string">
  Video operation to run. Supported values include `text-to-video`, `image-to-video`, `reference-to-video`, `start-end-to-video`, `video-to-video`, `video-extension`, `audio-to-video`, and `motion-control`. TokenLab can infer the operation from the supplied inputs, but explicit `operation` is recommended for production reliability.
</ParamField>

<ParamField body="image_url" type="string">
  Publicly accessible URL of the starting image for image-to-video generation. For best cross-model compatibility, prefer `image_url`.
</ParamField>

<ParamField body="image" type="string">
  Inline image as a data URL (for example, `data:image/jpeg;base64,...`). Supported by compatible models, but `image_url` provides the broadest compatibility across public video models.
</ParamField>

<ParamField body="reference_images" type="array">
  Reference image inputs for models that support dedicated reference conditioning. The supported count is model-dependent. For `seedance-2.0` and `seedance-2.0-fast`, TokenLab currently supports up to 9 reference images plus up to 3 reference videos and 3 reference audios. For model selection, 4K boundaries, and Mini notes, see the [Seedance 2.0 video models guide](/guides/seedance-2-video). Public `https` URLs are recommended; compatible models also accept inline `data:` URLs. For `grok-imagine-video`, reference-to-video accepts up to 7 image references and `duration` is capped at 10 seconds. `grok-imagine-video-1.5-preview` is image-to-video only and does not accept reference images.
</ParamField>

<ParamField body="material_asset_id" type="string">
  TokenLab Seedance material asset ID returned by [Create Material Asset](/api-reference/video/create-material-asset) or automatic image preparation. Use it after the asset is `ACTIVE` with Seedance models that can use the TokenLab material library.
</ParamField>

<ParamField body="material_asset_ids" type="array">
  Multiple TokenLab Seedance material asset IDs. They share the same Seedance image-reference limit as `reference_images`; the selected model must be able to use the TokenLab material library.
</ParamField>

<Info>
  When the selected Seedance model can use the TokenLab material library, TokenLab prepares image fields (`image`, `image_url`, `image_urls`, `reference_images`, `start_image`, `end_image`) as reusable materials before generation. If preparation is not complete within 60 seconds, the API returns `409 seedance_material_preparing` with `auto_material_asset_ids`; retry after those material assets become `ACTIVE`. If the selected model cannot use the material library, ordinary image inputs continue on the regular image path and explicit material IDs return a material availability error.
</Info>

<ParamField body="reference_image_type" type="string">
  Optional reference role for models that distinguish between `asset` and `style` references.
</ParamField>

<ParamField body="kling_elements" type="array">
  Kling 3.0 element reference definitions. Only supported by `kling-3.0-video` for image-conditioned requests. Define 1-3 elements; each element has `name`, optional `description`, and `element_input_urls` with 2-4 image URLs. Reference an element in `prompt` as `@name`. Do not combine `kling_elements` with `output_audio=true`; omit `output_audio` or set it to `false` for element-reference requests.
</ParamField>

<ParamField body="video_url" type="string">
  Publicly accessible URL of the source video. Required for video-url based `video-to-video` flows and for `motion-control`; some derivative flows use `task_id` instead.
</ParamField>

<ParamField body="video_urls" type="array">
  Additional reference video inputs for models that support multimodal reference conditioning. The supported count is model-dependent. For `seedance-2.0` and `seedance-2.0-fast`, TokenLab currently supports up to 3 reference videos.
</ParamField>

<ParamField body="audio_url" type="string">
  Publicly accessible audio URL for models that support `audio-to-video`.
</ParamField>

<ParamField body="audio_urls" type="array">
  Additional reference audio inputs for models that support multimodal reference conditioning. The supported count is model-dependent. For `seedance-2.0` and `seedance-2.0-fast`, TokenLab currently supports up to 3 reference audios.
</ParamField>

<ParamField body="task_id" type="string">
  Task identifier used by some continuation, extension, or derivative flows.
</ParamField>

<ParamField body="extend_at" type="integer">
  Model-specific extension start offset used by some `video-extension` flows.
</ParamField>

<ParamField body="extend_times" type="string">
  Model-specific extension multiplier or repeat count used by some `video-extension` flows.
</ParamField>

<ParamField body="duration" type="integer">
  Generated output video duration in seconds. For Seedance 1.5/2.0 models, omitting this field uses `5`; sending `-1` lets the model choose within its supported duration range, and billing is estimated conservatively until the task finishes.
</ParamField>

<ParamField body="seconds" type="integer">
  Compatibility alias for `duration`. If both `seconds` and `duration` are sent, they must be identical. For Seedance, `seconds=-1` has the same auto-duration meaning as `duration=-1`.
</ParamField>

<ParamField body="aspect_ratio" type="string">
  Canonical aspect ratio, for example `adaptive`, `16:9`, `9:16`, `1:1`, `4:3`, `3:4`, or `21:9`. Seedance defaults to `adaptive` when omitted.
</ParamField>

<ParamField body="resolution" type="string">
  Model-dependent output resolution. Seedance defaults to `720p`; `seedance-2.0` supports `480p`, `720p`, `1080p`, and `4k`, while `seedance-2.0-fast` and `seedance-2.0-mini` are limited to `480p` and `720p`.
</ParamField>

<ParamField body="output_audio" type="boolean">
  Canonical model-dependent audio output toggle. Veo 3 and Seedance default to `true` when omitted. `kling-3.0-video` accepts this selector for non-element-reference requests and defaults to silent output when omitted. Do not combine `output_audio=true` with `kling_elements`.
</ParamField>

<ParamField body="draft" type="boolean">
  Seedance 1.5 Pro draft workflow flag. Use `draft=true` with Seedance models that support draft tasks. Do not send it together with `draft_task_id`.
</ParamField>

<ParamField body="draft_task_id" type="string">
  Seedance 1.5 Pro draft promotion task ID. Send a previous draft task ID to create the final video; this is not a generic video field.
</ParamField>

<ParamField body="ratio" type="string">
  Compatibility alias for `aspect_ratio`. If both `ratio` and `aspect_ratio` are sent, they must be identical.
</ParamField>

<ParamField body="generate_audio" type="boolean">
  Compatibility alias for `output_audio`. If `generate_audio`, `output_audio`, and `outputAudio` appear together, all values must match.
</ParamField>

<ParamField body="execution_expires_after" type="integer">
  Optional execution expiry in seconds for compatible video models. Seedance defaults to `172800` seconds when omitted.
</ParamField>

<ParamField body="priority" type="integer">
  Optional task priority from `0` to `9` for compatible video models. Do not combine `priority` with `service_tier=flex`.
</ParamField>

<ParamField body="safety_identifier" type="string">
  Optional end-user safety identifier for compatible video models. If omitted for Seedance, TokenLab uses `user` when provided.
</ParamField>

<ParamField body="service_tier" type="string">
  `default` is accepted as a compatibility no-op for Seedance 2.0 models. `flex` is only allowed when the selected model supports it.
</ParamField>

<ParamField body="frames" type="integer">
  Optional frame count for compatible video models. Seedance 2.0 models and Seedance 1.5 Pro do not support this field.
</ParamField>

<ParamField body="camera_fixed" type="boolean">
  Optional fixed-camera selector for compatible video models. Seedance 2.0 models do not support this field.
</ParamField>

<ParamField body="fps" type="integer">
  Frames per second (1-120) for models that expose FPS control.
</ParamField>

<ParamField body="negative_prompt" type="string">
  What to avoid in the generated video.
</ParamField>

<ParamField body="seed" type="integer">
  Random seed for reproducible generation. Seedance uses `-1` for a random seed when omitted.
</ParamField>

<ParamField body="cfg_scale" type="number">
  Prompt adherence strength (0-20) for models that expose CFG-style control.
</ParamField>

<ParamField body="motion_strength" type="number">
  Motion intensity (0-1) for models that expose it.
</ParamField>

<ParamField body="start_image" type="string">
  URL or compatible image input for the first frame in `start-end-to-video`.
</ParamField>

<ParamField body="end_image" type="string">
  URL or compatible image input for the last frame in `start-end-to-video`.
</ParamField>

<ParamField body="size" type="string">
  Model-specific size tier for compatible video models.
</ParamField>

<ParamField body="watermark" type="boolean">
  Optional watermark toggle for models that expose it. Seedance defaults to `false` when omitted.
</ParamField>

<ParamField body="effect_type" type="string">
  Model-specific effect selector for specialized editing flows.
</ParamField>

<ParamField body="user" type="string">
  A unique identifier for the end-user. For Seedance, TokenLab also uses this value as `safety_identifier` when that field is omitted.
</ParamField>

## Compatibility Notes

* Canonical public fields remain snake\_case: `aspect_ratio`, `output_audio`, `reference_images`, and `reference_image_type`.
* For compatibility, TokenLab also accepts `ratio`, `generate_audio`, `outputAudio`, `seconds`, `referenceImages`, and `referenceImageType`.
* If canonical and alias fields are both sent, their values must match; conflicting aliases are rejected before the task is created.
* If `operation` is omitted, TokenLab infers it from the supplied inputs. For production traffic, explicit `operation` is still recommended.

## Media Input Best Practices

* Prefer publicly reachable `https` URLs over inline base64 for `image_url`, `reference_images`, `video_url`, and `audio_url`.
* Avoid mixing inline base64 and remote URLs in the same request when possible; using one representation per request is easier to reason about and debug.
* Keep remote media URLs valid long enough to cover retries and asynchronous task creation.

## Seedance Parameters

For Seedance 1.5/2.0 models, the unified endpoint follows TokenLab field names while accepting the compatible aliases `seconds`, `ratio`, and `generate_audio`. Omitted Seedance selectors use these defaults: `duration=5`, `resolution=720p`, `aspect_ratio=adaptive`, `output_audio=true`, `watermark=false`, `return_last_frame=false`, `execution_expires_after=172800`, `priority=0`, and `seed=-1`.

`duration=-1` or `seconds=-1` lets Seedance choose the output duration within the model-supported range. TokenLab estimates cost conservatively before the task finishes, then settles from the completed task usage when available. `service_tier=default` is accepted for Seedance 2.0 as a compatibility no-op; `service_tier=flex`, `frames`, and `camera_fixed` are rejected where the selected model does not support them.

### Seedance Example

```bash cURL theme={null}
curl -X POST "https://api.tokenlab.sh/v1/videos/generations" \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedance-2.0",
    "prompt": "A sleek product reveal with cinematic camera movement",
    "operation": "text-to-video",
    "duration": -1,
    "aspect_ratio": "adaptive",
    "resolution": "720p",
    "output_audio": true
  }'
```

## Response

<ResponseField name="id" type="string">
  Canonical async task identifier. Treat this as the same identity as `task_id` when both are present.
</ResponseField>

<ResponseField name="task_id" type="string">
  Canonical async task identifier for polling. This is the same task identity used by async status endpoints.
</ResponseField>

<ResponseField name="poll_url" type="string">
  Preferred polling URL for this task. Use this exact path when checking status.
</ResponseField>

<ResponseField name="billing_transaction_id" type="string">
  TokenLab billing transaction ID when settlement already completed. This is the dashboard/accounting transaction identifier and is separate from the async `id` / `task_id`.
</ResponseField>

<ResponseField name="status" type="string">
  Initial status: `pending`.
</ResponseField>

<ResponseField name="created" type="integer">
  Unix timestamp when the task was created.
</ResponseField>

<ResponseField name="model" type="string">
  Model used.
</ResponseField>

<ResponseField name="video_url" type="string">
  Direct video URL when the result is already available.
</ResponseField>

<ResponseField name="video" type="object">
  Single video payload with `url`, `duration`, `width`, and `height` when available.
</ResponseField>

<ResponseField name="videos" type="array">
  Multiple video payloads when the task returns more than one output.
</ResponseField>

<ResponseField name="error" type="string">
  Error message or structured error object when the task fails.
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.tokenlab.sh/v1/videos/generations" \
    -H "Authorization: Bearer sk-your-api-key" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "veo3.1",
      "prompt": "A cat walking through a garden, cinematic lighting",
      "operation": "text-to-video",
      "duration": 4,
      "aspect_ratio": "16:9"
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.tokenlab.sh/v1/videos/generations",
      headers={
          "Authorization": "Bearer sk-your-api-key",
          "Content-Type": "application/json"
      },
      json={
          "model": "veo3.1",
          "prompt": "A cat walking through a garden, cinematic lighting",
          "operation": "text-to-video",
          "duration": 4,
          "aspect_ratio": "16:9"
      }
  )

  data = response.json()
  task_id = data["task_id"]
  print(f"Poll URL: {data['poll_url']}")
  print(f"Task ID: {task_id}")
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.tokenlab.sh/v1/videos/generations', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer sk-your-api-key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      model: 'veo3.1',
      prompt: 'A cat walking through a garden, cinematic lighting',
      operation: 'text-to-video',
      duration: 4,
      aspect_ratio: '16:9'
    })
  });

  const data = await response.json();
  console.log(`Poll URL: ${data.poll_url}`);
  console.log(`Task ID: ${data.task_id}`);
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={null}
  {
    "id": "ldtask_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "task_id": "ldtask_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "poll_url": "/v1/tasks/ldtask_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "status": "pending",
    "model": "veo3.1",
    "created": 1706000000
  }
  ```
</ResponseExample>

## Image to Video

```python theme={null}
response = requests.post(
    "https://api.tokenlab.sh/v1/videos/generations",
    headers={"Authorization": "Bearer sk-your-api-key"},
    json={
        "model": "hailuo-2.3-standard",
        "prompt": "The scene begins from the provided image and adds gentle natural motion.",
        "operation": "image-to-video",
        "image_url": "https://example.com/image.jpg",
        "duration": 6,
        "aspect_ratio": "16:9"
    }
)
```

## Kling 3.0 Elements

Use `kling_elements` with `kling-3.0-video` when you need element references. Provide an image-conditioned request (`image_url`, `image_urls`, `start_image`, or `end_image`) and reference each element in the prompt with `@name`. Do not combine `kling_elements` with `output_audio=true`; omit `output_audio` or set it to `false` for element-reference requests.

```python theme={null}
response = requests.post("https://api.tokenlab.sh/v1/videos/generations",
    headers=headers,
    json={
        "model": "kling-3.0-video",
        "prompt": "Place @hero_bag on a studio turntable with soft product lighting.",
        "operation": "image-to-video",
        "image_url": "https://example.com/studio-start.png",
        "duration": 5,
        "resolution": "720p",
        "kling_elements": [
            {
                "name": "hero_bag",
                "description": "black leather handbag",
                "element_input_urls": [
                    "https://example.com/bag-front.png",
                    "https://example.com/bag-side.png"
                ]
            }
        ]
    }
)
```

## Reference to Video

Use `operation=reference-to-video` when the model supports dedicated reference conditioning. In TokenLab requests, image references use `reference_images`, while multimodal reference videos and audios use `video_urls` and `audio_urls`. For `seedance-2.0` and `seedance-2.0-fast`, TokenLab currently supports up to 9 reference images plus up to 3 reference videos and 3 reference audios. For model selection, 4K boundaries, and Mini notes, see the [Seedance 2.0 video models guide](/guides/seedance-2-video). `duration` controls generated output length only; it does not set a separate limit for reference video input duration. For `grok-imagine-video`, reference-to-video accepts up to 7 image references (`reference_images` or `image_urls`) and `duration` is capped at 10 seconds. Do not combine reference images with `image_url` / `image` first-frame inputs. `grok-imagine-video-1.5-preview` is image-to-video only.

```python theme={null}
response = requests.post(
    "https://api.tokenlab.sh/v1/videos/generations",
    headers={"Authorization": "Bearer sk-your-api-key"},
    json={
        "model": "veo3.1",
        "prompt": "Keep the same subject identity, palette, and framing while adding subtle natural motion.",
        "operation": "reference-to-video",
        "reference_images": [
            "https://example.com/ref-a.jpg",
            "https://example.com/ref-b.jpg"
        ],
        "reference_image_type": "asset",
        "duration": 8,
        "resolution": "720p",
        "aspect_ratio": "9:16"
    }
)
```

## Keyframe Control

Use `start_image` and `end_image` to control the first and last frames:

```python theme={null}
response = requests.post(
    "https://api.tokenlab.sh/v1/videos/generations",
    headers={"Authorization": "Bearer sk-your-api-key"},
    json={
        "model": "viduq2-pro",
        "prompt": "Smooth transition from day to night",
        "operation": "start-end-to-video",
        "start_image": "https://example.com/day.jpg",
        "end_image": "https://example.com/night.jpg",
        "duration": 5,
        "resolution": "720p",
        "aspect_ratio": "16:9"
    }
)
```

## Video to Video

For `grok-imagine-video` video-to-video, send a public HTTPS `.mp4` URL in `video_url`. TokenLab translates it to xAI's REST `video.url` body. You may set `resolution` to `480p` or `720p`; `duration` and `aspect_ratio` are not accepted for that edit flow.

Use `operation=video-to-video` when the model accepts an existing video as the primary input.

```python theme={null}
response = requests.post(
    "https://api.tokenlab.sh/v1/videos/generations",
    headers={"Authorization": "Bearer sk-your-api-key"},
    json={
        "model": "grok-imagine-video",
        "operation": "video-to-video",
        "video_url": "https://example.com/source.mp4",
        "prompt": "Enhance the clip while preserving the original motion.",
        "resolution": "720p"
    }
)
```

## Motion Control

Use `operation=motion-control` when the model expects both a subject image and a motion reference video. TokenLab maps the public `image_url` + `video_url` request shape to the motion-control request format for that model.

```python theme={null}
response = requests.post(
    "https://api.tokenlab.sh/v1/videos/generations",
    headers={"Authorization": "Bearer sk-your-api-key"},
    json={
        "model": "kling-3.0-motion-control",
        "operation": "motion-control",
        "prompt": "Keep the subject identity stable while following the motion reference.",
        "image_url": "https://example.com/subject.png",
        "video_url": "https://example.com/motion.mp4",
        "resolution": "720p"
    }
)
```

## Model Discovery

Public video inventory and supported operations change over time. Use the [Models API](/api-reference/models/list-models) to check current support before wiring a model-specific flow:

```bash theme={null}
curl "https://api.tokenlab.sh/v1/models?recommended_for=video" \
  -H "Authorization: Bearer sk-your-api-key"

curl "https://api.tokenlab.sh/v1/models/veo3.1" \
  -H "Authorization: Bearer sk-your-api-key"
```

Read the model detail response before relying on model-specific operations or fields. Operations such as `audio-to-video` and `video-extension` are model-specific; confirm current availability there instead of relying on static examples in this page.
