> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nunchux.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Authenticate every request with your API key in the `X-API-Key` header or `Authorization: Bearer`. Keys start with `sk-nunchux-`.
> Image generation is synchronous: the image is in the response.
> Video generation is asynchronous: submit the job, poll its task until it reaches a terminal status, then download the output promptly, because output URLs expire.

# Text-to-image

> Generate an image from a text prompt with a Nunchux Optimized model. The image is in the response.

# Text-to-image

Send a text prompt, and the response contains the generated image. The request is synchronous. There is no task to poll.

## Models

| Model | Model ID | Use it for |
| - | - | - |
| FLUX.2 Klein 9B | `nunchux-flux.2-klein-9b` | Production output. Strong prompt adherence and clean text. |
| FLUX.2 Klein 4B | `nunchux-flux.2-klein-4b` | The fastest output. Fast iteration and batch jobs. |
| FLUX.1 Schnell | `nunchux-flux.1-schnell` | The earlier FLUX generation, for work that already depends on it. |
| Qwen Image 2512 Lightning | `nunchux-qwen-image-2512` | The best text rendering, in English and Chinese. Typography and layout. |
| HiDream O1 | `nunchux-hidream-o1-image` | Large, photographic images up to four megapixels. Slower than FLUX and Qwen. |
| Ideogram 4 | `nunchux-ideogram-4` | Legible words in the image: posters, labels and covers. Slower than FLUX and Qwen. |

