HiAPI
  • Models
  • Pricing
Search

Search HiAPI models, tools, and resources.

  • Models
  • Pricing
HiAPI

One API, All AI Models

Generate images, video, and audio with leading models through one production-ready API.

Get a free API key

AI Image API

  • All image models
  • GPT Image 2
  • Nano Banana 2
  • Seedream 5.0 Pro
  • Qwen Image 2.0 Pro
  • FLUX 1.1 Pro

AI Video API

  • All video models
  • Seedance 2.5
  • FLUX.3 Video
  • Seedance 2.0
  • Veo 3.1
  • Kling 3.0 Omni

AI Audio API

  • All audio models
  • MiniMax Music 2.6
  • MiniMax Music 1.5
  • ElevenLabs v3
  • Text to music
  • Text to speech

Product

  • Model marketplace
  • Playground
  • Pricing
  • Image API Cost Calculator
  • Free GPT Image 2 Generator
  • Free Nano Banana Image Generator
  • Outfit Preview
  • Product Photo Lab

Developers

  • Documentation
  • API Reference
  • Agent Skills
  • LLM integration index
  • Blog

Company

  • About
  • Contact support
  • Terms of Service
  • Privacy Policy

© 2026 hiapi. All rights reserved.

Open source on GitHubPython SDK on PyPI
  • What you'll build, and what you need
  • The exact input schema (three fields, strictly validated)
  • Minimal working example: curl
  • Complete Python script
  • Production notes: callbacks, idempotency, errors
  • Prefer a callback over polling
  • Make retries idempotent
  • The errors you'll actually see
  • Related resources
  • FAQ
TutorialJul 10, 2026

How to Use the Hailuo 2.3 Text-to-Video API: curl, Python, and a Working Request

hiapitutorialvideorecipe

Latest models

Explore models

Contents
  • What you'll build, and what you need
  • The exact input schema (three fields, strictly validated)
  • Minimal working example: curl
  • Complete Python script
  • Production notes: callbacks, idempotency, errors
  • Prefer a callback over polling
  • Make retries idempotent
  • The errors you'll actually see
  • Related resources
  • FAQ

Generate it with HiAPI

Choose a model, enter your prompt, and see the result.

HiAPI Blog

Related articles

HiAPI

Generate it with HiAPI

Hailuo 2.3 is MiniMax's latest text-to-video model, and it has one standout trait: motion that actually obeys physics. Fabric ripples, liquids splash, animals move with believable weight — which is why it's a popular pick for product shots and cinematic b-roll. On hiapi you call it through the same unified async task API as every other video model, with the model id hailuo-2.3/text-to-video.

This guide gives you a request that works on the first try: the exact input schema (verified against the live API), a copy-paste curl call, a complete Python script, and the production details — callbacks, idempotent retries, and the error responses you'll actually see.

What you'll build, and what you need

Goal: submit a text prompt, get back an .mp4 clip of 6 or 10 seconds.

Prerequisites:

  • A hiapi API key — grab one from your dashboard. Keys look like sk-... and go in the Authorization: Bearer header.
  • Any HTTP client. We'll show curl and Python (requests).

Video generation is billed per second of output — see pricing for the current rate, and start with "duration": "6" while you iterate on prompts.

The exact input schema (three fields, strictly validated)

hailuo-2.3/text-to-video accepts exactly three input fields:

FieldTypeRequiredNotes
promptstringyesYour scene description. This is also where motion is controlled — see below.
durationstringno"6" or "10". A string, not a number — 6 fails validation.
prompt_optimizerbooleannoLet the model expand and refine your prompt before generating.

Two things trip people up:

  1. duration is a string enum. Send "duration": 6 and you get 400 INVALID_REQUEST: duration: got number, want string. Send "7" and you get value must be one of '6', '10'.
  2. The schema rejects unknown fields. There is no resolution, aspect_ratio, size, seed, or negative_prompt for this model. Any extra key returns 400: additional properties '<field>' not allowed. If you're porting code from another model (say, one that takes size), strip those fields first — input schemas on the task API vary per model.

