All video models

Video model guide · Updated October 7, 2026

Wan 2.6 API

Choose text-to-video for a prompt, image-to-video for an image, or a reference and extension endpoint for those inputs. Flash and Pro are separate variants with separate schemas and quotes.

One project key

Use the same Jevrouter key for chat, images and videos. Choose the exact model in the request body.

Bound the spend

Set a maximum reservation for each task and choose which models your key can access.

Keep the task record

Retrieve progress, outputs and the settled bill. Retrying with the same idempotency key keeps the original task.

Which Wan 2.6 endpoint should I choose?

8 currently available variants. Names such as Flash, Pro, 5B and Ultra Fast identify separate variants; they are not interchangeable request parameters. Catalog capabilities below are declarations, not independent performance measurements.

Start with Wan 2.6 Text-to-Video →

Compare all 8 variants and their parameters
EndpointTaskPublished options
Wan 2.6 · image to video FlashImage to videoduration: 2–15 · resolution: 720p, 1080p
Wan 2.6 · image to video ProImage to videoduration: 5, 10, 15 · resolution: 1080p, 2k, 4k
Wan 2.6 · image to video spicyImage to videoduration: 5, 10, 15 · resolution: 720p, 1080p
Wan 2.6 · image to videoImage to videoduration: 5, 10, 15 · resolution: 720p, 1080p
Wan 2.6 · reference to video FlashReference to videoduration: 5, 10 · size: 1280*720, 720*1280, 1920*1080, 1080*1920
Wan 2.6 · reference to videoReference to videoduration: 5, 10 · size: 1280*720, 720*1280, 1920*1080, 1080*1920
Wan 2.6 Text-to-VideoText to videoduration: 5, 10, 15 · size: 1280*720, 720*1280, 1920*1080, 1080*1920
Wan 2.6 · video extendVideo extendduration: 5, 10, 15 · resolution: 720p, 1080p

Open an endpoint to see required source media, conditional rules and the full parameter schema. Supplying a prompt alone is not sufficient for an image or reference job.

Video API pricing examples

USD per generated video, for the exact inputs below. Live quotes checked (UTC+8). These dated examples are not a price guarantee.

Wan 2.6 text-to-video · prompt expansion off · single shot
DurationSizeReserve up toEstimate
5s1280 × 720$0.50$0.50
10s1280 × 720$1.00$1.00
5s1920 × 1080$0.75$0.75

We reserve the quoted maximum before submission, settle the confirmed generation cost and release the remainder. Set jev.max_cost_usd to bound the reservation. If the current quote exceeds that limit, generation is rejected before it starts.

The estimated charge is not a receipt. Check the settled request record for what you actually paid. Other variants and input combinations require their own quote.

Call the Wan 2.6 API

This example creates one billable five-second text-to-video task with a fixed model and a reservation limit. Allow alibaba/wan-2.6/text-to-video:video on your key and load it into JEVROUTER_API_KEY. Use either the cURL or Python example for a test; running both creates separate jobs.

Submit with cURL

curl --fail-with-body https://api.jevrouter.io/v1/videos \
+  -H "Authorization: Bearer $JEVROUTER_API_KEY" \
+  -H "Content-Type: application/json" \
+  -H "Idempotency-Key: my-first-wan26-video" \
+  -d @- <<'JSON'
{
  "model": "alibaba/wan-2.6/text-to-video:video",
  "input": {
    "prompt": "A yellow sailboat on a quiet lake",
    "duration": 5,
    "size": "1280*720",
    "enable_prompt_expansion": false,
    "shot_type": "single"
  },
  "jev": {
    "max_cost_usd": "0.50"
  }
}
JSON

Save data.id. Retrieve GET /v1/videos/REQUEST_ID with the same authorization header, at least three seconds apart, until data.status is completed or failed. Completed results appear in data.outputs. Keep the same idempotency key when recovering an interrupted submission.

Python example: submit, resume and download

Python 3.10+; no extra packages. Save the script as generate_video.py and run it with your key in the environment. It persists video-task.json before submitting, then polls and saves video.mp4. Keep the state file to resume the same job; use a new JEV_VIDEO_STATE filename only for a deliberately new generation. Run one process per state file.

Show the complete Python example
Python
import json
import os
import shutil
import time
import uuid
from pathlib import Path
from urllib.error import HTTPError, URLError
from urllib.parse import quote, urlsplit
from urllib.request import Request, urlopen

