This reference describes requests, responses, and errors for developers using the video_generation service.
The compatibility baseline is the official MiniMax documentation for video generation and file upload.
Every request sends Authorization: Bearer <API_KEY> in the header. Request bodies use application/json except for file upload.
Overview
| Method | Path | Purpose |
|---|---|---|
POST | /v2/video_generation | Create a video generation task |
GET | /v2/query/video_generation/{task_id} | Query a single video task |
GET | /v2/query/video_generation | List video tasks |
DELETE | /v2/video_generation/{task_id} | Cancel or delete a task |
POST | /v1/files/upload | Upload a media file (multipart) |
GET | /v1/files/list?purpose=video_generation_input | List media files |
GET | /v1/files/retrieve?file_id={int64} | Get file metadata and download URL |
GET | /v1/files/retrieve_content?file_id={int64} | Get file content |
POST | /v1/files/delete | Delete a file |
Create a video generation task
POST /v2/video_generation
Success response
Success returns HTTP 200 with a JSON body:
{"task_id":"1d6085ca-1d9a-4d61-a4a6-30e02079990f"}| Field | Type | Description |
|---|---|---|
task_id | string | UUID of the new task; use it to query, cancel, or delete the task |
Top-level fields
| Field | Contract |
|---|---|
model | required; currently only MiniMax-H3 |
content | required non-empty array |
resolution | required; currently only 768P |
duration | required integer; 4–15 seconds |
ratio | conditional rules below |
callback_url | optional; status notifications are not currently supported |
aigc_watermark | optional boolean, default false; watermarks are not added during the current testing stage |
context_ir_enabled | EcoPhase extension; optional boolean, default true |
The current capability supports768P,24 FPS,MP4/H.264, text-only generation, and first/last-frame video generation.context_ir_enabledcontrols Context IR prompt optimization and defaults totrue, so prompt optimization is enabled unless explicitly disabled.
Create example
curl -X POST "https://ecotoken.ecophase-ai.com/v2/video_generation" \
-H "Authorization: Bearer ${VIDEO_API_KEY}" \
-H "Idempotency-Key: video-create-001" \
-H "Content-Type: application/json" \
-d '{
"model":"MiniMax-H3",
"content":[{"type":"text","text":"a cinematic sunrise over an alpine lake"}],
"resolution":"768P",
"duration":5,
"ratio":"16:9"
}'content
Every content item has a required type:
| type | Field that carries the value |
|---|---|
text | text; exactly one non-empty prompt required, maximum 7,000 characters |
image_url | image_url.url |
video_url | video_url.url |
audio_url | audio_url.url |
Supported URL forms are public HTTP(S), mm_file://{file_id}, and strict Base64-encoded data:<media-type>;base64,<standard-base64> values. The entire JSON request body is at most 64 MiB. Upload large or reusable media first.
data:<media-type>;base64,<standard-base64>is a Data URL that embeds a small file directly in the JSON request, so it does not need to be uploaded first to obtain a public URL. -data:indicates that the value contains file data rather than a normal network address. -<media-type>is the file MIME type, such asimage/pngoraudio/mpeg. -base64is the fixed marker declaring Base64 encoding. -<standard-base64>is the original file encoded with standard Base64.
Roles are first_frame, last_frame, reference_image, reference_video, and reference_audio. A single image with no role defaults to first frame. Video and audio inputs use their corresponding reference roles.
Accepted scenes:
- text only;
- text + first frame;
- text + last frame;
- text + first and last frame;
- text + any valid combination of reference images/videos/audio.
Frame roles and reference roles are mutually exclusive. First and last frame may each occur at most once.
Media validation
| Input | Format | Per-file | Complete request |
|---|---|---|---|
| image | JPG/JPEG, PNG, WebP, HEIC, HEIF | ≤30 MiB; width and height 256..5760 px; ratio 0.4..2.5 | first ≤1, last ≤1, reference images ≤9 |
| video | MP4/MOV; H.264/AVC or H.265/HEVC; AAC/MP3 audio | ≤50 MiB; 2..15 s; dimensions 256..5760; ratio 0.4..2.5; FPS 23.976..60 | videos ≤3; sum of all video durations ≤15 s |
| audio | PCM WAV/MP3 | ≤15 MiB; 2..15 s | audio files ≤3; sum of all audio durations ≤15 s |
ratio
- For T2VA,
ratiois required and cannot beadaptive; it must be one of21:9|16:9|4:3|1:1|3:4|9:16. - For I2VA, the ratio is derived from the input: an omitted value,
adaptive, or another otherwise-valid ratio is normalized toadaptive. - For R2VA, the default is
adaptive, and it can be changed to one of21:9|16:9|4:3|1:1|3:4|9:16.
Query a single task
GET /v2/query/video_generation/{task_id}
Response format
{
"task": {
"id": "1d6085ca-1d9a-4d61-a4a6-30e02079990f",
"model": "MiniMax-H3",
"status": "succeeded",
"created_at": 1787788800,
"updated_at": 1787789100,
"content": {"url": "https://SHORT_LIVED_DOWNLOAD_URL"},
"resolution": "768P",
"duration": 8,
"usage": {"input_image_count": 1},
"ratio": "adaptive",
"task_type": "generation",
"modality": "video"
}
}Task response fields
| Field | Type | Description |
|---|---|---|
task | object | Video task object |
task.id | string | Task UUID |
task.model | string | Model used to create the task |
task.status | string | queued, running, succeeded, failed, or cancelled |
task.error | object, optional | Failure details containing code and message; returned only on failure |
task.created_at | integer | Creation time as Unix seconds |
task.updated_at | integer | Last update time as Unix seconds |
task.content | object, optional | Contains the short-lived output url after success |
task.resolution | string, optional | Effective resolution tier, such as 768P |
task.duration | integer | Requested video duration in seconds |
task.usage | object | Confirmed usage; {} when no authoritative data exists, with absent counters treated as 0 |
task.ratio | string | Normalized aspect ratio; usually adaptive for frame generation |
task.task_type | string | generation for current video tasks |
task.modality | string | Always video |
task.internal_status | string, optional | EcoPhase's precise processing phase: submitting, context_ir_queued, context_ir_running, video_generation_submitting, video_generation_running, or completed |
task.phase_started_at | integer, optional | Current phase start time as Unix seconds |
task.completed_at | integer, optional | Completion time as Unix seconds |
task.failed_phase | string, optional | Failure phase: context_ir or video_generation |
task.context_ir | object, optional | Prompt optimization result and usage, described below |
Task status monitoring
We recommend using task.internal_status to monitor the precise processing phase. The MiniMax API field task.status does not distinguish every processing phase accurately.
Official MiniMax task.status | EcoPhase task.internal_status | Description |
|---|---|---|
queued | submitting | The request has been accepted and the task is being prepared |
queued | context_ir_queued | The Context IR prompt-optimization task is queued |
running | context_ir_running | Context IR is optimizing the prompt |
queued | video_generation_submitting | The task is being submitted to the video execution service |
queued or running | video_generation_running | The video task has been created; it is queued while waiting at the execution service and running after execution starts |
succeeded, failed, or cancelled | completed | EcoPhase orchestration has ended; use task.status for the final outcome. Internal expiry also maps to official failed |
task.context_ir fields:
| Field | Type | Description |
|---|---|---|
enabled | boolean | Whether Context IR was enabled for this task |
status | string | submitting, queued, running, succeeded, failed, cancelled, or skipped |
original_prompt | string | Original user prompt |
optimized_prompt | string, optional | Optimized prompt |
usage | object | Token usage, possibly including prompt_tokens, completion_tokens, and total_tokens |
started_at | integer, optional | Optimization start time as Unix seconds |
completed_at | integer, optional | Optimization completion time as Unix seconds |
error | object, optional | Optimization failure containing code and message |
Use task.content.url only after succeeded. The URL is short-lived and should not be persisted or cached for long periods.
task.context_ir reports enabled, status, original_prompt, optimized_prompt, token usage, started_at, completed_at, and an optional error. A Context IR failure fails the whole task and identifies failed_phase=context_ir.
Billing semantics
A video task is charged only when it succeeds:
- Only a terminal status of `succeeded` is charged at all: priced on the measured output seconds times the resolution tier, plus this run's Context IR call (
context_ir.status=succeeded, billed per call per task). - Any other terminal status (including `failed`, `cancelled`, and expiry) is free: output video, reference images, input audio/video, and the Context IR line are all waived. Prompt optimization is an intermediate step toward the video rather than a standalone deliverable, so no video means the whole pre-authorization is released.
- A task is entirely free in two cases: the video generation failed or was cancelled, and the Context IR stage itself failed (no prompt delivered).
- Retrying after a failure with a fresh idempotency key is therefore safe: a failure costs nothing. Resending with the same idempotency key does not re-execute the task and adds no charge (the original task is returned within 7 days).
List tasks
GET /v2/query/video_generation?page_num=&page_size=&filter.status=&filter.task_ids=&filter.model=
Tenant isolation is always applied. page_num defaults to 1; page_size defaults to 20 with a current maximum of 20. The list covers only tasks created in the most recent 7 days.
Query parameters support filter.status, filter.task_ids (repeat the parameter or use filter.task_ids[]; at most 100 lowercase canonical UUIDs), and filter.model. Response:
{
"items": [
{
"id": "1d6085ca-1d9a-4d61-a4a6-30e02079990f",
"model": "MiniMax-H3",
"status": "succeeded",
"created_at": 1787788800,
"updated_at": 1787789100,
"content": {"url": "https://SHORT_LIVED_DOWNLOAD_URL"},
"resolution": "768P",
"duration": 5,
"usage": {},
"ratio": "16:9",
"task_type": "generation",
"modality": "video"
}
],
"total": 1
}total is the number of tasks matching the filters in the most recent 7 days.
| Field | Type | Description |
|---|---|---|
items | array | Tasks on the current page; each item has the same shape as task in the single-task response |
total | integer | Total matching tasks inside the recent 7-day window |
Cancel or delete a task
DELETE /v2/video_generation/{task_id}
A queued task returns action=cancelled,status=cancelled only after cancellation is confirmed. While confirmation is pending, it remains queryable as queued and DELETE returns a retryable 503. If the first request used an Idempotency-Key, reuse that key when retrying. A running task cannot be cancelled and returns 400. A succeeded or failed terminal task can be logically removed from the compatibility list and returns action=deleted,status=deleted.
Success response body:
{
"task_id": "1d6085ca-1d9a-4d61-a4a6-30e02079990f",
"action": "cancelled",
"status": "cancelled"
}deleted describes the delete operation only; task.status in query responses never becomes deleted.
| Field | Type | Description |
|---|---|---|
task_id | string | UUID of the affected task |
action | string | cancelled or deleted |
status | string | cancelled or deleted, matching the operation result |
File upload and media management
Media is referenced through public HTTP(S) URLs or managed files. Five operations are provided, all scoped to the authenticated user's media space. Different API keys and workspaces for one user share that space. Another user only receives not-found responses and cannot infer whether a file exists.
File-management JSON responses reuse these objects:
| Field | Type | Description |
|---|---|---|
file.file_id | integer | File ID; reference it in video requests as mm_file://{file_id} |
file.bytes | integer | File size in bytes |
file.created_at | integer | Upload time as Unix seconds |
file.filename | string | Original upload filename |
file.purpose | string | Always video_generation_input |
file.download_url | string, optional | Short-lived download URL returned by file retrieval |
base_resp.status_code | integer | 0 indicates success |
base_resp.status_msg | string | success on success |
Upload
POST /v1/files/upload, using multipart/form-data. It must contain one purpose=video_generation_input field and one file part named file, with no other fields. The full request is limited to 64 MiB. Invalid media returns HTTP 400 and is not retained. Reference the result as mm_file://{file_id}. Files are retained for one day by default and can be deleted earlier.
curl -X POST "https://ecotoken.ecophase-ai.com/v1/files/upload" \
-H "Authorization: Bearer ${VIDEO_API_KEY}" \
-H "Idempotency-Key: media-upload-001" \
-F "purpose=video_generation_input" \
-F "file=@./reference.mp4;type=video/mp4"Success response:
{
"file": {
"file_id": 424010985738629,
"bytes": 1234567,
"created_at": 1788148800,
"filename": "reference.mp4",
"purpose": "video_generation_input"
},
"base_resp": {"status_code": 0, "status_msg": "success"}
}| Field | Type | Description |
|---|---|---|
file | object | Stored file object |
base_resp | object | MiniMax-compatible result; status_code=0 indicates success |
List
GET /v1/files/list?purpose=video_generation_input
The success response contains all unexpired files owned by the current user:
{
"files": [
{
"file_id": 424010985738629,
"bytes": 1234567,
"created_at": 1788148800,
"filename": "reference.mp4",
"purpose": "video_generation_input"
}
],
"base_resp": {"status_code": 0, "status_msg": "success"}
}| Field | Type | Description |
|---|---|---|
files | array | Unexpired file objects owned by the current user; [] when empty |
base_resp | object | MiniMax-compatible result; status_code=0 indicates success |
Retrieve a file
GET /v1/files/retrieve?file_id=424010985738629
{
"file": {
"file_id": 424010985738629,
"bytes": 1234567,
"created_at": 1788148800,
"filename": "reference.mp4",
"purpose": "video_generation_input",
"download_url": "https://download.example/reference.mp4"
},
"base_resp": {"status_code": 0, "status_msg": "success"}
}| Field | Type | Description |
|---|---|---|
file | object | File metadata with an additional short-lived download_url |
base_resp | object | MiniMax-compatible result; status_code=0 indicates success |
download_url is short-lived. Retrieve fresh metadata whenever a download is needed.
Download file content
GET /v1/files/retrieve_content?file_id=424010985738629
On success, the response body contains the file bytes with the corresponding Content-Type; it is not JSON. The client only sends its own EcoPhase API key.
| Response header | Description |
|---|---|
Content-Type | Actual file media type |
Content-Length | File size, when available |
Delete
POST /v1/files/delete. The delete request uses purpose=video_generation; upload and list continue to use video_generation_input.
{"file_id":424010985738629,"purpose":"video_generation"}Success response:
{
"file_id": 424010985738629,
"base_resp": {"status_code": 0, "status_msg": "success"}
}| Field | Type | Description |
|---|---|---|
file_id | integer | ID of the deleted file |
base_resp | object | MiniMax-compatible result; status_code=0 indicates success |
Deleting the same file_id and purpose again as the same user is idempotent.
Error envelope
Video generation uses the MiniMax-compatible error envelope:
{
"type": "error",
"error": {"type": "bad_request_error", "message": "...", "http_code": "400"},
"request_id": "..."
}| HTTP | Meaning |
|---|---|
400 | Invalid JSON, fields, multipart body, media constraints, query parameters, or task state; task/file missing, deleted, or owned by another user |
401 | Missing, invalid, revoked, or insufficiently scoped API key |
409 | An idempotency key conflicts with different content, or the same operation is still in progress |
413 | The JSON request body exceeds the 64 MiB limit |
422 | A synchronously detected content-policy rejection |
429 | Identity rate limit or video execution capacity is temporarily exhausted; follow Retry-After |
500 | Internal service error |
503 | A dependency, current deployment capability, or cancellation confirmation is temporarily unavailable |
Error response fields:
| Field | Type | Description |
|---|---|---|
type | string | Always error |
error.type | string | Error category such as bad_request_error, invalid_request_error, authorized_error, rate_limit_error, or server_error |
error.message | string | Human-readable error description suitable for display or logging |
error.http_code | string | HTTP status code represented as a string |
request_id | string | Request trace ID to include when reporting a problem |
Idempotency
Video generation, file upload, and task deletion support an optional Idempotency-Key. The value must contain 1–128 safe ASCII characters and is scoped to the current endpoint, service, workspace, and authenticated user. Rotating an API key for the same user does not change replay identity. A video-create key remains active for seven days after the first successful creation.
After an operation completes, the same key and request return the previous result. The same key with different content returns 409. An identical request may also receive 409 while the first operation is still in progress; retry later with exactly the same key and request. Deleting a task does not release its original create key. Reusing the key after the window expires creates a new task.
