qwen-image-2.0-pro is the Pro tier of Alibaba's Qwen image family — the variant you reach for when text rendering fidelity and photorealistic detail matter more than per-image cost. On hiapi it runs on the unified async task endpoint (/v1/tasks), so the integration is: create a task, poll (or receive a callback), download the result. This guide gives you a copy-paste curl request, a complete Python script, the exact parameter schema the model accepts today, and the differences from the base qwen-image-2.0.
What you're building, and what you need
Goal: send a text prompt to qwen-image-2.0-pro and get back an image file. You need exactly one thing — a hiapi API key (sk-...), which you can create in the dashboard. Every request below authenticates with the same header:
Authorization: Bearer sk-<your-key>
There is no synchronous endpoint for this model — qwen-image-2.0-pro only supports the task interface, so a generation is always two HTTP calls (create, then poll) or one call plus a webhook.
Minimal working example: curl
Create the task:
curl -X POST https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-<your-key>" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen-image-2.0-pro",
"input": {
"prompt": "A storefront window sign that reads \"GRAND OPENING - 50% OFF\" in bold red letters, photorealistic, golden-hour light",
"size": "2048*2048"
}
}'
A successful create returns a task ID:
{"code": 200, "data": {"taskId": "task_..."}}
Poll it until it reaches a terminal state:
curl https://api.hiapi.ai/v1/tasks/<taskId> \
-H "Authorization: Bearer sk-<your-key>"
When data.status becomes success, the image URL is at data.output[0].url. If it becomes fail, data.error tells you why. One important detail: the output URL is temporary (it carries an expireAt), so download the bytes immediately and store them yourself — don't hotlink it.
The exact input schema (verified against the live API)
The task API validates input strictly — unknown keys are rejected with HTTP 400, so this table is exhaustive:
| Field | Required | Notes |
|---|---|---|
prompt | yes | Missing it returns 400: missing required field "prompt". |
size | no | One of 2688*1536, 2368*1728, 2048*2048, 1728*2368, 1536*2688. Note the * separator — 2048x2048 or arbitrary dimensions won't validate. |
negative_prompt | no | What to steer away from. |
seed | no | Integer, for reproducible outputs. |
watermark | no | Boolean; set false to disable the watermark. |
prompt_extend | no | Boolean; lets the backend expand short prompts before generation. Turn it off when you need literal prompt control. |
Three things this model does not accept, which trip people up coming from other models on the platform:
- No
aspect_ratiofield. Some hiapi models takeaspect_ratio+resolution; the Qwen 2.0 family takes an explicitsizefrom the enum above. Sendingaspect_ratioreturns400: additional properties 'aspect_ratio' not allowed. - No
n(batch count). One task produces one image; fan out by creating multiple tasks. - No image input.
qwen-image-2.0-prois text-to-image only —image_input/ reference-image fields are rejected, so it can't be used for image editing.
Python: submit, poll, save
A complete script you can run as-is (only requests needed):
import time
import requests
API = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": "Bearer sk-<your-key>"}
def generate(prompt: str, size: str = "2048*2048", timeout_s: int = 600) -> bytes:
resp = requests.post(
API,
headers=HEADERS,
json={
"model": "qwen-image-2.0-pro",
"input": {"prompt": prompt, "size": size, "watermark": False},
},
timeout=60,
)
resp.raise_for_status()
task_id = resp.json()["data"]["taskId"]
deadline = time.time() + timeout_s
while time.time() < deadline:
task = requests.get(f"{API}/{task_id}", headers=HEADERS, timeout=30).json()["data"]
if task["status"] == "success":
url = task["output"][0]["url"] # expires — download now, store the bytes
return requests.get(url, timeout=120).content
if task["status"] == "fail":
raise RuntimeError(f"task {task_id} failed: {task.get('error')}")
time.sleep(5)
raise TimeoutError(f"task {task_id} still not terminal after {timeout_s}s")
if __name__ == "__main__":
png = generate(
'A minimalist conference poster, headline "SHIP FASTER" in a bold grotesque, '
"off-white background, single red accent shape"
)
with open("qwen-pro.png", "wb") as f:
f.write(png)
print(f"saved qwen-pro.png ({len(png)} bytes)")
The structure to copy even if you rewrite it in another language: create → poll every ~5s → on success download immediately → treat fail and timeout as distinct errors.
Production notes
Callbacks instead of polling. For anything beyond a script, register a webhook when you create the task and skip polling entirely:
{
"model": "qwen-image-2.0-pro",
"input": {"prompt": "...", "size": "2048*2048"},
"callback": {"url": "https://your-app.com/hooks/hiapi", "when": "final"}
}
With "when": "final" you get exactly one POST when the task reaches a terminal state. Polling is fine for scripts and low volume; callbacks are better once you have concurrent tasks or a queue, because a fleet of pollers is both slower to react and noisier against your rate limits. Keep a polling fallback for the rare case your webhook endpoint is down.
Idempotency. The create call is not idempotent — retrying a timed-out create can produce two billable tasks. Persist the taskId as soon as you receive it, and key your own job table by a request ID you generate, so a retry checks for an existing task before creating a new one.
Error handling. The API uses two error shapes, worth matching on both:
- Auth problems are HTTP
401with a nested error object, e.g.{"error": {"code": "permission_denied", "message": "This API key cannot use the selected model...", "type": "hiapi_error"}}. You'll see this for a missing key, an invalid key, or a key without access to this model. - Validation problems are HTTP
400with a flat shape:{"code": 400, "error_code": "INVALID_REQUEST", "message": "invalid input: size: value must be one of ..."}. The message names the offending field, so log it verbatim. - Polling an unknown or expired task ID returns
404with"task not found".
Cost. Pro-tier image generation is billed per image at a higher rate than the base model — check current numbers on the pricing page rather than hardcoding them into your budget math.
qwen-image-2.0-pro vs qwen-image-2.0: which one?
The two models share an identical request schema — same required prompt, same five-value size enum, same optional fields — so switching between them is literally a one-word change to model. That makes a cheap workflow possible:
- Iterate on the base model. Prompt engineering, composition tests, and size experiments on qwen-image-2.0 cost a fraction per image.
- Render finals on Pro. Once the prompt is locked, rerun it (same
seedif you want stability) againstqwen-image-2.0-profor the higher-fidelity output — it's positioned for stronger in-image text rendering and photorealistic detail, which is exactly where the base model is most likely to fall short on final assets.
If your images never contain legible text and don't need photorealism, the base model may be all you need — see our qwen-image-2.0 prompt recipes for six tested prompts, and the ecommerce product images walkthrough for a real pipeline built on the base model.
Related reading
- qwen-image-2.0-pro model page — playground, parameters, current pricing
- qwen-image-2.0 model page — the base tier
- hiapi docs — task API reference and platform concepts
- Pricing — per-image rates for both tiers
- qwen-image-2.0 prompt recipes
- Generating ecommerce product images with qwen-image-2.0
FAQ
Does the qwen image 2.0 pro API support image-to-image or editing?
No. The /v1/tasks input schema for qwen-image-2.0-pro accepts text fields only; reference-image fields like image_input are rejected with a 400. For editing workflows, pick a model that supports image input.
What image sizes does qwen-image-2.0-pro support?
Exactly five: 2688*1536, 2368*1728, 2048*2048, 1728*2368, 1536*2688 (landscape → square → portrait). Arbitrary dimensions and aspect_ratio values are not accepted.
How do I make outputs reproducible?
Pass an integer seed in input. Same model + prompt + size + seed gives you a stable starting point when you move a prompt from the base model to Pro.
How do I remove the watermark?
Set "watermark": false in input.
Why am I getting 401 permission_denied with a valid key?
The key exists but can't use this model — 401 covers missing keys, malformed keys, and keys without access to qwen-image-2.0-pro. Check the key's model permissions in the dashboard.
Can I generate several images in one request?
No — there's no n parameter. Create one task per image; they run concurrently, so fan-out is just multiple create calls.
How long do output URLs stay valid?
They expire (the task payload includes an expireAt). Download the image as soon as the task succeeds and store it in your own bucket.



