Search

Search HiAPI models, tools, and resources.

Back to blog
Tutorial

imagen4-ultra API: A Working Text-to-Image Request

hiapiimagen4-ultraImagen 4Text-to-ImageTask API

Imagen 4 Ultra is Google's highest-detail tier in the Imagen 4 family, and on hiapi it runs text-to-image through the same unified async task API as every other image model. This guide gives you one request that actually works — a real curl call, a Python poll loop, the exact parameters the server accepts, and the error cases verified against a live request. Everything below was run against the production endpoint before publishing; the sample taskId and output URL are from that run.

What you'll build

A single call that turns a text prompt into a finished image: submit a task to POST /v1/tasks, poll until it's done, and read the image URL from output[0].url. You need a hiapi API key — grab one from your dashboard and export it:

export HIAPI_API_KEY="your-hiapi-key"

Minimal working example (curl)

The model takes a prompt and an optional aspect_ratio. Create the task:

curl -X POST "https://api.hiapi.ai/v1/tasks" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "imagen4-ultra",
    "input": {
      "prompt": "Macro product photo of a matte ceramic coffee mug on a pale oak table, soft window light from the left, shallow depth of field, a few coffee beans in the foreground, no text, no logos",
      "aspect_ratio": "4:3"
    }
  }'

The create call returns immediately with a task id — generation continues in the background:

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

Poll the task with the id you got back:

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

Once status is success, the image is in output[0].url:

{
  "code": 200,
  "data": {
    "taskId": "tk-hiapi-01M5CVC8R62M0Z7CCM8WB38B61",
    "model": "imagen4-ultra",
    "status": "success",
    "storage": "temp",
    "created": 1792506471,
    "completed": 1792506479,
    "output": [
      {
        "artifactId": "279760",
        "type": "image",
        "url": "https://temp.hiapi.ai/7c6ttvrbpt/01M5CVC8R62M0Z7CCM8WB38B61-0.webp",
        "expireAt": 1793111279
      }
    ]
  },
  "message": "success"
}

That run completed in about 8 seconds and returned a single WebP (not PNG/JPEG). The URL lives on temporary storage ("storage": "temp") with expireAt set 7 days out — download it promptly rather than hotlinking.

Production: Python with a poll loop

The create response doesn't contain the image — only a taskId. A real integration submits, then polls (or uses a callback). This script does the full round trip and downloads the result immediately, since the URL is temporary:

import os, time, requests

API = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"}

def generate(prompt, aspect_ratio="1:1", negative_prompt=None, seed=None):
    body = {"model": "imagen4-ultra", "input": {"prompt": prompt, "aspect_ratio": aspect_ratio}}
    if negative_prompt:
        body["input"]["negative_prompt"] = negative_prompt
    if seed is not None:
        body["input"]["seed"] = str(seed)  # seed is a STRING, not a number

    r = requests.post(API, headers=HEADERS, json=body, timeout=60)
    r.raise_for_status()
    created = r.json()
    if created.get("code") != 200:
        raise RuntimeError(f"create rejected: {created}")
    task_id = created["data"]["taskId"]

    # Poll. Statuses other than success/fail (e.g. queued, running, archiving) mean "keep waiting".
    for _ in range(60):
        time.sleep(3)
        try:
            d = requests.get(f"{API}/{task_id}", headers=HEADERS, timeout=30).json()["data"]
        except requests.RequestException:
            continue  # tolerate a transient read; re-poll the same id
        status = d.get("status")
        if status == "success":
            return d["output"][0]["url"]
        if status in ("fail", "failed", "error"):
            raise RuntimeError(f"task failed: {d}")
    raise TimeoutError(f"task {task_id} did not finish in time")

url = generate(
    "A high-detail aerial landscape of terraced rice fields at golden hour, long shadows",
    aspect_ratio="16:9",
)
img = requests.get(url, timeout=60).content
open("out.webp", "wb").write(img)
print(f"saved {len(img)} bytes from {url}")

Notes that matter in production:

  • Poll vs callback. Polling is shown above. To avoid polling, attach a top-level callback object ({"url": "...", "when": "final"}) and hiapi will POST you when the task reaches a terminal state. See the Unified Async API docs for the callback contract.
  • Re-poll the saved id, don't recreate. Reading a task is idempotent; a dropped connection is a retry on GET /v1/tasks/<id>, never a second POST (which bills a second image).
  • Download on success. output[0].url is temporary (7-day TTL in this run). Fetch the bytes and push them to your own storage.

Parameters this model actually accepts

imagen4-ultra is text-to-image only — reference images are not supported (confirmed on the model page; this run only exercised text-to-image). The input schema is closed: unknown fields are rejected, so you can't sneak in extra params.

FieldTypeRequiredNotes
promptstringyes1–5,000 characters. Empty string fails (minLength: got 0, want 1).
aspect_ratioenumnoOne of 1:1, 16:9, 9:16, 3:4, 4:3, auto. Defaults to 1:1.
negative_promptstringnoUp to 5,000 characters; describe what to exclude.
seedstringnoUp to 500 characters. It's a string — passing a number is rejected.

One request produces exactly one image.

Verified error cases

These were produced against the live endpoint, so your error handling can rely on them. Rejected requests return an HTTP 400 with a flat envelope and no taskId:

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

A few behaviors worth coding around:

  • The validator reports every field error at once, joined by ; . Send a number for seed and a bad aspect_ratio and you get both in one message: invalid input: seed: got number, want string; aspect_ratio: value must be one of .... Don't assume one error per response.
  • Unknown fields fail the whole request with <root>: additional properties '<name>' not allowed. The schema is closed.
  • Empty prompt fails with prompt: minLength: got 0, want 1.
  • A successful create is code: 200 with data.taskId; a rejection has data: null. Branch on that before you try to read a task id.

Which Imagen 4 tier should you call?

imagen4-ultra is the top of three tiers; pick by job, not by habit (aspect ratio, negative prompt and seed do not change what you pay — see pricing):

  • Imagen 4 Fast — cheapest, for draft sweeps and exploring directions in bulk.
  • Imagen 4 — the everyday middle tier for product, lifestyle and content images.
  • Imagen 4 Ultra (this model) — the priciest of the three, positioned for finished-quality detail: macro texture, material rendering and lettering where the final image has to hold up. Reach for Ultra when the output ships as-is; use Fast or the base tier when you're iterating.

FAQ

How many images does one request return? One. The output array held a single item in the verified run.

What format is the output? WebP. The returned file was a .webp on temp.hiapi.ai.

How long is the output URL valid? About 7 days — expireAt was set 7 days after completion. Treat it as temporary and download right away.

Can I send a reference image? No. imagen4-ultra is text-to-image only; the model page lists reference images as not supported.

Why does my request fail with "additional properties not allowed"? The input schema is closed. Send only prompt, aspect_ratio, negative_prompt and seed; any other key fails the whole request.

Do negative prompt, seed or aspect ratio change the price? No. Billing is per image; those parameters don't affect cost.

Generate it with HiAPI

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

HiAPI Blog

Related articles

HiAPI

Generate it with HiAPI

Start generating