MiniMax H3 Video Generation
curl --request POST \
--url https://api.novita.ai/v3/minimax/v2/video_generation \
--header 'Authorization: <authorization>' \
--header 'Content-Type: <content-type>' \
--data '
{
"model": "<string>",
"content": [
{}
],
"content[].type": "<string>",
"content[].text": "<string>",
"content[].image_url.url": "<string>",
"content[].video_url.url": "<string>",
"content[].audio_url.url": "<string>",
"content[].role": "<string>",
"resolution": "<string>",
"duration": 123,
"ratio": "<string>",
"callback_url": "<string>"
}
'import requests
url = "https://api.novita.ai/v3/minimax/v2/video_generation"
payload = {
"model": "<string>",
"content": [{}],
"content[].type": "<string>",
"content[].text": "<string>",
"content[].image_url.url": "<string>",
"content[].video_url.url": "<string>",
"content[].audio_url.url": "<string>",
"content[].role": "<string>",
"resolution": "<string>",
"duration": 123,
"ratio": "<string>",
"callback_url": "<string>"
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "<content-type>"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': '<content-type>'},
body: JSON.stringify({
model: '<string>',
content: [{}],
'content[].type': '<string>',
'content[].text': '<string>',
'content[].image_url.url': '<string>',
'content[].video_url.url': '<string>',
'content[].audio_url.url': '<string>',
'content[].role': '<string>',
resolution: '<string>',
duration: 123,
ratio: '<string>',
callback_url: '<string>'
})
};
fetch('https://api.novita.ai/v3/minimax/v2/video_generation', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.novita.ai/v3/minimax/v2/video_generation",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'content' => [
[
]
],
'content[].type' => '<string>',
'content[].text' => '<string>',
'content[].image_url.url' => '<string>',
'content[].video_url.url' => '<string>',
'content[].audio_url.url' => '<string>',
'content[].role' => '<string>',
'resolution' => '<string>',
'duration' => 123,
'ratio' => '<string>',
'callback_url' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: <content-type>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.novita.ai/v3/minimax/v2/video_generation"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"content\": [\n {}\n ],\n \"content[].type\": \"<string>\",\n \"content[].text\": \"<string>\",\n \"content[].image_url.url\": \"<string>\",\n \"content[].video_url.url\": \"<string>\",\n \"content[].audio_url.url\": \"<string>\",\n \"content[].role\": \"<string>\",\n \"resolution\": \"<string>\",\n \"duration\": 123,\n \"ratio\": \"<string>\",\n \"callback_url\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "<content-type>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.novita.ai/v3/minimax/v2/video_generation")
.header("Authorization", "<authorization>")
.header("Content-Type", "<content-type>")
.body("{\n \"model\": \"<string>\",\n \"content\": [\n {}\n ],\n \"content[].type\": \"<string>\",\n \"content[].text\": \"<string>\",\n \"content[].image_url.url\": \"<string>\",\n \"content[].video_url.url\": \"<string>\",\n \"content[].audio_url.url\": \"<string>\",\n \"content[].role\": \"<string>\",\n \"resolution\": \"<string>\",\n \"duration\": 123,\n \"ratio\": \"<string>\",\n \"callback_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.novita.ai/v3/minimax/v2/video_generation")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = '<content-type>'
request.body = "{\n \"model\": \"<string>\",\n \"content\": [\n {}\n ],\n \"content[].type\": \"<string>\",\n \"content[].text\": \"<string>\",\n \"content[].image_url.url\": \"<string>\",\n \"content[].video_url.url\": \"<string>\",\n \"content[].audio_url.url\": \"<string>\",\n \"content[].role\": \"<string>\",\n \"resolution\": \"<string>\",\n \"duration\": 123,\n \"ratio\": \"<string>\",\n \"callback_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyVideo Generator
MiniMax H3 Video Generation
Create and query MiniMax H3 asynchronous video generation tasks
POST
/
v3
/
minimax
/
v2
/
video_generation
MiniMax H3 Video Generation
curl --request POST \
--url https://api.novita.ai/v3/minimax/v2/video_generation \
--header 'Authorization: <authorization>' \
--header 'Content-Type: <content-type>' \
--data '
{
"model": "<string>",
"content": [
{}
],
"content[].type": "<string>",
"content[].text": "<string>",
"content[].image_url.url": "<string>",
"content[].video_url.url": "<string>",
"content[].audio_url.url": "<string>",
"content[].role": "<string>",
"resolution": "<string>",
"duration": 123,
"ratio": "<string>",
"callback_url": "<string>"
}
'import requests
url = "https://api.novita.ai/v3/minimax/v2/video_generation"
payload = {
"model": "<string>",
"content": [{}],
"content[].type": "<string>",
"content[].text": "<string>",
"content[].image_url.url": "<string>",
"content[].video_url.url": "<string>",
"content[].audio_url.url": "<string>",
"content[].role": "<string>",
"resolution": "<string>",
"duration": 123,
"ratio": "<string>",
"callback_url": "<string>"
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "<content-type>"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': '<content-type>'},
body: JSON.stringify({
model: '<string>',
content: [{}],
'content[].type': '<string>',
'content[].text': '<string>',
'content[].image_url.url': '<string>',
'content[].video_url.url': '<string>',
'content[].audio_url.url': '<string>',
'content[].role': '<string>',
resolution: '<string>',
duration: 123,
ratio: '<string>',
callback_url: '<string>'
})
};
fetch('https://api.novita.ai/v3/minimax/v2/video_generation', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.novita.ai/v3/minimax/v2/video_generation",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'model' => '<string>',
'content' => [
[
]
],
'content[].type' => '<string>',
'content[].text' => '<string>',
'content[].image_url.url' => '<string>',
'content[].video_url.url' => '<string>',
'content[].audio_url.url' => '<string>',
'content[].role' => '<string>',
'resolution' => '<string>',
'duration' => 123,
'ratio' => '<string>',
'callback_url' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: <content-type>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.novita.ai/v3/minimax/v2/video_generation"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"content\": [\n {}\n ],\n \"content[].type\": \"<string>\",\n \"content[].text\": \"<string>\",\n \"content[].image_url.url\": \"<string>\",\n \"content[].video_url.url\": \"<string>\",\n \"content[].audio_url.url\": \"<string>\",\n \"content[].role\": \"<string>\",\n \"resolution\": \"<string>\",\n \"duration\": 123,\n \"ratio\": \"<string>\",\n \"callback_url\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "<content-type>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.novita.ai/v3/minimax/v2/video_generation")
.header("Authorization", "<authorization>")
.header("Content-Type", "<content-type>")
.body("{\n \"model\": \"<string>\",\n \"content\": [\n {}\n ],\n \"content[].type\": \"<string>\",\n \"content[].text\": \"<string>\",\n \"content[].image_url.url\": \"<string>\",\n \"content[].video_url.url\": \"<string>\",\n \"content[].audio_url.url\": \"<string>\",\n \"content[].role\": \"<string>\",\n \"resolution\": \"<string>\",\n \"duration\": 123,\n \"ratio\": \"<string>\",\n \"callback_url\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.novita.ai/v3/minimax/v2/video_generation")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = '<content-type>'
request.body = "{\n \"model\": \"<string>\",\n \"content\": [\n {}\n ],\n \"content[].type\": \"<string>\",\n \"content[].text\": \"<string>\",\n \"content[].image_url.url\": \"<string>\",\n \"content[].video_url.url\": \"<string>\",\n \"content[].audio_url.url\": \"<string>\",\n \"content[].role\": \"<string>\",\n \"resolution\": \"<string>\",\n \"duration\": 123,\n \"ratio\": \"<string>\",\n \"callback_url\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyMiniMax H3 is an asynchronous video generation API. Create a task, then query its status with the returned task ID. When a task succeeds,
Save this ID; it is the unique identifier for status queries and results.
Only tasks created in the last 7 days can be queried (UTC window
For
Usage fields include
The charge is the sum of each billable item. The task is settled once it succeeds; failed and cancelled tasks are not charged. Read the resolution from
HTTP errors use this top-level structure, which differs from an asynchronous
task.content.url contains the generated video URL.
The parameters and usage align with the official MiniMax API. Refer to the official documentation for detailed parameter descriptions.
Endpoints
- Create task:
POST https://api.novita.ai/v3/minimax/v2/video_generation - Query task:
GET https://api.novita.ai/v3/minimax/v2/query/video_generation/{task_id}
Request headers
string
requis
Bearer API key:
Bearer <YOUR_API_KEY>.string
requis
Required for task creation. Set to
application/json.Create a video task
Request body
string
requis
Fixed value:
MiniMax-H3.array
requis
Multimodal input items. Every request must include a non-empty
text item.string
requis
Item type:
text, image_url, video_url, or audio_url.string
Required for
text items. A non-empty prompt; each text item supports up to 7,000 characters.string
Required for image items. A public URL,
mm_file://{file_id}, or an image Base64 data URI.string
Required for video items. A public URL,
mm_file://{file_id}, or an MP4 Base64 data URI.string
Required for audio items. A public URL,
mm_file://{file_id}, or an audio Base64 data URI.string
Required according to the scenario. Values:
first_frame, last_frame, reference_image, reference_video, or reference_audio. A single image without a role is treated as the first frame.string
requis
Output resolution:
768P or 2K.integer
requis
Output duration in seconds. An integer from
4 to 15.string
Aspect ratio:
adaptive, 21:9, 16:9, 4:3, 1:1, 3:4, or 9:16. Required for text-to-video and cannot be adaptive; image-to-video always uses adaptive and ignores other valid values.string
Optional task-status callback URL. On initial configuration, return the verification request’s
challenge unchanged within 3 seconds.Content combinations
| Input | Constraint |
|---|---|
| Text | Required; each text item is limited to 7,000 characters. |
| First and last frame | At most one of each. First-frame only, last-frame only, and first-and-last-frame modes are supported. |
| Reference images | Up to 9, using role=reference_image. |
| Reference videos | Up to 3, using role=reference_video; each is 2-15 seconds and total duration is at most 15 seconds. |
| Reference audio | Up to 3, using role=reference_audio; each is 2-15 seconds and total duration is at most 15 seconds. It can be the only reference-media type used with text. |
| Media modes | First/last-frame mode cannot be combined with reference-image, reference-video, or reference-audio mode. |
Input media limits
The complete request body must not exceed 64 MB. Base64 increases payload size by about 33%; use public URLs ormm_file://{file_id} for large media.
| Media | Formats | Per-file limit | Other limits |
|---|---|---|---|
| Image | JPG, JPEG, PNG, WEBP, HEIC, HEIF | 30 MB | Width and height: 256-5760 px; aspect ratio: 0.4-2.5. One first frame, one last frame, or up to 9 reference images. |
| Reference video | MP4, MOV; H.264/AVC or H.265/HEVC video, AAC or MP3 audio | 50 MB | Up to 3; each 2-15 seconds, total at most 15 seconds; width and height: 256-5760 px; aspect ratio: 0.4-2.5; 23.976-60 fps. |
| Reference audio | WAV, MP3 | 15 MB | Up to 3; each 2-15 seconds, total at most 15 seconds. |
Examples
Text to video
curl -X POST 'https://api.novita.ai/v3/minimax/v2/video_generation' \
-H 'Authorization: Bearer <YOUR_API_KEY>' \
-H 'Content-Type: application/json' \
-d '{
"model": "MiniMax-H3",
"content": [{"type": "text", "text": "A cinematic product video in a clean studio"}],
"resolution": "768P",
"duration": 4,
"ratio": "16:9"
}'
First-frame to video
{
"model": "MiniMax-H3",
"content": [
{"type": "text", "text": "Animate the subject naturally and keep the composition stable"},
{"type": "image_url", "image_url": {"url": "https://your-cdn.example.com/first-frame.png"}, "role": "first_frame"}
],
"resolution": "768P",
"duration": 4,
"ratio": "adaptive"
}
Reference media to video
{
"model": "MiniMax-H3",
"content": [
{"type": "text", "text": "Create a product demonstration while preserving the reference style"},
{"type": "image_url", "image_url": {"url": "https://your-cdn.example.com/product.png"}, "role": "reference_image"},
{"type": "video_url", "video_url": {"url": "https://your-cdn.example.com/reference.mp4"}, "role": "reference_video"},
{"type": "audio_url", "audio_url": {"url": "https://your-cdn.example.com/reference.mp3"}, "role": "reference_audio"}
],
"resolution": "2K",
"duration": 6,
"ratio": "16:9"
}
Create response
{"task_id": "427916141998479"}
Query a task
curl -X GET 'https://api.novita.ai/v3/minimax/v2/query/video_generation/427916141998479' \
-H 'Authorization: Bearer <YOUR_API_KEY>'
[T-7d, T)). Querying an older ID returns invalid task_id. Poll at a 10-30 second interval; do not query at high frequency.
Task statuses
| Status | Meaning |
|---|---|
queued | Created and waiting for processing. |
running | Generation is in progress. |
succeeded | Generation succeeded; read task.content.url. |
failed | Generation failed; see task.error.code and task.error.message. |
cancelled | Task was cancelled. |
Successful response
{
"task": {
"id": "427916141998479",
"model": "MiniMax-H3",
"status": "succeeded",
"created_at": 1785125529,
"updated_at": 1785125946,
"content": {"url": "https://your-result-cdn.example.com/video.mp4"},
"resolution": "768P",
"duration": 4,
"usage": {"total_seconds": 4, "input_seconds": 0, "output_seconds": 4, "input_image_count": 0},
"ratio": "16:9",
"task_type": "generation",
"modality": "video"
}
}
content.url is a time-limited download URL. Download or save the video promptly; query the task again for a new URL after it expires.
Failed response
{
"task": {
"id": "427916141998479",
"model": "MiniMax-H3",
"status": "failed",
"error": {"code": "1026", "message": "video description contains sensitive content"},
"created_at": 1785125529,
"updated_at": 1785125700,
"resolution": "768P",
"duration": 4,
"usage": {},
"ratio": "16:9",
"task_type": "generation",
"modality": "video"
}
}
failed or cancelled tasks, do not continue waiting on the same task ID. Correct the request and create a new task.
Query response fields
| Field | Type | Description |
|---|---|---|
task.id | string | Task ID. |
task.model | string | Model used, for example MiniMax-H3. |
task.status | string | queued, running, succeeded, failed, or cancelled. |
task.error.code | string | Business error code for an asynchronous failure. Returned only on failure. |
task.error.message | string | Error message for an asynchronous failure. Returned only on failure. |
task.created_at | integer | Unix timestamp in seconds when the task was created. |
task.updated_at | integer | Unix timestamp in seconds of the last status update. |
task.content.url | string | Time-limited output-video URL, returned after video generation succeeds. |
task.content.prompt | string | Structured enhanced prompt from H3-Context-IR, returned only for its successful tasks. |
task.resolution | string | Output resolution. |
task.duration | integer | Output duration in seconds. |
task.usage | object | Usage information; metering fields are returned on success and may be empty on failure. |
task.ratio | string | Actual output aspect ratio; may be empty when not applicable. |
task.task_type | string | generation, h3_context_ir, or regeneration. |
task.modality | string | Output modality: video for video tasks and text for H3-Context-IR. |
total_seconds (input plus output seconds), input_seconds (reference-video seconds), output_seconds (output-video seconds), input_image_count (all first, last, and reference images), optional input_audio_seconds, and token statistics: total_tokens, prompt_tokens, and completion_tokens.
Billing
MiniMax H3 bills successful generation by actual use; no charge is reserved when submitting a task. Pricing tiers differ for 768P and 2K. Refer to your platform pricing page for unit prices.| Usage field | Billable | Rule |
|---|---|---|
output_seconds | Yes | Resolution unit price x output_seconds. |
input_seconds | Yes when non-zero | Resolution unit price x input_seconds. |
input_image_count | Above five images | (input_image_count - 5) x image unit price. |
total_seconds | No | Summary check only. |
total_tokens, prompt_tokens, completion_tokens | No | Reference statistics only. |
task.resolution in the query response.
Python example
import os
import time
import requests
api_domain = "api.novita.ai"
api_key = os.environ["PLATFORM_API_KEY"]
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
payload = {
"model": "MiniMax-H3",
"content": [{"type": "text", "text": "A calm cinematic landscape"}],
"resolution": "768P",
"duration": 4,
"ratio": "16:9",
}
created = requests.post(f"https://api.novita.ai/v3/minimax/v2/video_generation", headers=headers, json=payload, timeout=30)
created.raise_for_status()
task_id = created.json()["task_id"]
while True:
result = requests.get(f"https://api.novita.ai/v3/minimax/v2/query/video_generation/{task_id}", headers=headers, timeout=30)
result.raise_for_status()
task = result.json()["task"]
if task["status"] == "succeeded":
print(task["content"]["url"])
break
if task["status"] in ("failed", "cancelled"):
raise RuntimeError(task)
time.sleep(20)
Errors
| HTTP status | Scenario | Recommended handling |
|---|---|---|
400 | Invalid JSON, model, ratio, duration, or content combination | Correct the request using error.message. |
401 | Missing or invalid API key | Check the Authorization: Bearer <API_KEY> header. |
402 | Insufficient balance or quota when creating a task | Top up or adjust the quota, then retry. |
422 | Sensitive input content when creating a task | Revise the prompt or media and create a new task. |
429 | Rate limit exceeded | Reduce creation or polling frequency and use exponential-backoff retries. |
500 | Server error | Retry with exponential backoff; avoid creating duplicate business tasks without idempotency control. |
task.error failure:
{
"type": "error",
"error": {
"type": "bad_request_error",
"message": "invalid params, content must include a non-empty text item (prompt is required) (2013)",
"http_code": "400"
},
"request_id": "021785229015510a2c883cf675b9804d"
}
Dernière modification le 25 août 2026