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

# Video generation APIs

> Choose CometAPI video routes for Seedance, HappyHorse, Sora 2, Veo 3, Wan, xAI, Vidu, Omni, Kling, and Runway workflows.

Use CometAPI video model docs by choosing the provider workflow that matches your job type. Most video endpoints create asynchronous tasks, so save the task ID and use polling to retrieve results. Add callbacks only when the model-specific page documents callback support.

## Choose a video API

<CardGroup cols={2}>
  <Card title="Create a Seedance video" icon="sparkles" href="/api/video/seedance/create">
    Create Seedance video tasks.
  </Card>

  <Card title="Create a HappyHorse video" icon="sparkles" href="/api/video/happyhorse/create">
    Create HappyHorse text-to-video jobs.
  </Card>

  <Card title="Create a Sora 2 video" icon="film" href="/api/video/sora-2/create">
    Create Sora 2 video jobs.
  </Card>

  <Card title="Retrieve a Sora 2 video" icon="refresh" href="/api/video/sora-2/retrieve">
    Query Sora video jobs.
  </Card>

  <Card title="Create a Veo 3 video" icon="film" href="/api/video/veo3/create">
    Create Veo video jobs.
  </Card>

  <Card title="Create a Wan video" icon="sparkles" href="/api/video/wan/create">
    Create Wan text-to-video jobs.
  </Card>

  <Card title="Create an xAI video" icon="film" href="/api/video/xai/video-generation">
    Generate xAI video jobs.
  </Card>

  <Card title="Create a Vidu video" icon="sparkles" href="/api/video/vidu/create">
    Create Vidu text-to-video jobs.
  </Card>

  <Card title="Create an Omni video (Beta)" icon="sparkles" href="/api/video/omni/create">
    Create beta Omni video jobs.
  </Card>

  <Card title="Create a Kling text-to-video task" icon="film" href="/api/video/kling/text-to-video">
    Generate Kling videos from text prompts.
  </Card>

  <Card title="Create a Runway image-to-video task" icon="film" href="/api/video/runway/official-format/runway-images-raw-video">
    Generate Runway videos from images.
  </Card>
</CardGroup>

## Create and poll a video task

