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

# Grok Imagine Video Generation API Reference

> Grok Imagine video generation API reference and live testing — text-to-video / image-to-video, async three-step flow, 1–15 seconds, 480p / 720p / 1080p, priced the same as xAI per second

> [!WARNING]
>
> **🔒 Requires the `GrokOfficial` group, granted on application**: Grok Imagine Video is not in the `Default` group; access must be requested before you can call it (including the Playground on this page). Without access, or with a pay-per-request Token, every call returns `503`. See [Grok Imagine Video Overview - Group Setup](/en/api-capabilities/grok-imagine-video/overview#group-setup).

> [!NOTE]
>
> The interactive Playground on the right lets you test the endpoint directly. Enter your API Key in **Authorization** (format: `Bearer sk-xxx`), pick the `model`, fill in `prompt` / `seconds` / `size`, and send; add `input_reference` for image-to-video. **The Playground only performs step 1 (submit)** — once you have the task `id`, poll and download as shown below.

> [!WARNING]
>
> **⚠️ The three most common pitfalls**
>
> 1. **Without `size` / `seconds` the default is 480p and 8 seconds**, and that is what you are billed for.
> 2. **`grok-imagine-video` has no 1080p**: `1920x1080` returns 400; use `-1.5` or `-1.5-lite` for 1080p.
> 3. **Moderation blocks are billed**: a blocked task still reports `completed`, but carries `error.code: "moderation_blocked"` and has no video.

> [!WARNING]
>
> **Three-step async flow — this page covers step 1 (submit) only**
>
> * **Step 1 (this page)**: `POST /v1/videos` → returns the task `id` + `status: "queued"`
> * **Step 2**: poll `GET /v1/videos/{id}` until `status` is `"completed"` or `"failed"`
> * **Step 3**: download the MP4 from `GET /v1/videos/{id}/content`
>
> Submitting returns within seconds and does **not** wait for the video to finish.

## Code Examples

### Python (text-to-video, all three steps)

```python theme={null}
import os, time, requests

BASE = "https://api.apiyi.com/v1"
H = {"Authorization": f"Bearer {os.environ['APIYI_API_KEY']}"}

# Step 1: submit
task = requests.post(f"{BASE}/videos", headers=H, json={
    "model": "grok-imagine-video-1.5",
    "prompt": "A lighthouse on the coast at dusk, slow push-in, waves lapping the rocks, seabirds calling, cinematic lighting",
    "seconds": "5",
    "size": "1280x720",      # 720p landscape; the default without it is 480p
}, timeout=60).json()
vid = task["id"]

# Step 2: poll
for _ in range(75):           # about 10 minutes at most
    time.sleep(8)
    job = requests.get(f"{BASE}/videos/{vid}", headers=H, timeout=60).json()
    if job["status"] in ("completed", "failed"):
        break

if job["status"] != "completed" or job.get("error"):
    # moderation_blocked: blocked by moderation, no video, but billed
    raise RuntimeError(job.get("error"))

# Step 3: download and store right away
mp4 = requests.get(f"{BASE}/videos/{vid}/content", headers=H, timeout=300)
open("out.mp4", "wb").write(mp4.content)
```

### Python (image-to-video, base64 input image)

```python theme={null}
import base64, os, requests

H = {"Authorization": f"Bearer {os.environ['APIYI_API_KEY']}"}
img = base64.b64encode(open("first-frame.jpg", "rb").read()).decode()

task = requests.post("https://api.apiyi.com/v1/videos", headers=H, json={
    "model": "grok-imagine-video",
    "prompt": "the cat slowly turns its head and blinks",
    "seconds": "3",
    "input_reference": f"data:image/jpeg;base64,{img}",   # a public image URL works too
}, timeout=60).json()
print(task["id"])  # then poll and download as above; the output frame follows the input image
```

### cURL

```bash theme={null}
# Step 1: submit text-to-video (1.5-lite, 2 seconds at 480p)
curl -X POST "https://api.apiyi.com/v1/videos" \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-imagine-video-1.5-lite",
    "prompt": "a red paper boat drifting on a calm lake, gentle ripples",
    "seconds": "2",
    "size": "854x480"
  }'

# Image-to-video can also upload a local file with multipart
curl -X POST "https://api.apiyi.com/v1/videos" \
  -H "Authorization: Bearer sk-your-api-key" \
  -F "model=grok-imagine-video" \
  -F "prompt=the cat slowly turns its head" \
  -F "seconds=2" \
  -F "input_reference=@first-frame.jpg"

# Step 2: check status
curl "https://api.apiyi.com/v1/videos/task_xxxxxxxx" \
  -H "Authorization: Bearer sk-your-api-key"

# Step 3: download the video
curl -o out.mp4 "https://api.apiyi.com/v1/videos/task_xxxxxxxx/content" \
  -H "Authorization: Bearer sk-your-api-key"
```

### Node.js (fetch)

```javascript theme={null}
import fs from 'node:fs';

const BASE = 'https://api.apiyi.com/v1';
const H = { 'Authorization': `Bearer ${process.env.APIYI_API_KEY}`, 'Content-Type': 'application/json' };

const task = await fetch(`${BASE}/videos`, {
    method: 'POST',
    headers: H,
    body: JSON.stringify({
        model: 'grok-imagine-video-1.5-lite',
        prompt: 'A serene Japanese garden with cherry blossoms drifting, koi pond, golden hour',
        seconds: '4',
        size: '720x1280'          // 720p portrait
    })
}).then(r => r.json());

let job;
for (let i = 0; i < 75; i++) {
    await new Promise(r => setTimeout(r, 8000));
    job = await fetch(`${BASE}/videos/${task.id}`, { headers: H }).then(r => r.json());
    if (['completed', 'failed'].includes(job.status)) break;
}
if (job.status !== 'completed' || job.error) throw new Error(JSON.stringify(job.error));

const mp4 = await fetch(`${BASE}/videos/${task.id}/content`, { headers: H });
fs.writeFileSync('out.mp4', Buffer.from(await mp4.arrayBuffer()));
```

## Parameter Quick Reference

| Parameter | Type | Required | Default | Notes |
| - | - | - | - | - |
| `model` | string | ✅ | — | `grok-imagine-video` / `grok-imagine-video-1.5` / `grok-imagine-video-1.5-lite` |
| `prompt` | string | Required for text-to-video | — | Scene, subject, action, camera, lighting; for image-to-video it describes the motion |
| `seconds` | string / integer | ❌ | `8` | 1–15 seconds; out of range returns 400 |
| `size` | string | ❌ | 480p | `WIDTHxHEIGHT` pixels; the shorter side sets resolution and the aspect ratio snaps to the nearest; `480p` / `720p` / `1080p` also work |
| `resolution` / `aspect_ratio` | string | ❌ | — | xAI's native fields; they win when sent together with `size` |
| `input_reference` | string / file | ❌ | — | Input image for image-to-video: public URL, data URI, or multipart file |

**Price per second** (same as xAI):

| Model | 480p | 720p | 1080p | Input image |
| - | - | - | - | - |
| `grok-imagine-video` | \$0.05 | \$0.07 | Not supported | \$0.002 / image |
| `grok-imagine-video-1.5` | \$0.08 | \$0.14 | \$0.25 | \$0.01 / image |
| `grok-imagine-video-1.5-lite` | \$0.02 | \$0.03 | \$0.14 | \$0.01 / image |

> [!NOTE]
>
> Model pricing is aligned with the official sites and may change when they do; the table above is for reference only, and the **Model Pricing** tab in the top navigation is authoritative: [Model Pricing](/en/models/index).

## Response Examples

**Submit (step 1)**:

```json theme={null}
{
  "id": "task_xxxxxxxxxxxxxxxx",
  "object": "video",
  "model": "grok-imagine-video-1.5-lite",
  "status": "queued",
  "progress": 0,
  "created_at": 1792320668
}
```

**Done (step 2 poll result)**:

```json theme={null}
{
  "id": "task_xxxxxxxxxxxxxxxx",
  "object": "video",
  "model": "grok-imagine-video-1.5-lite",
  "status": "completed",
  "progress": 100,
  "seconds": "2",
  "created_at": 1792320668,
  "completed_at": 1792320715
}
```

**Blocked by moderation**: `status` is still `completed`, but there is an extra `error` field and no video to download:

```json theme={null}
{
  "id": "task_xxxxxxxxxxxxxxxx",
  "status": "completed",
  "error": { "code": "moderation_blocked", "message": "..." }
}
```

## Related Docs

* [Grok Imagine Video Overview](/en/api-capabilities/grok-imagine-video/overview) - pricing, group application, parameters, FAQ
* [Grok Imagine Official Images](/en/api-capabilities/grok-imagine-image-official/overview) - image generation in the same group


## OpenAPI

````yaml api-reference/grok-imagine-video-openapi-en.yaml POST /v1/videos
openapi: 3.1.0
info:
  title: Grok Imagine Video Generation API
  description: >
    xAI Grok Imagine video official channel — an OpenAI Videos-compatible async
    task API for text-to-video and image-to-video, priced the same as xAI per
    second.


    - Three models: `grok-imagine-video` (480p \$0.05/s, 720p \$0.07/s),
    `grok-imagine-video-1.5` (\$0.08 / \$0.14 / \$0.25 per second),
    `grok-imagine-video-1.5-lite` (\$0.02 / \$0.03 / \$0.14 per second)

    - `seconds` 1–15, **default 8**; without `size` the **default is 480p**

    - Image-to-video: add `input_reference` (image URL or base64 data URI); each
    input image costs an extra \$0.002 (video) / \$0.01 (1.5 / lite)

    - **Async task endpoint**: this call only submits; poll `GET
    /v1/videos/{id}` and download from `GET /v1/videos/{id}/content`

    - A task blocked by moderation still reports `completed` with `error.code:
    moderation_blocked`, has no video, and is billed


    **Authentication**: add `Authorization: Bearer YOUR_API_KEY` to the request
    headers


    **API Key setup**: the Token group must include **`GrokOfficial`** (granted
    on application) with billing mode **Pay-as-you-go Priority** or
    **Pay-as-you-go**; without access, or with a pay-per-request Token, calls
    return 503


    **Get an API Key**: create a Token in the [APIYI
    console](https://api.apiyi.com/token)
  version: 1.0.0
servers:
  - url: https://api.apiyi.com
    description: Primary endpoint
security:
  - bearerAuth: []
paths:
  /v1/videos:
    post:
      tags:
        - Video Generation
      summary: Submit a video generation task (text-to-video / image-to-video)
      description: >
        Submit a Grok Imagine video generation task (async); returns the task
        `id` and `status: "queued"`.


        - Required: `model`; text-to-video also needs `prompt`

        - Optional: `seconds` (default 8), `size` (default 480p),
        `input_reference` (makes it image-to-video)

        - **The response has no video**; poll `GET /v1/videos/{id}` until
        `status: "completed"`, then download the MP4 from `GET
        /v1/videos/{id}/content`

        - Typical time: about 20–25 s for 2 s at 480p, 35–50 s for
        image-to-video, about 110 s for 1080p on 1.5
      operationId: generateGrokImagineVideo
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GrokImagineVideoRequest'
            example:
              model: grok-imagine-video-1.5-lite
              prompt: >-
                a red paper boat drifting on a calm lake, gentle ripples, soft
                morning light
              seconds: '2'
              size: 854x480
      responses:
        '200':
          description: Task submitted; returns the task id and queued status
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GrokImagineVideoTask'
        '400':
          description: >-
            Invalid parameters (resolution not supported by the model, seconds
            outside 1–15, missing prompt, etc.); `message` explains
        '401':
          description: Unauthorized - invalid API Key
        '429':
          description: Rate limit hit or insufficient balance
        '503':
          description: >-
            Token lacks the `GrokOfficial` group, or uses pay-per-request
            billing
      security:
        - bearerAuth: []
components:
  schemas:
    GrokImagineVideoRequest:
      type: object
      required:
        - model
      properties:
        model:
          type: string
          description: >
            Model ID (billed per second × resolution rate):

            - `grok-imagine-video` — 480p \$0.05/s, 720p \$0.07/s, **no 1080p**

            - `grok-imagine-video-1.5` — 480p \$0.08, 720p \$0.14, 1080p \$0.25
            per second

            - `grok-imagine-video-1.5-lite` — 480p \$0.02, 720p \$0.03, 1080p
            \$0.14 per second
          enum:
            - grok-imagine-video
            - grok-imagine-video-1.5
            - grok-imagine-video-1.5-lite
          default: grok-imagine-video-1.5-lite
        prompt:
          type: string
          description: >-
            Prompt: scene + subject + action + camera + lighting. Required for
            text-to-video; for image-to-video it describes motion and camera
          example: >-
            a red paper boat drifting on a calm lake, gentle ripples, soft
            morning light
        seconds:
          type: string
          description: >
            Duration from 1 to 15 seconds, as a string or a number; **default
            8**. Out-of-range values return 400. Cost scales with seconds — use
            1–2 seconds while testing.
          example: '2'
        size:
          type: string
          description: >
            Output size in `WIDTHxHEIGHT` pixels: the **shorter side** sets the
            resolution (≥1080 is 1080p, ≥720 is 720p, otherwise 480p) and the
            aspect ratio snaps to the nearest supported one.

            You can also pass `480p` / `720p` / `1080p` directly. **Without it,
            the default is 480p.**


            - `854x480` — 480p landscape (measured 848×480)

            - `1280x720` / `720x1280` — 720p landscape / portrait

            - `1920x1080` / `1080x1920` — 1080p (1.5 / 1.5-lite only)
          enum:
            - 854x480
            - 480x854
            - 1280x720
            - 720x1280
            - 1920x1080
            - 1080x1920
          default: 854x480
        input_reference:
          type: string
          description: >
            Input image for image-to-video: a public image URL or a
            `data:image/jpeg;base64,...` data URI. Passing it makes the job
            image-to-video, and the output frame follows the input image.

            Each input image costs an extra \$0.002 (`grok-imagine-video`) or
            \$0.01 (1.5 / 1.5-lite).
          example: https://example.com/first-frame.jpg
    GrokImagineVideoTask:
      type: object
      properties:
        id:
          type: string
          description: Task ID for polling and download
          example: task_xxxxxxxxxxxxxxxx
        object:
          type: string
          description: Always `video`
          example: video
        model:
          type: string
          example: grok-imagine-video-1.5-lite
        status:
          type: string
          description: >
            Task status:

            - `queued` — submitted, waiting

            - `in_progress` — generating

            - `completed` — done, download from `/v1/videos/{id}/content`; with
            `error.code: moderation_blocked` it was blocked and has no video

            - `failed` — failed
          enum:
            - queued
            - in_progress
            - completed
            - failed
          example: queued
        progress:
          type: integer
          description: >-
            Progress 0–100, coarse-grained; not suitable for a precise progress
            bar
          example: 0
        seconds:
          type: string
          description: Video duration, returned once done
        created_at:
          type: integer
          description: Task creation Unix timestamp (seconds)
        completed_at:
          type: integer
          description: Task completion Unix timestamp (seconds), returned once done
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API Key from the APIYI console (Token group must include GrokOfficial)

````

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