Where are the motion physics parameters? There aren't any — and that's by design. Hailuo 2.3's physics simulation is native model behavior, steered entirely through prompt language. Describe the motion you want ("ice cubes tumbling", "cape snapping in the wind", "slow dolly-in") and the model handles momentum, gravity, and collision on its own. Setting "prompt_optimizer": true helps when your prompt is short: the model rewrites it with more concrete motion and camera detail before generating.

Minimal working example: curl

Create the task:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "hailuo-2.3/text-to-video",
    "input": {
      "prompt": "A glass of iced tea tipping over in slow motion, splash arcing across a wooden table, ice cubes tumbling, macro shot, shallow depth of field",
      "duration": "6",
      "prompt_optimizer": true
    }
  }'

The response includes a task id (trimmed):

{ "data": { "taskId": "task_01jz..." } }

Poll it until it reaches a terminal state:

curl -s https://api.hiapi.ai/v1/tasks/task_01jz... \
  -H "Authorization: Bearer sk-YOUR_KEY"

While the job is running, data.status reports an in-progress state. The two terminal states are success and fail. On success (trimmed):

{
  "data": {
    "taskId": "task_01jz...",
    "status": "success",
    "output": [ { "url": "https://.../clip.mp4" } ]
  }
}

Download data.output[0].url immediately. Output URLs are signed and expire — persist the bytes to your own storage, never hot-link the task URL.

Complete Python script

import time
import requests

API_BASE = "https://api.hiapi.ai/v1"
API_KEY = "sk-YOUR_KEY"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}


def create_task(prompt: str, duration: str = "6") -> str:
    resp = requests.post(
        f"{API_BASE}/tasks",
        headers=HEADERS,
        json={
            "model": "hailuo-2.3/text-to-video",
            "input": {
                "prompt": prompt,
                "duration": duration,          # "6" or "10" — a string, not a number
                "prompt_optimizer": True,
            },
        },
        timeout=30,
    )
    resp.raise_for_status()
    return resp.json()["data"]["taskId"]


def wait_task(task_id: str, timeout_s: int = 900, poll_interval: int = 5) -> dict:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        resp = requests.get(f"{API_BASE}/tasks/{task_id}", headers=HEADERS, timeout=30)
        resp.raise_for_status()
        task = resp.json()["data"]
        if task["status"] == "success":
            return task
        if task["status"] == "fail":
            err = task.get("error") or {}
            raise RuntimeError(f"task failed: {err.get('code')}: {err.get('message')}")
        time.sleep(poll_interval)  # anything else = still running
    raise TimeoutError(f"task {task_id} not finished after {timeout_s}s")


task_id = create_task(
    "A snow leopard sprinting across a rocky ridge at dawn, loose stones "
    "scattering under its paws, fur rippling in the wind, cinematic tracking shot"
)
print("task created:", task_id)

task = wait_task(task_id)
video_url = task["output"][0]["url"]

# Output URLs expire — download right away and store the bytes yourself.
video = requests.get(video_url, timeout=120).content
with open("hailuo-clip.mp4", "wb") as f:
    f.write(video)
print(f"saved hailuo-clip.mp4 ({len(video) / 1e6:.1f} MB)")

Run it with pip install requests, swap in your key, and you'll have an .mp4 on disk when the task completes. Video tasks take longer than image tasks — give your poll loop a generous deadline (the script above allows 15 minutes) rather than assuming completion in seconds.

Production notes: callbacks, idempotency, errors

Prefer a callback over polling

For anything beyond a script, register a webhook when you create the task instead of polling:

{
  "model": "hailuo-2.3/text-to-video",
  "input": { "prompt": "...", "duration": "10" },
  "callback": { "url": "https://your-app.example.com/hooks/hiapi", "when": "final" }
}

With "when": "final" hiapi calls your endpoint once, when the task reaches a terminal state — no poll traffic, no missed completions between intervals. Polling is still the right choice for CLIs, notebooks, and environments that can't expose an HTTPS endpoint. If your handler never fires, work through why your hiapi task callback isn't firing — it's almost always URL reachability or a non-2xx handler response.

Make retries idempotent

Persist the taskId the moment the create call returns. If your process crashes mid-generation, resume by polling the stored id — don't re-create the task, or you'll pay for a second render. Only re-create when the original create request itself failed before returning a task id.

