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.5 Flare
  • GPT Image 2.5 Sunburst
  • 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

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 Background Remover
  • Free Nano Banana Image Generator
  • Outfit Preview
  • Product Photo Lab

Developers

  • Agent setup
  • 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
  • Prerequisites
  • Minimal runnable example
  • 1. Create a task
  • 2. Poll for the result
  • Production patterns
  • Use callbacks instead of polling in production
  • Idempotent retries
  • Handle validation errors per model
  • Related reading
  • FAQ
Back to blog
TutorialOct 8, 2026

Building Multi-Model AI Apps with a Single Unified API on hiapi

hiapiapi-integrationtutorialasync-apimulti-model

Latest models

  • GPT Image 2.5 Flare50% offFrom $0.050/image$0.025/image
  • GPT Image 2.5 Sunburst50% offFrom $0.050/image$0.025/image
  • GPT Image 2From $0.030/image
  • Nano Banana 250% offFrom $0.036/image$0.018/image
View all models

Explore models

TextChat and reasoningImageGenerate and editVideoText and image to videoAudioSpeech and music
Contents
  • What you'll build
  • Prerequisites
  • Minimal runnable example
  • 1. Create a task
  • 2. Poll for the result
  • Production patterns
  • Use callbacks instead of polling in production
  • Idempotent retries
  • Handle validation errors per model
  • Related reading
  • FAQ

What you'll build

Most teams end up calling three or four different AI providers for one product: a text-to-image model for thumbnails, a text-to-video model for social clips, maybe a TTS model for voiceover. Each provider ships its own SDK, its own auth scheme, its own polling logic. hiapi collapses all of that into one endpoint pattern: POST /v1/tasks to create a task, GET /v1/tasks/:id to check it, for every generation model on the platform.

This recipe shows the integration pattern using three real, currently live models — z-image (text-to-image), qwen-image-2.0 (text-to-image, different schema), and seedance-2.5 (text-to-video) — so you can see where the API stays identical and where only the input object changes per model.

Prerequisites

  • An hiapi API key from your dashboard
  • curl or any HTTP client that can send JSON
  • No SDK required — every example below is a plain HTTP call

Every request needs one header:

Authorization: Bearer <your-api-key>

An invalid or missing key returns a 401-style error before any model is touched:

{
  "error": {
    "code": "permission_denied",
    "message": "invalid api key",
    "request_id": "req_...",
    "type": "hiapi_error"
  }
}

There is no keyless or anonymous mode — every /v1/tasks call must carry a valid bearer token. See authentication for key rotation and scoping.

Minimal runnable example

1. Create a task

The create call always has the same shape: a model id and a model-specific input object. Here's an image task with z-image:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "z-image",
    "input": {
      "prompt": "a minimalist workspace, soft morning light, isometric illustration",
      "aspect_ratio": "16:9"
    }
  }'

The response returns immediately — generation happens asynchronously:

{
  "code": 200,
  "message": "ok",
  "data": {
    "taskId": "tk-hiapi-xxxxxxxxxxxx",
    "status": "queued"
  }
}

Now the same pattern with qwen-image-2.0. Same endpoint, same envelope — only input differs (this model takes a size string instead of aspect_ratio):

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen-image-2.0",
    "input": {
      "prompt": "a minimalist workspace, soft morning light, isometric illustration",
      "size": "2048*2048"
    }
  }'

And a video task with seedance-2.5/text-to-video — still the same envelope, now with duration and a wider aspect_ratio enum:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "seedance-2.5/text-to-video",
    "input": {
      "prompt": "a paper airplane gliding through a sunlit office, slow motion",
      "duration": 5,
      "aspect_ratio": "16:9"
    }
  }'

This is the core lesson: the task envelope never changes, only input does. Every model on hiapi documents its own input schema on its model page — always check the specific model's schema before building a new integration, since fields like aspect_ratio, size, and duration are not interchangeable across models.

2. Poll for the result

curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-xxxxxxxxxxxx \
  -H "Authorization: Bearer $HIAPI_API_KEY"

status moves through queued → handling → archiving → a terminal state of success or fail. On success, data.output is an array — most image/video models return one entry, but a single task can return multiple output types (e.g. a video model returning video plus a thumbnail):

{
  "code": 200,
  "message": "ok",
  "data": {
    "taskId": "tk-hiapi-xxxxxxxxxxxx",
    "status": "success",
    "output": [
      { "type": "image", "url": "https://...", "expireAt": "2026-10-09T00:00:00Z" }
    ]
  }
}

expireAt matters — output URLs are ephemeral by default. Download the bytes (or re-upload to your own storage) as soon as the task finishes. If you need the platform to retain the file longer-term, set storage: "persistent" on creation or promote it afterward — see storage.

On failure, you get an error object instead of output:

{
  "code": 200,
  "message": "ok",
  "data": {
    "taskId": "tk-hiapi-xxxxxxxxxxxx",
    "status": "fail",
    "error": { "code": "...", "message": "..." }
  }
}

A minimal Python polling loop that works identically for every model above:

import time
import requests

def run_task(model: str, input_payload: dict, api_key: str) -> list[dict]:
    headers = {"Authorization": f"Bearer {api_key}"}
    create = requests.post(
        "https://api.hiapi.ai/v1/tasks",
        headers=headers,
        json={"model": model, "input": input_payload},
    ).json()
    task_id = create["data"]["taskId"]

    time.sleep(3)  # initial wait before first poll
    while True:
        poll = requests.get(
            f"https://api.hiapi.ai/v1/tasks/{task_id}", headers=headers
        ).json()
        status = poll["data"]["status"]
        if status == "success":
            return poll["data"]["output"]
        if status == "fail":
            raise RuntimeError(poll["data"]["error"])
        time.sleep(4)  # 3-5s between polls; use 5-10s for video models

