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 need
  • The input schema (verified)
  • Minimal working request: curl
  • Complete Python script
  • Production notes
  • Callback instead of polling
  • Idempotency
  • Errors you'll actually see
  • Related reading
  • FAQ
TutorialJul 10, 2026

How to Use the hailuo 2.3 Fast Image to Video API: curl, Python, and a Working Request

hiapiHailuoVideo GenerationImage to VideoTutorial

Latest models

Explore models

Contents
  • What you need
  • The input schema (verified)
  • Minimal working request: curl
  • Complete Python script
  • Production notes
  • Callback instead of polling
  • Idempotency
  • Errors you'll actually see
  • Related reading
  • FAQ

Generate it with HiAPI

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

HiAPI Blog

Related articles

HiAPI

Generate it with HiAPI

You have a still image and you want a short video clip from it. This guide wires up hailuo-2.3-fast/image-to-video through the hiapi task API: the exact input schema (verified against the live validator), a copy-paste curl request, a complete Python script that polls to completion, and the production details — callbacks, idempotent retries, and the error responses you'll actually see.

What you need

  • A hiapi API key — grab one from your dashboard. Keys look like sk-... and go in the Authorization: Bearer header.
  • A source image hosted at a publicly reachable HTTPS URL. The API takes a URL, not an upload.
  • Any HTTP client. Examples below use curl and Python's requests.

Per-second pricing for this model is listed on the pricing page.

The input schema (verified)

hailuo-2.3-fast/image-to-video uses the unified async task endpoint: POST /v1/tasks to create, GET /v1/tasks/<taskId> to poll. The input schema is strict — unknown fields are rejected with a 400, not silently ignored.

FieldTypeRequiredNotes
promptstring✅Describes the motion you want
image_urlstring✅Singular — one URL string, not an image_urls array
durationstringoptional"6" or "10" — a string, not a number
prompt_optimizerbooleanoptionalLet the backend rewrite your prompt for motion

Three gotchas the validator will catch you on:

  1. duration must be a string. Sending "duration": 6 returns 400 with duration: got number, want string. Send "duration": "6".
  2. The field is image_url, singular. Many other video models on the platform (Grok Imagine, Kling) take an image_urls array. This one takes a single string.
  3. There is no resolution, aspect_ratio, seed, watermark, or end_image_url. All of them come back as additional properties ... not allowed. Output framing follows your source image; motion control is prompt-only.

Minimal working request: curl

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-fast/image-to-video",
    "input": {
      "prompt": "The camera slowly pushes in as steam rises from the coffee cup, soft morning light",
      "image_url": "https://your-cdn.example.com/coffee.jpg",
      "duration": "6"
    }
  }'

Success response:

{
  "code": 200,
  "data": { "taskId": "tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V" },
  "message": "success"
}

Then poll:

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

While the video renders, data.status is "handling":

{
  "code": 200,
  "data": {
    "taskId": "tk-hiapi-01KX4W3SVW8S8EHD5VX45JH95V",
    "model": "hailuo-2.3-fast/image-to-video",
    "status": "handling",
    "storage": "temp",
    "completed": 0,
    "created": 1783648872
  },
  "message": "success"
}

Terminal states are "success" (video URL in data.output[0].url) and "fail" (details in data.error).

Complete Python script

import os
import time

import requests

API_BASE = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"]  # sk-...
HEADERS = {"Authorization": f"Bearer {TOKEN}"}


def create_task(prompt: str, image_url: str, duration: str = "6") -> str:
    resp = requests.post(
        API_BASE,
        headers={**HEADERS, "Content-Type": "application/json"},
        json={
            "model": "hailuo-2.3-fast/image-to-video",
            "input": {
                "prompt": prompt,
                "image_url": image_url,
                "duration": duration,  # string: "6" or "10"
            },
        },
        timeout=60,
    )
    body = resp.json()
    if resp.status_code != 200 or not body.get("data", {}).get("taskId"):
        raise RuntimeError(f"create failed: {resp.status_code} {body}")
    return body["data"]["taskId"]


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


