Skip to main content

Video Generation

Video generation lets applications submit prompt-to-video tasks through AISIX while keeping caller authentication, model aliases, upstream credentials, rate limits, and content guardrails in one gateway path.

AISIX exposes an OpenAI-compatible video surface with three routes that mirror the provider-side asynchronous workflow: submit a task, poll its status, and download the result. The gateway holds no task state — the returned video ID encodes everything AISIX needs to route later status and download calls to the right provider.

In this guide, you will generate a video through AISIX using an Alibaba Model Studio video model and follow the task to a downloadable result.

Prerequisites

Before starting, prepare the following:

  • A running AISIX gateway that can serve proxy requests.
  • A caller API key that can access the video model alias.
  • A model alias whose configured provider is one of the supported video providers (see Endpoint Behavior). Every provider except OpenAI needs a provider key whose api_base reaches the provider's API — there is no built-in default base URL for them. An OpenAI model falls back to the standard OpenAI base URL when api_base is unset. The examples below use an Alibaba Model Studio model.

The examples use a model alias configured like the following. The upstream model name is a text-to-video model from the provider's catalog:

{
"display_name": "wan-video-prod",
"model_name": "wan2.7-t2v",
"provider_key_id": "YOUR_PROVIDER_KEY_ID"
}

Export the gateway connection and request values:

# AISIX_PROXY has no trailing slash or endpoint path such as /v1.
# The local quickstarts use http://127.0.0.1:3000.
export AISIX_PROXY="YOUR_AISIX_GATEWAY_ORIGIN"
export AISIX_API_KEY="YOUR_CALLER_API_KEY"
export AISIX_MODEL="wan-video-prod"

Create a Video Generation Task

Submit the task with the model alias, a prompt, and optionally a duration in seconds:

curl -sS -X POST "${AISIX_PROXY}/v1/videos" \
-H "Authorization: Bearer ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "'"${AISIX_MODEL}"'",
"prompt": "A miniature city built from cardboard comes alive at night.",
"seconds": 5
}'

AISIX resolves the alias, runs input guardrails on the prompt, reserves rate-limit capacity, and submits the task to the provider asynchronously. The response is a video job object:

{
"id": "bW9kZWwtaWQtMTpkMkZ1TFhacFpHVnZMWEJ5YjJROnRhc2stMDE",
"object": "video",
"model": "wan-video-prod",
"status": "queued",
"progress": 0,
"created_at": 1753257600,
"seconds": "5"
}

The id value is an opaque gateway-issued video ID. Store it — the status and download routes take it as the path parameter.

Request fields:

FieldRequiredMeaning
modelYesThe AISIX model alias.
promptYesThe text prompt for the video.
secondsNoVideo duration in seconds, as an integer or a numeric string. Forwarded as the provider's own duration parameter — see Parameter Mapping.
sizeNoPixel dimensions as WIDTHxHEIGHT, for example 1280x720. Each provider expresses output dimensions differently and validates the value against its own per-model list, so check Parameter Mapping and the provider's model documentation before setting it.

Unset optional fields are omitted from the upstream request entirely.

Poll the Task Status

Poll the task with the video ID until the status reaches a terminal value:

curl -sS "${AISIX_PROXY}/v1/videos/YOUR_VIDEO_ID" \
-H "Authorization: Bearer ${AISIX_API_KEY}"

A finished task reports completed and, when the provider states it, the actual video duration:

{
"id": "bW9kZWwtaWQtMTpkMkZ1TFhacFpHVnZMWEJ5YjJROnRhc2stMDE",
"object": "video",
"model": "wan-video-prod",
"status": "completed",
"progress": 100,
"created_at": 0,
"seconds": "5"
}

The status field is a four-value enum:

StatusMeaning
queuedThe provider accepted the task and has not started it.
in_progressThe provider is generating the video.
completedThe video is ready to download.
failedGeneration failed, was canceled, or the provider no longer knows the task (for example, an expired task). The response carries an error object with the provider's code and message when available.