See [Choosing a model](/nunchux-optimized/overview#choosing-a-model) for a comparison, and [Performance tiers](/performance-tiers) for the tiers that each model serves.

## Endpoint

```text theme={"system"}
POST https://api.nunchux.ai/v1/images/generations
```

## Request

Every request must include your API key and a JSON content type. See [Authentication](/authentication).

<ParamField header="X-API-Key" type="string" required>
  Your API key.
</ParamField>

<ParamField header="Content-Type" type="string" required>
  Must be `application/json`.
</ParamField>

<ParamField body="model" type="string" required>
  The model that generates the image.

  Options: `nunchux-flux.2-klein-4b`, `nunchux-flux.2-klein-9b`, `nunchux-flux.1-schnell`, `nunchux-qwen-image-2512`, `nunchux-hidream-o1-image`, `nunchux-ideogram-4`
</ParamField>

<ParamField body="prompt" type="string" required>
  A text description of the image. Specific, descriptive prompts give better results.
</ParamField>

<ParamField body="tier" type="string" default="radical_speed">
  The balance of speed and cost. See [Performance tiers](/performance-tiers).

  Options: `radical_speed`, `radical_value`

  Do not send this field to Ideogram 4. On Ideogram 4, `steps` selects the tier.
</ParamField>

<ParamField body="width" type="integer">
  Output width in pixels. Send it together with `height`. Required on models priced per megapixel. Today, that is every model except Ideogram 4, which uses 1024x1024 when you send no dimensions. Range: 1 to 8192. On Ideogram 4: 1024 to 2048, in steps of 16.
</ParamField>

<ParamField body="height" type="integer">
  Output height in pixels. Send it together with `width`. Required on models priced per megapixel. Today, that is every model except Ideogram 4, which uses 1024x1024 when you send no dimensions. Range: 1 to 8192. On Ideogram 4: 1024 to 2048, in steps of 16.
</ParamField>

<ParamField body="steps" type="integer">
  Ideogram 4 and HiDream O1 only. The number of denoising steps. Range: 1 to 50. Default: 48 on Ideogram 4, 50 on HiDream O1. More steps give more detail, but take longer.

  On Ideogram 4, the step count selects the tier. Send 12 for Turbo, 20 for Balanced, or 48 for Quality. Fewer steps are faster and cost less, but give less detail. A request without `steps` runs 48 steps and is billed as Quality.
</ParamField>

<ParamField body="true_cfg_scale" type="number" default={5}>
  HiDream O1 only. How closely the image follows the prompt. Range: 0.0 to 20.0. Higher values follow the prompt more closely. Lower values give the model more freedom.
</ParamField>

<ParamField body="prompt_expansion" type="string" default="off">
  Ideogram 4 only. When `standard`, a language model rewrites the prompt into a detailed scene description before the image renders. The response returns the rewritten prompt as `revised_prompt`. If the rewrite fails, the image renders from your prompt, and the response has no `revised_prompt`.

  Options: `off`, `standard`
</ParamField>

<ParamField body="n" type="integer" default={1}>
  The number of images to generate. Only 1 is supported.
</ParamField>

<ParamField body="response_format" type="string" default="b64_json">
  The format of the returned image.

  Options: `url`, `b64_json`

  In both formats, Nunchux keeps the generated image for 7 days, so that it appears in your request history. Then Nunchux deletes it.
</ParamField>

<ParamField body="seed" type="integer">
  The random seed. The same seed with the same parameters gives the same result.
</ParamField>

<Note>
  Dimensions

  * Send `width` and `height` together. A request with only one of them returns a 400.
  * Models priced per megapixel charge from the output area, so they require `width` and `height`. A request with no dimensions returns a 400. The API does not choose a default size for these models. The [pricing page](https://nunchux.ai/pricing) shows each model's unit. Today, every text-to-image model except Ideogram 4 is priced per megapixel.
  * Both values must be integers. The string `"1024"` is rejected, not converted.
  * Larger images take longer to generate.
  * HiDream O1 renders these sizes: 1024x1024, 2048x2048, 2304x1728, 1728x2304, 2560x1440, 1440x2560, 2496x1664, 1664x2496, 3104x1312, 1312x3104, 2304x1792, 1792x2304.
</Note>

A minimal request body:

```json theme={"system"}
{
  "model": "nunchux-qwen-image-2512",
  "tier": "radical_speed",
  "prompt": "A beautiful sunset over mountains",
  "width": 1024,
  "height": 1024,
  "response_format": "b64_json",
  "seed": 42
}
```

## Response

The response is JSON. The `data` array contains the image, as base64 data or as a URL.

<ResponseField name="created" type="integer" required>
  The Unix timestamp of the generation.
</ResponseField>

<ResponseField name="data" type="array" required>
  The generated items.

  <Expandable title="Item properties">
    <ResponseField name="url" type="string">
      The URL of the image. Returned when `response_format` is `url`.
    </ResponseField>

    <ResponseField name="b64_json" type="string">
      The image as base64 data. Returned when `response_format` is `b64_json`.
    </ResponseField>

    <ResponseField name="revised_prompt" type="string">
      Ideogram 4 only. The rewritten prompt that the model rendered. Returned when `prompt_expansion` is `standard` and the rewrite succeeds. To make the same image again, send it as `prompt` with `prompt_expansion` set to `off`, the same `seed`, the same `steps`, and the same size.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="model" type="string" required>
  The model that generated the image.
</ResponseField>

```json Base64 format theme={"system"}
{
  "created": 1234567890,
  "data": [
    {
      "b64_json": "iVBORw0KGgoAAAANSUhEUgAABAAAAAQACAYAAAB/HSuDAAAACXBIWXMAAA7EAAAOxAGVKw4b..."
    }
  ],
  "model": "nunchux-qwen-image-2512"
}
```

```json URL format theme={"system"}
{
  "created": 1234567890,
  "data": [
    {
      "url": "https://example.com/generated-image.png"
    }
  ],
  "model": "nunchux-qwen-image-2512"
}
```

To save a base64 result from cURL, add this pipe to the command:

```bash theme={"system"}
# Replace output.jpg with the file name that you want.
| jq -r '.data[0].b64_json // error(.error.message // .detail // tostring)' | base64 -d > output.jpg
```

## Example

<CodeGroup>
  ```bash cURL theme={"system"}
  curl -X POST https://api.nunchux.ai/v1/images/generations \
    -H "Content-Type: application/json" \
    -H "X-API-Key: $NUNCHUX_API_KEY" \
    -d '{
      "model": "nunchux-flux.2-klein-9b",
      "tier": "radical_speed",
      "prompt": "cozy coffee shop interior with vintage furniture",
      "width": 1024,
      "height": 1024,
      "response_format": "b64_json",
      "seed": 42
    }' | jq -r '.data[0].b64_json // error(.error.message // .detail // tostring)' | base64 -d > output.jpg
  ```

  ```python Python theme={"system"}
  import os
  import base64
  import requests

  response = requests.post(
      "https://api.nunchux.ai/v1/images/generations",
      headers={
          "Content-Type": "application/json",
          "X-API-Key": os.environ["NUNCHUX_API_KEY"],
      },
      json={
          "model": "nunchux-flux.2-klein-9b",
          "tier": "radical_speed",
          "prompt": "cozy coffee shop interior with vintage furniture",
          "width": 1024,
          "height": 1024,
          "response_format": "b64_json",
          "seed": 42,
      },
  )

  # Decode the base64 image and save it. Change output.jpg to any file name.
  image_b64 = response.json()["data"][0]["b64_json"]
  with open("output.jpg", "wb") as f:
      f.write(base64.b64decode(image_b64))
  ```

  ```javascript JavaScript theme={"system"}
  import { writeFile } from "node:fs/promises";

  const response = await fetch("https://api.nunchux.ai/v1/images/generations", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "X-API-Key": process.env.NUNCHUX_API_KEY,
    },
    body: JSON.stringify({
      model: "nunchux-flux.2-klein-9b",
      tier: "radical_speed",
      prompt: "cozy coffee shop interior with vintage furniture",
      width: 1024,
      height: 1024,
      response_format: "b64_json",
      seed: 42,
    }),
  });
  const data = await response.json();

  // Decode the base64 image and save it. Change output.jpg to any file name.
  await writeFile("output.jpg", Buffer.from(data.data[0].b64_json, "base64"));
  ```

  ```python Python (OpenAI) theme={"system"}
  import os
  import base64

  from openai import OpenAI

  client = OpenAI(
      base_url="https://api.nunchux.ai/v1",
      api_key=os.environ["NUNCHUX_API_KEY"],
  )

  # The OpenAI SDK has no width/height parameter. Send them in `extra_body`,
  # which the SDK merges into the request body.
  response = client.images.generate(
      model="nunchux-flux.2-klein-9b",
      prompt="cozy coffee shop interior with vintage furniture",
      n=1,
      response_format="b64_json",
      extra_body={"width": 1024, "height": 1024},
  )

  # Decode the base64 image and save it. Change output.jpg to any file name.
  image_b64 = response.data[0].b64_json
  with open("output.jpg", "wb") as f:
      f.write(base64.b64decode(image_b64))
  ```
</CodeGroup>

## Tips

* Write detailed prompts. Include the style, lighting, composition, colors, materials and atmosphere.
* Use FLUX.2 Klein 9B for production output. Use FLUX.2 Klein 4B when speed is more important than detail.
* Use Qwen Image when the image must contain text, and for Chinese text. Use Ideogram 4 when the words must be legible on a poster, a label or a cover. Put the exact words in quotes or capitals, and say where they go.
* Use HiDream O1 for large, photographic images. Describe the light and the materials. A larger size costs more, because the price is per megapixel.
* On Ideogram 4, draft at Turbo (12 steps). Use Quality (48 steps) for the final image.
* On FLUX, Qwen and HiDream O1, use `radical_speed` when response time is important. Use `radical_value` for large batches where cost per image is more important.
* Keep the `seed` when you like a result. Then change one parameter at a time.

## Errors and limits

| Status | Code | Cause |
| - | - | - |
| 400 | none | A required field is missing, the model ID is not valid, or a value is not valid. The body is a plain `detail` string. |
| 400 | `engine_error` | The model cannot render the request, for example the dimensions. |
| 403 | `model_not_available` | Your account does not have access to this model. |

<Note>
  Refused requests

  * Nunchux charges only after a successful generation. A refused request is never billed.
  * Do not branch on a dimension-specific code. A refusal always carries the `engine_error` code.
</Note>

For authentication, credit and rate-limit errors, see [Error codes](/errors). Every request counts toward the requests-per-minute cap of your plan. See [Rate limits](/rate-limits).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.