Tutorial
How to Call flux-3-max/text-to-video via the HiAPI API: curl and Python Guide
A practical integration walkthrough for asynchronous text-to-video requests on HiAPI
What flux-3-max/text-to-video Does and When to Use It
flux-3-max/text-to-video is a text-to-video endpoint on HiAPI: you send a prompt describing the scene, and the model returns a generated video clip. It is the right tool when you have a written idea rather than source footage — product teasers, short social clips, storyboard previews, or batch-generated b-roll — and you want the generation handled as a managed job rather than something you run yourself.
It fits workflows where video is one step in a larger pipeline. A script generator produces a prompt, flux-3-max/text-to-video turns it into a clip, and your application stores or delivers the result. Because the call is asynchronous, it also suits backend services that cannot hold a request open for the length of a render.
Do not reach for it when you need frame-accurate editing of existing video, or when your prompt is really a single static image — a text-to-image endpoint is cheaper and faster for that. If the output must react to supplied footage, you want an image-to-video variant instead. Treat flux-3-max/text-to-video as the entry point for prompt-to-clip generation, and design your integration around a submitted job rather than a synchronous response.
Request Anatomy: Endpoint, Auth, and Payload
Every request to flux-3-max/text-to-video has three parts: the endpoint path, the authentication header, and a JSON body naming the model and its inputs.
Authentication
HiAPI uses a bearer token. Put your API key in the Authorization header:
Authorization: Bearer $HIAPI_API_KEY
Content-Type: application/json
Keep the key server-side. Do not embed it in client-side code or commit it; load it from an environment variable in development and a secret manager in production.
The model identifier
Inside the request body, the model field selects the endpoint. Use the exact identifier flux-3-max/text-to-video; a typo here is the most common cause of a rejected request.
The payload shape
A minimal body carries the model name and a prompt:
{
"model": "flux-3-max/text-to-video",
"prompt": "A slow aerial shot over a misty pine forest at sunrise, cinematic lighting"
}
Optional fields — duration and the native audio toggle — are covered in the next section. Because generation is asynchronous, the immediate response to this POST is a job object with an identifier you will poll, not the finished video. Design your code to read that identifier first and everything else second.
Controlling Duration and Native Audio
Two request-level controls shape what you get back: how long the clip runs, and whether the model generates audio alongside the video.
Duration
Set the clip length in the payload with the duration field. Pick the shortest length that serves the story — short clips render faster and are easier to review, and you can always request another. Validate the value against the documented range for flux-3-max/text-to-video before submitting; out-of-range durations are rejected at submit time, and catching that locally saves a round trip.
Native audio
The native audio toggle decides whether the model produces a soundtrack with the clip. Turn it on when the video will be watched with sound and off when it will be muted, captioned, or scored separately in post. Generating audio you will discard adds time to the job for no benefit.
Choosing deliberately
Avoid letting defaults decide for you. For a quick storyboard pass, a short silent clip is usually enough. For a finished social asset, a longer clip with native audio may be the target. Encode that choice in your application config rather than hard-coding it at the call site, so you can change it per feature without editing request code. Send only the fields you actually want to override and let the endpoint apply its defaults for the rest.
A Working curl Request
The fastest way to confirm your credentials and payload is a single curl call that submits a job.
curl -X POST "$HIAPI_BASE_URL/v1/videos/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "flux-3-max/text-to-video",
"prompt": "A paper boat drifting down a rain-soaked street, warm streetlights, shallow depth of field",
"duration": 5,
"native_audio": false
}'
Set HIAPI_BASE_URL and HIAPI_API_KEY in your shell first. The duration and audio values here are illustrative — use values within the documented range for this model.
Reading the immediate response
The response is a job object, not a video. It contains a job_id (or equivalent identifier) and a status such as queued or processing. Save the identifier; it is your handle for every follow-up call. If the response looks like an error object instead, check the status code and message before retrying — a malformed payload will fail the same way every time.
A successful submit tells you the job was accepted, nothing more. Do not try to find a video URL in this first response; it will not be there until the job finishes.
Handling the Asynchronous Job Lifecycle
Video generation takes seconds to minutes, so HiAPI models it as a job. Your client submits once, then checks status until the job reaches a terminal state.
The states
A job moves from queued to processing to a terminal state — completed or failed. Only terminal states are final; anything in between means keep waiting.
Polling without hammering
Poll a status endpoint with the job identifier you saved. Two rules keep this healthy:
- Wait between polls. Start with a short interval and back off, or use a fixed interval that is clearly longer than typical queue time. Hammering the status endpoint gains nothing.
- Set a ceiling. Cap total wait time and total attempts. If the job has not finished by then, surface it to your application rather than looping forever.
In a web handler, do not block the request thread on the polling loop. Submit, store the job identifier, return immediately, and let a background worker or a client-side poll complete the lifecycle. In batch contexts, a simple loop with sleep is fine.
Reading the result
When the job reports completed, the response carries the output reference — a video URL or asset handle your application can download or stream. On failure, read the error field; it usually names the cause (invalid parameter, content rejection, internal error). Log the job identifier and the failure message together so a support request or retry has something to work with. Never treat a missing output field as success — check the status explicitly.
The Same Request in Python
The curl flow maps directly to Python. A minimal client needs submission, a polling loop, and enough error handling to tell the difference between a bad request and a slow job.
import os, time
import requests
BASE = os.environ["HIAPI_BASE_URL"]
API_KEY = os.environ["HIAPI_API_KEY"]
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
def submit(prompt, duration=5, native_audio=False):
body = {
"model": "flux-3-max/text-to-video",
"prompt": prompt,
"duration": duration,
"native_audio": native_audio,
}
resp = requests.post(f"{BASE}/v1/videos/generations",
headers=HEADERS, json=body, timeout=30)
resp.raise_for_status()
return resp.json()["job_id"]
def wait(job_id, interval=5, max_attempts=60):
for attempt in range(max_attempts):
time.sleep(interval)
r = requests.get(f"{BASE}/v1/videos/generations/{job_id}",
headers=HEADERS, timeout=30)
r.raise_for_status()
data = r.json()
status = data.get("status")
if status == "completed":
return data
if status == "failed":
raise RuntimeError(data.get("error", "job failed"))
raise TimeoutError(f"job {job_id} did not finish in time")
Notes on the implementation
raise_for_status() separates transport and HTTP errors (auth, malformed payload) from job-level failure, which arrives inside a successful response. The failed check reads the error field explicitly rather than assuming a completed status. The attempt ceiling turns an unbounded wait into a predictable exception.
For production, wrap the poll in a retry policy for transient network errors and reuse a single requests.Session. If you run many jobs, move wait to a worker rather than the request path.
Troubleshooting Common Failures
Most integration problems fall into a few categories. Each has a concrete check.
Auth errors
A 401 or 403 means the key is missing, expired, or malformed. Confirm the Authorization header is present, uses the Bearer scheme, and that the environment variable is actually populated in the runtime — not just your shell.
Malformed payloads
A 400 usually means the body does not match the schema. Verify the JSON parses, model is exactly flux-3-max/text-to-video, and the request sends Content-Type: application/json. Serialize with a JSON library rather than hand-building strings.
Invalid parameter values
Duration outside the documented range, an unknown field name, or a wrong type for the audio toggle causes rejection at submit time. Validate locally against the model's documented parameters before sending.
Premature polling
Polling immediately and repeatedly right after submit does not make the job finish faster. Use a backoff or fixed interval, and let the job object tell you when it has moved past queued.
Unhandled job failures
A job that reaches failed is not a bug in your request necessarily — it can be content rejection or an internal error. Read the error message, log the job identifier, and decide whether to retry with a revised prompt or report it.
Treating the submit response as the result
If your code expects a video URL right after submission, it will break. The first response is a job; only terminal status carries output. Once these six checks are in place, most integration issues are resolved.
Related articles
View all articles →-
Tutorial
How to Call hailuo-2.3-fast/image-to-video via the HiAPI API: curl and Python
A first working request for the fast, low-cost image-to-video tier — from model ID to downloaded MP4
9 min read -
Tutorial
How to Use hailuo-2.3/text-to-video via the HiAPI API: curl, Python, and a Working Request
11 min read -
Tutorial
Kandinsky 6.0 Pro Text-to-Video on HiAPI: curl and Python Tutorial
A request-first walkthrough: build the prompt-to-clip call, submit it, poll for completion, and download the result
11 min read