HiAPI
Blog

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

Nov 3, 2026 9 min read
陶土色与棕褐色的阶梯状横带在米色背景上从左向右下行,构成简洁的封面底图。

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 →

Start building with persistent AI artifacts

Get your API key and call image, video and audio models through one task-based API.

Read the API docs