Production patterns

Use callbacks instead of polling in production

Polling is fine for a script or a CLI tool, but at any real traffic volume, prefer a callback: pass a callback object on task creation and hiapi POSTs the terminal result to your endpoint instead of you hammering GET /v1/tasks/:id in a loop.

{
  "model": "z-image",
  "input": { "prompt": "...", "aspect_ratio": "1:1" },
  "callback": { "url": "https://yourapp.com/webhooks/hiapi", "when": "final" }
}

when: "final" means you only get one POST, on the terminal state (success or fail) — no intermediate handling/archiving noise. If you've wired up a callback and nothing is arriving, check your endpoint is publicly reachable and returns a 2xx quickly; see this related writeup on the most common cause of silently-missing callbacks.

Idempotent retries

Network blips happen. If you retry a POST /v1/tasks call after a timeout without protection, you risk creating (and getting billed for) a duplicate task. Send an Idempotency-Key header (any string up to 255 bytes, typically a UUID you generate per logical request) and retries of the same key return the original task instead of creating a new one:

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Idempotency-Key: 8f14e45f-ceea-467e-bd5f-...-9a2c" \
  -H "Content-Type: application/json" \
  -d '{"model": "z-image", "input": {"prompt": "...", "aspect_ratio": "1:1"}}'

Handle validation errors per model

Because every model has its own input schema, the most common failure mode is a 400 on a field that's valid for one model but not another — e.g. sending aspect_ratio to a model that expects size:

{
  "code": 400,
  "data": null,
  "error_code": "INVALID_REQUEST",
  "message": "invalid input: aspect_ratio: value must be one of '1:1', '4:3', '3:4', '16:9', '9:16'"
}

If you're building a multi-model router (letting users or your own logic pick a model at runtime), keep a small per-model input-builder registry rather than one shared payload shape:

MODEL_INPUT_BUILDERS = {
    "z-image": lambda prompt, **kw: {
        "prompt": prompt, "aspect_ratio": kw.get("aspect_ratio", "1:1")
    },
    "qwen-image-2.0": lambda prompt, **kw: {
        "prompt": prompt, "size": kw.get("size", "2048*2048")
    },
    "seedance-2.5/text-to-video": lambda prompt, **kw: {
        "prompt": prompt,
        "duration": kw.get("duration", 5),
        "aspect_ratio": kw.get("aspect_ratio", "16:9"),
    },
}

def build_task_payload(model: str, prompt: str, **kw) -> dict:
    return {"model": model, "input": MODEL_INPUT_BUILDERS[model](prompt, **kw)}

This keeps the per-model quirks in one place instead of scattered across every call site. A nonexistent or cross-account taskId returns a plain 404:

{ "code": 404, "message": "task not found", "data": null }

And a transient 503 should be retried with exponential backoff rather than surfaced straight to the user — rate limits and capacity limits are documented in rate limits.

Related reading

  • Async task API reference — full create/detail contract
  • Authentication — API key scoping and rotation
  • Storage — persisting output beyond the default expiry
  • Why your task callback might not be firing
  • Browse all models — every model's own input schema lives on its page
  • Pricing — cost is per-model and per-output, not flat per request

FAQ

Do I need a different SDK or API key per model? No. One API key, one endpoint pattern (/v1/tasks), for every model on the platform. Only the input object inside the request body changes.

Why doesn't my response have output yet right after creating the task? Generation is asynchronous. The create call only returns taskId and status: "queued" — you have to poll GET /v1/tasks/:id (or use a callback) until status reaches success or fail.

Can I call the API without authentication for a quick test? No — every /v1/tasks call requires a valid Authorization: Bearer key. There's no keyless or demo mode for production calls; generate a key from your dashboard first.

What happens if I poll after the output URL has expired? The task record itself persists, but the output[].url from a non-persistent task will stop resolving after expireAt. Download the file immediately on success, or set storage: "persistent" at creation time if you need it to stick around.

How do I know which fields a given model accepts? Check that model's page under Models — each one documents its exact input schema. Don't assume aspect_ratio, size, or duration carry over between models; as shown above, z-image and qwen-image-2.0 already disagree on how to express image shape.

Latest models

Explore models

Generate it with HiAPI

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

Start generatingView model pricing

HiAPI Blog

Related articles

View all articles
HiAPI 402 Error: How to Fix 'Insufficient Balance'

HiAPI 402 Error: How to Fix 'Insufficient Balance'

Seedream API Cost Optimization: How to Cut Image Generation Costs on hiapi

Seedream API Cost Optimization: How to Cut Image Generation Costs on hiapi

Seedance 2.0 Ext First-Frame Video Prompts: Anchor vs Interpolation

Seedance 2.0 Ext First-Frame Video Prompts: Anchor vs Interpolation

Seedance 2.0 Realistic Prompt: Making AI Video Look Like Real Phone Footage

Seedance 2.0 Realistic Prompt: Making AI Video Look Like Real Phone Footage

HiAPI Task Timeout and 504 Errors: How to Fix Them

HiAPI Task Timeout and 504 Errors: How to Fix Them

Seedance 2.0 Ext 2D Sticker Composite Prompt: Full Breakdown

Seedance 2.0 Ext 2D Sticker Composite Prompt: Full Breakdown

HiAPI

Generate it with HiAPI

Start generating
View all models
GPT Image 2.5 Flare50% offFrom $0.025/image
GPT Image 2.5 Sunburst50% offFrom $0.025/image
GPT Image 2From $0.030/image
Nano Banana 250% offFrom $0.018/image
Text
Image
Video
Audio