# MiniMax H3 Max Turbo

MiniMax H3 Max Turbo generates short videos from text or frame images. Use model ID `minimax-h3-max-turbo`, keep the returned task ID, and poll for the finished video. This page describes the native content-array interface offered on SeedRouter.

## Model IDs

| Model ID               | Inputs                                 | Resolutions | Length       |
| ---------------------- | -------------------------------------- | ----------- | ------------ |
| `minimax-h3-max-turbo` | text, first frame, optional last frame | 480P, 768P  | 5–15 seconds |

See the [model page](https://seedrouter.ai/models/minimax-h3-max-turbo#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": "minimax-h3-max-turbo",
    "content": [
      {"type": "text", "text": "A small sailboat glides across a calm turquoise bay at sunrise, seagulls in the distance, the sound of water and wind. No text, no logos."}
    ],
    "resolution": "768P",
    "duration": 5,
    "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": "minimax-h3-max-turbo",
        "content": [
            {"type": "text", "text": "A small sailboat glides across a calm turquoise bay at sunrise, seagulls in the distance, the sound of water and wind. No text, no logos."}
        ],
        "resolution": "768P",
        "duration": 5,
        "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: 'minimax-h3-max-turbo',
    content: [
      { type: 'text', text: 'A small sailboat glides across a calm turquoise bay at sunrise, seagulls in the distance, the sound of water and wind. No text, no logos.' },
    ],
    resolution: '768P',
    duration: 5,
    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": "minimax-h3-max-turbo",
      "content": [
        {"type": "text", "text": "A small sailboat glides across a calm turquoise bay at sunrise, seagulls in the distance, the sound of water and wind. No text, no logos."}
      ],
      "resolution": "768P",
      "duration": 5,
      "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   | `minimax-h3-max-turbo`                                                                                              |
| `content`                     | array   | required   | The prompt and any media, as items described below. Exactly one non-empty `text` item.                              |
| `resolution`                  | enum    | required   | `480P` or `768P`.                                                                                                   |
| `duration`                    | integer | required   | Any integer from 5 to 15 seconds.                                                                                   |
| `ratio`                       | enum    | by input   | `adaptive`, `21:9`, `16:9`, `4:3`, `1:1`, `3:4`, `9:16`. Required for text alone, where `adaptive` is not accepted. |
| `extra`                       | object  | omitted    | Optional prompt expansion settings.                                                                                 |
| `extra.prompt_expansion_mode` | enum    | `balanced` | `disabled`, `balanced`, or `quality`. Omitting the object or property preserves the model default.                  |
| `content_filter`              | boolean | `true`     | SeedRouter's content filter, described below. Not sent to the model.                                                |

The schema is strict: unknown fields are rejected rather than ignored. `callback_url` is not available; poll the task instead. `extra` is an optional strict object containing only `prompt_expansion_mode`. All fields reject `null`; omit optional fields instead.

## Content items

| `type`      | Item                                                                          | `role`                        |
| ----------- | ----------------------------------------------------------------------------- | ----------------------------- |
| `text`      | `{"type":"text","text":"..."}`, up to 7,000 characters                        | none                          |
| `image_url` | `{"type":"image_url","image_url":{"url":"https://..."},"role":"first_frame"}` | `first_frame` or `last_frame` |

Exactly one non-empty text item is required. A single image without a role is treated as the first frame. At most one first frame and one last frame are accepted; a last frame requires a first frame. Reference images, video and audio are not supported.

## Modes

The items in `content` determine the mode; no `mode` field is sent.

| Mode           | Content                                         | Ratio                                                       |
| -------------- | ----------------------------------------------- | ----------------------------------------------------------- |
| Text to video  | one text item                                   | required; one of six concrete ratios, never `adaptive`      |
| Image to video | text and a first frame, optionally a last frame | follows the frame images; another valid value has no effect |

```json
{
  "model": "minimax-h3-max-turbo",
  "content": [
    {"type":"text","text":"Slowly move closer to the ceramic bowl. Keep the glaze and window lighting consistent."},
    {"type":"image_url","image_url":{"url":"https://example.com/first.jpg"},"role":"first_frame"},
    {"type":"image_url","image_url":{"url":"https://example.com/last.jpg"},"role":"last_frame"}
  ],
  "resolution": "480P",
  "duration": 5,
  "ratio": "adaptive",
  "extra": {"prompt_expansion_mode":"balanced"}
}
```

## Frame images

Use public HTTP(S) URLs without embedded credentials. Base64 and `mm_file://` IDs are not accepted. Images may be JPG, JPEG, PNG, WebP, HEIC or HEIF, no larger than 30 MB each, with each side 256–5760 pixels and width/height between 0.4 and 2.5. The input is checked before generation. Use matching compositions and aspect ratios for two frames.

## Content filter

`content_filter` is `true` unless you set it. With the filter on, the request, its text and its media, is moderated before generation. A flagged request fails with code `60001` and is not charged. Set `content_filter` to `false` to skip moderation; the website Playground always keeps it on.

## Pricing dimensions

The [model pricing section](https://seedrouter.ai/models/minimax-h3-max-turbo#pricing) shows current rates. Turbo has one charge: output seconds at the selected resolution. First and last frames and prompt expansion have no separate charge.

```text
cost = reported output seconds × output-second rate for the resolution
```

The estimate uses requested whole seconds. Final billing uses the completed task's output-second usage at the rate captured for the request. If valid usage is unavailable, the accepted estimate is used. Media-container duration can differ slightly from billed seconds. View charges in your account usage history; public task responses do not include fees. Failed tasks are not charged.

## Output schema

Submission returns the task:

```json
{"id": "task_...", "model": "minimax-h3-max-turbo", "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": "minimax-h3-max-turbo",
  "status": "completed",
  "created_at": 1789689600,
  "finished_at": 1789689740,
  "output": {
    "video_url": "https://static.seedrouter.ai/media/tasks/task_example/0.mp4",
    "resolution": "768P",
    "ratio": "16:9",
    "duration": 5
  }
}
```

`ratio` is the aspect ratio the clip was made at, including the one chosen for `adaptive`. The task contains the actual resolution, ratio and duration when reported. The JSON above illustrates the response shape; it is not a measured generation result.

## 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": "minimax-h3-max-turbo",
  "status": "failed",
  "error": {
    "code": 60001,
    "message": "the request was blocked by content moderation"
  }
}
```

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

## Tips

* Describe one subject, action, camera movement and lighting setup per shot.
* Use 480P for a draft and 768P for more output detail. Every new generation is a separate paid request.
* Supply a first frame to establish the opening composition; add a last frame only when you also supply the first.
* Use `extra.prompt_expansion_mode` to choose `disabled`, `balanced` or `quality`; omission preserves `balanced`.
* Review the full clip and its audio before publishing. A prompt does not guarantee precise product geometry or lettering.

## Related

* [MiniMax H3 Max Turbo Playground and pricing](https://seedrouter.ai/models/minimax-h3-max-turbo)
* [Download OpenAPI](https://seedrouter.ai/docs/minimax-h3-max-turbo.openapi.json)
* [Copyable Markdown](https://seedrouter.ai/docs/minimax-h3-max-turbo.md)

## Contract scope

This interface uses MiniMax's content-array request format with SeedRouter model IDs, asynchronous tasks, URL-only images and hosted result delivery. Callbacks and cancellation are unavailable. `content_filter` is a SeedRouter input check, not a MiniMax parameter.

The separate fal-hosted interface has different fields and limits; its `1080P`, fractional durations, target-audio and ordered-reference controls do not apply here. Seed and watermark controls are not accepted by this interface. See the [comparison guide](https://seedrouter.ai/blog/minimax-h3-max-turbo-vs-max) for the distinction and linked sources.
