# Grok Imagine Video 1.5

Grok Imagine Video 1.5 is xAI's video model. One request makes a 6–15 second clip with sound from a prompt, or from a prompt plus one image, at 480p or 720p in 16:9, 9:16 or 1:1. Send the request, keep the returned task ID, and read the finished video from the task. Images go in as URLs.

## Model IDs

| Model ID                 | Inputs          | Resolutions    | Length       |
| ------------------------ | --------------- | -------------- | ------------ |
| `grok-imagine-video-1-5` | text, one image | `480p`, `720p` | 6–15 seconds |

See the [model page](https://seedrouter.ai/models/grok-imagine-video-1-5#pricing) for current prices.

## Quick example

```bash
curl https://api.seedrouter.ai/v1/videos/generations \
  -H "Authorization: Bearer $SEEDROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-imagine-video-1-5",
    "prompt": "A red paper boat drifting on a calm pond at sunrise, soft mist, slow push-in, birdsong. No text, no logos.",
    "resolution": "480p",
    "duration": 8,
    "aspect_ratio": "16:9"
  }'
```

```python
import os
import requests

response = requests.post(
    "https://api.seedrouter.ai/v1/videos/generations",
    headers={"Authorization": f"Bearer {os.environ['SEEDROUTER_API_KEY']}"},
    json={
        "model": "grok-imagine-video-1-5",
        "prompt": "A red paper boat drifting on a calm pond at sunrise, soft mist, slow push-in, birdsong. No text, no logos.",
        "resolution": "480p",
        "duration": 8,
        "aspect_ratio": "16:9",
    },
    timeout=60,
)
response.raise_for_status()
task_id = response.json()["id"]
```

```javascript
const response = await fetch('https://api.seedrouter.ai/v1/videos/generations', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.SEEDROUTER_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    model: 'grok-imagine-video-1-5',
    prompt: 'A red paper boat drifting on a calm pond at sunrise, soft mist, slow push-in, birdsong. No text, no logos.',
    resolution: '480p',
    duration: 8,
    aspect_ratio: '16:9',
  }),
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const { id: taskId } = await response.json();
```

```go
package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "os"
    "strings"
    "time"
)

func main() {
    body := strings.NewReader(`{
      "model": "grok-imagine-video-1-5",
      "prompt": "A red paper boat drifting on a calm pond at sunrise, soft mist, slow push-in, birdsong. No text, no logos.",
      "resolution": "480p",
      "duration": 8,
      "aspect_ratio": "16:9"
    }`)
    req, err := http.NewRequest("POST", "https://api.seedrouter.ai/v1/videos/generations", body)
    if err != nil { panic(err) }
    req.Header.Set("Authorization", "Bearer " + os.Getenv("SEEDROUTER_API_KEY"))
    req.Header.Set("Content-Type", "application/json")
    client := &http.Client{Timeout: 60 * time.Second}
    res, err := client.Do(req)
    if err != nil { panic(err) }
    defer res.Body.Close()
    if res.StatusCode != http.StatusOK { panic(res.Status) }
    var task struct { ID string `json:"id"` }
    if err := json.NewDecoder(res.Body).Decode(&task); err != nil { panic(err) }
    fmt.Println(task.ID)
}
```

## Endpoint

```text
POST https://api.seedrouter.ai/v1/videos/generations
```

| Header        | Value                 |
| ------------- | --------------------- |
| Authorization | `Bearer YOUR_API_KEY` |
| Content-Type  | `application/json`    |

The response is a task (`{"id": "task_...", "status": "processing"}`), not the finished video. Poll `GET /v1/tasks/{task_id}` for the result. Keep API keys in server-side code.

## Parameters

| Field          | Type     | Default  | Notes                                                                                  |
| -------------- | -------- | -------- | -------------------------------------------------------------------------------------- |
| `model`        | string   | required | `grok-imagine-video-1-5`                                                               |
| `prompt`       | string   | required | Up to 10,000 characters. Required with an image too.                                   |
| `image_urls`   | URL list | none     | At most one image. With it the clip is image to video; without it, text to video.      |
| `resolution`   | enum     | `480p`   | `480p` or `720p`.                                                                      |
| `duration`     | integer  | `8`      | 6–15 seconds.                                                                          |
| `aspect_ratio` | enum     | `16:9`   | `16:9`, `9:16` or `1:1`. With an image, the clip follows the image's shape.            |
| `audio`        | boolean  | `true`   | Accepted for compatibility. Every clip has sound: `false` does not make a silent clip. |
| `fallback`     | object   | none     | `{"enabled": true}` or `{"enabled": false}`. Accepted for compatibility and ignored.   |

The schema is strict: unknown fields are rejected rather than ignored. `callback_url` is not available; poll the task instead.

## Image to video

Pass one image in `image_urls` and describe what happens next in `prompt`. The clip starts from the image and keeps its shape, so a portrait image gives a portrait clip whatever `aspect_ratio` says.

```json
{
  "model": "grok-imagine-video-1-5",
  "prompt": "The subject slowly turns toward the camera, soft natural light, gentle breeze, quiet room tone.",
  "image_urls": ["https://example.com/start.png"],
  "resolution": "720p",
  "duration": 6
}
```

## Media inputs

The image is a public HTTP(S) URL. Base64 data URIs are not accepted: upload the file to your own storage and pass its URL. Use a JPG or PNG image of 10 MB or less.

## Pricing dimensions

Check the [model pricing section](https://seedrouter.ai/models/grok-imagine-video-1-5#pricing) for current rates. Grok Imagine Video 1.5 is billed per second of video, at a rate set by the resolution:

```text
cost = duration × rate per second for the resolution
```

Text to video and image to video cost the same. The duration is known when the request is accepted, so the amount reserved is the amount charged. View final charges in your account usage history. Failed tasks are not charged.

## Output schema

Submission returns the task:

```json
{"id": "task_...", "model": "grok-imagine-video-1-5", "status": "processing", "created_at": 1789689600}
```

### Get the task

```text
GET https://api.seedrouter.ai/v1/tasks/{task_id}
```

Poll every 10–20 seconds until `status` is `completed` or `failed`. A network timeout while polling does not mean generation failed: keep the task ID and resume checking it. Do not create another task to check progress.

### Completed task

```json
{
  "id": "task_...",
  "model": "grok-imagine-video-1-5",
  "status": "completed",
  "created_at": 1789689600,
  "finished_at": 1789689720,
  "output": {
    "video_url": "https://static.seedrouter.ai/media/tasks/task_example/0.mp4"
  }
}
```

In our tests 8-second `720p` clips came back as MP4 (H.264) with an AAC audio track at 1280 × 720 for `16:9`, 720 × 1280 for `9:16` and 720 × 720 for `1:1`, 111–133 seconds after submission. `480p` clips came back in 45–84 seconds.

## Errors

Requests rejected before a task is created return an HTTP error with an `error` object and are not charged. A task that fails after acceptance returns HTTP 200 when queried, with `status: "failed"` and an `error` object.

See the [shared error catalog](https://seedrouter.ai/docs/api/errors) for codes, HTTP statuses, and retry guidance.

```json
{
  "id": "task_...",
  "model": "grok-imagine-video-1-5",
  "status": "failed",
  "error": {
    "code": 60001,
    "message": "The request was rejected by the content policy. Please revise the prompt or input images."
  }
}
```

If submission itself times out, check your tasks before submitting again: the first request may have been accepted.

## Tips

* Describe subject, place, camera move and light, and name the sounds you want; the audio is generated together with the picture.
* Draft at `480p`, then render the final shot at `720p` with the same request.
* For vertical video, send `aspect_ratio: "9:16"`, or a portrait image.
* Add `no text, no logos` to keep invented marks out.

## Related

* [Grok Imagine Video 1.5 Playground and pricing](https://seedrouter.ai/models/grok-imagine-video-1-5)
* [Kling 3.0 Turbo API reference](https://seedrouter.ai/docs/kling-3-0-turbo)
* [Download OpenAPI](https://seedrouter.ai/docs/grok-imagine-video-1-5.openapi.json)
* [Copyable Markdown](https://seedrouter.ai/docs/grok-imagine-video-1-5.md)
