Images
Generate images with image.generate: resolution and aspect ratio, pixel sizes, seeds, prompting and reading the output.
image.generate turns a text prompt into one image. It runs on z-image-turbo, a fast text-to-image model, and costs 0.08 credits at 1k or 0.30 credits at 2k (read current prices from the catalog). Most images finish within a few seconds of being picked up.
curl -X POST https://api.windpaint.ai/v1/generation/capabilities/image.generate \
-H "Authorization: Bearer $WINDPAINT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt": "a ceramic teapot on a linen tablecloth, soft window light"}'
That’s a 1024 × 1024 image: model, resolution and aspect_ratio all have defaults. Poll the returned status_url until status is completed, then read outputs[0]. The overview has polling loops.
Parameters that matter
| Field | Values | Default | Notes |
|---|---|---|---|
prompt | string | none | Required. |
resolution | 1k, 2k | 1k | Sets the long edge: 1024 or 2048 px. 2k costs more. |
aspect_ratio | 1:1, 4:3, 3:4, 3:2, 2:3, 16:9, 9:16, 21:9, 4:5, 5:4 | 1:1 | Sets the short edge from the long edge. |
seed | integer | random | Same seed + same request = same image. |
model | z-image-turbo | z-image-turbo | The only image model today. |
webhook_url | https URL | none | See Webhooks. |
image.generate takes no input assets, no duration and no quality; sending inputs, duration or quality returns 422. There is no negative prompt field and no way to request more than one image per call.
Pixel sizes
The resolution tier fixes the long edge and the aspect ratio sets the other, rounded to the nearest multiple of 16. Portrait ratios swap the edges.
| Aspect ratio | 1k | 2k |
|---|---|---|
1:1 | 1024 × 1024 | 2048 × 2048 |
4:3 / 3:4 | 1024 × 768 / 768 × 1024 | 2048 × 1536 / 1536 × 2048 |
3:2 / 2:3 | 1024 × 688 / 688 × 1024 | 2048 × 1360 / 1360 × 2048 |
16:9 / 9:16 | 1024 × 576 / 576 × 1024 | 2048 × 1152 / 1152 × 2048 |
21:9 | 1024 × 432 | 2048 × 880 |
5:4 / 4:5 | 1024 × 816 / 816 × 1024 | 2048 × 1632 / 1632 × 2048 |
Because of the rounding, some sizes aren’t the exact ratio (1024 × 688 is 1.488:1, not 1.5:1). If you need an exact size, crop afterwards. POST /v1/generation/estimate returns width and height for any request without running it; see Models.
The price depends only on the tier, not the aspect ratio: a 1k 21:9 image costs the same as a 1k 1:1 one.
Seeds
Pass a seed to make a result reproducible. The same prompt, model, resolution, aspect ratio and seed give you the same image, so you can regenerate one later or change one setting and compare.
The API doesn’t report the seed it picked when you leave it out, so a result made without a seed can’t be reproduced. If you might want an image again, always send a seed.
To get variations of one prompt, submit the same request several times with different seeds. Each request is a separate job, billed separately:
import os
import requests
API = "https://api.windpaint.ai/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['WINDPAINT_API_KEY']}"}
body = {"prompt": "a ceramic teapot on a linen tablecloth, soft window light", "aspect_ratio": "4:5"}
jobs = []
for seed in (1, 2, 3, 4):
resp = requests.post(
f"{API}/generation/capabilities/image.generate",
headers=HEADERS,
json={**body, "seed": seed},
)
resp.raise_for_status()
jobs.append(resp.json()["request_id"])
Record each request_id as soon as you get it. There are no idempotency keys, so a blind retry of a submit can create and bill a second job; see Retries and double billing.
Prompting
z-image-turbo responds to plain descriptive prompts. Some things that tend to help:
- Describe the subject first, then the setting, then lighting and style: “a ceramic teapot on a linen tablecloth, soft window light, 35mm photo”.
- Name the medium you want (“watercolor”, “studio product photo”, “flat vector illustration”); without it the model picks one.
- Say what should be in the frame rather than what shouldn’t. There’s no negative prompt.
- Pick the aspect ratio for the composition instead of describing it in words: a wide landscape reads better at
16:9or21:9than at1:1. - Keep a seed fixed while you iterate on wording, so changes in the image come from the prompt.
If the model refuses a prompt on content grounds, the job ends with status nsfw, no output, and no charge.
Output
A completed job has one entry in outputs (and the same entry in images):
{
"id": "d77a4c1e-9b2f-4a3d-8e6f-7a8b9c0d1e2f",
"url": "https://api.windpaint.ai/v1/generation/assets/d77a4c1e-9b2f-4a3d-8e6f-7a8b9c0d1e2f/content",
"content_type": "image/png",
"width": 1024,
"height": 576,
"duration_s": null
}
The format comes from what the model returned: Windpaint detects it from the file’s bytes and sets content_type to image/png, image/jpeg or image/webp accordingly. Use content_type, not an assumed extension, when you save the file.
url is the asset’s API URL. Fetching it needs your API key and answers with a redirect to a short-lived download link; Assets covers how to download it or hand it to a browser. The id can go straight into another job’s inputs, for example as the start_frame of a video.
End to end
Submit, wait, and save the image to disk.
The curl version names the file .png for brevity; check .outputs[0].content_type if you need the right extension every time. The CLI picks the extension for you when -o is a directory.