
How to Use the MiniMax H3 API
MiniMax H3, also searched as Hailuo 3 or Hailuo 03, is MiniMax's latest video generation model. It supports three distinct workflows: generating a video from text, animating a start or end image, and creating a new clip from image, video, and audio references.
This guide shows how to access MiniMax H3 through EvoLink, choose the correct model ID, submit a request, track the asynchronous task, and retrieve the finished video. The examples use the same unified video endpoint across all three modes, so you can add H3 to an existing production workflow without building a separate task system.
Quick answer
- Endpoint:
POST https://api.evolink.ai/v1/videos/generations - Authentication: Bearer API key
- Text-to-video model:
minimax-h3-text-to-video - Image-to-video model:
minimax-h3-image-to-video - Reference-to-video model:
minimax-h3-reference-to-video - Output: 2K video
- Duration: 4–15 seconds
- Task flow: Submit a request, receive a task ID, then poll the task endpoint or use an HTTPS callback
- Result lifetime: Download and store completed videos within 24 hours
Table of contents
- What MiniMax H3 can do
- Key features and practical upgrades
- MiniMax H3 API at a glance
- How to access the MiniMax H3 API
- Choose the right generation mode
- Quick start: submit your first request in 60 seconds
- Understand the async workflow
- Text-to-video example
- Image-to-video examples
- Reference-to-video example
- Upload local assets
- Complete TypeScript implementation
- Complete Python implementation
- Parameter and prompt cheat sheet
- Common errors and fixes
- Pricing and cost planning
- Production checklist
- Practical use cases
- FAQ
1. What MiniMax H3 can do
MiniMax H3 is designed for short-form video generation with different levels of creative control. The three API modes share the same task lifecycle but accept different inputs.
| Mode | What it does | Common uses |
|---|---|---|
| Text-to-video | Creates a video directly from a written scene description | Ad concepts, cinematic shots, social clips, storyboards |
| Image-to-video | Animates a start image, an end image, or both | Product animation, character motion, controlled transitions |
| Reference-to-video | Uses images, videos, and optional audio as references for a new video | Character and style references, motion direction, multi-asset production |
The key distinction is control. Text-to-video gives the model the most freedom. Image-to-video anchors the composition to one or two frames. Reference-to-video lets you describe how multiple source assets should influence the result.
2. Key features and practical upgrades
The most useful H3 changes for developers are visible in the input and output contract:
- Three purpose-built workflows. Text, keyframe, and multimodal reference generation have separate model IDs but use one EvoLink endpoint.
- 2K output. The current H3 routes expose a single
2kquality option. - Flexible 4–15 second clips. Duration is an integer, which makes it easier to align generation length with a shot plan.
- First- and last-frame control. Image-to-video accepts a starting image, an ending image, or both.
- Richer reference inputs. Reference-to-video accepts ordered image, video, and audio arrays, enabling more explicit creative direction than a single subject image.
- Production-oriented task handling. EvoLink provides a consistent async task endpoint and optional completion callback across the three modes.
The last point is an EvoLink integration feature, not a model capability. It matters because a production application needs predictable task states, callbacks, logging, and result handling regardless of the model selected.
How this differs from Hailuo 2.3
| Area | Hailuo 2.3 through EvoLink | MiniMax H3 through EvoLink |
|---|---|---|
| Output tiers | 768P or 1080P, depending on duration | 2K |
| Clip length | 6 or 10 seconds; 1080P is limited to 6 seconds | Any integer from 4 to 15 seconds |
| Image control | One input image for image-to-video | Start image, end image, or both |
| Reference media | No separate multimodal reference route | Ordered image, video, and audio references |
| Mode selection | One model ID with automatic text/image mode detection | Three explicit model IDs for text, image, and reference workflows |
Official example: video and voice reference
video_urls and audio_urls, rather than treating every input as a generic attachment.Audio 1 is used as the voice-timbre reference.3. MiniMax H3 API at a glance
All three modes use:
POST https://api.evolink.ai/v1/videos/generationsmodel value determines which input contract applies.| Model ID | Required input | Accepted reference fields | Aspect ratio |
|---|---|---|---|
minimax-h3-text-to-video | prompt | None | Adaptive or a supported preset |
minimax-h3-image-to-video | prompt and at least one of image_start or image_end | Start/end image only | Determined by the input image |
minimax-h3-reference-to-video | prompt and at least one image or video reference | image_urls, video_urls, audio_urls | Adaptive |
Shared rules:
durationaccepts integers from 5 through 15; the default is 5.qualitymust be2k. Do not send768p.- Prompts can be written in English or Chinese.
- Keep prompts within approximately 1,000 English words or 500 Chinese characters.
- Bitrate, frame rate, and codec are not configurable.
- Generation is asynchronous.
4. How to access the MiniMax H3 API
You need an EvoLink account, an API key, and sufficient credit for the requested task.
- Create or sign in to your EvoLink account.
- Open the API Keys dashboard and create a key.
- Store the key in a server-side environment variable.
- Choose the H3 mode that matches your available inputs.
- Submit a request to the unified video endpoint.
EVOLINK_API_KEY=your_api_keyNever expose this key in browser JavaScript, a public repository, or a mobile application bundle. Call the EvoLink API from your server, Server Action, API route, worker, or another trusted runtime.
5. Choose the right generation mode
Use this routing table before constructing a payload:
| Your input or goal | Use this mode |
|---|---|
| You have only a scene description | Text-to-video |
| You want to animate one product or character image | Image-to-video |
| You know how the video should begin and end | Image-to-video with image_start and image_end |
| You need multiple images to guide the output | Reference-to-video |
| You want a video clip to guide action or camera movement | Reference-to-video |
| You want audio to act as an additional reference | Reference-to-video with an image or video |
| You have only an audio file | Add an image or video; audio-only reference requests are invalid |