if __name__ == "__main__":
    task_id = create_task(
        prompt="The cat blinks and turns its head toward the window, gentle breeze in its fur",
        image_url="https://your-cdn.example.com/cat.jpg",
        duration="6",
    )
    print("task:", task_id)

    task = wait_task(task_id)
    video_url = task["output"][0]["url"]
    print("video:", video_url)

    # The URL is on temp storage with an expiry — download it now, don't hot-link it.
    mp4 = requests.get(video_url, timeout=120).content
    with open("output.mp4", "wb") as f:
        f.write(mp4)
    print(f"saved output.mp4 ({len(mp4)} bytes)")

Two things this script gets right that quick hacks miss:

  • It downloads the video immediately. storage: "temp" means the output URL carries an expiry (expireAt). Persist the bytes to your own storage; never store the returned URL in your database.
  • It treats fail as terminal. Re-polling a failed task won't revive it — create a new task instead.

Production notes

Callback instead of polling

For anything beyond a script, register a webhook at creation time and skip the poll loop entirely:

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

With "when": "final" your endpoint is called once, when the task reaches success or fail. Rule of thumb: polling is fine for CLIs, batch jobs, and anything ephemeral; callbacks win once you have a server that's already listening — video tasks run minutes, and a poll loop is a held connection slot and a wasted worker for exactly that long.

Idempotency

The create call is not idempotent by itself — every POST /v1/tasks that validates makes a new (billable) task. If your job runner retries on timeouts, store the taskId you got back before acting on the result, keyed by your own request id. On retry, if a taskId already exists for that key, poll it instead of creating a duplicate.

Errors you'll actually see

SymptomMeaningFix
401 — {"error":{"code":"permission_denied","type":"hiapi_error"}}Bad key, or the key can't use this modelCheck the key in your dashboard; the response includes a request_id for support
400 INVALID_REQUEST — duration: got number, want stringJSON number instead of string"duration": "6"
400 INVALID_REQUEST — additional properties '...' not allowedYou sent a field outside the schemaStrip it — the message names each offending field
400 INVALID_REQUEST — missing required field "prompt" / "image_url"Empty or misnamed inputBoth fields are required
Task reaches fail after creationRuntime failure — commonly an image URL the backend couldn't fetchThe validator doesn't fetch your image at creation time; make sure the URL is publicly reachable

That last row deserves emphasis: creation-time validation is schema-only. A typo'd or private image_url gives you a healthy-looking taskId and a task that dies minutes later — so alert on fail, not just on HTTP errors.

Related reading

  • hailuo-2.3-fast/image-to-video model page — playground and per-second pricing
  • Image to Video API Workflow: A Production Guide — batching, storage, and retry architecture around i2v endpoints
  • Text-to-Video vs Image-to-Video API — when to anchor generation on a source image
  • Kling Image-to-Video API Guide — same task API, different input schema, useful contrast

FAQ

Can I set the resolution or aspect ratio? No. The schema for hailuo-2.3-fast/image-to-video rejects resolution and aspect_ratio as unknown fields. Framing follows your source image; if you need a specific aspect ratio, crop the input image first.

What durations are supported? Exactly two: "6" and "10" seconds, passed as strings. Anything else returns 400 with value must be one of '6', '10'.

Can I pass multiple reference images? No — the field is a single image_url string. Models that accept image arrays (e.g. Grok Imagine's image_urls) use a different schema; don't copy request bodies between models without checking.

How do I control the motion? Through prompt only — there are no motion-strength or camera parameters. Describe the movement explicitly ("camera slowly pushes in", "hair sways in the wind"). Optionally set "prompt_optimizer": true to let the backend expand your prompt.

Is there a slower, higher-quality variant? Yes — hailuo-2.3/image-to-video (without -fast) is also live on the platform, and hailuo-2.3/text-to-video covers the no-source-image case. Check each variant's schema before switching; input fields are not guaranteed to match.

How much does it cost? Billing is per second of generated video and varies by model; see current rates on the pricing page.

Do I need an API key to try it? Yes — all task API calls require a Bearer sk-... key. You can create one in the dashboard and test in the model page playground first.

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