AISIX normalizes each provider's own task states onto that enum. Some providers report no distinct queued state, so a submission there starts directly at in_progress:

provider valuequeuedin_progresscompletedfailed
alibabaPENDINGRUNNINGSUCCEEDEDFAILED, CANCELED, UNKNOWN, or any other state
zhipuaiNot reported — a task starts at in_progressPROCESSINGSUCCESSFAIL or any other state
volcenginequeuedrunningsucceededfailed, cancelled, expired, or any other state
runwaymlPENDING, THROTTLEDRUNNINGSUCCEEDEDFAILED, CANCELLED, or any other state
openaiqueuedin_progresscompletedfailed or any other state

progress reports a real completion percentage for providers that expose one (OpenAI Sora). For providers that do not, it reports 0 until the task completes and 100 afterward. Because the gateway stores no task state, created_at is populated on the submit response only; poll responses report 0.

Download the Video

When the status is completed, request the content route. Use curl -L so the command works for every provider — AISIX either redirects to the provider's download URL or streams the video itself, depending on how the provider delivers finished files:

curl -sS -L -o video.mp4 \
"${AISIX_PROXY}/v1/videos/YOUR_VIDEO_ID/content" \
-H "Authorization: Bearer ${AISIX_API_KEY}"

Both paths save the same MP4. The difference matters when you script around the response:

DeliveryProvidersWhat the content route returns
RedirectAlibaba, Zhipu, Volcengine Ark, Runway302 with a Location header pointing at the provider's signed download URL. The transfer goes directly from the provider's storage to the client and does not pass through the gateway. AISIX only redirects to absolute http or https URLs.
Gateway streamOpenAI200 with the MP4 bytes, the provider's Content-Type (normally video/mp4), and a Content-Disposition attachment header. The provider requires its own credential to download the file, so AISIX fetches it with the configured provider key and streams the bytes through. The provider credential is never exposed to the caller.

Streamed responses pass through the gateway chunk by chunk rather than being held in memory, so a large file does not grow the gateway's memory use. Per-chunk reads are bounded by the model's stream timeout: if a slow upstream stalls, the transfer is cut mid-body. When the provider declares a Content-Length, the gateway relays it, so an interrupted transfer surfaces to the client as a short read against that length — retry the content request.

To inspect which path a provider uses, ask curl for the status without following redirects:

curl -sS -o /dev/null -w "%{http_code} %{redirect_url}\n" \
"${AISIX_PROXY}/v1/videos/YOUR_VIDEO_ID/content" \
-H "Authorization: Bearer ${AISIX_API_KEY}"

A redirect provider prints the redirect status and the provider-hosted URL:

302 https://provider-cdn.example.com/videos/task-01/out.mp4

A gateway-stream provider prints 200 with an empty redirect URL. On that path the probe transfers the whole file to /dev/null, so run it against a small task:

200

If the task is not finished, the content route returns 400 with a message telling the caller to keep polling. If the task failed, it returns 400 with the provider's failure detail. An error from the provider's download endpoint is always returned as a JSON error envelope, never as a truncated video body.

Rate Limits and Guardrails

Before a task reaches the provider, the submit route reserves the caller API key layers and the model's limits, as it does for other modeled routes. Model limits include the inline rate_limit and any model-scope rate limit policies. See API Key and Model Rate Limits and Rate Limit Policies.

The status and content routes reserve only the caller API key layers. Task polling is deliberately exempt from model-level limits: a client that submits a task and then hits the model's submission cap can still poll that task to completion. For gateway-stream providers this also means the video bytes transit the gateway without counting against the model's limits — size the gateway's egress accordingly.

Input guardrails resolved for the request — whether attached to the model, the caller API key, the team, or the environment — scan the prompt before submission. A blocked prompt is rejected before any provider task is created and does not consume the model's rate-limit capacity.