image_start, and the reference route does not accept image_start or image_end.6. Quick start: submit your first request in 60 seconds
Step 1: Submit a text-to-video request
curl -X POST https://api.evolink.ai/v1/videos/generations \
-H "Authorization: Bearer $EVOLINK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "minimax-h3-text-to-video",
"prompt": "A compact electric concept car drives through a rain-soaked city at night. The camera tracks beside the car, then slowly pulls back to reveal neon reflections across the street.",
"quality": "2k",
"aspect_ratio": "16:9",
"duration": 5
}'The API returns an asynchronous task:
{
"id": "task-unified-example",
"status": "pending",
"created": 1785470400
}Step 2: Check the task
curl https://api.evolink.ai/v1/tasks/task-unified-example \
-H "Authorization: Bearer $EVOLINK_API_KEY"status is completed, read the generated video URL from results.{
"id": "task-unified-example",
"status": "completed",
"results": [
"https://example-cdn.com/generated-video.mp4"
]
}Download the result within 24 hours. Copy it to your own durable storage if your application needs it later.
7. Understand the async workflow
Video generation takes longer than a normal HTTP request. The create call therefore returns a task instead of holding the connection open until the video is finished.
Submit request
↓
Receive task ID
↓
pending → processing
↓
completed or failed
↓
Download completed resultThe task status can be:
pending: The request is queued.processing: Generation is in progress.completed: Theresultsarray contains the output.failed: Inspect the error information and decide whether the request should be corrected or retried.
Polling or callback?
GET /v1/tasks/{task_id} with a bounded interval and an overall timeout.callback_url to the generation request. EvoLink sends the callback after a task reaches completed or failed and billing is confirmed. The callback URL must:- Use HTTPS.
- Be no longer than 2,048 characters.
- Resolve to a public destination, not a private IP.
- Respond within 10 seconds.
- Return a 2xx response after the event is accepted.
Failed deliveries are retried three times with approximately 1-, 2-, and 4-second delays. Your handler should be safe if the same event is received more than once.
8. Text-to-video example
Text-to-video accepts a prompt without any media input.
{
"model": "minimax-h3-text-to-video",
"prompt": "A ceramic coffee cup sits on a wooden table beside a window. Morning steam curls upward while the camera makes a slow clockwise orbit. Natural light, realistic texture, quiet editorial mood.",
"quality": "2k",
"aspect_ratio": "4:3",
"duration": 8,
"callback_url": "https://api.example.com/webhooks/evolink"
}Supported aspect ratios include:
21:916:94:31:13:49:16- Adaptive
image_start, image_end, image_urls, video_urls, or audio_urls. If the scene depends on a specific visual subject, switch to image-to-video or reference-to-video.9. Image-to-video examples
image_start or image_end.Animate a starting image
{
"model": "minimax-h3-image-to-video",
"prompt": "The camera slowly moves closer as the fabric responds to a soft breeze. Preserve the product shape, label, and lighting.",
"image_start": "https://assets.example.com/product-start.webp",
"quality": "2k",
"duration": 6
}Generate toward an ending frame
{
"model": "minimax-h3-image-to-video",
"prompt": "A wide landscape shot gradually resolves into the supplied final frame, with continuous forward camera movement and stable natural lighting.",
"image_end": "https://assets.example.com/landscape-end.jpg",
"quality": "2k",
"duration": 10
}Control both the first and last frame
{
"model": "minimax-h3-image-to-video",
"prompt": "The sealed package opens smoothly and the product rises into the final display position. Keep the logo legible and avoid sudden camera cuts.",
"image_start": "https://assets.example.com/package-closed.png",
"image_end": "https://assets.example.com/package-open.png",
"quality": "2k",
"duration": 8
}Input images must:
- Use JPG, JPEG, PNG, WEBP, HEIC, or HEIF.
- Be no larger than 30 MB.
- Have width and height between 256 and 5,760 pixels.
- Have a width-to-height ratio between 0.4 and 2.5.
- Be available from a public HTTP(S) URL.
mm_file:// references are not accepted by this route. The input image determines the output aspect ratio. This route does not accept an aspect_ratio field at all, and sending one returns a parameter error.10. Reference-to-video example
Reference-to-video accepts ordered arrays of images, videos, and optional audio. It is useful when a prompt alone cannot describe the subject, movement, or pacing precisely enough.
{
"model": "minimax-h3-reference-to-video",
"prompt": "Use Image 1 for the main character and Image 2 for the wardrobe. Follow the camera movement and walking rhythm from Video 1. Use Audio 1 only as a pacing reference. The character crosses a modern gallery and stops beside a large window.",
"image_urls": [
"https://assets.example.com/character.jpg",
"https://assets.example.com/wardrobe.jpg"
],
"video_urls": [
"https://assets.example.com/camera-reference.mp4"
],
"audio_urls": [
"https://assets.example.com/pacing-reference.mp3"
],
"quality": "2k",
"duration": 10
}Reference limits
- Up to 9 items in
image_urls. - Up to 3 items in
video_urls. - Up to 3 items in
audio_urls. - No more than 12 reference files in total, so a full 9 + 3 + 3 set is rejected.
- At least one image or video is required.
- Audio cannot be the only reference type.
- Reference video and audio clips must each be 2–15 seconds.
- Total reference video duration must not exceed 15 seconds.
- Total reference audio duration must not exceed 15 seconds.
- Reference videos must use MP4 or MOV with H.264 or H.265 video and can contain AAC or MP3 audio.
- Each reference video can be up to 50 MB.
- Reference video dimensions must be 256–5,760 pixels per side, with a width-to-height ratio from 0.4 to 2.5 and a frame rate from 23.976 to 60 FPS.
- Reference audio must use WAV or MP3 and can be up to 15 MB per clip.
- The complete JSON request body must remain below 64 MB.
Reference images follow the same format, size, dimension, and URL rules as image-to-video.
Refer to assets by array order
Image 1, Image 2, Video 1, and Audio 1 in the prompt. The number corresponds to the asset's position in its array. Do not use @image1; that syntax is not part of this API contract.Reference video duration contributes to billable usage, so avoid attaching longer clips than the task needs.
11. Upload local assets
The generation routes require public HTTP(S) media URLs. To use a file from a local disk or private application upload, send it to the EvoLink file service first.
curl -X POST https://files-api.evolink.ai/api/v1/files/upload/stream \
-H "Authorization: Bearer $EVOLINK_API_KEY" \
-F "file=@./product-start.png"file_url from the response and pass it as image_start, image_end, or an item in a reference array.12. Complete TypeScript implementation
Run this example in a trusted server environment on Node.js 18 or later.
const API_BASE = "https://api.evolink.ai";
type TaskStatus = "pending" | "processing" | "completed" | "failed";
interface VideoTask {
id: string;
status: TaskStatus;
results?: string[];
error?: {
code?: string;
message?: string;
};
}
interface BaseRequest {
prompt: string;
quality?: "2k";
duration?: number;
callback_url?: string;
}
type AspectRatio =
| "adaptive"
| "21:9"
| "16:9"
| "4:3"
| "1:1"
| "3:4"
| "9:16";
// One type per route, so an invalid field combination fails to compile.
interface TextToVideoRequest extends BaseRequest {
model: "minimax-h3-text-to-video";
aspect_ratio?: AspectRatio;
}
interface ImageToVideoRequest extends BaseRequest {
model: "minimax-h3-image-to-video";
image_start?: string;
image_end?: string;
// No aspect_ratio: the route rejects the field and derives the ratio
// from the input image.
}
interface ReferenceToVideoRequest extends BaseRequest {
model: "minimax-h3-reference-to-video";
aspect_ratio?: AspectRatio;
image_urls?: string[];
video_urls?: string[];
audio_urls?: string[];
}
type VideoRequest =
| TextToVideoRequest
| ImageToVideoRequest
| ReferenceToVideoRequest;
function getApiKey(): string {
const apiKey = process.env.EVOLINK_API_KEY;
if (!apiKey) {
throw new Error("EVOLINK_API_KEY is not configured");
}
return apiKey;
}
async function requestJson<T>(
path: string,
init?: RequestInit,
): Promise<T> {
const response = await fetch(`${API_BASE}${path}`, {
...init,
headers: {
Authorization: `Bearer ${getApiKey()}`,
"Content-Type": "application/json",
...init?.headers,
},
});
if (!response.ok) {
const body = await response.text();
throw new Error(`EvoLink request failed (${response.status}): ${body}`);
}
return response.json() as Promise<T>;
}
async function submitVideo(payload: VideoRequest): Promise<VideoTask> {
return requestJson<VideoTask>("/v1/videos/generations", {
method: "POST",
body: JSON.stringify(payload),
});
}
async function getTask(taskId: string): Promise<VideoTask> {
return requestJson<VideoTask>(
`/v1/tasks/${encodeURIComponent(taskId)}`,
);
}
function wait(milliseconds: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
}
async function waitForVideo(
taskId: string,
timeoutMs = 10 * 60 * 1000,
pollIntervalMs = 5_000,
): Promise<string> {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const task = await getTask(taskId);
if (task.status === "completed") {
const resultUrl = task.results?.[0];
if (!resultUrl) {
throw new Error("Task completed without a result URL");
}
return resultUrl;
}
if (task.status === "failed") {
throw new Error(task.error?.message ?? "Video generation failed");
}
await wait(pollIntervalMs);
}
throw new Error(`Timed out while waiting for task ${taskId}`);
}
async function main(): Promise<void> {
const task = await submitVideo({
model: "minimax-h3-text-to-video",
prompt:
"A slow aerial approach toward a coastal observatory at sunrise, " +
"natural cloud movement, cinematic wide shot",
quality: "2k",
aspect_ratio: "16:9",
duration: 6,
});
const videoUrl = await waitForVideo(task.id);
console.log(videoUrl);
}
void main();For high-volume systems, replace application-side polling with callbacks and a durable job record. Keep the task ID as the primary link between your request, billing record, logs, and result.
13. Complete Python implementation
import os
import time
from typing import NotRequired, TypedDict, cast
import requests
API_BASE = "https://api.evolink.ai"
API_KEY = os.environ["EVOLINK_API_KEY"]
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
class VideoError(TypedDict):
code: NotRequired[str]
message: NotRequired[str]
class VideoTask(TypedDict):
id: str
status: str
results: NotRequired[list[str]]
error: NotRequired[VideoError]
class VideoPayload(TypedDict):
model: str
prompt: str
image_start: NotRequired[str]
quality: NotRequired[str]
duration: NotRequired[int]
def submit_video(payload: VideoPayload) -> VideoTask:
response = requests.post(
f"{API_BASE}/v1/videos/generations",
headers=HEADERS,
json=payload,
timeout=30,
)
response.raise_for_status()
return cast(VideoTask, response.json())
def get_task(task_id: str) -> VideoTask:
response = requests.get(
f"{API_BASE}/v1/tasks/{task_id}",
headers=HEADERS,
timeout=30,
)
response.raise_for_status()
return cast(VideoTask, response.json())
def wait_for_video(
task_id: str,
timeout_seconds: int = 600,
poll_interval_seconds: int = 5,
) -> str:
deadline = time.monotonic() + timeout_seconds
while time.monotonic() < deadline:
task = get_task(task_id)
status = task["status"]
if status == "completed":
results = task.get("results", [])
if not results:
raise RuntimeError("Task completed without a result URL")
return str(results[0])
if status == "failed":
error = task.get("error", {})
message = error.get("message", "Video generation failed")
raise RuntimeError(message)
time.sleep(poll_interval_seconds)
raise TimeoutError(f"Timed out while waiting for task {task_id}")
task = submit_video(
{
"model": "minimax-h3-image-to-video",
"prompt": (
"The camera slowly orbits the product while the background "
"light shifts from warm to cool. Preserve the product design."
),
"image_start": "https://assets.example.com/product.webp",
"quality": "2k",
"duration": 8,
}
)
print(wait_for_video(task["id"]))This example stays dependency-light while still declaring the fields it consumes. In a larger Python service, validate the full response with Pydantic before storing it.
14. Parameter and prompt cheat sheet
Parameter support
| Parameter | Text | Image | Reference | Notes |
|---|---|---|---|---|
model | Yes | Yes | Yes | Use the mode-specific model ID |
prompt | Required | Required | Required | English or Chinese |
quality | Yes | Yes | Yes | 2k only |
duration | Yes | Yes | Yes | Integer from 4 to 15 |
aspect_ratio | Yes | No | Yes | Text and reference routes accept adaptive or a fixed ratio; image-to-video rejects the field and derives the ratio from the input image |
image_start | No | Yes | No | Start frame |
image_end | No | Yes | No | End frame |
image_urls | No | No | Yes | Up to 9 |
video_urls | No | No | Yes | Up to 3 |
audio_urls | No | No | Yes | Up to 3; cannot be used alone |
callback_url | Yes | Yes | Yes | Public HTTPS URL |
Prompt pattern: text-to-video
[subject] + [action] + [environment] + [camera movement] +
[lighting] + [visual mood]Example:
A cyclist crosses a suspended bridge above a foggy forest at dawn. The camera follows from behind, then rises into a wide aerial view. Soft natural light and realistic motion.
Prompt pattern: image-to-video
[motion to add] + [camera movement] + [elements to preserve] +
[transition or ending state]Example:
The camera makes a slow half-circle around the chair as sunlight moves across the floor. Preserve the chair's exact shape, material, and color.
Prompt pattern: reference-to-video
Use [Image/Video/Audio number] for [specific purpose].
[Describe the new scene, action, camera, and final composition.]Example:
Use Image 1 for the character, Image 2 for the vehicle, and Video 1 for the camera movement. The character exits the vehicle in a quiet desert at sunset while the camera makes the same forward arc as Video 1.
15. Common errors and fixes
| Error or symptom | Likely cause | What to do |
|---|---|---|
401 unauthorized | Missing, malformed, or invalid API key | Check the Bearer header and server environment |
402 insufficient quota | Insufficient account credit | Add credit or reduce the planned workload |
403 permission_denied | Key or account cannot access the route | Verify key permissions and model availability |
404 task_not_found | Incorrect or expired task ID | Store the returned task ID without modification |
429 rate_limit_exceeded | Too many requests | Apply exponential backoff and limit concurrency |
Request rejects 768p | H3 accepts 2k only | Set "quality": "2k" |
| Image cannot be fetched | URL is private, expired, or blocks external requests | Upload it through the EvoLink file service |
| Base64 image is rejected | The route expects a public URL | Upload the file and use its file_url |
| Reference request is invalid | Only audio was supplied | Add at least one image or video |
| Reference input is rejected | Count, size, format, or total duration exceeds a limit | Validate assets before submitting |
| Task completed but the URL no longer works | Result URL exceeded its 24-hour lifetime | Copy completed videos to durable storage |
| Repeated callback processing | Delivery was retried or handled twice | Make the callback handler idempotent in your database |
Retry only errors that can succeed without changing the request, such as temporary network failures or rate limits. Invalid parameters and unsupported assets should be corrected before another submission.
16. Pricing and cost planning
For planning purposes:
- Longer output duration increases the work requested.
- Reference-to-video can also bill input reference video duration.
- Use the shortest useful duration while validating a prompt or workflow.
- Run a small set of test generations and review the results before starting a large batch.
- Record mode, output duration, reference video duration, status, and cost for every task.
- Separate failed generations from usable results when evaluating cost per usable video.
EvoLink's unified API also lets a production team compare H3 with other video models without replacing its authentication, task tracking, and billing integration.
17. Production checklist
Before shipping:
- Keep the API key on the server.
- Validate all mode-specific parameters before submission.
- Confirm media URLs are public and remain available during generation.
- Set request timeouts.
- Bound polling frequency and total polling time.
- Back off after
429and transient server errors. - Store the task ID before beginning to poll.
- Do not assume an H3 task can be canceled; the current task contract reports
can_cancel: false. - Treat callbacks as repeatable events.
- Return a 2xx callback response only after accepting the event.
- Persist completed videos before their temporary URLs expire.
- Log the model ID, duration, input references, status, and result.
- Apply account-level concurrency and budget controls.
- Do not depend on undocumented headers or output settings.
18. Practical use cases
| Use case | Recommended mode | Why |
|---|---|---|
| Rapid ad concept generation | Text-to-video | Fastest route from copy to a visual test |
| Product photo animation | Image-to-video | Preserves the supplied product composition |
| Before-and-after transition | Image-to-video | Start and end frames define both states |
| Character-led short video | Reference-to-video | Multiple visual references can guide the subject |
| Camera-motion matching | Reference-to-video | A short reference clip can guide movement |
| Storyboard exploration | Text-to-video or image-to-video | Choose based on whether approved frames already exist |
| Video generation inside an app | Any mode | One endpoint and task lifecycle simplify integration |
| Multi-model production routing | Any mode | The same EvoLink key and task system can serve other models |
19. FAQ
How do I access the MiniMax H3 API?
POST https://api.evolink.ai/v1/videos/generations.Which MiniMax H3 model ID should I use?
minimax-h3-text-to-video for prompt-only generation, minimax-h3-image-to-video for start/end-frame control, and minimax-h3-reference-to-video for ordered image, video, and audio references.Does MiniMax H3 support 2K video?
2k as the quality value.Does the API support 4K or 60 FPS?
Those controls are not part of the current H3 API contract. Do not send undocumented quality, frame-rate, bitrate, or codec settings.
What is the maximum video duration?
The current duration range is 4–15 seconds, using an integer value.
Can I upload a local image?
file_url to the generation request.Does the generation API accept Base64 images?
No. Use a public HTTP(S) URL.
How many references can I use?
Reference-to-video accepts up to 9 images, 3 videos, and 3 audio files, subject to the per-file and total-duration limits.
Can I generate a video from an audio reference alone?
No. A reference request must include at least one image or video. Audio can be added as another reference.
How do I check the generation status?
GET /v1/tasks/{task_id} or provide a public HTTPS callback URL in the original request.How long is the generated video URL available?
The result URL is available for 24 hours. Download the video or move it to your own storage before it expires.
Can I use MiniMax H3 from JavaScript or Python?
Yes. The API is standard HTTPS and can be called from any server-side environment that supports JSON requests and Bearer authentication.
Should I poll the task or use a callback?
Polling is convenient for tests and low-volume scripts. Callbacks are generally more efficient for production queues and larger workloads.


