
Seedream 5.0 Lite is ByteDance's fast, lower-cost text-to-image model. On hiapi you call it through the unified async task API — the same POST /v1/tasks → poll (or callback) flow every image model on the platform uses — with the bare model id seedream-5.0-lite/text-to-image.
This guide gives you a request that works on the first try: the exact required parameters (this model rejects anything it doesn't know), a copy-paste curl and Python example, and the production details — callbacks, idempotency, and the error shapes you'll actually see.
Goal: send a text prompt, get back a hosted image URL you can download.
You need one thing: a hiapi API key. Create one in the hiapi dashboard — it looks like sk-... and goes in the Authorization: Bearer header. Per-image cost depends on the resolution tier; see the pricing page for current rates.
seedream-5.0-lite/text-to-image validates its input object strictly. All three fields are required, and any extra field is a 400:
| Field | Required | Allowed values |
|---|---|---|
prompt | yes | string, minimum 3 characters |
aspect_ratio | yes | 1:1, 4:3, 3:4, 16:9, 9:16, 2:3, 3:2, 21:9 |
resolution | yes | 2K, 4K |
Two things trip people up coming from other models:
1K tier. This model only renders 2K or 4K. If you're porting code from a model that defaults to 1K, you'll get: resolution: value must be one of '2K', '4K'.seed, negative_prompt, n, size, guidance_scale, and watermark are all rejected with additional properties ... not allowed. Schemas differ per model on hiapi (for example, gpt-image-2/text-to-image accepts a different parameter set), so always check the model page when you swap models.Seedream 5.0 Lite's headline strengths are legible in-image text rendering and prompts that reference real-world entities and layouts (ByteDance markets this as its web-knowledge training) — so it's a good pick for posters, UI mockups, and diagrams where text usually falls apart.
Create the task:
curl -s -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "seedream-5.0-lite/text-to-image",
"input": {
"prompt": "A minimalist poster for a developer conference, bold headline text \"SHIP IT\", off-white background, Swiss typography",
"aspect_ratio": "3:4",
"resolution": "2K"
}
}'
A successful create returns a task id:
{"code": 200, "data": {"taskId": "task_abc123..."}}
Poll until the task reaches a terminal state:
curl -s https://api.hiapi.ai/v1/tasks/task_abc123 \
-H "Authorization: Bearer sk-YOUR_KEY"
While rendering, data.status is pending/processing. When it flips to success, the image is at data.output[0].url:
{
"code": 200,
"data": {
"taskId": "task_abc123...",
"status": "success",
"output": [{"url": "https://...", "expireAt": "..."}]
}
}
Download the file immediately. The output URL carries an expireAt — it's a temporary link, not permanent hosting. Save the bytes to your own storage (S3, R2, local disk) as soon as the task succeeds; never hot-link the task URL from your app.
The same flow with requests, including the polling loop and the expiring-URL download:
import time
import requests
API_KEY = "sk-YOUR_KEY"
BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}
def generate(prompt: str, aspect_ratio: str = "1:1", resolution: str = "2K") -> bytes:
# 1. create the task
resp = requests.post(BASE, headers=HEADERS, json={
"model": "seedream-5.0-lite/text-to-image",
"input": {
"prompt": prompt,
"aspect_ratio": aspect_ratio,
"resolution": resolution,
},
}, timeout=60)
body = resp.json()
if resp.status_code != 200 or not (body.get("data") or {}).get("taskId"):
raise RuntimeError(f"create failed: {resp.status_code} {body}")
task_id = body["data"]["taskId"]
# 2. poll to a terminal state
deadline = time.time() + 600
while time.time() < deadline:
task = requests.get(f"{BASE}/{task_id}", headers=HEADERS, timeout=30).json()["data"]
if task["status"] == "success":
# 3. the URL expires -- download bytes now, store them yourself
return requests.get(task["output"][0]["url"], timeout=120).content
if task["status"] == "fail":
err = task.get("error") or {}
raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
time.sleep(5)
raise TimeoutError(f"task {task_id} did not finish in 10 minutes")
png = generate(
'Storefront sign that reads "OPEN 24/7", neon style, night street, photorealistic',
aspect_ratio="16:9",
)
with open("out.png", "wb") as f:
f.write(png)
Prefer a callback over polling. Pass a top-level callback object when you create the task and hiapi will POST the finished task to your endpoint instead of making you poll:
{
"model": "seedream-5.0-lite/text-to-image",
"input": {"prompt": "...", "aspect_ratio": "1:1", "resolution": "2K"},
"callback": {"url": "https://your-app.com/hooks/hiapi", "when": "final"}
}
when accepts only "final" — you get exactly one delivery, at the terminal state, so your handler doesn't need to dedupe intermediate progress events. Polling is fine for scripts and notebooks; callbacks are the right shape for servers, since a 2K/4K render can take a while and a poll loop holds a worker the whole time.
Make creation idempotent on your side. If your worker crashes between "task created" and "taskId saved", a naive retry renders (and bills) a second image. Store the taskId in the same transaction as the job row that triggered it; on retry, if a taskId already exists, skip creation and go straight to GET /v1/tasks/{id}.
Error handling — the three shapes you'll see:
error_code: "INVALID_REQUEST" and a message that names each bad field, e.g. aspect_ratio: value must be one of '1:1', '4:3', .... These are safe to surface to developers verbatim.error.code: "permission_denied" and a request_id. Log the request_id — support will ask for it.data.status: "fail", with the cause in data.error. Creation succeeding does not guarantee rendering succeeds; always branch on the terminal status, not on the create call.Why do I get resolution: value must be one of '2K', '4K'?
Seedream 5.0 Lite has no 1K tier — 2K is its minimum. This differs from most other image models on hiapi, so hardcoded "resolution": "1K" from another integration is the usual culprit.
Can I set a seed or negative prompt with seedream-5.0-lite?
No. The input schema accepts exactly prompt, aspect_ratio, and resolution; anything else returns a 400 (additional properties not allowed). Put style and exclusions in the prompt text itself.
How do I generate multiple images per request?
There's no n parameter on this model — create one task per image. Tasks are asynchronous and independent, so submitting several in parallel is the intended pattern.
Is the same schema used for seedream-5.0-lite/image-to-image?
No — the image-to-image variant takes reference-image input and has its own schema. Model ids on hiapi are family/task pairs; each pair validates independently.
How long do output URLs stay valid?
Each output URL includes an expireAt timestamp. Treat it as a short-lived download link: fetch the bytes when the task succeeds and store them on infrastructure you control.
Do I need a separate SDK?
No. The task API is plain HTTPS + JSON — curl, requests, fetch, or any HTTP client works. The examples above are the whole integration.