# MiniMax H3

## Standard and Pro

Both channels support `content_filter`. It defaults to true and checks content before generation; API callers can set it to false. Upstream content restrictions may still apply.

`minimax-h3` is **Pro** and keeps its existing request format and behavior. The native-format sections below describe Pro. **Standard** uses `minimax-h3-standard` with its own flat JSON body at the same `/v1/videos/generations` endpoint. It is not a Max or Turbo version. The two variants do not automatically fall back to one another.

```json
{
  "model": "minimax-h3-standard",
  "prompt": "A sailboat crosses a quiet bay, with soft wind and waves.",
  "quality": "high",
  "content_filter": true,
  "duration_s": 5,
  "resolution": "768p",
  "aspect_ratio": "16:9"
}
```

Standard accepts these fields only. URLs must be public HTTP(S), without credentials; file uploads and base64 are not accepted.

| Field                   | Type      | Required / default | Values                                                        |
| ----------------------- | --------- | ------------------ | ------------------------------------------------------------- |
| `model`                 | string    | required           | `minimax-h3-standard`                                         |
| `prompt`                | string    | required           | non-empty; required in every mode                             |
| `quality`               | string    | required           | `low`, `high`; same price                                     |
| `duration_s`            | number    | 5                  | 5–15, including decimals                                      |
| `resolution`            | string    | `768p`             | `480p`, `768p`, `1080p`, `2k`, `4k`                           |
| `aspect_ratio`          | string    | `16:9`             | `16:9`, `9:16`, `1:1`, `4:3`, `3:4`, `21:9`                   |
| `seed`                  | integer   | random             | 0–9223372036854775807                                         |
| `watermark`             | boolean   | false              | true / false                                                  |
| `enhance`               | boolean   | true               | prompt rewriting; false preserves the prompt                  |
| `priority`              | integer   | 1000               | 1000 / 0                                                      |
| `content_filter`        | boolean   | true               | TokLab content check before generation; false skips the check |
| `first_frame_image_url` | string    | optional           | one image URL                                                 |
| `last_frame_image_url`  | string    | optional           | requires first frame                                          |
| `reference_image_url`   | string\[] | optional           | 1–4 image URLs                                                |
| `reference_video_url`   | string\[] | optional           | one video URL                                                 |

First/last frames cannot be combined with references. No media means text-to-video. Reference images and a reference video can be combined. Independent reference audio is not supported. Every output includes native audio. Low favors speed; High favors fidelity, with no claim that either matches Pro's quality.

Images: up to 30 MiB each; JPEG, PNG, WebP, GIF, BMP, TIFF, HEIC, HEIF or AVIF. There is no image dimension limit; large images may be resized before generation. Videos: up to 100 MiB, 0.5–600 seconds, readable video stream (including MP4, MOV and WebM), even width and height of at least 64 pixels.

Standard bills **ceil(duration\_s) × the live rate for the resolution**. Reference media, audio, quality and prompt rewriting add no fee. Failed tasks are not charged. Prices come from the [live pricing page](https://toklab.ai/pricing).

Creation and polling use the shared asynchronous protocol below. Successful output contains `video_url`, `resolution`, `ratio` and `duration`; `duration` reflects the requested duration. Fees, supplier identifiers and supplier URLs are not returned. An unknown submission outcome must not be retried automatically. For seeds above JavaScript's safe-integer limit, serialize the integer losslessly; do not round it through `Number`.

## Pro reference

MiniMax H3 (Hailuo 03) is MiniMax's multimodal video model. One request makes the picture and the sound together: a 4–15 second clip at 768P or 2K with its own dialogue, ambience and effects. The request body is MiniMax's official format with the model ID `minimax-h3`. 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` | text, first and last frame, reference images, videos and audio | 768P, 2K    | 4–15 seconds |

See the [pricing page](https://toklab.ai/pricing) for current prices.

## Quick example

```bash
curl https://api.toklab.ai/v1/videos/generations \
  -H "Authorization: Bearer $TOKLAB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "minimax-h3",
    "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.toklab.ai/v1/videos/generations",
    headers={"Authorization": f"Bearer {os.environ['TOKLAB_API_KEY']}"},
    json={
        "model": "minimax-h3",
        "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.toklab.ai/v1/videos/generations', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.TOKLAB_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    model: 'minimax-h3',
    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",
      "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.toklab.ai/v1/videos/generations", body)
    if err != nil { panic(err) }
    req.Header.Set("Authorization", "Bearer " + os.Getenv("TOKLAB_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.toklab.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`                                                                                                        |
| `content`        | array   | required | The prompt and any media, as items described below. Exactly one non-empty `text` item.                              |
| `resolution`     | enum    | required | `768P` or `2K`.                                                                                                     |
| `duration`       | integer | required | Any integer from 4 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. |
| `content_filter` | boolean | `true`   | TokLab'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` belongs to MiniMax-H3-Max and is not accepted for this model.

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

```json
{
  "model": "minimax-h3",
  "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": "2K",
  "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.

## Pricing dimensions

Check the [pricing page](https://toklab.ai/pricing) for current rates. MiniMax H3 is billed per second of video, at a rate set by the output resolution, plus input images beyond the first five:

```text
billed seconds = duration + ceil(Σ each reference video's seconds)
extra images   = max(0, number of images − 5)
cost = billed seconds × rate per second + extra images × rate per image
```

First frames, last frames and reference images all count as images. Reference audio is not billed. Both quantities are 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": "minimax-h3", "status": "processing", "created_at": 1789689600}
```

### Get the task

```text
GET https://api.toklab.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",
  "status": "completed",
  "created_at": 1789689600,
  "finished_at": 1789689740,
  "output": {
    "video_url": "https://cdn.example.com/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`. In our test, a 4-second 768P clip at `16:9` came back as MP4 (H.264) at 1344 × 768 and 24 fps, with a stereo AAC track at 32 kHz.

## 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://toklab.ai/docs/api/errors) for codes, HTTP statuses, and retry guidance.

```json
{
  "id": "task_...",
  "model": "minimax-h3",
  "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 `768P`, then render the final shot at `2K` with the same request.
* 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.

## Pricing

Every rate this model is billed at, read live from the price list billing uses. A tier applies when its condition matches, checked top to bottom.

### minimax-h3

| When | Output + reference video (per second) | Extra reference image (per image) |
| --- | --- | --- |
| Resolution: 2k | $0.11863 | $0.03575 after the first 5 |
| Otherwise | $0.07313 | $0.03575 after the first 5 |

### minimax-h3-standard

| When | Output video (per second) |
| --- | --- |
| Resolution: 4k | $0.07692 |
| Otherwise | $0.01539 |

## Related

* [MiniMax H3 pricing](https://toklab.ai/pricing)
* [Download OpenAPI](https://toklab.ai/docs/minimax-h3.openapi.json)
* [Copyable Markdown](https://toklab.ai/docs/minimax-h3.md)
