Sign in
ActivePOST /v1/generations

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.

How to get an API key

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.

Read acceptable use

Quick example

Send a generation in 5 lines. Pick your language below.

curl
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.

NameTypeRequiredDefaultDescription
endUserEmailstring (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: "alice@your-product.com"

modelstringyes—

Public model alias. Required — pass `xZI1.0Pro` to use this model.

Example: "xZI1.0Pro"

promptstringyes—

Text prompt describing the image: subject and action first, then setting, then style, lighting and composition.

Example: "A cinematic portrait of an astronaut standing in a field of wildflowers at golden hour"

sizestringno"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: "1440x2560"

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: "landscape"

nintegerno1

Images per request. This model produces exactly one, so only `1` is accepted; send several requests for several images.

Example: 1

seedintegernorandom (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: 42

promptExtendbooleannofalse

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: true

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.

referencesstring | 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.

webhookUrlstring (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: "https://your-app.example.com/hooks/xmode"

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.

JSON
{
  "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"
}
NameTypeRequiredDefaultDescription
requestIdstringyes—

Unique id of the generation. Use it with GET /v1/generations/:requestId to poll.

modelstringyes—

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.

pollUrlstringno—

Present on `queued` responses only. Absolute URL to GET for status. Recommended polling cadence: every 5 seconds until terminal.

imagesarrayno—

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.

errorobjectno—

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).

costobjectno—

Present only when status=`succeeded`. `{ xTokens: number }`. Debited at request time; refunded automatically on `failed`.

finishedAtstring (ISO 8601)no—

Present on terminal statuses (`succeeded`, `failed`, `expired`). When the generation reached its final state.

endUserEmailstringyes—

Echoed back so you can confirm the grouping. Always lowercase.

createdAtstring (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
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
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
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
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
Errors follow our standard format — see all error codes →