TL;DR
- Ideogram 4.5 is a typography-first family:
ideogram-v4.5/text-to-imagegenerates posters, wordmarks, and bilingual packaging with in-image text, whileideogram-v4.5/image-to-imageoffers Precise Edit for surgical text changes, reference-image restyling, and masked local edits. Choose a task on the model page, or use the API examples below. - Pricing is per image and tiered: LOW $0.043, MEDIUM (default) $0.086, HIGH $0.3145; editing adds VERY_LOW at $0.0115; each request returns 1 image;
num_imagesmust be 1. See the pricing guide. - Everything runs on HiAPI
/v1/tasks: submit and readdata.taskId, querydata.status, then download thetype=imageentry fromdata.outputon success.
What it does
- Organize text hierarchy: quote the required words and specify positions for the headline, subtitle, date, and lineup. Proofread the generated text.
- Single-image composition tests: each request returns 1 image. Vary the prompt or seed and submit separate tasks for alternatives.
- A matching editor: Precise Edit (
edit_precision=high) supports focused changes such as names or dates; compare preserved areas with the source. - References and masks: up to 4 references (3 with a mask); mask black repaints, white keeps.
Here's a real LOW-tier output:
Minimal modern brand poster for a design conference. Huge bold headline text "DESIGN FORWARD" centered, smaller subtitle "Typography Summit 2026" below, clean Swiss grid layout, warm orange and deep navy palette, geometric shapes, crisp sharp lettering

