MiniMax Hailuo
Hailuo is MiniMax’s video generation family. One channel serves two API generations: MiniMax-H3 and MiniMax-H3-Max use MiniMax’s /v2 API with a content array and settle per second, while the MiniMax-Hailuo-2.3 family uses the older /v1 API with a per-task price (covered at the end of this page).
Tasks are submitted, polled and downloaded through the shared endpoints described in Create a task and Get a task. This page covers what this vendor reads, how the request is built, and how it is billed.
Models
Section titled “Models”| Model ID | Resolutions | Duration (integer seconds) | Defaults | Prompt expansion |
|---|---|---|---|---|
MiniMax-H3 | 768P, 2K | 4–15 | 768P, 5 s | No |
MiniMax-H3-Max | 480P, 768P | 5–15 | 768P, 5 s | Yes |
- Use the model ID exactly as written here — IDs are case-sensitive. Your account can use only the models routed to it, and price is per account;
GET /v1/modelsis the authoritative list for your key. MiniMax-H3-Maxis the only model that acceptsextra. SendingextratoMiniMax-H3returns400.- Text-to-video, first-frame, first-and-last-frame, and reference image / video / audio are all supported by both models.
Request parameters
Section titled “Request parameters”| Field | Type | Required | Default | Description |
|---|---|---|---|---|
model | string | Yes | — | Model ID from GET /v1/models |
prompt | string | Yes | — | Text prompt; blank after trimming is rejected. Up to 7000 characters |
resolution | string | No | 768P | Case-insensitive; must be one of the model’s resolutions |
duration | integer | No | 5 | Integer seconds inside the model’s range |
seconds | string | No | — | String form of the duration; read only when duration is missing or 0 |
ratio | string | No | see below | Aspect ratio |
images | string[] | No | — | 1 image = first frame; 2 images = first frame then last frame. At most 2 |
image | string | No | — | Single image; used only when images is empty |
metadata | object | No | — | MiniMax parameters, see the next section |
Precedence rules:
metadata.resolution,metadata.durationandmetadata.ratiooverride the top-level fields of the same name.secondsis only read when the top-leveldurationis absent or0, andmetadata.durationoverrides both.metadata.durationis parsed as a number, so5.5fails withinvalid duration. Unlike the top-levelduration,0is not “unset” there — it is out of range. Omit the key to keep the default.sizeis not supported. A top-levelsizeormetadata.sizereturnsMiniMax-H3 请使用 resolution(480P/768P/2K),不支持 size; useresolutioninstead.- Apart from
size, top-level fields this vendor does not read (for examplegenerate_audioorinput_reference) are ignored rather than rejected.
metadata parameters
Section titled “metadata parameters”| Field | Type | Description |
|---|---|---|
content | array | Input material, see Content items. Cannot be combined with top-level images / image |
resolution | string | Overrides the top-level resolution |
duration | number | Overrides the top-level duration and seconds; must be an integer in range |
ratio | string | Overrides the top-level ratio |
aigc_watermark | boolean or string | true / false. A string "true" or "false" is also accepted, which is what multipart forms send. Omitted = upstream decides |
extra.prompt_expansion_mode | string | disabled, balanced or quality. MiniMax-H3-Max only |
size | — | Rejected with 400 |
metadata is decoded into a typed structure: a wrong JSON type for one of the keys above (for example "duration": "abc", or content as an object) returns 400 with invalid metadata: ... and nothing is charged. Keys that are not in the table — seed, callback_url and so on — are ignored and never reach MiniMax; no callback is sent, so poll for the result.
Aspect ratio
Section titled “Aspect ratio”Accepted values: adaptive, 21:9, 16:9, 4:3, 1:1, 3:4, 9:16. The value is case-insensitive.
| Request shape | Ratio omitted | Rules |
|---|---|---|
| Text only (no frames, no references) | 16:9 | adaptive is rejected with text-to-video does not support ratio adaptive |
| First frame, or first and last frame | adaptive | Forced to adaptive; any value you send is ignored, and is not validated |
| Reference media | adaptive | Any of the seven values |
Content items and limits
Section titled “Content items and limits”metadata.content is an ordered array. Each item has a type, a payload field matching that type, and an optional role:
type | Payload | Allowed role | Limit |
|---|---|---|---|
text | text | none | 1, and must equal prompt |
image_url | image_url.url | first_frame | 1 |
image_url | image_url.url | last_frame | 1, and requires first_frame |
image_url | image_url.url | reference_image | 9 |
image_url | image_url.url | none | only as the single media item |
video_url | video_url.url | reference_video (required) | 3 |
audio_url | audio_url.url | reference_audio (required) | 3 |
{ "type": "image_url", "role": "reference_image", "image_url": { "url": "https://..." } }{ "type": "video_url", "role": "reference_video", "video_url": { "url": "https://..." } }{ "type": "audio_url", "role": "reference_audio", "audio_url": { "url": "https://..." } }Rules enforced before the request is sent:
- At most 12 media items per request, and at most 9 reference images, 3 reference videos and 3 reference audios.
- First / last frame images and reference media cannot be mixed.
reference_image,reference_videoandreference_audiocombine freely. - An
image_urlitem without aroleis allowed only when it is the only media item; it is then treated asfirst_frame. - If
contenthas notextitem, RouteAPI prepends one carrying the top-levelprompt. If it has one, there can be only one, and its text must equal the trimmedprompt; otherwise the request fails withprompt 与 metadata.content 中的 text 冲突. contentand top-levelimages/imageare mutually exclusive.- Only the field matching the item
typeis forwarded; extra keys on an item are dropped. - Media URLs — including top-level
imagesandimage— must behttp://,https://ordata:URIs (for exampledata:image/png;base64,...) and must be downloadable without authentication. MiniMax file IDs (mm_file://) are not supported. URLs that MiniMax quotes back in a rejection are replaced with[url omitted], so signed asset links never appear in error messages. - Per-asset format, dimension, length and size limits are MiniMax’s own; RouteAPI does not check them. A bad asset is either rejected at submit (
400, nothing charged) or rejected during generation (the task becomesFAILUREand the reservation is refunded).
Examples
Section titled “Examples”Text to video
Section titled “Text to video”curl https://api.routeapi.ai/v1/video/generations \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "MiniMax-H3", "prompt": "A paper boat drifting down a rain-soaked street, cinematic lighting", "resolution": "768P", "ratio": "16:9", "duration": 5 }'First frame
Section titled “First frame”curl https://api.routeapi.ai/v1/video/generations \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "MiniMax-H3", "prompt": "The camera slowly pushes in as the subject looks up and smiles", "images": ["https://cdn.example.com/first.jpg"], "resolution": "768P", "duration": 5 }'First and last frame
Section titled “First and last frame”Two entries in images become first_frame and last_frame. ratio is forced to adaptive.
curl https://api.routeapi.ai/v1/video/generations \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "MiniMax-H3", "prompt": "The scene transitions from morning to sunset while the camera pans smoothly", "images": [ "https://cdn.example.com/first.jpg", "https://cdn.example.com/last.jpg" ], "resolution": "768P", "duration": 5 }'Reference images, video and audio
Section titled “Reference images, video and audio”Use metadata.content when you need more than two images or any reference video / audio. Reference videos are billed, so keep them between 2 and 15 seconds — see Billing.
curl https://api.routeapi.ai/v1/video/generations \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "MiniMax-H3", "prompt": "The character in the image dances to the rhythm of the reference audio, copying the motion of the reference video", "resolution": "768P", "ratio": "9:16", "duration": 8, "metadata": { "content": [ { "type": "image_url", "role": "reference_image", "image_url": { "url": "https://cdn.example.com/character.jpg" } }, { "type": "video_url", "role": "reference_video", "video_url": { "url": "https://cdn.example.com/motion.mp4" } }, { "type": "audio_url", "role": "reference_audio", "audio_url": { "url": "https://cdn.example.com/music.mp3" } } ] } }'H3-Max prompt expansion and watermark
Section titled “H3-Max prompt expansion and watermark”curl https://api.routeapi.ai/v1/video/generations \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "MiniMax-H3-Max", "prompt": "A rainy city street at night, neon signs reflected in puddles", "resolution": "480P", "duration": 6, "metadata": { "aigc_watermark": false, "extra": { "prompt_expansion_mode": "quality" } } }'Task status and result
Section titled “Task status and result”Status mapping
Section titled “Status mapping”MiniMax task.status | data.status | data.progress |
|---|---|---|
queued | QUEUED | 20% |
running | IN_PROGRESS | 50% |
succeeded with content.url | SUCCESS | 100% |
succeeded without content.url | FAILURE | 100% |
failed, cancelled | FAILURE | 100% |
| any other value | IN_PROGRESS | 30% |
A succeeded task with no video URL is failed with fail_reason upstream succeeded without video url and refunded. A failed or cancelled task reports MiniMax’s task.error.message (every URL removed and replaced with [url omitted]); when MiniMax sends no message the reason is task failed or task cancelled.
An error envelope ({"type":"error","error":{...}}) makes that poll cycle fail and the task is queried again next time. A body with no task object at all falls back to the older /v1 response shape, which is empty, so the task simply stays IN_PROGRESS. A task that never reaches a terminal state is failed by the platform timeout — 24 hours by default — with fail_reason 任务超时(1440分钟), and the reservation is refunded.
The task record
Section titled “The task record”GET /v1/video/generations/{task_id} returns the RouteAPI task row; Get a task documents every field. For this vendor the useful ones are:
| Field | Description |
|---|---|
data.status / data.progress | Task state and progress, from the table above |
data.result_url | Video URL once the task succeeded |
data.fail_reason | Failure reason, empty otherwise |
data.quota | Quota charged for the task |
data.properties.input | Snapshot of the request RouteAPI sent upstream, with media URLs replaced by [omitted, N bytes]; useful when disputing a charge |
data.data | The latest MiniMax payload |
{ "code": "success", "message": "", "data": { "task_id": "task_FQvcRkHE9wjSWwyISDcrWCKoqCPNdkCx", "platform": "35", "group": "default", "action": "generate", "status": "SUCCESS", "progress": "100%", "fail_reason": "", "result_url": "https://cdn.minimax.example/video/424010985738629.mp4?Expires=...", "submit_time": 1792412645, "start_time": 1792412650, "finish_time": 1792412780, "data": { "task": { "id": "424010985738629", "status": "succeeded", "content": { "url": "https://cdn.minimax.example/video/424010985738629.mp4?Expires=..." }, "resolution": "768P", "usage": { "output_seconds": 5, "input_seconds": 0, "input_image_count": 1 } } } }}Inner fields worth reading:
| Field | Description |
|---|---|
data.data.task.id | MiniMax task ID, different from the RouteAPI task_id |
data.data.task.status | queued, running, succeeded, failed or cancelled |
data.data.task.content.url | Video URL on success; this is what result_url holds |
data.data.task.resolution | Resolution MiniMax reports. Billing uses the requested one, not this |
data.data.task.usage.output_seconds | Length of the produced video, used for settlement |
data.data.task.usage.input_seconds | Length of the reference video, used for settlement |
data.data.task.usage.input_image_count | Image count reported by MiniMax; settlement uses the submitted count instead |
data.data.task.error.code / .message | Failure detail when MiniMax reports one |
Before the first successful poll, data.data is the raw submit response ({"task_id": "..."}) and has no task field. task.usage appears when MiniMax returns it, which is normally on success. Always branch on the outer data.status.
Downloading the video
Section titled “Downloading the video”data.result_url already points at MiniMax’s CDN. That link expires on MiniMax’s schedule, so download it as soon as the task reports SUCCESS.
- Direct CDN link: fetch it without an
Authorizationheader; some storage rejects extra auth headers. https://api.routeapi.ai/v1/videos/{task_id}/content: streams the same stored URL through RouteAPI and needsAuthorization: Bearer $ROUTEAPI_KEY. It re-fetches the stored link, so it does not extend the expiry. Use it when your client must not see the upstream host, or when the CDN refuses direct access. It answers404 Task not foundfor an unknown task, and400 Task is not completed yet, current status: ...until the task succeeds.
# direct CDN linkcurl -L -o out.mp4 "$RESULT_URL"# RouteAPI proxycurl -L -o out.mp4 -H "Authorization: Bearer $ROUTEAPI_KEY" \ "https://api.routeapi.ai/v1/videos/$TASK_ID/content"Billing
Section titled “Billing”Per-second billing applies when the model has a fixed price configured for your account (the console model detail page shows it). If the model is priced only by model ratio, the normal per-task charge applies and there is no completion-time settlement. With per-second billing, a charge has three components:
| Component | Unit price | Counted at submit (reservation) | Counted at settlement |
|---|---|---|---|
| Output video | per second, for the requested resolution | the requested duration | min(usage.output_seconds, duration) |
| Reference video input | per second, for the requested resolution | 15 s whenever content contains a reference_video | usage.input_seconds, valid only in the 2–15 s range |
| Images | per image beyond the free allowance | every image item in the built content, frames included | the same count from the submit snapshot |
Prices and the free-image allowance are configured per account; the built-in defaults allow 5 free images on MiniMax-H3 and 2 on MiniMax-H3-Max, but the console is authoritative. No prices are quoted on this page.
| Timing | Output seconds | Reference-video seconds |
|---|---|---|
| Reserved at submit | the requested duration | 15 s if the request has a reference video |
| Settled on success | usage.output_seconds, capped at the requested duration | usage.input_seconds when it is between 2 and 15 s |
Rules:
- Settlement only ever refunds: the final charge is the smaller of the recomputed amount and the reservation.
- Settlement uses the unit prices frozen at submit time. A price change while a task is running does not affect it.
- Without a reference video there is no input-seconds component at all, and
usage.input_secondsis ignored. - Reference audio is free, and the image component does not change at settlement.
- Because a request with a reference video reserves 15 s of input, the balance must cover that worst case even when the video is shorter.
- If
usageis missing,output_secondsis0or above 15, or (with a reference video)input_secondsis missing or outside 2–15, RouteAPI keeps the whole reservation and refunds nothing. Keep reference videos between 2 and 15 seconds to avoid that. - A failed or timed-out task refunds the whole reservation; a request rejected with
400is never charged. - The submit response’s
X-New-Api-Other-Ratiosheader carries the multiplier applied to the model price ash3_units(a 5-second768Ptask is{"h3_units": 5}) when per-second billing applies. It is{}for the 2.3 family, and for an H3 model that is not priced with a fixed task price.
Worked example
Section titled “Worked example”Hypothetical prices, for arithmetic only: MiniMax-H3 at 768P costs $0.10 per output second, $0.10 per reference-video second, and $0.04 per image beyond 5 free images. A 10-second request with two reference images and one reference video:
- Reservation: 10 × 0.10 (output) + 15 × 0.10 (reference video, capped) + max(0, 2 − 5) × 0.04 (images) = $2.50.
- MiniMax returns
output_seconds: 8andinput_seconds: 6: 8 × 0.10 + 6 × 0.10 + 0 = $1.40. - The difference, $1.10, is returned to the balance.
Errors
Section titled “Errors”Submission is validated before anything is reserved, so a 400 costs nothing. MiniMax business rejections arrive inside an HTTP 200 response and are mapped like this:
MiniMax base_resp.status_code | Meaning | HTTP to you | code |
|---|---|---|---|
1026 | Content / safety rejection | 400 | 1026 |
2013 | Parameter error | 400 | 2013 |
1002 | Rate limited | 429 | 1002 |
1004, 2049 | Upstream key / auth failure | 401, normally returned as 503 | 1004 / 2049, or get_channel_failed |
1008 | Upstream balance exhausted | 503 | get_channel_failed |
| any other code | Unknown business error | 502 | the numeric code |
— (unparsable body, or a type: "error" envelope) | Malformed submit response | 502 | invalid_response |
— (empty task_id) | No upstream task ID | 502 | upstream_task_id_missing |
Upstream account failures are never shown verbatim. The adaptor maps 1008 to 402 and the auth codes 1004 / 2049 to 401; RouteAPI then classifies the failure as a channel fault and answers 503 get_channel_failed with a generic “upstream service is temporarily unavailable” message, after trying another channel if one is available. The 402 from 1008 is surfaced as 503 for the same reason. MiniMax’s status_msg in these cases never reaches you. A 429 keeps its status but the message is replaced with a generic saturation notice. A 400 carries MiniMax’s own text prefixed with hailuo api error: .
If MiniMax answers with a non-200 HTTP status, the body is not parsed: you get code fail_to_fetch_task with that status. Querying an unknown or foreign task_id returns 400 with code task_not_exist.
Errors raised before the request reaches MiniMax follow the shared rules in Common Errors: 401 for a missing or invalid API key, 403 insufficient_user_quota when the balance cannot cover the reservation (including the 15-second reference-video worst case), and 403 with This token has no access to model ... when the key is not allowed to use the model.
Common 400 messages (code invalid_request unless noted):
message | Cause |
|---|---|
prompt is required | prompt is missing or blank |
seconds must be between 1 and 3600 (code invalid_seconds) | Top-level duration is negative or above 3600 |
invalid seconds: abc | seconds is not an integer string |
<model> 请使用 resolution(480P/768P/2K),不支持 size | size was sent at the top level or in metadata; the message names your model and always lists 480P/768P/2K |
invalid resolution: 1080P, MiniMax-H3 supports 768P, 2K | Resolution not supported by that model |
invalid duration: 3, MiniMax-H3 supports integer 4-15 | Duration below the model minimum, above 15, or not an integer |
invalid ratio: 2:1, supports adaptive, 21:9, 16:9, 4:3, 1:1, 3:4, 9:16 | Ratio not in the list |
text-to-video does not support ratio adaptive | adaptive on a request with no frames and no references |
at most 2 top-level images (first_frame, last_frame), got 3; use metadata.content for reference media | More than 2 entries in images |
images must not contain empty values | Blank entry in images |
metadata.content cannot be combined with top-level images | Both were sent |
metadata.content must be a non-empty array | content is [] |
prompt 与 metadata.content 中的 text 冲突 | The text item differs from prompt |
metadata.content accepts at most one text item | More than one text item |
text exceeds 7000 characters | Prompt over 7000 characters |
invalid content type "foo" | Unknown type |
invalid role "foo" for image_url | Unknown image role |
image_url without role is only allowed as the single input image | Untagged image mixed with other media |
last_frame requires first_frame | Only a last frame was sent |
at most one first_frame and one last_frame | Duplicate frame roles |
first/last frame images cannot be combined with reference media | Frames mixed with reference media |
at most 9 reference images / at most 3 reference videos / at most 3 reference audios / at most 12 media items | A per-type or total media limit was exceeded |
video_url requires role reference_video / audio_url requires role reference_audio | Wrong or missing role for that item type |
image_url.url must be an http(s) URL or data URI (same for video_url / audio_url) | Unsupported URL scheme, including mm_file:// |
MiniMax-H3 does not support extra | metadata.extra sent to a non-Max model |
invalid extra.prompt_expansion_mode: balance, supports disabled, balanced, quality | Unknown expansion mode |
invalid metadata: ... | A metadata key has the wrong JSON type |
Failures that happen after a successful submission — content moderation, an asset that cannot be downloaded, a cancelled or timed-out task — never appear as HTTP errors. They show up on the task record as FAILURE with a fail_reason, and the reservation is refunded.
Differences from the MiniMax API
Section titled “Differences from the MiniMax API”- The paths are RouteAPI’s:
POST /v1/video/generationsandGET /v1/video/generations/{task_id}. MiniMax’s/v2/video_generationand/v2/query/video_generation/{id}are not exposed, so swapping the base URL in an official SDK does not work. - The prompt goes in the top-level
prompt, and MiniMax’scontentarray goes inmetadata.content. RouteAPI builds the upstreamcontent, including the text item, and the first-frame / last-frame shortcuts throughimageshave no MiniMax equivalent. - The
task_idyou receive is RouteAPI’s. MiniMax’s own task ID only appears indata.data.task.id. - RouteAPI validates the item types, roles, counts and URL schemes before forwarding — stricter than MiniMax, which leaves most of it to the generation step.
- Only
model,content,resolution,duration,ratio,aigc_watermarkandextraare forwarded. Other MiniMax parameters,callback_urlincluded, are dropped. - Media must be public
http(s)ordata:URLs; MiniMaxmm_file://file IDs cannot be used. resolutionanddurationare filled in by RouteAPI when omitted (768P, 5 s), so the upstream always receives explicit values.- On success RouteAPI stores MiniMax’s
content.urlasresult_url; there is no separate file-retrieval step to call.
Complete polling script
Section titled “Complete polling script”Needs bash, curl and jq. It submits a 5-second text-to-video task, polls every 15 seconds for up to 30 minutes, downloads the result (adding Authorization only for the RouteAPI proxy form) and prints the billed usage.
#!/usr/bin/env bashset -euo pipefail
: "${ROUTEAPI_KEY:?export ROUTEAPI_KEY first}"BASE="${ROUTEAPI_BASE:-https://api.routeapi.ai}"AUTH="Authorization: Bearer $ROUTEAPI_KEY"
TASK_ID=$(curl -sS -X POST "$BASE/v1/video/generations" \ -H "$AUTH" -H "Content-Type: application/json" \ -d '{ "model": "MiniMax-H3", "prompt": "A paper boat drifting down a rain-soaked street, cinematic lighting", "resolution": "768P", "ratio": "16:9", "duration": 5 }' | jq -er '.task_id')
echo "task: $TASK_ID"
for _ in $(seq 1 120); do RESP=$(curl -sS "$BASE/v1/video/generations/$TASK_ID" -H "$AUTH") STATUS=$(jq -r '.data.status // empty' <<<"$RESP") echo "status: ${STATUS:-unknown} $(jq -r '.data.progress // ""' <<<"$RESP")"
case "$STATUS" in SUCCESS) URL=$(jq -r '.data.result_url' <<<"$RESP") OUT="$TASK_ID.mp4" if [[ "$URL" == *"/v1/videos/"*"/content" ]]; then curl -sSL -o "$OUT" -H "$AUTH" "$URL" else curl -sSL -o "$OUT" "$URL" fi echo "saved: $OUT" jq -r '.data.data.task.usage // {}' <<<"$RESP" exit 0 ;; FAILURE) echo "failed: $(jq -r '.data.fail_reason' <<<"$RESP")" >&2 exit 1 ;; esac
sleep 15done
echo "gave up after 30 minutes" >&2exit 1MiniMax-Hailuo-2.3
Section titled “MiniMax-Hailuo-2.3”MiniMax-Hailuo-2.3 and MiniMax-Hailuo-2.3-Fast use MiniMax’s /v1/video_generation API and are priced per task, not per second. RouteAPI submits, polls /v1/query/video_generation, then resolves the result through MiniMax’s /v1/files/retrieve and stores the download URL in result_url.
| Model ID | Notes |
|---|---|
MiniMax-Hailuo-2.3 | Text-to-video and image-to-video |
MiniMax-Hailuo-2.3-Fast | Faster, cheaper variant of 2.3 |
Both default to 768P and 6 seconds. The Task API does not range-check resolution or duration for this family beyond the shared 0–3600 limit: values are forwarded and MiniMax decides. The console playground offers 768P / 1080P and 6 or 10 seconds, with 1080P limited to 6 seconds.
How the request maps (2.3)
Section titled “How the request maps (2.3)”| Envelope field | What the adaptor does |
|---|---|
prompt | Sent as prompt; metadata.prompt overrides it |
duration | Sent as duration; omitted or 0 becomes 6 |
size | Converted to resolution by substring: 1080 → 1080P, 768 → 768P, 720 → 720P, 512 → 512P; anything else falls back to the model default |
images / image | Not read. Image input must go through metadata.first_frame_image |
ratio, generate_audio, seconds | Not read. This family has no aspect-ratio or soundtrack parameter |
metadata | Decoded into MiniMax’s fields using MiniMax’s names |
resolution is not read from the top level for this family: use size or metadata.resolution.
Vendor parameters (2.3)
Section titled “Vendor parameters (2.3)”These go under metadata. A value of the wrong JSON type (for example "duration": "abc") fails the conversion with 500 build_request_failed, not 400; unknown keys are ignored.
| Field | Type | Description |
|---|---|---|
resolution | string | 768P or 1080P; overrides whatever size produced |
duration | integer | 6 or 10 seconds; overrides the top-level duration |
first_frame_image | string | First-frame image (public URL or base64 data: URI), forwarded as sent |
last_frame_image | string | Last frame for start-end-to-video, forwarded as sent |
subject_reference | array | Subject reference for subject-reference-to-video: [{"type": "character", "image": ["<url>"]}] |
prompt_optimizer | boolean | Let MiniMax rewrite the prompt; an explicit false is forwarded |
fast_pretreatment | boolean | MiniMax fast pre-treatment flag, forwarded as sent |
aigc_watermark | boolean | Add the provider’s AIGC watermark |
callback_url | string | Forwarded to MiniMax. RouteAPI does not register or receive callbacks — poll for the result |
prompt | string | Overrides the top-level prompt |
metadata.model is overwritten with the channel’s upstream model name, so a request cannot switch to a different model through metadata.
Image to video (2.3)
Section titled “Image to video (2.3)”curl https://api.routeapi.ai/v1/video/generations \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "MiniMax-Hailuo-2.3", "prompt": "The camera slowly pushes in as the subject looks up and smiles", "duration": 6, "metadata": { "resolution": "1080P", "first_frame_image": "https://cdn.example.com/first.jpg" } }'Status mapping (2.3)
Section titled “Status mapping (2.3)”MiniMax v1 reports Preparing, Queueing, Processing, Success and Fail.
| Upstream status | Task record status | Progress |
|---|---|---|
Preparing, Queueing | IN_PROGRESS | 30% |
Processing | IN_PROGRESS | 50% |
Success | SUCCESS | 100% |
Fail | FAILURE | 100% |
On success the adaptor calls MiniMax’s file-retrieval endpoint for the returned file_id and stores the resulting download URL in result_url. That URL expires on MiniMax’s schedule; GET /v1/videos/{task_id}/content streams the stored URL through RouteAPI and needs Authorization.
Billing (2.3)
Section titled “Billing (2.3)”The 2.3 family is charged the model’s task price configured in the console. The resolution and duration you send do not change the charge, and there is no completion-time settlement; a failed task refunds the reservation. X-New-Api-Other-Ratios is {}.
Errors (2.3)
Section titled “Errors (2.3)”| Status | code | Meaning |
|---|---|---|
| 400 | invalid_request | Missing or blank prompt, or malformed JSON |
| 400 | invalid_seconds | duration / seconds is negative or above 3600 |
| 400 | MiniMax’s numeric code | MiniMax rejected the task; the message is its status_msg |
| 400 | task_not_exist | The task_id is unknown or belongs to another account |
| 500 | build_request_failed, do_request_failed | Metadata conversion failed, or the upstream was unreachable |
| 500 | unmarshal_response_body_failed | MiniMax answered in a shape the adaptor does not recognize |
| 502 | upstream_task_id_missing | The submit response carried no task ID |
| upstream status | fail_to_fetch_task | MiniMax answered with a non-200 HTTP status |
For this family every MiniMax business rejection is returned as 400 with MiniMax’s numeric code and status_msg, including rate limiting — check the numeric code, not the HTTP status. The exception is an upstream balance failure: when MiniMax’s status_msg matches RouteAPI’s built-in billing keywords (insufficient balance and similar), the response is sanitized to 503 get_channel_failed with a generic message, and the failure is recorded as a channel fault (the channel is auto-disabled only when automatic disabling is enabled and the channel allows it).
Failures after submission (moderation, provider timeout) appear on the task record as FAILURE with a fail_reason, and the pre-charged amount is refunded.