Endpoint Behavior

  • If the provider key's api_base ends with the provider's OpenAI-compatible or versioned suffix (/compatible-mode/v1, /api/v1, or /v1 for Alibaba; /api/paas/v4 for Zhipu; /api/v3 for Volcengine Ark), AISIX derives the provider root automatically — an existing key configured for chat traffic works unchanged. Runway's documented base is the bare host, and OpenAI accepts either the bare host or a /v1 base.
  • The submit route requires a JSON media type, such as application/json. The video create helper in the OpenAI Python SDK sends multipart/form-data on every call, even without a reference asset, so it cannot drive this route — submit with an ordinary HTTP client. The two GET routes are plain GETs and have no such constraint.
  • OpenAI is the only video provider with a built-in default base URL: an OpenAI model with no api_base resolves to the standard OpenAI API. Every other provider requires api_base on the provider key.
  • Each submission that reaches a provider is recorded in usage logs with zero tokens. A request rejected before dispatch — malformed JSON, or a provider outside the allowlist — emits no usage event. Duration-based cost accounting for video tasks is not yet applied to budgets.
  • Submission is not at-most-once. AISIX retries a send-phase transport failure or an upstream 5xx, and whether the first attempt reached the provider is unknowable, so a retry can start a second billable task whose ID the caller never sees. AISIX deliberately does not retry once the provider has responded and only the body failed to read or decode.

Supported Providers

AISIX dispatches the video routes on the model alias's own provider value, not on the upstream model name; the provider key attached to the alias supplies the credential and api_base. The routes accept direct aliases only — a routing or ensemble alias returns 400.

AISIX keeps no allowlist of model IDs. It forwards the configured upstream model name through the fixed mapping below, so a generation still depends on that model accepting the resulting request shape. Check the provider's current catalog, and that model's own parameter rules, before creating an alias.

provider valueProvider setupVideo modelsDelivery
alibabaQwen (Alibaba Cloud)Model Studio Wan and HappyHorse text-to-video, such as wan2.7-t2v, wan2.2-t2v-plus, and happyhorse-1.1-t2vRedirect
zhipuai (zhipu also accepted)Zhipu AICogVideoX, such as cogvideox-3Redirect
volcengineVolcengine ArkArk Seedance, such as doubao-seedance-2-0-260128Redirect
runwayml (runway also accepted)RunwayMLRunway Gen and Runway-hosted models on the text-to-video endpoint, such as gen4.5, veo3.1, and seedance2Redirect
openaiOpenAISora: sora-2 and sora-2-proGateway stream
caution

OpenAI deprecated the Videos API and the Sora 2 models on March 24, 2026 and will remove them from the API on September 24, 2026. Aliases backed by sora-2 or sora-2-pro stop working on that date.

A model alias whose provider is not in this table returns 501 not_implemented on submit. Reach those providers' native video APIs through a passthrough route instead.

Two provider values that serve chat traffic are deliberately outside this list: alibaba-cn and zai. Both reach a different API root than their video-capable counterpart, so a video alias must use alibaba or zhipuai.

Parameter Mapping

AISIX maps the unified seconds and size fields onto each provider's own parameters. The mapping is per provider, not per model: AISIX does not inspect which model family the alias names, so where a provider's newer models expect different parameters, omitting the unified field is the caller's job. A field the provider cannot express at all is dropped rather than translated into a different parameter, and the provider validates whatever it receives against its own per-model list.

