# MiniMax H3 Max

MiniMax H3 Max is the faster-generation variant of MiniMax H3. One request makes the picture and the sound together: a 5–15 second clip at 480P or 768P with its own dialogue, ambience and effects. The request body is MiniMax's official format with the model ID `minimax-h3-max`. Send it, keep the returned task ID, and read the finished video from the task. Frames and references go in as URLs.

## Model IDs

| Model ID         | Inputs                                                         | Resolutions | Length       |
| ---------------- | -------------------------------------------------------------- | ----------- | ------------ |
| `minimax-h3-max` | text, first and last frame, reference images, videos and audio | 480P, 768P  | 5–15 seconds |

See the [model page](https://seedrouter.ai/models/minimax-h3-max#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",
    "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",
        "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',
    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",
      "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`                                                                                                    |
| `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`, `last_frame` or `reference_image` |
| `video_url` | `{"type": "video_url", "video_url": {"url": "https://..."}, "role": "reference_video"}` | `reference_video`                                |
| `audio_url` | `{"type": "audio_url", "audio_url": {"url": "https://..."}, "role": "reference_audio"}` | `reference_audio`                                |

A single image without a `role` is the first frame. With more than one image, every image needs a `role`.

## Modes

The items in `content` decide the mode; there is no mode field.

| Mode               | `content` holds                                                                                     | `ratio`                                                      |
| ------------------ | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
| Text to video      | one `text` item                                                                                     | required, not `adaptive`                                     |
| Image to video     | `text` plus a `first_frame` and/or a `last_frame` image                                             | any value is treated as `adaptive`: the image sets the shape |
| Reference to video | `text` plus any mix of up to 9 `reference_image`, 3 `reference_video` and 3 `reference_audio` items | optional, default `adaptive`                                 |

Frames and references cannot be combined in one request. The official documentation lists last-frame-only input, but also contains a conflicting requirement to pair it with a first frame. That case has not been verified on SeedRouter. Use both frames when an ending image is required.

```json
{
  "model": "minimax-h3-max",
  "content": [
    {"type": "text", "text": "The person in the photo speaks to camera: Follow the wind. Voice follows the reference audio."},
    {"type": "image_url", "image_url": {"url": "https://example.com/person.jpg"}, "role": "reference_image"},
    {"type": "audio_url", "audio_url": {"url": "https://example.com/voice.mp3"}, "role": "reference_audio"}
  ],
  "resolution": "768P",
  "duration": 6
}
```

## Media inputs

Every image, video and audio item is a public HTTP(S) URL. Base64 data URIs and `mm_file://` IDs are not accepted: upload the file to your own storage and pass its URL.

| Input | Format                           | Limits                                                                                                              |
| ----- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| Image | JPG, JPEG, PNG, WebP, HEIC, HEIF | 30 MB or less; each side 256–5760 px; width / height 0.4–2.5                                                        |
| Video | MP4, MOV (H.264 or H.265)        | 50 MB or less; 2–15 seconds each, 15 seconds in total; each side 256–5760 px; width / height 0.4–2.5; 23.976–60 fps |
| Audio | WAV, MP3                         | 15 MB or less; 2–15 seconds each, 15 seconds in total                                                               |

Reference videos are measured when the request is accepted; one whose length cannot be read is refused with nothing charged. Other limits are checked before generation, and a request that breaks one fails without charge.

## 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

Check the [model pricing section](https://seedrouter.ai/models/minimax-h3-max#pricing) for current rates. MiniMax H3 Max prices generated output seconds and reference-video seconds separately, by the output resolution. The first two images are free; every later image adds a charge.

```text
output seconds = reported generated seconds
input seconds  = reported reference-video seconds
extra images   = max(0, reported input image count − 2)
cost = output seconds × output rate
     + input seconds × reference-video rate
     + extra images × image rate
```

Reference-video lengths are added together and rounded to the nearest whole second for final usage. Two 2.4-second clips therefore contribute five input seconds. Reference audio has no input charge. First and last frames count as images, so two frames alone add no image charge.

The Playground estimate rounds reference-video lengths up to cover the possible final charge. Final usage is priced at the rate captured for your request. If a complete usage report is unavailable, the accepted estimate is used. View charges in 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", "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",
  "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",
  "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 the shot and its sound together: subject, place, camera, light, dialogue and effects.
* Write dialogue into the prompt and attach a reference audio clip when the voice should follow it.
* Draft at `480P`, then select `768P` when you need more detail. A new render is a separate paid request.
* Use `extra: {"prompt_expansion_mode": "disabled"}` for an already complete prompt, or choose `balanced` / `quality` expansion.
* Use a first and a last frame to control where a shot starts and ends; use references to keep a product, a person or a motion.
* Add `no text, no logos` to keep invented marks out.

## Related

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

## Contract sources

Parameters follow [MiniMax’s video-generation documentation](https://platform.minimax.io/docs/api-reference/video-generation-v2-create). SeedRouter uses its own model ID and asynchronous task interface, URL-only media and hosted result delivery; callbacks and cancellation are unavailable. `content_filter` is a SeedRouter extension.
