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

# Create video

> Start a text-to-video generation job

Starts generating a video from a text prompt and returns the job straight away with `status: "queued"`. Generation takes minutes, so the response never contains the video: poll [Retrieve video](https://docs.inworld.ai/api-reference/videoAPI/retrieve-video.md) until the job finishes, then download the MP4 from `output.videos[0].url`.

Send an `Idempotency-Key` header so that a retry after a network error returns the original job instead of starting and billing a second one. Generate the key once per video and store it before the first attempt, so that retries and restarts of your program send the same value. See [retries and idempotency](https://docs.inworld.ai/router/video-generation.md#retries-and-idempotency). Your account needs a payment method on file. See the [Video generation guide](https://docs.inworld.ai/router/video-generation.md) for models, parameters, limits and billing.

## API reference

**Endpoint:** `POST https://api.inworld.ai/v1/videos`

### Authorization

- `Authorization` (string; required) — Your [authentication](https://docs.inworld.ai/api-reference/introduction.md) credentials. For Basic authentication, populate `Basic $INWORLD_API_KEY`.

### Request body

Content type: `application/json`

- `model` (enum<string>; required; options: "alibaba/wan-3.0", "minimax/minimax-h3") — The video model. See [models and parameters](https://docs.inworld.ai/router/video-generation.md#models-and-parameters).
- `prompt` (string; required) — What the video should show. Up to 2,000 characters for `alibaba/wan-3.0` and 7,000 for `minimax/minimax-h3`.
- `seconds` (integer) — Clip length in whole seconds. `alibaba/wan-3.0`: 2 to 30, default 5. `minimax/minimax-h3`: 5 to 15, default 6.
- `resolution` (string) — Output resolution, case-insensitive. `alibaba/wan-3.0`: `480p` (default), `720p` or `1080p`. `minimax/minimax-h3`: `768p` (default) or `2k`.
- `aspect_ratio` (string) — Frame shape, default `16:9`. `alibaba/wan-3.0`: `16:9`, `4:3`, `1:1`, `3:4` or `9:16`. `minimax/minimax-h3` also accepts `21:9`.

#### Request example

```json
{
  "model": "alibaba/wan-3.0",
  "prompt": "A red fox trots across a snowy meadow at sunrise, slow tracking shot, soft golden light",
  "seconds": 5,
  "resolution": "720p",
  "aspect_ratio": "16:9"
}
```

### Response

Status: `200`. Content type: `application/json`.

- `id` (string; required) — The job id.
- `object` (enum<string>; required; options: "video")
- `model` (string; required)
- `status` (enum<string>; required; options: "queued", "in_progress", "completed", "failed", "cancelled") — `queued`: accepted; waiting for or being submitted for generation, so cancellation may already be unavailable. `in_progress`: generating. `completed`: generation succeeded; download available until `expires_at`. `failed`: see `error`. `cancelled`: cancelled before generation started. The last three are terminal.
- `created_at` (integer; required) — When the job was created, in Unix seconds.
- `completed_at` (integer) — When the video finished, in Unix seconds. Present once `status` is `completed`.
- `expires_at` (integer) — Until when the video can be downloaded, in Unix seconds: 7 days after it finished. Present only when `status` is `completed`.
- `seconds` (integer; required) — The requested clip length, with the model's default filled in.
- `resolution` (string; required) — The requested resolution, with the model's default filled in.
- `aspect_ratio` (string; required) — The requested aspect ratio, with the model's default filled in.
- `operation` (string) — The job's [long-running operation](https://google.aip.dev/151). Poll it with `GET https://api.inworld.ai/lro/v1alpha/{operation}` as an alternative to retrieving the job. The operation reports progress and the outcome but never the download link. See [Poll the operation instead](https://docs.inworld.ai/router/video-generation.md#poll-the-operation-instead).
- `error` (object) — Why the job failed. Present only when `status` is `failed`.
  - `code` (enum<string>; options: "content_filtered", "invalid_request", "generation_failed", "generation_timeout") — `content_filtered`: the prompt or the generated video was blocked by the model provider's content policy. `invalid_request`: the model provider rejected the request. `generation_failed`: generation failed for another reason. `generation_timeout`: generation did not finish in time.
  - `message` (string)
- `output` (object) — The finished video. Returned only by [Retrieve video](https://docs.inworld.ai/api-reference/videoAPI/retrieve-video.md), only while `status` is `completed` and before `expires_at`.
  - `videos` (object[])
    - `index` (integer)
    - `content_type` (string)
    - `bytes` (integer) — File size in bytes.
    - `url` (string) — A signed HTTPS link to the MP4. Anyone with the link can download the file until `url_expires_at`, so treat it like a secret.
    - `url_expires_at` (integer) — When `url` stops working, in Unix seconds: up to an hour after the request, and never after the job's `expires_at`.

### Response examples

#### 200: default_response

```json
{
  "id": "video_8f14e45fceea167a5a36dedd4bea2543",
  "object": "video",
  "model": "alibaba/wan-3.0",
  "status": "queued",
  "created_at": 1790000000,
  "seconds": 5,
  "resolution": "720p",
  "aspect_ratio": "16:9",
  "operation": "workspaces/my-workspace/videoGenerationJobs/video_8f14e45fceea167a5a36dedd4bea2543/operations/1790000000000-a1b2c3"
}
```

#### 400: default_response

```json
{
  "error": {
    "message": "seconds must be an integer from 2 to 30",
    "type": "invalid_request_error",
    "code": "string",
    "param": "seconds"
  }
}
```

#### 401: default_response

```json
"Unauthorized"
```

#### 403: default_response

```json
"Forbidden"
```

#### 409: default_response

```json
{
  "error": {
    "message": "seconds must be an integer from 2 to 30",
    "type": "invalid_request_error",
    "code": "string",
    "param": "seconds"
  }
}
```

#### 429: default_response

```json
{
  "error": {
    "message": "seconds must be an integer from 2 to 30",
    "type": "invalid_request_error",
    "code": "string",
    "param": "seconds"
  }
}
```

#### 500: default_response

```json
{
  "error": {
    "message": "seconds must be an integer from 2 to 30",
    "type": "invalid_request_error",
    "code": "string",
    "param": "seconds"
  }
}
```

#### 503: default_response

```json
{
  "error": {
    "message": "seconds must be an integer from 2 to 30",
    "type": "invalid_request_error",
    "code": "string",
    "param": "seconds"
  }
}
```

### Code examples

#### cURL

```bash
# Generate one key per video and reuse it for every retry of that video.
# export VIDEO_REQUEST_KEY="$(uuidgen)"
curl -X POST 'https://api.inworld.ai/v1/videos' \
  -H "Authorization: Basic $INWORLD_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $VIDEO_REQUEST_KEY" \
  -d '{
    "model": "alibaba/wan-3.0",
    "prompt": "A red fox trots across a snowy meadow at sunrise, slow tracking shot, soft golden light",
    "seconds": 5,
    "resolution": "720p",
    "aspect_ratio": "16:9"
  }'
```

#### Python

```python
import os
import requests

# One key per video, kept outside the process so a rerun after a timeout
# returns the same job instead of starting a second one.
request_key = os.environ["VIDEO_REQUEST_KEY"]

response = requests.post(
    "https://api.inworld.ai/v1/videos",
    headers={
        "Authorization": f"Basic {os.environ['INWORLD_API_KEY']}",
        "Idempotency-Key": request_key,
    },
    json={
        "model": "alibaba/wan-3.0",
        "prompt": "A red fox trots across a snowy meadow at sunrise, slow tracking shot, soft golden light",
        "seconds": 5,
        "resolution": "720p",
        "aspect_ratio": "16:9",
    },
    timeout=30,
)
response.raise_for_status()
video = response.json()
print(video["id"], video["status"])
```

#### JavaScript

```javascript
const options = {method: 'POST', headers: {"Authorization":"<api_key>","Content-Type":"application/json"}, body: JSON.stringify({
  "model": "alibaba/wan-3.0",
  "prompt": "A red fox trots across a snowy meadow at sunrise, slow tracking shot, soft golden light",
  "seconds": 5,
  "resolution": "720p",
  "aspect_ratio": "16:9"
})};

fetch('https://api.inworld.ai/v1/videos', options)
  .then(response => response.json())
  .then(response => console.log(response))
  .catch(err => console.error(err));
```

#### Node

```javascript
// One key per video, kept outside the process so a rerun after a timeout
// returns the same job instead of starting a second one.
const requestKey = process.env.VIDEO_REQUEST_KEY;

const response = await fetch('https://api.inworld.ai/v1/videos', {
  method: 'POST',
  headers: {
    Authorization: `Basic ${process.env.INWORLD_API_KEY}`,
    'Content-Type': 'application/json',
    'Idempotency-Key': requestKey,
  },
  body: JSON.stringify({
    model: 'alibaba/wan-3.0',
    prompt: 'A red fox trots across a snowy meadow at sunrise, slow tracking shot, soft golden light',
    seconds: 5,
    resolution: '720p',
    aspect_ratio: '16:9',
  }),
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
const video = await response.json();
console.log(video.id, video.status);
```
