> For the complete documentation index, see [llms.txt](https://docs.nebulablock.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.nebulablock.com/products/serverless-inference/image-generation.md).

# Image Generation

Generate and edit images on Nebula Block with Nano Banana and Seedream through the OpenAI-compatible images API.

Generate images from a text prompt, or edit an existing image, through the OpenAI-compatible images endpoint.

## Models available

| Model                  | Model ID                                | Does                                     |
| ---------------------- | --------------------------------------- | ---------------------------------------- |
| Nano-Banana-2          | `gemini/gemini-3.1-flash-image-preview` | Text-to-image, up to 14 reference images |
| Nano-Banana-Pro        | `gemini/gemini-3-pro-image-preview`     | Text-to-image, highest quality           |
| Nano-Banana-Pro-Edit   | `gemini/gemini-3-pro-image-edit`        | Image editing                            |
| Nano-Banana-Edit       | `gemini/gemini-2.5-flash-image-edit`    | Image editing                            |
| Bytedance-Seedream-3.0 | `Bytedance/seedream-3-0-t2i-250415`     | Bilingual text-to-image, native 2K       |

See the [Model Catalog](/products/serverless-inference/model-catalog.md#image-generation) for the current list.

## Generate an image

### Using cURL

```bash
curl -X POST "https://inference.nebulablock.com/v1/images/generations" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $NEBULA_API_KEY" \
    --data-raw '{
        "model": "gemini/gemini-3.1-flash-image-preview",
        "prompt": "A snowy street in Old Montreal at dusk, warm window light, film photography",
        "size": "1536x1024"
    }'
```

### Using Python

```python
import base64
import os

from openai import OpenAI

client = OpenAI(
    base_url="https://inference.nebulablock.com/v1",
    api_key=os.environ["NEBULA_API_KEY"],
)

result = client.images.generate(
    model="gemini/gemini-3.1-flash-image-preview",
    prompt="A snowy street in Old Montreal at dusk, warm window light, film photography",
    size="1536x1024",
)

with open("output.png", "wb") as f:
    f.write(base64.b64decode(result.data[0].b64_json))
```

### Using JavaScript

```javascript
import fs from "node:fs";
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://inference.nebulablock.com/v1",
  apiKey: process.env.NEBULA_API_KEY,
});

const result = await client.images.generate({
  model: "gemini/gemini-3.1-flash-image-preview",
  prompt: "A snowy street in Old Montreal at dusk, warm window light, film photography",
  size: "1536x1024",
});

fs.writeFileSync("output.png", Buffer.from(result.data[0].b64_json, "base64"));
```

The response follows the OpenAI shape — a `created` timestamp and a `data` array whose entries carry `b64_json`.

## Controlling the output

`size` takes a `WxH` string and is mapped to the nearest aspect ratio the model supports: `1:1`, `16:9`, `9:16`, `4:3`, `3:4`, `3:2`, `2:3`, `21:9`, `4:5`, and `5:4`.

For anything a model supports beyond the OpenAI fields, use `provider_options`:

| Option                | Description                                          |
| --------------------- | ---------------------------------------------------- |
| `aspect_ratio`        | Set the ratio directly instead of via `size`         |
| `image_size`          | Output resolution, where the model supports multiple |
| `image_urls`          | Reference images to condition the generation on      |
| `person_generation`   | The model's policy for generating people             |
| `output_mime_type`    | Output format, such as `image/png` or `image/jpeg`   |
| `compression_quality` | Compression quality for lossy formats                |
| `thinking_level`      | How much the model reasons before generating         |

```bash
curl -X POST "https://inference.nebulablock.com/v1/images/generations" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $NEBULA_API_KEY" \
    --data-raw '{
        "model": "gemini/gemini-3.1-flash-image-preview",
        "prompt": "Same scene, but in summer",
        "provider_options": {
            "aspect_ratio": "16:9",
            "output_mime_type": "image/png"
        }
    }'
```

## Edit an image

Editing takes a multipart upload rather than JSON, and needs one of the edit models:

```bash
curl -X POST "https://inference.nebulablock.com/v1/images/edits" \
    -H "Authorization: Bearer $NEBULA_API_KEY" \
    -F 'model=gemini/gemini-2.5-flash-image-edit' \
    -F 'prompt=Replace the sky with an aurora' \
    -F 'size=1024x1024' \
    -F 'image=@./input.png'
```

Accepted input formats are PNG, JPEG, WebP, and GIF.

## Through the console

Every image model has a playground under [**Serverless**](https://console.nebulablock.com/serverless) — useful for finding a prompt and a model before you write any code.

## Cost

Image models are billed per generation, and prices carry promotional rates from time to time. Check the [pricing page](https://www.nebulablock.com/pricing/serverless-ai) or the model's card in the console for the current rate.

## See also

* [Images API reference](/api-reference/inference-api/images.md)
* [Video Generation](/products/serverless-inference/video-generation.md)
* [Model Catalog](/products/serverless-inference/model-catalog.md)
