Tutorial
How to Use imagen-4.0-fast via the HiAPI API: curl and Python Guide
A practical integration guide for developers: request setup, parameter handling, and reliability patterns for the fast image model
What imagen-4.0-fast Is Optimized For
imagen-4.0-fast is the latency-oriented tier of the imagen-4.0 family: it targets fast turnaround on image generation requests while keeping the same request-and-response shape you would use for the rest of the family. In practice, that makes it the tier you reach for when an image needs to appear inside a user-facing interaction — a draft thumbnail, a preview the user will refine, an asset for a live layout — rather than in an offline batch where wall-clock time is irrelevant.
A useful way to think about model selection is to separate the interaction budget from the quality ceiling. Fast tiers win when the interaction budget is tight and a good-enough image unblocks the next step. Higher-quality tiers win when the image itself is the deliverable. Because imagen-4.0-fast lives behind the same HiAPI interface as other image models, switching tiers later is a configuration change, not a rewrite — so you can start on the fast tier, measure whether output quality meets your product bar, and only then consider moving specific use cases up the tier ladder.
The other thing the fast tier is optimized for is predictability under load. Short generations mean connections are held for less time, which makes concurrency budgets behave more linearly: doubling workers roughly doubles throughput until you hit account-level rate limits rather than timing out mid-generation. That property is what the later sections on timeouts and concurrency build on.
If your use case involves multi-step user flows, batching, or anything where a request might be retried, the fast tier is the safer default — you can afford one extra attempt and still land inside a human's patience window.
Prerequisites and API Setup
Before the first call, gather four things.
1. A HiAPI account and API key
All image generation goes through the HiAPI unified API. Create an API key in your HiAPI dashboard and store it as an environment variable rather than in source code:
export HIAPI_API_KEY="your_key_here"
Never commit the key. If your code runs in CI or a container, inject the variable through your secret manager at runtime.
2. A base URL and model identifier
Keep two constants in one config module so every request in your codebase points at the same place:
HIAPI_BASE_URL = "https://api.hiapi.ai"
HIAPI_IMAGE_MODEL = "imagen-4.0-fast"
The model identifier is what selects imagen-4.0-fast inside a request payload. Treat it as data, not as a hardcoded string scattered across files.
3. An HTTP client you trust
For Python, httpx or requests both work; httpx gives you cleaner timeout objects. For shell work, curl is enough and is the fastest way to isolate whether a problem is in your code or in the request itself.
4. A minimal test harness
Decide up front where generated output will land — writing to a file on disk for a smoke test is fine, but production code should stream or store deliberately rather than leave large payloads in memory.
Two configuration habits pay off early. First, centralize authentication in one helper that attaches the Authorization header, so rotating a key touches one place. Second, keep a DEBUG flag that lets you print request IDs and timing without changing payloads. When something fails at 2am, those two habits are the difference between a five-minute fix and an hour of guessing.
A Working Request with curl
Here is a complete, runnable curl call. It generates a single image from a text prompt:
curl -sS -X POST "$HIAPI_BASE_URL/v1/images/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "imagen-4.0-fast",
"prompt": "a quiet harbor at dawn, soft mist over wooden docks, photographic",
"n": 1,
"size": "1024x1024"
}'
Walking through the fields:
-sSsilences the progress meter but still shows errors. For debugging, add-ito see response headers, which usually carry a request ID you can quote when asking for help.-X POSTwith theContent-Type: application/jsonheader is what makes the payload a structured request rather than an opaque body.Authorization: Bearer $HIAPI_API_KEYis the only authentication mechanism. The key is read from the environment so it never appears in your shell history in plaintext if you set it in your session.modelselects imagen-4.0-fast within the HiAPI image endpoint. Omit it and you may get a different default model — always be explicit.promptis the only required content field. Keep it descriptive but not encyclopedic; long prompts cost tokens and rarely improve fast-tier output past a point.ncontrols how many images the request returns. Start at 1 while integrating.sizeis the output resolution request. Section five covers how to choose it.
Run it once and inspect the response body before writing any Python. If curl succeeds, every later failure is in your client code. If curl fails, the problem is the key, the payload, or the account — and you have already eliminated half the search space.
The Same Request in Python
Here is the minimal Python client, translated field-for-field from the curl call, with error handling wrapped around the HTTP layer:
import os
import httpx
HIAPI_BASE_URL = "https://api.hiapi.ai"
HIAPI_IMAGE_MODEL = "imagen-4.0-fast"
def generate_image(prompt: str, size: str = "1024x1024") -> dict:
api_key = os.environ["HIAPI_API_KEY"] # fail fast if unset
payload = {
"model": HIAPI_IMAGE_MODEL,
"prompt": prompt,
"n": 1,
"size": size,
}
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
with httpx.Client(timeout=httpx.Timeout(60.0, connect=10.0)) as client:
response = client.post(
f"{HIAPI_BASE_URL}/v1/images/generations",
json=payload,
headers=headers,
)
if response.status_code == 401:
raise RuntimeError("HiAPI rejected the API key")
if response.status_code == 429:
raise RuntimeError("Rate limited; back off and retry")
response.raise_for_status()
return response.json()
if __name__ == "__main__":
result = generate_image("a quiet harbor at dawn, soft mist over wooden docks, photographic")
print(result)
A few deliberate choices in that snippet:
os.environ["HIAPI_API_KEY"]raisesKeyErrorimmediately if the variable is missing, which is better than sending an unauthenticated request and misreading the 401 as a key problem.- Explicit timeouts — a connect timeout and a read timeout separately. The read timeout is the one that matters for image generation, because the server holds the connection while the image is produced.
- Status-specific branches before
raise_for_status(). A 401 and a 429 need completely different responses from your code; collapsing them into one exception makes retries accident-prone. - A
Clientcontext manager so connections are closed deterministically. In a long-lived service, create one client at startup and reuse it instead — connection reuse matters for throughput.
The response body carries the generated image reference plus metadata. Log the full body on the first few calls during integration so you know exactly what field names your code depends on.
Parameters and Resolution Choices
Parameter handling for imagen-4.0-fast rewards a boring, explicit style. Keep the payload as a dict built by one function, and validate before sending rather than after a failure.
Prompt
The prompt is the highest-leverage parameter and the easiest to over-engineer. Describe subject, setting, and style in that order. Avoid stacking contradictory style words; the fast tier will resolve them into an average, not a compromise you control. If you generate the same prompt repeatedly, cache the result server-side rather than re-requesting.
n
Requesting multiple images in one call is convenient for user-facing pickers, but it multiplies the work done in a single request and therefore the time the connection is held. During integration keep n at 1; add it only after you have measured end-to-end latency with it enabled.
size
The resolution parameter is where costs and latency quietly accumulate. Larger output means more generation work and larger response bodies. Pick the smallest resolution that satisfies the display context — a thumbnail slot does not need a hero image's dimensions. Decouple the generation size from the display size and let your own image pipeline upscale or downscale afterward; that keeps requests predictable and makes it easy to tune quality against latency later without changing prompt logic.
Determinism and reproducibility
Record every parameter you send alongside the output, keyed by a request ID. When someone asks why an image looks different from last week, a stored payload answers the question in seconds. If you build payloads by merging user input over defaults, validate the merged result as a whole — partial overrides are the usual source of malformed requests.
A practical rule: the payload should be small, fully explicit, and reproducible from logs. Anything you cannot reconstruct from your logs is a parameter you will eventually regret adding.
Handling Timeouts and Concurrency
Because imagen-4.0-fast keeps generation time short, most reliability problems are client-side: timeouts set too low, retries that fire when they shouldn't, or too much parallelism against an account-level limit.
Timeouts
Set two numbers, not one. A short connect timeout catches network and DNS problems quickly; a longer read timeout accommodates generation plus transfer. Choose the read timeout from observed p95 latency in your environment with headroom, not from a guess. Retrying a request that timed out while the server was still working wastes capacity — so if you do retry, treat it as a new attempt with its own budget rather than assuming the first one was free.
Retries
Retry only what is safe to retry: connection errors and 5xx responses. Never retry a 4xx — a malformed payload will fail identically every time. Use exponential backoff with jitter, and cap the total number of attempts. A useful structure is three attempts with delays of roughly 1s, 2s, and 4s plus randomization, which spreads load when many clients fail simultaneously.
Concurrency
For batch work, use a bounded worker pool rather than unbounded asyncio.gather. Each in-flight request holds a connection and consumes your account's rate budget. Start with a small pool — a handful of concurrent requests — measure throughput, and increase until latency stops improving or you begin seeing 429s. The fast tier's short generations make their own case here: because each request finishes quickly, a modest pool sustains high throughput without long-lived open connections.
Backpressure
When you receive a 429, the correct response is to slow down, not to retry immediately. Add a short delay informed by the backoff pattern above, and consider temporarily reducing pool size. Log the concurrency level at the time of the 429 — that number is your practical ceiling.
Debugging Common Request Failures
Work through failures in the order that eliminates the most uncertainty per step: reproduce with curl first, then move into your client.
401 Unauthorized
The key is missing, malformed, or not sent as a Bearer token. Check the Authorization header directly, confirm the environment variable is populated in the exact process making the call (containers and CI runners differ from your shell), and verify there are no stray quotes or trailing whitespace around the value. If curl works with a literal key but your app fails, the problem is definitely environment loading.
400 Bad Request
A malformed payload or an invalid parameter value. Reproduce with the exact JSON your client sent — log the serialized payload, not your in-memory dict — and compare it against the working curl example. Frequent causes: Content-Type missing, model misspelled, a numeric field sent as a string, and leftover fields from an earlier API shape.
422 / validation errors
Fields are present but outside permitted bounds — typically n or size set to a value the model does not accept. Reduce the payload to the minimum required fields, confirm it succeeds, then add parameters back one at a time.
429 Rate limited or quota exhausted
You are sending more requests, or more concurrent requests, than your account allows. Confirm with your concurrency logs, reduce pool size, and confirm the backoff pattern is actually being applied. If it persists at low volume, check whether other processes share the same key.
5xx and timeouts
Server-side or network. Retry with backoff once or twice; if the failure is repeatable for a specific payload, capture the request ID from response headers and the exact payload — that is what makes escalation productive.
A general habit
Keep a --verbose curl reproduction for every production failure. Getting from an application error to a single copy-pasteable curl command shrinks the debugging surface to the request itself. From there, imagen-4.0-fast through the HiAPI API behaves predictably.
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