provider valueseconds maps tosize maps to
alibabaparameters.durationparameters.size as WIDTH*HEIGHT. This matches the Wan 2.6 and earlier request protocol. Wan 2.7 models replaced size with resolution and ratio tiers; AISIX still forwards whatever you send, so omit size yourself on a Wan 2.7 alias and let the provider default apply.
zhipuaidurationsize as WIDTHxHEIGHT, forwarded verbatim
volcenginedurationNot forwarded. Ark expresses output dimensions as resolution and ratio quality tiers, which cannot carry an arbitrary WIDTHxHEIGHT. AISIX validates the format and then drops the value, so the provider default applies. The submit response still echoes the size you sent, which does not mean Ark used it; poll responses omit it.
runwaymldurationratio as WIDTH:HEIGHT. AISIX only swaps the separator; Runway validates the result against its per-model resolution list.
openaiseconds, rendered as a string. OpenAI's create-video schema accepts 4, 8, or 12.size as WIDTHxHEIGHT, forwarded verbatim. The schema lists 720x1280, 1280x720, 1024x1792, and 1792x1024, but OpenAI publishes a narrower set per model, so check the model's own page. AISIX validates only the WIDTHxHEIGHT syntax.

Request Fields the Routes Do Not Model

The modeled routes cover text-to-video generation. Fields other than model, prompt, seconds, and size are ignored rather than rejected, so a request carrying them still generates a video — from the prompt alone.

  • input_reference is ignored. Image-to-video and video-to-video generation are not modeled on these routes.
  • Provider-native generation controls, such as a negative prompt, a seed, a reference image, or Wan 2.7's resolution and ratio tiers, have no unified field and are not forwarded.
  • POST /v1/videos, GET /v1/videos/{video_id}, and GET /v1/videos/{video_id}/content are the only modeled video routes AISIX serves. Provider routes that list, delete, remix, edit, or extend a video are not modeled, and neither is any provider-specific route beyond generation.

Configure a passthrough route when a caller needs any of these — it reaches the provider's native video API with the gateway still holding the credential and the caller key's access rules.

Errors

The table lists the statuses AISIX itself produces. A provider's own 4xx keeps its status and is relayed in an upstream error envelope; a provider 5xx, a transport failure, or a response AISIX cannot decode becomes 502; an upstream timeout becomes 504; a request body over the size limit becomes 413.

How a failed download surfaces depends on the delivery mode. On gateway-stream delivery, AISIX checks the provider's content endpoint before it starts the transfer, so a failure there is a JSON envelope; a stream cut after the response headers are sent is not, and the caller sees a short read against the declared Content-Length when the provider supplied one. On redirect delivery, AISIX never fetches the file: it returns the absolute http or https URL the provider reported, without verifying it, so anything that fails after the client follows the redirect comes from the provider or its CDN, in whatever format they use.

StatusWhen
400The request is malformed: seconds is not a positive integer, or size is not WIDTHxHEIGHT. The content route also returns 400 when the task is still running, with a message telling the caller to keep polling, and when the task failed, with the provider's failure detail.
401The caller API key is missing or invalid.
403On submit, the caller API key is not allowed to use the model alias, or the request comes from a client IP outside the model's allowlist. The error type is permission_denied; an IP rejection also carries the ip_restricted code.
404On submit, the model names no alias the gateway knows; the error type is model_not_found. On the GET routes, the video ID is unknown or malformed, or it belongs to a model the caller key cannot access; the error type is video_not_found. The GET routes fold both an ACL denial and a not-implemented provider into 404, so an ID cannot be used to probe which models exist.
422An input guardrail blocked the prompt. No provider task is created and no rate-limit capacity is consumed.
429A rate limit or a budget rejected the request. Submissions count against both the caller key layers and the model's limits; status and content calls count against the caller key layers only. The caller's budget check applies to all three routes, so an over-budget caller cannot poll or download a task it already paid to submit.
501The model alias resolves to a provider outside the video route's allowlist. The error type is not_implemented.

A task that the provider reports as failed is not an HTTP error on the status route: GET /v1/videos/{video_id} returns 200 with "status": "failed" and an error object carrying the provider's code and message.

Next Steps

You have now generated a video through the gateway's modeled video surface. For provider video APIs that AISIX has not modeled yet, configure a passthrough route — on inject-mode routes, model-level rate limits apply there as well when the request body names a configured model.