xZI 1.0 Pro
Text-to-image with free dimensions and one flat price.
xZI 1.0 Pro generates one image from a text prompt. Its distinguishing feature is size freedom: besides the presets, it takes any explicit `WxH` inside its per-side window — a small square thumbnail, a wide banner, a tall story frame — and what the request costs does not change with it.
- Any width and height inside its published per-side window, not just presets
- Flat per-image billing: the size never changes the cost
- Text-to-image only — reference images are refused rather than quietly ignored
- Optional prompt rewriting, off by default
Generation is asynchronous. POST answers `202` with a `requestId` and a `pollUrl`; the result arrives by polling that URL or through an HMAC-signed webhook when you pass `webhookUrl`. Signed output URLs stay valid for 23 hours.
Authentication. Add Authorization: Bearer xm_live_… to every request.
Account responsibility. Every request must include the real email of YOUR end-user via endUserEmail. You are accountable for what they generate — monitor activity and act on abuse, or your account may be suspended.
Quick example
Send a generation in 5 lines. Pick your language below.
curl -X POST https://api.xmode.ai/v1/generations \
-H "Authorization: Bearer xm_live_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"endUserEmail": "alice@your-product.com",
"model": "xZI1.0Pro",
"prompt": "A cinematic portrait of an astronaut standing in a field of wildflowers at golden hour"
}'Request parameters
The fields you can include in the request body. Anything not listed is ignored.
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
endUserEmail | string (email) | yes | — | REQUIRED. Email of YOUR real end-user inside your product — the person who actually triggered this generation. We use it to attribute every request and give you a chain of responsibility: you can list, audit, and delete that user's generations. Do NOT pass a fake address, a shared placeholder, or someone else's email — that's a policy violation. If an end-user generates disallowed content and you do not act, your account can be suspended (see Acceptable use). Example: |
model | string | yes | — | Public model alias. Required — pass `xZI1.0Pro` to use this model. Example: |
prompt | string | yes | — | Text prompt describing the image: subject and action first, then setting, then style, lighting and composition. Example: |
size | string | no | "1K" | Output dimensions: preset `1K` or `2K`, or explicit pixels `WxH` with **each side between 256 and 2560** (e.g. `1440x2560` for a tall 9:16, `2560x1080` for an ultrawide banner). Anything outside that window is rejected with `400 validation_error` before any debit. A preset is always resolved to explicit pixels before generation — see `aspectRatio` for which shape you get. The price is the same for every size. Example: |
aspectRatio | "auto" | "square" | "landscape" | "portrait" | no | "auto" | Shape of a preset `size`: `square` (1:1), `landscape` (16:9), `portrait` (3:4). `auto` resolves to the square shape of the chosen preset, because this model is always sent explicit pixels. The exact dimensions behind a preset are not a fixed contract; pass an explicit `WxH` to pin them (an explicit size wins and `aspectRatio` is then ignored). Example: |
n | integer | no | 1 | Images per request. This model produces exactly one, so only `1` is accepted; send several requests for several images. Example: |
seed | integer | no | random (server-generated) | Determinism seed. Same seed + same prompt + same size + same other params = same output. If omitted, the server picks a random seed for you and returns it in `GET /v1/generations/:requestId` (`input.seed`), so any generation can be reproduced after the fact. Pass a value of 1 or more to reproduce: `0` asks the model to pick a random seed of its own. With `promptExtend: true` the prompt is rewritten before generation and the rewrite differs between runs, so the same seed no longer guarantees the same image. Example: |
promptExtend | boolean | no | false | Let the model rewrite your prompt into a longer, more detailed one before generating. Off by default. It usually helps short prompts and gets in the way of carefully written ones — the prompt that runs is not the prompt you sent. With this on, the same seed no longer guarantees the same image. Example: |
responseFormat | "url" | "b64_json" | no | "url" | How images are returned. Only "url" is supported — signed CDN URLs valid for 23 hours. "b64_json" is rejected with `400 validation_error` before any debit; download from the returned URL instead. |
sequential | "auto" | "disabled" | no | "disabled" | Not supported by this model — it produces one independent image. Passing `"auto"` is rejected with `400 validation_error` before any debit. |
references | string | string[] | no | — | Not accepted — this model is text-to-image only. Any value is rejected with `400 validation_error` before any debit, rather than silently ignored. |
webhookUrl | string (https URL) | no | — | Optional public HTTPS URL we will POST the final record to once the generation is succeeded or failed. The body is identical to what GET /v1/generations/:requestId returns. Each delivery is HMAC-signed (`X-XMode-Signature: v1=<hex>`) and timestamped (`X-XMode-Timestamp`); reject anything older than 5 minutes. Private/loopback IPs are refused (SSRF guard). See the Webhook delivery section in the Introduction for verification code. Example: |
Response
The POST answers 202 Accepted with this shape — the job is queued, not finished. Read the result from pollUrl, which returns the same record with the fields below filled in. Output URLs are signed and valid for 23 hours.
{
"requestId": "req_4Hq8nV2cRtK7pWxZ",
"model": "xZI1.0Pro",
"status": "queued",
"prompt": "A cinematic portrait of an astronaut standing in a field of wildflowers",
"referencesCount": 0,
"endUserEmail": "alice@your-product.com",
"createdAt": "2026-09-17T09:12:44.108Z",
"pollUrl": "https://api.xmode.ai/v1/generations/req_4Hq8nV2cRtK7pWxZ"
}| Name | Type | Required | Default | Description |
|---|---|---|---|---|
requestId | string | yes | — | Unique id of the generation. Use it with GET /v1/generations/:requestId to poll. |
model | string | yes | — | Public alias of the model that will produce the images. |
status | "queued" | "processing" | "succeeded" | "failed" | "expired" | yes | — | Lifecycle marker. POST always returns `queued`. GET returns the current state. `expired` means the request succeeded more than 23 hours ago and signed URLs no longer work — re-run if you need the images again. |
pollUrl | string | no | — | Present on `queued` responses only. Absolute URL to GET for status. Recommended polling cadence: every 5 seconds until terminal. |
images | array | no | — | Present only when status=`succeeded`. Holds one item with `id`, `expiresAt`, and EITHER `url` (signed, valid 23 h, PNG) OR `error: { code: "storage_failed" }` if our storage layer dropped the image — in which case there is nothing to deliver and the request comes back `failed` and refunded instead. The URL is re-signed on every read, but that never moves `expiresAt`, which is fixed when the generation completed. Once it passes, the record returns status `expired` with no URL and the bytes are gone. |
error | object | no | — | Present only when status=`failed`. `{ code, message }`. The same code values as the top-level error format (validation_error, content_policy, provider_error, provider_timeout, internal_error). |
cost | object | no | — | Present only when status=`succeeded`. `{ xTokens: number }`. Debited at request time; refunded automatically on `failed`. |
finishedAt | string (ISO 8601) | no | — | Present on terminal statuses (`succeeded`, `failed`, `expired`). When the generation reached its final state. |
endUserEmail | string | yes | — | Echoed back so you can confirm the grouping. Always lowercase. |
createdAt | string (ISO 8601) | yes | — | When the request was accepted (POST time). |
Use cases
Common patterns. Copy any block, replace the API key, and you have a runnable request.
Text to image
Simplest case: a prompt, the model alias, and the end-user email. Returns one square image at the default size.
curl -X POST https://api.xmode.ai/v1/generations \
-H "Authorization: Bearer xm_live_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"endUserEmail": "alice@your-product.com",
"model": "xZI1.0Pro",
"prompt": "A cinematic portrait of an astronaut standing in a field of wildflowers at golden hour"
}'Any exact size
Pass explicit `WxH` for the frame you need — here a tall 9:16 story. Each side can be anything from 256 to 2560 px, and the price does not change.
curl -X POST https://api.xmode.ai/v1/generations \
-H "Authorization: Bearer xm_live_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"endUserEmail": "alice@your-product.com",
"model": "xZI1.0Pro",
"prompt": "A neon-lit alley at night after rain, reflections on the pavement, vertical composition",
"size": "1440x2560"
}'Reproducible output
Pin a seed and leave `promptExtend` off: the same prompt, size and seed give the same image.
curl -X POST https://api.xmode.ai/v1/generations \
-H "Authorization: Bearer xm_live_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"endUserEmail": "alice@your-product.com",
"model": "xZI1.0Pro",
"prompt": "Product shot of a ceramic mug on a linen tablecloth, soft window light",
"size": "2K",
"aspectRatio": "landscape",
"seed": 42
}'Skip polling — receive a webhook
Pass `webhookUrl` and we POST the final record there once the generation is done. The body is the same shape as GET /v1/generations/:requestId. Verify `X-XMode-Signature: v1=<hex>` against your account webhook secret (HMAC-SHA256 of `"<timestamp>.<rawBody>"`).
curl -X POST https://api.xmode.ai/v1/generations \
-H "Authorization: Bearer xm_live_<your-key>" \
-H "Content-Type: application/json" \
-d '{
"endUserEmail": "alice@your-product.com",
"model": "xZI1.0Pro",
"prompt": "A watercolor fox curled up in autumn leaves",
"webhookUrl": "https://your-app.example.com/hooks/xmode"
}'Limits
- Images per request (`n`): 1
- Side length: 256–2560 px, width and height each
- Total pixels range: 0.07M – 6.55M (presets 1K ≈1 MP, 2K ≈4 MP)
- Aspect ratio range: 1/10 – 10
- Input images: not accepted (text-to-image only)
- Prompt max length: 8000 characters
- Output format: PNG
- Signed URL lifetime: 23 hours