MiniMax H3 is listed in the CometAPI catalog as minimax-h3. The provider's direct API uses MiniMax-H3. The distinction matters: a catalog route can have a different request contract and availability policy from the provider endpoint.
This guide uses MiniMax's documented API directly so the integration steps are explicit. Before production, verify the current CometAPI route, account access, region, and price for your project.
What the current contract says
MiniMax documents:
-
POST https://api.minimax.io/v2/video_generationto create a task -
GET https://api.minimax.io/v2/query/video_generation/{task_id}to query it - Text, image, video, and audio inputs
- 4-15 second output at 24 FPS with 32 kHz stereo audio
- Maximum 12 reference files, including up to nine images, three videos, and three audio clips
- Audio references cannot be used alone
MiniMax's published output rates are $0.08 per second at 768p and $0.13 per second at 2K. A five-second output is therefore $0.40 or $0.65 for the output component, before reference, Context-IR, regeneration, and retry charges.
Install the small test client
python -m venv .venv
source .venv/bin/activate
python -m pip install requests
export MINIMAX_API_KEY="your-key"
Do not commit the key. The example below reads it from MINIMAX_API_KEY.
Create and poll a task
import os
import time
from decimal import Decimal
import requests
CREATE_URL = "https://api.minimax.io/v2/video_generation"
QUERY_URL = "https://api.minimax.io/v2/query/video_generation"
def create_task(prompt: str, resolution: str = "768P", duration: int = 5) -> dict:
api_key = os.environ["MINIMAX_API_KEY"]
if not prompt.strip():
raise ValueError("prompt cannot be empty")
if resolution not in {"768P", "2K"}:
raise ValueError("resolution must be 768P or 2K")
if duration not in range(4, 16):
raise ValueError("duration must be between 4 and 15 seconds")
payload = {
"model": "MiniMax-H3",
"content": [{"type": "text", "text": prompt}],
"resolution": resolution,
"duration": duration,
"ratio": "16:9",
}
response = requests.post(
CREATE_URL,
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
},
json=payload,
timeout=60,
)
response.raise_for_status()
result = response.json()
task_id = result.get("task_id") or result.get("data", {}).get("task_id")
if not task_id:
raise RuntimeError(f"create response did not include task_id: {result}")
return result
def query_task(task_id: str) -> dict:
api_key = os.environ["MINIMAX_API_KEY"]
response = requests.get(
f"{QUERY_URL}/{task_id}",
headers={"Authorization": f"Bearer {api_key}"},
timeout=60,
)
response.raise_for_status()
return response.json()
def get_status(result: dict) -> str:
value = result.get("status")
if value is None:
value = result.get("data", {}).get("status")
return str(value or "UNKNOWN").upper()
def main() -> None:
resolution = "768P"
task = create_task(
"A glass product on a desk in soft morning light; slow camera move, clean commercial style.",
resolution=resolution,
duration=5,
)
task_id = task.get("task_id") or task.get("data", {}).get("task_id")
terminal = {"SUCCESS", "SUCCEEDED", "FAILED", "ERROR", "CANCELED", "CANCELLED"}
while True:
result = query_task(task_id)
status = get_status(result)
print({"task_id": task_id, "status": status})
if status in terminal:
print(result)
break
time.sleep(5)
# Planning estimate only; reconcile with the usage object and invoice.
rate = Decimal("0.08") if resolution == "768P" else Decimal("0.13")
print("estimated output component USD:", rate * Decimal("5"))
if __name__ == "__main__":
main()
The response keys can change with API revisions, so keep the raw create and query responses in your task log and compare them with the current API reference. The script intentionally prints the terminal response instead of assuming a particular output-URL field.
Validate multimodal content before sending
The most common first-request failure is an invalid reference combination. Validate these rules in your own request builder:
| Input rule | Check |
|---|---|
| Text | Include a non-empty text item |
| Audio | Never send audio as the only reference |
| Total files | At most 12 |
| Images | At most 9 |
| Videos | At most 3; each 2-15 seconds; total 15 seconds |
| Audio clips | At most 3; each 2-15 seconds; total 15 seconds |
| Modes | Do not mix first/last-frame mode with reference-to-video mode |
| Request size | Keep the body within 64 MB; use public media URLs for large files |
Failing locally protects a queue slot and makes errors easier to attribute.
Log accepted-output economics
Per task, store:
{
"model": "MiniMax-H3",
"route_id": "minimax-h3",
"task_id": "provider-task-id",
"resolution": "768P",
"requested_seconds": 5,
"input_seconds": 0,
"output_seconds": 5,
"input_image_count": 0,
"latency_seconds": 0,
"retry_count": 0,
"charged_usd": 0,
"review_result": "accepted"
}
The zero values are test-record defaults, not provider results. Keep charged_usd and the provider's usage object as the billing source of truth.
API versus open weights
H3-Base is downloadable under the MiniMax H3 Community License, but the default license territory excludes the United States, European Union, United Kingdom, and South Korea. Commercial products have attribution and safeguard requirements. H3-Context-IR is hosted and is not included in the initial open-weight release.
Use the hosted API for the fastest evaluation. Consider self-hosting only after checking territory, authorization, GPU capacity, storage, queueing, and whether a local H3-Base deployment actually meets your workflow needs.
CometAPI is useful as a unified route to check when a project already manages multiple models, but do not assume that a catalog announcement means every account or region is enabled. Probe minimax-h3, record the returned contract, and keep a fallback route.
Top comments (0)