Wan
curl --request POST \
--url https://api.mixroute.ai/v1/video/generationsimport requests
url = "https://api.mixroute.ai/v1/video/generations"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.mixroute.ai/v1/video/generations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.mixroute.ai/v1/video/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.mixroute.ai/v1/video/generations"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.mixroute.ai/v1/video/generations")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixroute.ai/v1/video/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyVideo Series
Wan
Wan 3.0, 2.7, and 2.6 video generation, reference inputs, editing, and asynchronous task handling.
Wan
curl --request POST \
--url https://api.mixroute.ai/v1/video/generationsimport requests
url = "https://api.mixroute.ai/v1/video/generations"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.mixroute.ai/v1/video/generations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.mixroute.ai/v1/video/generations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.mixroute.ai/v1/video/generations"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.mixroute.ai/v1/video/generations")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.mixroute.ai/v1/video/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyWan uses one MixRoute video endpoint. Keep model at the root and place the provider input and parameters objects inside metadata. Model versions use different input protocols; choose the exact ID and schema below.
Model availability depends on your account’s model list. A vendor model or dated snapshot not returned by your account should not be assumed available.
Use metadata.input.prompt for the prompt. Compatibility fallbacks are metadata.prompt, then top-level prompt, in that order; when present, metadata.input.prompt takes precedence. Supply a prompt or valid media input, and obey the selected model’s own required-input rules.
Native fields are forwarded without renaming. New provider fields may be supplied in their original input/parameters location; the upstream service validates model-specific combinations. This does not make a field supported by every model.
For I2V continuation with first_clip, duration controls the final total length including the source clip, not just the added seconds. For R2V, use Image 1 / Video 1 references, counting images and videos separately. Wan 2.7 uses resolution/ratio rather than the Wan 2.6 T2V/R2V size field; shot_type is no longer used. I2V output follows the source aspect ratio and omits ratio.
Wan 2.6 R2V uses character1, character2, etc., in reference_urls order, rather than the Wan 2.7 Image/Video labels. Its references require public HTTP/HTTPS or accessible OSS URLs. The standard 2.6 models listed here do not expose the audio=false switch of the separate Flash variants. Legacy effect templates are not a common capability of these eight models.
Use public URLs for portable requests. OSS temporary links and provider asset IDs are scoped to the upstream account/region and must be accessible to the selected channel. Do not send your MixRoute key when fetching a third-party CDN result URL.
The complete upstream result is retained at data.data; read usage and request_id there. UNKNOWN means the upstream task is missing or expired, not necessarily a generation error. Poll about every 15 seconds and back off on rate limits/transient errors. Upstream task lookup and result links have limited retention, typically 24 hours; save completed output promptly.
Use the console bill for final charges. Submission can reserve quota before completion; request estimates and final settlement may differ. Do not treat input/negative/zero duration values as a way to obtain a zero-cost task.
POST https://api.mixroute.ai/v1/video/generations
Models
| Model ID | Mode | Resolution | Duration (seconds) |
|---|---|---|---|
| wan3.0-video | All-in-One Video Generation | 480P / 720P / 1080P | 2-30 / -1 |
| wan2.7-t2v | Text-to-Video | 720P / 1080P | 2-15 |
| wan2.7-i2v | Image-to-Video | 720P / 1080P | 2-15 |
| wan2.7-r2v | Reference-to-Video | 720P / 1080P | 2-15 (no video) / 2-10 (with video) |
| wan2.7-videoedit | Video Editing | 720P / 1080P | 2-10 |
| wan2.6-t2v | Text-to-Video | 720P / 1080P | 2-15 |
| wan2.6-i2v | Image-to-Video | 720P / 1080P | 2-15 |
| wan2.6-r2v | Reference-to-Video | 720P / 1080P | 2-10 |
Request Envelope
| Field | Type | Required | Description |
|---|---|---|---|
model | string | Yes | Exact MixRoute model ID. |
metadata | object | Yes | Container for the provider request body, excluding model. |
metadata.input | object | Yes | Native input object. Prompt and media requirements depend on the selected model. |
metadata.parameters | object | No | Native generation settings. Preserve their field names and nesting. |
Authenticate with Authorization: Bearer and your MixRoute key. No Alibaba key, workspace ID, regional endpoint, or X-DashScope-Async header is needed. Do not send input/parameters at the root or flatten their contents directly into metadata.
Wan 3.0
| Field | Type | Required | Description |
|---|---|---|---|
metadata.input.prompt | string | By mode | Text instruction, at most 20000 characters; excess text is truncated. Required unless media is supplied. |
metadata.input.media | object[] | By mode | Media items; required unless prompt is supplied. Use the combinations below. |
metadata.input.media[].type | string | By mode | Required per item: first_frame, last_frame, reference_image, reference_video, reference_audio, file, or link. |
metadata.input.media[].url | string | By mode | Required per item. Public HTTP/HTTPS URL; supported images may use a Base64 data URI. Native OSS resources must be accessible to the route account. |
metadata.parameters.resolution | string | No | 480P, 720P, or 1080P. MixRoute explicitly fills 1080P when omitted. |
metadata.parameters.ratio | string | No | adaptive (default), 16:9, 4:3, 1:1, 3:4, or 9:16. Use adaptive for extension. |
metadata.parameters.duration | integer | No | Default 5. Without source video: 2-30 seconds. With video: total source-video duration plus generated duration must not exceed 30 seconds. -1 selects duration automatically. |
metadata.parameters.audio | boolean | No | Default true. false produces video without an audio track. |
metadata.parameters.seed | integer | No | -1 or 0-2147483647. -1 or omission selects a random seed; repeatability is not guaranteed. |
metadata.parameters.prompt_extend | boolean | No | Prompt rewriting; default true. |
metadata.parameters.watermark | boolean | No | Add an AI watermark; default false. |
Media Types
| type | Limit / Usage |
|---|---|
first_frame / last_frame | At most one of each; first frame alone or first+last frame. Do not use a last frame alone. |
reference_image | Up to 10 images. |
reference_video | Up to five videos, 1-15 seconds each, at most 15 seconds total. |
reference_audio | Up to five audio clips, 1-15 seconds each, at most 15 seconds total. |
file | One public document, at most 100 MB and 50 pages for paginated formats. |
link | One publicly accessible webpage that does not require login. |
- Frame mode (first_frame/last_frame) is mutually exclusive with reference_*, file, and link. Unlike Wan 2.7 I2V, Wan 3.0 frame mode cannot include driving audio.
- Reference images, videos, and audio may be combined. file and link are mutually exclusive, but either may accompany reference_* media. Respect every per-type limit and the overall limit of 20 media items.
- Refer to media by type-specific order: Image 1, Video 1, Audio 1, or 图1、视频1、音频1.
- Editing/extension require reference_video and a matching prompt. Use ratio=adaptive for extension; for editing, adaptive and duration=-1 preserve source framing and let the model choose the duration. Input video time plus output time must still fit within 30 seconds.
Wan 3.0 does not use size, negative_prompt, template, img_url, first_frame_url, last_frame_url, or audio_url. The gateway removes legacy fields and can convert audio_url to a reference_audio item. New requests should use input.media directly.
Wan 2.7
| Field | Type | Required | Description |
|---|---|---|---|
metadata.input.prompt | string | By mode | Up to 5000 characters, with excess truncated. Required for T2V/R2V; optional for I2V/VideoEdit when required media is present. |
metadata.input.negative_prompt | string | No | Content to exclude; at most 500 characters, with excess truncated. |
metadata.input.audio_url | string | No | T2V only: driving audio URL, WAV/MP3, 2-30 seconds, at most 15 MB. Long audio is trimmed; a short clip leaves a silent tail. |
metadata.input.media | object[] | By mode | Required for I2V, R2V, and VideoEdit. Each mode has different item types and combinations. |
metadata.input.media[].type | string | By mode | Required per media item; use the model-specific types below. |
metadata.input.media[].url | string | By mode | Required per media item. Public HTTP/HTTPS URL; image inputs also support data:image/…;base64,… . Accessible native OSS references are supported. |
metadata.input.media[].reference_voice | string | No | R2V reference_image/reference_video only: voice-timbre reference URL, WAV/MP3, 1-10 seconds, at most 15 MB. Overrides the reference video voice. |
metadata.parameters.resolution | string | No | 720P or 1080P (default), with exact capitalization. |
metadata.parameters.ratio | string | No | T2V/R2V/VideoEdit: 16:9, 9:16, 1:1, 4:3, or 3:4. T2V/R2V default to 16:9; R2V ignores ratio when a first frame is supplied. VideoEdit follows its source when omitted. I2V follows its image/video input and does not use this setting. |
metadata.parameters.duration | integer | No | T2V/I2V: 2-15 seconds, default 5. R2V: 2-15 without video references, 2-10 with video, default 5. VideoEdit: omit to retain source length; 2-10 trims from the start. |
metadata.parameters.audio_setting | string | No | VideoEdit only: auto (default) lets the prompt guide audio handling; origin preserves source audio. |
metadata.parameters.prompt_extend | boolean | No | Prompt rewriting; default true. |
metadata.parameters.watermark | boolean | No | Add an AI watermark; default false. |
metadata.parameters.seed | integer | No | 0-2147483647; omitted means random. Identical seeds do not guarantee identical output. |
Input Modes
| Model | Media Rules |
|---|---|
wan2.7-t2v | prompt plus optional input.audio_url; no media array. |
wan2.7-i2v | first_frame; first_frame+driving_audio; first_frame+last_frame; first_frame+last_frame+driving_audio; first_clip; or first_clip+last_frame. Each type appears at most once. |
wan2.7-r2v | 1-5 reference_image/reference_video items total, optionally one first_frame. reference_voice belongs to each reference item, not a separate media type. |
wan2.7-videoedit | Exactly one video item (type=video), optionally up to four reference_image items. |
Wan 2.6
| Field | Type | Required | Description |
|---|---|---|---|
metadata.input.prompt | string | By mode | At most 1500 characters, with excess truncated. Required for T2V/R2V; optional for I2V with a source image. R2V references use character1, character2, etc. |
metadata.input.negative_prompt | string | No | Content to exclude; at most 500 characters, with excess truncated. |
metadata.input.img_url | string | By mode | I2V only, required: first-frame image URL or image Base64 data URI. |
metadata.input.audio_url | string | No | T2V/I2V only: driving audio URL, WAV/MP3, 2-30 seconds, at most 15 MB. |
metadata.input.reference_urls | string[] | By mode | R2V only, required: 1-5 source URLs, at most five images and three videos, with at most five total. Each source identifies one subject. |
metadata.input.reference_video_urls | string[] | No | Deprecated R2V video-only input, at most three videos. Prefer reference_urls; do not mix both formats. |
metadata.parameters.size | string | No | T2V/R2V only: width*height from the size table; default 1920*1080. |
metadata.parameters.resolution | string | No | I2V only: 720P or 1080P (default). The aspect ratio follows the first-frame image. |
metadata.parameters.duration | integer | No | T2V/I2V: 2-15 seconds; R2V: 2-10 seconds. Default 5. |
metadata.parameters.prompt_extend | boolean | No | T2V/I2V only: prompt rewriting, default true. Not an R2V setting. |
metadata.parameters.shot_type | string | No | single (default) or multi. For T2V/I2V, effective only when prompt_extend=true. R2V uses this field directly. Takes precedence over shot instructions in the prompt. |
metadata.parameters.watermark | boolean | No | Add an AI watermark; default false. |
metadata.parameters.seed | integer | No | 0-2147483647; omitted means random. Identical seeds do not guarantee identical output. |
T2V / R2V Sizes
| Tier | Allowed size Values |
|---|---|
| 720P | 1280*720, 720*1280, 960*960, 1088*832, 832*1088 |
| 1080P | 1920*1080, 1080*1920, 1440*1440, 1632*1248, 1248*1632 |
Media Constraints
| Input | Constraints |
|---|---|
| Images | JPEG/JPG, PNG without transparency, BMP, WebP; 240-8000 px per edge, at most 20 MB. Wan 3.0/2.7 additionally limit the long/short ratio to 8:1. |
| Wan 3.0 reference video | MP4/MOV; 1-15 seconds each, total at most 15 seconds; at least 16 fps; 240-4096 px per edge; ratio up to 8:1; at most 100 MB per file. |
| Wan 2.7 video | MP4/MOV; 240-4096 px per edge, ratio up to 8:1, at most 100 MB. first_clip/VideoEdit source: 2-10 seconds. R2V reference: 1-30 seconds. |
| Wan 2.6 R2V video | reference_urls: MP4/MOV, 1-30 seconds, at most 100 MB. The deprecated reference_video_urls format requires 2-30 seconds. |
| Audio | WAV/MP3, at most 15 MB each. Wan 3.0 reference audio: 1-15 seconds, total at most 15. Wan 2.7 reference_voice: 1-10 seconds. T2V driving audio / I2V driving_audio: 2-30 seconds. |
| Wan 3.0 files | docx, doc, xlsx, xls, pptx, ppt, pdf, txt, key, pages, numbers, md; at most 100 MB. PDF/Word/PowerPoint/Keynote/Pages documents: at most 50 pages. |
Request Examples
Set MIXROUTE_API_KEY and replace example.com media URLs with accessible source files. Each POST creates a separate task; do not automatically repeat a timed-out submission.Wan 3.0 Video
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan3.0-video",
"metadata": {
"input": {
"prompt": "A red ceramic mug slowly rotates on a white tabletop. Static camera, soft studio lighting."
},
"parameters": {
"resolution": "480P",
"ratio": "16:9",
"duration": 2,
"audio": false,
"prompt_extend": false,
"watermark": false
}
}
}'
Wan 2.7 T2V
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.7-t2v",
"metadata": {
"input": {
"prompt": "A red ceramic mug slowly rotates on a white tabletop. Static camera, soft studio lighting."
},
"parameters": {
"resolution": "720P",
"ratio": "9:16",
"duration": 2,
"prompt_extend": false,
"watermark": false
}
}
}'
Wan 2.7 I2V
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.7-i2v",
"metadata": {
"input": {
"prompt": "A red ceramic mug slowly rotates on a white tabletop. Static camera, soft studio lighting.",
"media": [
{
"type": "first_frame",
"url": "https://example.com/reference.png"
}
]
},
"parameters": {
"resolution": "720P",
"duration": 2,
"prompt_extend": false,
"watermark": false
}
}
}'
Wan 2.7 R2V
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.7-r2v",
"metadata": {
"input": {
"prompt": "Image 1 slowly rotates on a white tabletop. Static camera, soft studio lighting.",
"media": [
{
"type": "reference_image",
"url": "https://example.com/reference.png"
}
]
},
"parameters": {
"resolution": "720P",
"ratio": "1:1",
"duration": 2,
"watermark": false
}
}
}'
Wan 2.7 VideoEdit
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.7-videoedit",
"metadata": {
"input": {
"prompt": "Change the mug color to blue while preserving the original motion and white tabletop.",
"media": [
{
"type": "video",
"url": "https://example.com/source.mp4"
}
]
},
"parameters": {
"resolution": "720P",
"duration": 2,
"watermark": false
}
}
}'
Wan 2.6 T2V
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.6-t2v",
"metadata": {
"input": {
"prompt": "A red ceramic mug slowly rotates on a white tabletop. Static camera, soft studio lighting."
},
"parameters": {
"size": "1280*720",
"duration": 2,
"prompt_extend": false,
"watermark": false
}
}
}'
Wan 2.6 I2V
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.6-i2v",
"metadata": {
"input": {
"prompt": "A red ceramic mug slowly rotates on a white tabletop. Static camera, soft studio lighting.",
"img_url": "https://example.com/reference.png"
},
"parameters": {
"resolution": "720P",
"duration": 2,
"prompt_extend": false,
"watermark": false
}
}
}'
Wan 2.6 R2V
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.6-r2v",
"metadata": {
"input": {
"prompt": "character1 slowly rotates on a white tabletop. Static camera, soft studio lighting.",
"reference_urls": [
"https://example.com/reference.png"
]
},
"parameters": {
"size": "1280*720",
"duration": 2,
"watermark": false
}
}
}'
First and Last Frames
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan2.7-i2v",
"metadata": {
"input": {
"prompt": "A closed gift box slowly opens, revealing a red ceramic mug.",
"media": [
{
"type": "first_frame",
"url": "https://example.com/first.png"
},
{
"type": "last_frame",
"url": "https://example.com/last.png"
}
]
},
"parameters": {
"resolution": "720P",
"duration": 5
}
}
}'
File Input Without a Prompt
curl --request POST "https://api.mixroute.ai/v1/video/generations" \
--header "Authorization: Bearer $MIXROUTE_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"model": "wan3.0-video",
"metadata": {
"input": {
"media": [
{
"type": "file",
"url": "https://example.com/product.pptx"
}
]
},
"parameters": {
"resolution": "480P",
"duration": 5
}
}
}'
Responses and Polling
Submission returns a MixRoute task_id (and id alias). This is not the upstream task ID.{
"id": "TASK_ID",
"task_id": "TASK_ID",
"object": "video",
"model": "wan3.0-video",
"status": "queued"
}
GET https://api.mixroute.ai/v1/video/generations/{task_id}
| Gateway Status | Upstream Status | Action |
|---|---|---|
NOT_START / QUEUED | PENDING | Wait and query again. |
IN_PROGRESS | RUNNING | Continue polling. |
SUCCESS | SUCCEEDED | Read data.result_url. |
FAILURE | FAILED / CANCELED / UNKNOWN | Stop; inspect data.fail_reason and the upstream response. |
{
"code": "success",
"message": "",
"data": {
"task_id": "TASK_ID",
"status": "SUCCESS",
"progress": "100%",
"result_url": "https://example.com/generated.mp4",
"fail_reason": "",
"data": {
"request_id": "UPSTREAM_REQUEST_ID",
"output": {
"task_id": "UPSTREAM_TASK_ID",
"task_status": "SUCCEEDED",
"video_url": "https://example.com/generated.mp4"
},
"usage": {
"output_video_duration": 2,
"SR": 480,
"video_count": 1
}
}
}
}
Read result_url only after SUCCESS. On failure the gateway may place the failure text in result_url, so it is not necessarily a URL. The code=“success” envelope only means the query succeeded, not that the generation succeeded.
Python Workflow
import os
import time
from urllib.parse import quote, urlparse
import requests
BASE_URL = "https://api.mixroute.ai"
def create_video(session, payload):
response = session.post(BASE_URL + "/v1/video/generations", json=payload, timeout=120)
response.raise_for_status()
result = response.json()
task_id = result.get("task_id") or result.get("id")
if not task_id:
raise RuntimeError(result.get("message") or result)
return task_id
def wait_for_video(session, task_id, timeout_seconds=1200):
url = BASE_URL + "/v1/video/generations/" + quote(task_id, safe="")
deadline = time.monotonic() + timeout_seconds
delay = 15
while time.monotonic() < deadline:
remaining = deadline - time.monotonic()
if remaining <= 0:
break
try:
response = session.get(url, timeout=min(30, remaining))
except (requests.Timeout, requests.ConnectionError):
delay = min(delay * 2, 60)
else:
if response.status_code in (429, 500, 502, 503, 504):
delay = min(delay * 2, 60)
else:
response.raise_for_status()
result = response.json()
if result.get("code") not in (None, 0, 200, "0", "200", "success"):
raise RuntimeError(result.get("message") or result)
task = result.get("data") or {}
status = str(task.get("status", "")).upper()
if status == "SUCCESS":
video_url = task.get("result_url", "")
parsed = urlparse(video_url)
if parsed.scheme not in ("http", "https") or not parsed.netloc:
raise RuntimeError("Successful task has no valid video URL")
return task
if status in {"FAILURE", "FAILED", "EXPIRED", "CANCELED", "CANCELLED"}:
raise RuntimeError(task.get("fail_reason") or task)
if status not in {"QUEUED", "NOT_START", "PENDING", "IN_PROGRESS", "RUNNING"}:
raise RuntimeError("Unknown task status: " + status)
delay = 15
remaining = deadline - time.monotonic()
if remaining <= 0:
break
time.sleep(min(delay, remaining))
raise TimeoutError("Video task is still pending; keep its task ID and query it later")
if __name__ == "__main__":
payload = {
"model": "wan3.0-video",
"metadata": {
"input": {"prompt": "A red ceramic mug slowly rotates on a white tabletop."},
"parameters": {"resolution": "480P", "ratio": "16:9", "duration": 2, "audio": False},
},
}
with requests.Session() as session:
session.headers["Authorization"] = "Bearer " + os.environ["MIXROUTE_API_KEY"]
task_id = create_video(session, payload)
print("task_id:", task_id, flush=True)
task = wait_for_video(session, task_id)
print(task["result_url"])
print(task.get("data", {}).get("usage", {}))