Use a video-capable model ID from the [Models page](/overview/models) or the [model directory](https://www.cometapi.com/models/). The examples below create a video task with `POST /v1/videos`, then poll the returned task ID until the task reaches a terminal state.

<Note>
  These examples use the placeholder `your-video-model-id`. Replace it with an available video model ID from the [Models page](/overview/models) or [model directory](https://www.cometapi.com/models/) before you run the request.
</Note>

<Tip>
  Open [Create a Seedance video](/api/video/seedance/create) and [Retrieve a Seedance video](/api/video/seedance/query) to use the API playgrounds and endpoint schemas.
</Tip>

<CodeGroup>
  ```python Python theme={null}
  import os
  import time
  import requests

  headers = {"Authorization": "Bearer " + os.environ["COMETAPI_KEY"]}

  create_response = requests.post(
      "https://api.cometapi.com/v1/videos",
      headers=headers,
      data={
          "model": "your-video-model-id",
          "prompt": "A calm camera move across a desk with a paper airplane",
      },
      timeout=30,
  )
  create_response.raise_for_status()
  task = create_response.json()
  task_id = task["id"]

  terminal_statuses = {"completed", "failed", "error"}

  while True:
      poll_response = requests.get(
          f"https://api.cometapi.com/v1/videos/{task_id}",
          headers=headers,
          timeout=30,
      )
      poll_response.raise_for_status()
      result = poll_response.json()
      print(result["status"], result.get("progress"))

      if result["status"] in terminal_statuses:
          print(result.get("video_url"))
          break

      time.sleep(10)
  ```

  ```javascript Node.js theme={null}
  const form = new FormData();
  form.append("model", "your-video-model-id");
  form.append("prompt", "A calm camera move across a desk with a paper airplane");

  const createResponse = await fetch("https://api.cometapi.com/v1/videos", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.COMETAPI_KEY}`,
    },
    body: form,
  });

  if (!createResponse.ok) {
    throw new Error(await createResponse.text());
  }

  const task = await createResponse.json();
  const terminalStatuses = new Set(["completed", "failed", "error"]);

  while (true) {
    const pollResponse = await fetch(
      `https://api.cometapi.com/v1/videos/${task.id}`,
      {
        headers: {
          Authorization: `Bearer ${process.env.COMETAPI_KEY}`,
        },
      },
    );

    if (!pollResponse.ok) {
      throw new Error(await pollResponse.text());
    }

    const result = await pollResponse.json();
    console.log(result.status, result.progress);

    if (terminalStatuses.has(result.status)) {
      console.log(result.video_url);
      break;
    }

    await new Promise((resolve) => setTimeout(resolve, 10_000));
  }
  ```

  ```bash cURL theme={null}
  curl https://api.cometapi.com/v1/videos \
    -H "Authorization: Bearer $COMETAPI_KEY" \
    -F "model=your-video-model-id" \
    -F "prompt=A calm camera move across a desk with a paper airplane"

  curl https://api.cometapi.com/v1/videos/task_example \
    -H "Authorization: Bearer $COMETAPI_KEY"
  ```
</CodeGroup>

## Response examples

A successful create response can look like this. Store the task ID before polling:

```json theme={null}
{
  "id": "task_example",
  "task_id": "task_example",
  "object": "video",
  "model": "your-video-model-id",
  "status": "queued",
  "progress": 0,
  "created_at": 1779872000
}
```

A successful polling response can look like this. Completed responses can include `video_url`; some provider formats use model-specific result fields or the video content route when that route is documented:

```json theme={null}
{
  "id": "task_example",
  "object": "video",
  "model": "your-video-model-id",
  "status": "completed",
  "progress": 100,
  "completed_at": 1779872300,
  "video_url": "https://example.com/generated-video.mp4"
}
```

## Example model records

<Info>
  This example model catalog response shows the `/api/models` envelope and one video model record shape. It is not a complete model list.
</Info>

```bash cURL theme={null}
curl https://api.cometapi.com/api/models
```

```json theme={null}
{
  "success": true,
  "page": 1,
  "page_size": 20,
  "total": 302,
  "data": [
    {
      "created": 1767529753,
      "id": "your-video-model-id",
      "code": "your-video-model-id",
      "provider": "ExampleProvider",
      "provider_code": "example",
      "name": "Example video model",
      "model_type": "video",
      "features": [
        "text-to-video"
      ],
      "endpoints": "{\n  \"seedance\": {\n    \"path\": \"/v1/videos\",\n    \"method\": \"POST\"\n  }\n}",
      "pricing": {
        "currency": "USD / M Tokens",
        "input": null,
        "output": null,
        "per_request": null,
        "per_second": 0.024
      }
    }
  ]
}
```

## Common errors

<AccordionGroup>
  <Accordion title="Missing task ID">
    Store the ID from the create response before returning from your job handler.
  </Accordion>

  <Accordion title="Polling too fast">
    Add delay and backoff between status checks.
  </Accordion>

  <Accordion title="Unsupported duration or size">
    Use the duration and resolution fields documented for the selected video endpoint.
  </Accordion>

  <Accordion title="Missing video_url">
    Treat `video_url` as optional and fall back to model-specific result fields or the content route when available.
  </Accordion>

  <Accordion title="Callback not received">
    Use polling as the source of truth and verify that your callback URL accepts POST requests.
  </Accordion>
</AccordionGroup>

## Error codes and retry strategy

<AccordionGroup>
  <Accordion title="400">
    Do not retry until the prompt, files, duration, or size fields are fixed.
  </Accordion>

  <Accordion title="401">
    Do not retry until the API key is present and valid.
  </Accordion>

  <Accordion title="404">
    Check the task ID, base URL, path, and model ID before retrying.
  </Accordion>

  <Accordion title="413">
    Reduce upload size before retrying.
  </Accordion>

  <Accordion title="429">
    Retry with exponential backoff and reduce create or polling concurrency.
  </Accordion>

  <Accordion title="500 or 503">
    Retry task creation with backoff; keep polling existing tasks unless the task reaches a terminal error.
  </Accordion>
</AccordionGroup>

<Tip>
  For implementation patterns, see [Error codes and retry strategy](/guides/error-codes-and-retry-strategy), [Rate limits and concurrency](/guides/rate-limits-and-concurrency), and [Webhook and polling for video generation](/guides/webhook-and-polling-for-video-generation).
</Tip>

## Pricing and model directory

<CardGroup cols={3}>
  <Card title="Models page" icon="list" href="/overview/models">
    Read how CometAPI exposes model IDs in the docs.
  </Card>

  <Card title="Model directory" icon="puzzle-piece" href="https://www.cometapi.com/models/">
    Browse model availability and capabilities.
  </Card>

  <Card title="Pricing" icon="tag" href="https://www.cometapi.com/pricing/">
    Check pricing before you call a model.
  </Card>
</CardGroup>
