Tutorial
How to Use imagen-4.0 via the HiAPI API: curl, Python, and a Working Request
What imagen-4.0 Gives You Through HiAPI
imagen-4.0 is a text-to-image model: you send a natural-language prompt, and it returns a generated image. What matters for you as an integrator is not the model's architecture but the contract around it. Through HiAPI, that contract is a single HTTP endpoint that accepts JSON and authenticates with a bearer key — the same pattern you already know from chat completion and embedding calls.
The practical consequences of using HiAPI rather than wiring up a model directly:
- One auth scheme. The same API key works across models on the platform, so you don't juggle per-provider credentials.
- One request format. A JSON body with a model identifier and a prompt. No SDK-specific shapes to learn.
- Synchronous delivery. imagen-4.0 returns the result in the same HTTP response, so there is no polling loop or webhook to build for the basic case.
This guide walks from zero to a working request in both curl and Python, then covers how to read the response and what to do before you put this in production.
Get Your API Key and Set Up Authentication
Every imagen-4.0 call on HiAPI is authenticated with a bearer token. You create an API key in your HiAPI account, and from then on the key is the only credential the request needs — no separate project ID, no signed headers.
The rule that prevents most incidents: the key goes in an environment variable, never in committed source. A key pasted into a script and pushed to a repository is a key you have to rotate.
Local setup
Export the key in your shell session:
export HIAPI_API_KEY="your-key-here"
Add that line to your shell profile if you want it to persist, or use a .env file that is listed in .gitignore and loaded by your application at startup.
Deployed environments
In CI and production, set HIAPI_API_KEY through the platform's secret manager — environment variables injected at runtime, not files baked into the image. The application code is then identical across local and deployed environments; only the source of the variable changes.
The header
Every request carries:
Authorization: Bearer $HIAPI_API_KEY
If you ever see a 401, the first thing to check is whether the header was actually sent and whether the variable resolved to a non-empty value. A shell that never exported the variable will happily send Bearer with nothing after it.
Understand the Request Shape Before You Send It
The body of an imagen-4.0 request is small enough to hold in your head, which is the point — once you understand the shape, you can construct requests in any language instead of translating a copy-paste snippet.
At minimum you send:
{
"model": "imagen-4.0",
"prompt": "A weathered lighthouse on a cliff at dusk, long exposure, muted colors"
}
Two fields do the work:
modelidentifies which model handles the request. It is a string, and it is the same identifier the platform uses everywhere imagen-4.0 is listed. Get it wrong and you get an error, not a silent fallback.promptis the description of the image you want. Write it the way you would describe the picture to a person: subject, setting, style, lighting. Specific prompts produce more predictable results than single-word ones.
The request is sent as POST with Content-Type: application/json to the platform's image generation endpoint. Additional optional parameters may exist for the model, but the two-field body above is a complete, valid request — start there and add options only when you need them.
Because the body is plain JSON, curl, Python, Node, and anything else with an HTTP client are all first-class citizens. The next two sections show the same request twice.
A Working curl Request
Start in the terminal, where you can see the raw response without any parsing in the way.
curl -sS -X POST "$HIAPI_BASE_URL/images/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "imagen-4.0",
"prompt": "A weathered lighthouse on a cliff at dusk, long exposure, muted colors"
}'
Line by line:
-sSsilences the progress meter but still shows errors, which keeps the output readable without hiding failures.-X POSTsets the method. Image generation creates something, so it is aPOST.- The URL is the image generation endpoint on the platform, built from your base URL plus the path. Keep the base URL in a variable so the same command works across environments.
- The first header carries your bearer key, read from the environment variable you exported earlier.
Content-Type: application/jsontells the server how to parse the body.-dsupplies the JSON body. The single quotes keep your shell from interpreting the braces and quotes; inside them the JSON is literal.
Pipe the output through a JSON formatter if you want to inspect it:
curl -sS -X POST "$HIAPI_BASE_URL/images/generations" \
-H "Authorization: Bearer $HIAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"imagen-4.0","prompt":"A weathered lighthouse on a cliff at dusk"}' \
| python -m json.tool
If the response contains an image reference, the request worked. The next section turns this into application code.
The Same Request in Python
The curl call translates directly. The only real decision is the HTTP client; the standard library's urllib works everywhere, but requests is the shorter read and what most codebases already depend on.
A reusable helper
import os
import requests
HIAPI_BASE_URL = os.environ.get("HIAPI_BASE_URL", "https://api.hiapi.ai/v1")
def generate_image(prompt: str, model: str = "imagen-4.0") -> dict:
api_key = os.environ["HIAPI_API_KEY"]
response = requests.post(
f"{HIAPI_BASE_URL}/images/generations",
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
},
json={"model": model, "prompt": prompt},
timeout=120,
)
response.raise_for_status()
return response.json()
result = generate_image("A weathered lighthouse on a cliff at dusk")
print(result)
Three things worth noting:
os.environ["HIAPI_API_KEY"]raises aKeyErrorimmediately if the variable is missing, which fails fast and loudly instead of sending an empty token.json=serializes the dict and sets the content type for you, so the request is behaviorally identical to the curl version.timeout=120bounds the call. Image generation takes longer than a text completion, so use a generous timeout rather than the default of none.
The function takes the prompt as an argument and returns the parsed JSON, which means the rest of your code never touches HTTP details. Test it from a REPL before wiring it into anything.
Read the Synchronous Response and Handle Errors
imagen-4.0 responds synchronously: the generated image arrives in the body of the same HTTP response. There is no job ID to poll and no polling loop to write for the basic case — treat the call like any other request-response interaction.
What comes back
A successful response is a JSON object. Parse it with response.json() in Python, or pipe curl output through a JSON formatter, and locate the image data in the returned structure — typically a URL or an encoded image payload alongside metadata about the generation. Read the exact field names from a real response once, then code against them.
What to guard against
Wrap the call and check status before parsing:
try:
result = generate_image("A weathered lighthouse on a cliff at dusk")
except requests.HTTPError as e:
print("HTTP error:", e.response.status_code, e.response.text)
except requests.Timeout:
print("Request timed out")
The failure modes worth handling explicitly:
401— missing or invalid key. Fix the environment variable, not the code.4xxgenerally — a malformed body, a wrong model identifier, or a rejected prompt. The response body usually says which. Log it.5xx— server-side failure. These are the ones worth retrying with backoff.- Timeouts — treat as unknown outcome rather than success; do not assume the image was generated.
Always log the status code and a truncated response body on failure. Debugging without that information is guesswork.
Going From Your First Request to Production
The request works. Before you scale it up, walk this checklist:
- Configuration. Base URL and API key both come from the environment. No literals in source, no keys in images.
- Timeouts. Every image call has one. Without a timeout, a stalled request can hold a worker indefinitely.
- Retries. Retry only on
5xxand timeouts, with exponential backoff and a cap. Never retry401or a malformed-body4xx— they will fail identically. - Logging. Log the model, prompt length, status code, and latency per call. Not the key, and not full prompts if they may contain user data.
- Cost awareness. Image generation is billed by the output produced, so track how many images you request per user or per job and cap it at the application layer. Current rates live in the platform's pricing panel rather than in this guide.
- Concurrency. Image calls are slower than text calls. Size your worker pool with that in mind rather than assuming chat-completion latencies.
Once these are in place, the same generate_image helper covers batch jobs, user-facing features, and internal tooling without modification. For further integration details, see the platform documentation.
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