API = "https://api.jevrouter.io/v1/videos"
KEY = os.environ["JEVROUTER_API_KEY"]
STATE = Path(os.environ.get("JEV_VIDEO_STATE", "video-task.json"))

# One state file per intended video. Keep it when retrying or resuming.
# Run only one copy of this script against a state file at a time.
if not STATE.exists():
    with STATE.open("x") as file:
        json.dump({"idempotency_key": str(uuid.uuid4()), "body": {
    "model": "alibaba/wan-2.6/text-to-video:video",
    "input": {
        "prompt": "A yellow sailboat on a quiet lake",
        "duration": 5,
        "size": "1280*720",
        "enable_prompt_expansion": False,
        "shot_type": "single"
    },
    "jev": {
        "max_cost_usd": "0.50"
    }
}}, file)
state = json.loads(STATE.read_text())

def save():
    temporary = STATE.with_name(STATE.name + ".tmp")
    temporary.write_text(json.dumps(state))
    temporary.replace(STATE)

def api(url, body=None):
    headers = {"Authorization": "Bearer " + KEY}
    if body is not None:
        headers.update({"Content-Type": "application/json",
                        "Idempotency-Key": state["idempotency_key"]})
    request = Request(url, data=json.dumps(body).encode() if body is not None else None,
                      headers=headers, method="POST" if body is not None else "GET")
    try:
        with urlopen(request, timeout=90) as response:
            return response.status, json.load(response)
    except HTTPError as error:
        return error.code, json.loads(error.read())
    except (URLError, TimeoutError):
        raise SystemExit("Connection interrupted. Keep the state file and run again to resume.")

if not state.get("request_id"):
    status, result = api(API, state["body"])
    if status == 200:
        state["request_id"] = result["data"]["id"]
    else:
        error = result.get("error", {})
        recoverable = status in (409, 503) and error.get("code") in (
            "request_already_exists", "outcome_unknown")
        request_id = (error.get("details") or {}).get("request_id") or error.get("request_id")
        if not recoverable or not request_id:
            raise SystemExit(result)
        state["request_id"] = request_id
    save()

task_url = API + "/" + quote(state["request_id"], safe="")
print("Task:", state["request_id"])
deadline = time.monotonic() + 900
while time.monotonic() < deadline:
    time.sleep(5)
    status, result = api(task_url)
    error = result.get("error", {})
    if status == 429 or (status in (409, 503) and error.get("code") in (
            "request_already_exists", "outcome_unknown")):
        continue  # Inspect the same task; never submit a replacement.
    if status != 200:
        raise SystemExit(result)
    task = result["data"]
    if task["status"] == "failed":
        raise SystemExit(task.get("error") or "Video generation failed")
    if task["status"] != "completed":
        continue
    print("Outputs:", task["outputs"])
    outputs = task["outputs"]
    if outputs and isinstance(outputs[0], str):
        media_url = outputs[0]
        parts = urlsplit(media_url)
        if parts.scheme != "https" or not parts.hostname or parts.username or parts.password:
            raise SystemExit("Unexpected media URL; inspect outputs manually")
        # Separate media request: NEVER send your Jevrouter key to a media host.
        with urlopen(media_url, timeout=120) as response, open("video.mp4", "wb") as output:
            shutil.copyfileobj(response, output)
        print("Saved video.mp4")
    else:
        print("This model returned structured outputs; inspect the printed result.")
    break
else:
    raise SystemExit("Still pending. Keep the state file and run again to resume.")

Read the full tutorial: status, errors, billing and safe retries →

What we have verified

We verified live text-to-video quotes for the three parameter combinations below on October 7. We have not independently generated a Wan 2.6 video in this integration check, or benchmarked its quality, speed or audio output.

A model being listed does not mean every variant or option has been independently tested. Start with your own representative inputs before choosing on output quality.

Fixed model or Auto?

Use the explicit model above when you need that particular variant. Use jev/auto and task: "text-to-video" when you want routing among compatible models allowed by your key. Auto must also be enabled on the project and allowed on the key.

Auto checks task type and parameter compatibility, then compares live quotes for up to eight candidates shortlisted by catalog price. It chooses within that shortlist and your limit. It does not promise the best quality or search every possible model. Model-specific input fields can narrow the compatible pool.

Read the video API contract →

Keep your result

Closing your connection does not cancel an accepted job. The platform tracks completion and settlement independently. Results may be ready before billing finishes; inspect the request record for the confirmed charge.

Media links are retained for up to seven days and can expire earlier. Download while available and keep your own copy. Customer callbacks and task cancellation are not supported.