Asynchronous video generation
Use one asynchronous task API for text-to-video, first-frame, last-frame, and first-and-last-frame video-with-audio generation (FL2VA), plus multimodal reference video-with-audio generation (Ref2VA). Query the task by ID and download the MP4 result after it succeeds.
Authorization and request format
$WYLON_API_KEY environment variable.application/json when creating a task.Confirm model capabilities
FL2VA and Ref2VA use separate models. Call List models first to confirm that your API key can access the target model.
| Model ID | Capability | Supported inputs |
|---|---|---|
MiniMaxAI/MiniMax-H3 | Text-to-video and first-frame, last-frame, or first-and-last-frame video with audio | Text and 0–2 images |
MiniMaxAI/MiniMax-H3-Ref2VA | Multimodal reference video with audio | Text + at least one reference image or video; reference audio may also be added |
| Parameter | FL2VA | Ref2VA | Default |
|---|---|---|---|
duration | 5–15 seconds | 5–15 seconds | 5 |
resolution | 768P | 768P | 768P |
ratio | 21:9, 16:9, 4:3, 1:1, 3:4, 9:16, adaptive | 21:9, 16:9, 4:3, 1:1, 3:4, 9:16 | 16:9; adaptive when FL2VA includes images |
Create a video task
Pass the prompt and reference media in the content array. Every request must contain exactly one non-empty type=text block. The following example creates an FL2VA task from a first-frame image.
curl -sS --max-time 60 \
-X POST "https://api.wylon.cn/v1/contents/generations/tasks" \
-H "Authorization: Bearer ${WYLON_API_KEY}" \
-H "Content-Type: application/json" \
--data-binary '{
"type": "video",
"model": "MiniMaxAI/MiniMax-H3",
"content": [
{"type": "text", "text": "Slowly push the camera forward as the subject turns naturally in the breeze, maintaining a cinematic look."},
{"type": "image_url", "image_url": {"url": "https://example.com/first-frame.jpg"}, "role": "first_frame"}
],
"duration": 5,
"resolution": "768p",
"ratio": "16:9"
}' -o video-create-response.json
import os
import requests
response = requests.post(
"https://api.wylon.cn/v1/contents/generations/tasks",
headers={"Authorization": f"Bearer {os.environ['WYLON_API_KEY']}"},
json={
"type": "video",
"model": "MiniMaxAI/MiniMax-H3",
"content": [
{"type": "text", "text": "Slowly push the camera forward as the subject turns naturally in the breeze, maintaining a cinematic look."},
{"type": "image_url", "image_url": {"url": "https://example.com/first-frame.jpg"}, "role": "first_frame"},
],
"duration": 5,
"resolution": "768p",
"ratio": "16:9",
},
timeout=60,
)
response.raise_for_status()
task = response.json()
print(task["id"])
const response = await fetch(
"https://api.wylon.cn/v1/contents/generations/tasks",
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.WYLON_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
type: "video",
model: "MiniMaxAI/MiniMax-H3",
content: [
{ type: "text", text: "Slowly push the camera forward as the subject turns naturally in the breeze, maintaining a cinematic look." },
{ type: "image_url", image_url: { url: "https://example.com/first-frame.jpg" }, role: "first_frame" },
],
duration: 5,
resolution: "768p",
ratio: "16:9",
}),
},
);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const task = await response.json();
console.log(task.id);
Create parameters
video for video generation. If omitted, the server treats the request as a video task.MiniMaxAI/MiniMax-H3 or MiniMaxAI/MiniMax-H3-Ref2VA. Check access in the Model Hub or through List models.text, image_url, video_url, or audio_url.data:image/<format>;base64,<data>.data:audio/<format>;base64,<data>.first_frame, last_frame, or reference_image; videos support reference_video; audio supports reference_audio. A single first-frame image may omit role.Input combinations and limits
| Generation mode | content combination |
|---|---|
| Text-to-video | text |
| First-frame video with audio | text + one image_url with role=first_frame, or with role omitted |
| Last-frame video with audio | text + one image_url with role=last_frame |
| First-and-last-frame video with audio | text + two image_url blocks whose roles are first_frame and last_frame |
| Multimodal reference video with audio | text + at least one reference image or video block; reference audio may also be added |
- FL2VA: Do not mix
first_frame/last_framewith Ref2VAreference_*roles. For two-image requests, label one first frame and one last frame. - Ref2VA:
reference_audiocannot be the only media input. Include at least onereference_imageorreference_video.
Ref2VA request example
{
"type": "video",
"model": "MiniMaxAI/MiniMax-H3-Ref2VA",
"content": [
{"type": "text", "text": "Use the reference character and camera motion, timed to the audio."},
{"type": "image_url", "image_url": {"url": "https://example.com/character.jpg"}, "role": "reference_image"},
{"type": "video_url", "video_url": {"url": "https://example.com/camera-motion.mp4"}, "role": "reference_video"},
{"type": "audio_url", "audio_url": {"url": "https://example.com/music.mp3"}, "role": "reference_audio"}
],
"duration": 8,
"resolution": "768p",
"ratio": "16:9"
}Input media limits
| Type | Formats | Per-file limits | Count / duration |
|---|---|---|---|
| Image | JPEG, PNG, WebP, BMP, TIFF, GIF, HEIC, HEIF | 30 MB; 300–5760 px; aspect ratio 0.4–2.5 | Up to 2 for FL2VA or 9 for Ref2VA |
| Video | MP4 or MOV; H.264/AVC or H.265/HEVC; AAC or MP3 audio, plus PCM in MOV | 50 MB; 2–15 seconds; 300–5760 px; aspect ratio 0.4–2.5; 23.976–60 fps | Up to 3 for Ref2VA; 15 seconds total for MiniMax H3 |
| Audio | WAV, MP3 | 15 MB; 2–15 seconds each | Up to 3 for Ref2VA; 15 seconds total for MiniMax H3 |
Input images are measured by valid image count, while input video and audio are measured by valid duration. Output is measured by successfully generated duration and resolution. See the pricing page and your bill for current rates.
Query a task
Query the task using the id returned by the create response. Set detail=true to include the effective video_parameters in the response.
VIDEO_TASK_ID=$(jq -r '.id' video-create-response.json)
curl -sS --get \
"https://api.wylon.cn/v1/contents/generations/tasks/${VIDEO_TASK_ID}" \
-H "Authorization: Bearer ${WYLON_API_KEY}" \
--data-urlencode "detail=true" \
-o video-task-response.json
import os
import requests
task_id = os.environ["VIDEO_TASK_ID"]
response = requests.get(
f"https://api.wylon.cn/v1/contents/generations/tasks/{task_id}",
headers={"Authorization": f"Bearer {os.environ['WYLON_API_KEY']}"},
params={"detail": "true"},
timeout=30,
)
response.raise_for_status()
task = response.json()
print(task["status"])
const taskId = process.env.VIDEO_TASK_ID;
const url = new URL(
`https://api.wylon.cn/v1/contents/generations/tasks/${taskId}`,
);
url.searchParams.set("detail", "true");
const response = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.WYLON_API_KEY}` },
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const task = await response.json();
console.log(task.status);
| Status | Meaning | Recommended action |
|---|---|---|
queued | Task accepted and waiting to run | Query again later |
running | Video is being generated | Query again later |
succeeded | Task succeeded | Retrieve and download the video |
failed | Task failed | Read error |
cancelled | Queued task was cancelled | Stop polling |
expired | Task or result expired | Create a new task if needed |
Read and download the result
When status=succeeded and file_status=available, the video URL is available at content.video_url. A task returns only one MP4. If native audio is generated, it is embedded in the same file; no separate audio file or metadata is returned.
{
"id": "9065e7fd-2845-4e26-8850-1cf49a5d57c5",
"status": "succeeded",
"type": "video",
"content": {
"type": "video_url",
"video_url": "https://example.com/generated/output.mp4?signature=REDACTED",
"video_url_expires_at": 1788853117
},
"file_status": "available",
"model": "MiniMaxAI/MiniMax-H3",
"duration": 5,
"resolution": "768p",
"ratio": "16:9",
"framespersecond": 24,
"width": 1344,
"height": 768,
"output_format": "mp4",
"watermark": true
}VIDEO_URL=$(jq -r '.content.video_url // empty' video-task-response.json)
curl -L --fail --show-error "${VIDEO_URL}" -o generated-video.mp4
import json
import requests
with open("video-task-response.json", encoding="utf-8") as file:
video_url = json.load(file)["content"]["video_url"]
with requests.get(video_url, stream=True, timeout=300) as response:
response.raise_for_status()
with open("generated-video.mp4", "wb") as file:
for chunk in response.iter_content(1024 * 1024):
file.write(chunk)
import { readFile, writeFile } from "node:fs/promises";
const task = JSON.parse(
await readFile("video-task-response.json", "utf8"),
);
const response = await fetch(task.content.video_url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
await writeFile(
"generated-video.mp4",
Buffer.from(await response.arrayBuffer()),
);
The signed URL includes short-lived access credentials, so downloading normally does not require the wylon API key. Do not log or disclose the full signed URL.
Cancel or delete a task (Coming soon)
curl -sS -X DELETE \
"https://api.wylon.cn/v1/contents/generations/tasks/${VIDEO_TASK_ID}" \
-H "Authorization: Bearer ${WYLON_API_KEY}"queued: Cancels the queued task.running: A running task cannot be cancelled.succeeded,failed,expired: Deletes the task record.cancelled: No further action is allowed.
Deleting a task record or cancelling a task may be irreversible. Confirm the task ID and current status before proceeding.
Error handling and production guidance
| Status code | Common cause | Recommended action |
|---|---|---|
400 | Invalid prompt, media type, role, count, file specification, or model capability | Correct the request based on the error code and current model limits |
401, 403 | Invalid key or insufficient model or task permissions | Check authentication and account permissions |
404 | Model or task not found | Check the complete model ID, task ID, and environment |
429 | Rate, concurrency, or capacity limit reached | Reduce the request rate and retry later |
500, 503 | Internal service error or model temporarily unavailable | If creation succeeded, query the original task before retrying |