ideogram-v4.5/text-to-image, LOW, landscape_16_9, 1280×720, $0.043.
Two endpoints: which to use
ideogram-v4.5/text-to-image | ideogram-v4.5/image-to-image | |
|---|---|---|
| What it does | Generates typeset frames from text | Edits existing images |
| Required input | prompt | image_url + prompt |
| Quality tiers | low / medium / high | very_low / low / medium / high |
| Special parameters | num_images: 1, enable_prompt_expansion | edit_precision (Precise), reference_image_urls, mask_url |
| Size | 6 presets, default square_hd | auto (default) or 6 presets; masks and Precise are auto-only |
| Best for | Posters, logos, packaging, signage drafts | Text fixes, recolors, seasonal variants, local repaints |
Typical pipeline: generate the brand poster, then use Edit to swap in each client's name and date. A LOW generation ($0.043) plus a Precise LOW edit ($0.043) is $0.086 a set.
Two ways to start
Browser, 3 steps: open the model page → paste the prompt, pick a tier → generate.
API, 3 steps: POST /v1/tasks to submit → read data.taskId → query until data.status is success, then download.
curl: your first image
Set HIAPI_IDEMPOTENCY_KEY in the terminal to a unique ID for this business operation and reuse it for retries. This example explicitly selects LOW, a landscape size, and expansion enabled.
curl -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $HIAPI_IDEMPOTENCY_KEY" \
-d '{
"model": "ideogram-v4.5/text-to-image",
"input": {
"prompt": "Minimal modern brand poster for a design conference. Huge bold headline text \"DESIGN FORWARD\" centered, smaller subtitle \"Typography Summit 2026\" below, clean Swiss grid layout, warm orange and deep navy palette, geometric shapes, crisp sharp lettering",
"quality": "low",
"image_size": "landscape_16_9",
"enable_prompt_expansion": true,
"num_images": 1
}
}'
For editing, switch model to ideogram-v4.5/image-to-image with a source image and instruction. This Precise Edit request asks for a text change while keeping the layout; compare the output with the source:
Set a separate HIAPI_EDIT_IDEMPOTENCY_KEY for this editing operation; do not reuse the generation task’s key.
curl -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $HIAPI_EDIT_IDEMPOTENCY_KEY" \
-d '{
"model": "ideogram-v4.5/image-to-image",
"input": {
"prompt": "Change the logo text from \"Ember & Oak\" to \"Maple & Co\", keep the same serif lettering style, emblem, tagline, colors and layout exactly unchanged",
"image_url": "https://static.hiapi.ai/gallery/2026/10/88567ad2baf46b32.png",
"edit_precision": "high",
"quality": "low",
"image_size": "auto",
"num_images": 1
}
}'
Python: submit, poll, download
Install requests and set HIAPI_API_KEY. For a new submission, also set HIAPI_IDEMPOTENCY_KEY: use a unique value for each new business operation and keep it unchanged for retries. The program prints the task ID first. After an interruption, set HIAPI_TASK_ID to resume polling and downloading without submitting another generation task.
import os
import time
from pathlib import Path
import requests
BASE = "https://api.hiapi.ai/v1/tasks"
headers = {"Authorization": "Bearer " + os.environ["HIAPI_API_KEY"]}
payload = {
"model": "ideogram-v4.5/text-to-image",
"input": {
"prompt": "Minimal modern brand poster for a design conference. Huge bold headline text \"DESIGN FORWARD\" centered, smaller subtitle \"Typography Summit 2026\" below, clean Swiss grid layout, warm orange and deep navy palette, geometric shapes, crisp sharp lettering",
"quality": "low",
"image_size": "landscape_16_9",
"enable_prompt_expansion": True,
"num_images": 1,
},
}
# Set HIAPI_TASK_ID to resume polling without creating another task.
task_id = os.environ.get("HIAPI_TASK_ID")
if not task_id:
# Use one unique key per business operation; keep it for retries.
submission_key = os.environ["HIAPI_IDEMPOTENCY_KEY"]
response = requests.post(
BASE, headers={**headers, "Idempotency-Key": submission_key},
json=payload, timeout=30,
)
response.raise_for_status()
created = response.json()
if created.get("code") != 200:
raise RuntimeError(created)
task_id = created["data"]["taskId"]
print("Keep this task ID:", task_id, flush=True)
deadline = time.monotonic() + 600
while time.monotonic() < deadline:
response = requests.get(f"{BASE}/{task_id}", headers=headers, timeout=30)
response.raise_for_status()
result = response.json()
if result.get("code") != 200:
raise RuntimeError(result)
task = result["data"]
if task["status"] in ("fail", "failed"):
raise RuntimeError(task.get("error", task))
if task["status"] == "success":
image_url = next(
(item["url"] for item in task.get("output", [])
if item.get("type") == "image" and item.get("url")), None,
)
if not image_url:
raise RuntimeError("Successful task has no image URL")
# Do not forward API authorization to the media download host.
image = requests.get(image_url, timeout=60)
image.raise_for_status()
media_type = image.headers.get("Content-Type", "").split(";", 1)[0].lower()
suffix = {"image/png": ".png", "image/jpeg": ".jpg",
"image/webp": ".webp"}.get(media_type)
if not suffix:
raise RuntimeError("Unexpected image content type: " + media_type)
target = Path(task_id + suffix)
partial = target.with_suffix(suffix + ".part")
partial.write_bytes(image.content)
partial.replace(target)
print("Saved:", target)
break
time.sleep(3)
else:
raise TimeoutError(f"Polling timed out; keep checking task {task_id}")
If a query or download has a network error, resume with the printed task ID; the script does not automatically repeat task creation. It polls for up to 600 seconds with 3-second waits, downloads to a .part file, and renames it only when complete.
Parameters
Generation: ideogram-v4.5/text-to-image
| Field | Required | Values | Notes |
|---|---|---|---|
prompt | yes | 1–10,000 chars | Four parts: the job → text and palette → layout → finish and limits |
quality | no | low / medium / high, default medium | low for exploration, medium daily, high for small-type finals |
image_size | no | 6 presets, default square_hd | No custom sizes |
num_images | no | Must be 1 | One output image per task |
enable_prompt_expansion | no | default true | Prompt expansion; false disables expansion, but output text still needs checking |
seed | no | integer | Reproduce with identical inputs |
Editing: ideogram-v4.5/image-to-image
| Field | Required | Values | Notes |
|---|---|---|---|
image_url | yes | image URL | Source image |
prompt | yes | 1–10,000 chars | The change; state what stays |
edit_precision | no | regular / high, default regular | high = Precise Edit, for focused text changes |
quality | no | very_low / low / medium / high, default medium | very_low works with regular only |
image_size | no | auto or 6 presets, default auto | Masks and Precise are auto-only |
reference_image_urls | no | up to 4 | At most 3 when a mask is supplied |
mask_url | no | image URL | Black repaints, white keeps |
num_images | no | Must be 1 | One output image per task |
seed | no | integer |
Unknown fields inside input return 400; top-level fields such as model and callback follow the task-endpoint format.
Errors you'll actually hit
| Status | Meaning | What to do |
|---|---|---|
| 400 INVALID_REQUEST | Malformed body (missing prompt or image_url, bad enum, unknown field) | Fix the payload against the tables |
| 402 INSUFFICIENT_QUOTA | Out of credits (no charge) | Top up and retry |
| 429 RATE_LIMITED | Rate limited | Slow your submissions |
| 409 IDEMPOTENCY_KEY_PROCESSING | A task is being created for this key | Wait and retry the same key and body |
| 422 IDEMPOTENCY_KEY_MISMATCH | The key was reused with a different body | Restore the original body; use a new key only for a new task |
Terminal failures may include CONTENT_POLICY_VIOLATION, TASK_FAILED, and TASK_TIMEOUT. Keep the taskId and error, then reconcile the final task state with the account record. A query or download failure does not establish generation failure.
Before you ship
- Callbacks: pass
"callback": {"url": "https://..."}at the request top level. - Persist outputs: result URLs in
data.outputexpire; download them after success. - Single-image tasks and idempotency: each task returns 1 image. Reuse the same key for retries of the same logical submission; assign a new key only to a new task.
- Small Chinese text: compare tiers using your actual copy, and proofread before delivery. Medium or high is not a substitute for checking.
FAQ
How many images can one request generate?
Generation and editing currently return 1 image per task; num_images must be 1. Submit separate tasks for alternatives.
Is LOW the default quality tier?
No. MEDIUM is the default at $0.086 per image. Set quality: "low" explicitly for LOW at $0.043.
Which mode fits a brand-name or date change?
Use Precise Edit with explicit edit_precision: "high", quality: "low", and image_size: "auto", at $0.043 per image.
What do black and white mask regions mean?
Black regions are repainted and white regions are kept. Match the mask to the source dimensions and choose image_size: "auto" with a mask.
Should a timeout retry use a new idempotency key?
Not for the same logical submission. Reuse the same Idempotency-Key and body; use a new key only when you intend to create a new task.
Next: take the DESIGN FORWARD prompt, generate a poster, then swap in your own event name with one Precise instruction. Related: quality-tier prices and budgets · 4 editing prompt examples.