The errors you'll actually see

SymptomResponseFix
Missing/invalid key401 with error.code: "permission_denied"Check the Authorization: Bearer sk-... header and that the key has access to this model.
duration: got number, want string400 INVALID_REQUESTQuote it: "duration": "6".
additional properties 'X' not allowed400 INVALID_REQUESTRemove the field — this model only takes prompt, duration, prompt_optimizer.
task not found404 on GETWrong task id, or you're querying with a different account's key.
status: "fail" in pollingterminal task stateRead data.error.code / data.error.message; content-policy rejections and upstream capacity issues land here. Retry with a reworded prompt if it's a content flag.
Task seems stucknon-terminal status for a long timeSee when a hiapi /v1/tasks job hangs or times out for a diagnosis checklist before you bail.

Related resources

  • hailuo-2.3/text-to-video model page — playground, pricing, and live status
  • Text-to-video vs image-to-video API workflow — when to feed a reference frame instead of a pure text prompt
  • hiapi pricing — per-second video rates across all models

FAQ

Can I set the resolution or aspect ratio for hailuo-2.3 text-to-video? No. The input schema accepts only prompt, duration, and prompt_optimizer; sending resolution, aspect_ratio, or size returns a 400. Framing (wide shot, portrait composition, macro) is controlled through the prompt itself.

Is duration in seconds? Why does 6 fail? Yes — clips are 6 or 10 seconds. But the API expects a string enum, so send "6" or "10". The number 6 fails schema validation with got number, want string.

What does prompt_optimizer do, and should I turn it on? When true, the model rewrites your prompt with richer motion and camera detail before generating. Turn it on for short or vague prompts; consider leaving it false when you've hand-tuned exact wording and want maximum prompt fidelity.

How do I control Hailuo's motion physics via the API? Through the prompt — there is no separate motion parameter. Name the physical interactions you want (splashes, collisions, wind, weight shifts) and the camera move (tracking shot, dolly-in, handheld). The model's physics simulation takes it from there.

How long does a generation take, and how should I wait? Expect minutes, not seconds — budget a 10–15 minute poll deadline or use a callback with "when": "final" so hiapi notifies you at the terminal state.

Does Hailuo 2.3 support image-to-video too? Yes, as separate model ids on the same task API: hailuo-2.3/image-to-video and the cheaper/faster hailuo-2.3-fast/image-to-video. The input schema differs from text-to-video, so probe it before reusing this request body.

How much does a 6-second clip cost? Video is billed per second of output and rates change — check the pricing page for the current per-second price.

Latest models

View all models
  • GPT Image 2From $0.030/image
  • Nano Banana 2From $0.051/image
  • Seedream 5.0 ProFrom $0.050/image
  • Seedance 2.5From $0.231/s

Explore models

TextImageVideoAudio
Back to blog
GPT Image 2From $0.030/image
Nano Banana 2From $0.051/image
Seedream 5.0 ProFrom $0.050/image
Seedance 2.5From $0.231/s
View all models
TextChat and reasoning
ImageGenerate and edit
VideoText and image to video
AudioSpeech and music
Start generating
View model pricing
View all articles
How to Use the flux-3 API for Text-to-Video, Audio, and Continuation

How to Use the flux-3 API for Text-to-Video, Audio, and Continuation

minimax-music-3 API: curl & Python Guide

minimax-music-3 API: curl & Python Guide

How to use grok-imagine-image-2.0/image-to-image via the hiapi API: curl, Python, and a working request

How to use grok-imagine-image-2.0/image-to-image via the hiapi API: curl, Python, and a working request

How to Use grok-imagine-image-2.0/text-to-image via the hiapi API: curl, Python, and a Working Request

How to Use grok-imagine-image-2.0/text-to-image via the hiapi API: curl, Python, and a Working Request

How to Use the qwen-image-3.0 API: curl, Python, and a Working Request

How to Use the qwen-image-3.0 API: curl, Python, and a Working Request

How to Use qwen-image-3.0-pro via the hiapi API: curl, Python, and a Working Request

How to Use qwen-image-3.0-pro via the hiapi API: curl, Python, and a Working Request

Start generating