Nebul Docs

Image Models

Generate, edit, and vary images from text prompts with the OpenAI-compatible Images API

The Images API generates and edits images from text prompts through three OpenAI-compatible endpoints: /v1/images/generations from a prompt, /v1/images/edits from a prompt plus an input image, and /v1/images/variations from an input image alone. Images come back base64-encoded in the JSON response, ready to save or serve.

The served model is Tongyi-MAI/Z-Image-Turbo, a 6B diffusion model built for fast generation and inpainting. It is in preview: details may change before general availability.

Every example reads your key from NEBUL_API_KEY; export it first. The Quick Start covers key setup.

Generate images

POST https://api.inference.nebul.io/v1/images/generations

Parameters

ParameterTypeRequiredDescription
promptStringYesDescription of the image to generate.
modelStringYesThe model ID, Tongyi-MAI/Z-Image-Turbo.
nIntegerNoNumber of images to generate. Defaults to 1.
response_formatStringNo"b64_json" (default) for inline images.
output_formatStringNo"png" (default) or "jpeg".

Example

import base64
import os

import requests

response = requests.post(
    "https://api.inference.nebul.io/v1/images/generations",
    headers={
        "Authorization": f"Bearer {os.environ['NEBUL_API_KEY']}",
        "Content-Type": "application/json",
    },
    json={
        "model": "Tongyi-MAI/Z-Image-Turbo",
        "prompt": "A photo of a cat sitting on a windowsill at sunset",
        "n": 1,
    },
)

image_bytes = base64.b64decode(response.json()["data"][0]["b64_json"])

with open("generated.png", "wb") as f:
    f.write(image_bytes)

A request for one 1024x1024 image finishes in a few seconds and writes a valid PNG to generated.png. Images default to 1024x1024; output_format: "jpeg" returns JPEG instead.

Edit images

POST https://api.inference.nebul.io/v1/images/edits

Send an input image plus a prompt describing the change. The request is multipart:

ParameterTypeRequiredDescription
modelStringYesThe model ID, Tongyi-MAI/Z-Image-Turbo.
promptStringYesDescription of the edit to apply.
imageFileYesThe image to edit.
nIntegerNoNumber of images to generate. Defaults to 1.
response_formatStringNo"b64_json" (default) for inline images.
import base64
import os

import requests

with open("original.png", "rb") as f:
    response = requests.post(
        "https://api.inference.nebul.io/v1/images/edits",
        headers={"Authorization": f"Bearer {os.environ['NEBUL_API_KEY']}"},
        files={"image": ("original.png", f, "image/png")},
        data={
            "model": "Tongyi-MAI/Z-Image-Turbo",
            "prompt": "Add a red hat to the cat",
        },
    )

image_bytes = base64.b64decode(response.json()["data"][0]["b64_json"])

with open("edited.png", "wb") as f:
    f.write(image_bytes)

The same request with curl:

curl https://api.inference.nebul.io/v1/images/edits \
  -H "Authorization: Bearer $NEBUL_API_KEY" \
  -F "model=Tongyi-MAI/Z-Image-Turbo" \
  -F "prompt=Add a red hat to the cat" \
  -F "image=@original.png" \
  -o response.json

jq -r '.data[0].b64_json' response.json | base64 --decode > edited.png

Create variations

POST https://api.inference.nebul.io/v1/images/variations

Send an image with no prompt and get a new image in the same style:

ParameterTypeRequiredDescription
modelStringYesThe model ID, Tongyi-MAI/Z-Image-Turbo.
imageFileYesThe image to vary.
nIntegerNoNumber of images to generate. Defaults to 1.
response_formatStringNo"b64_json" (default) for inline images.
import base64
import os

import requests

with open("original.png", "rb") as f:
    response = requests.post(
        "https://api.inference.nebul.io/v1/images/variations",
        headers={"Authorization": f"Bearer {os.environ['NEBUL_API_KEY']}"},
        files={"image": ("original.png", f, "image/png")},
        data={"model": "Tongyi-MAI/Z-Image-Turbo"},
    )

image_bytes = base64.b64decode(response.json()["data"][0]["b64_json"])

with open("variation.png", "wb") as f:
    f.write(image_bytes)

Quick reference

Match the problem to the fix:

  • Image doesn't match the prompt: make the prompt more specific. Name the subject, setting, lighting, composition, and style.
  • Need variations of one prompt: set n higher, up to what your budget allows; each image bills separately.
  • Need a smaller file: request output_format: "jpeg".
  • Storing or piping the image: the response is already inline base64 (b64_json); no URL round trip to make.

Response

All three endpoints return the same shape:

{
  "created": 1792150343,
  "data": [
    {
      "b64_json": "iVBORw0KGgoAAAANSUhEUgAABAAAAAQACAIAA...",
      "url": null
    }
  ],
  "size": "1024x1024",
  "quality": "auto",
  "background": "auto",
  "output_format": "png",
  "usage": {
    "total_tokens": 1036,
    "input_tokens": 12,
    "output_tokens": 1024,
    "input_tokens_details": {
      "text_tokens": 12,
      "image_tokens": 0
    },
    "output_tokens_details": {
      "text_tokens": 0,
      "image_tokens": 1024
    }
  }
}
FieldTypeDescription
createdIntegerUnix timestamp of the response.
data[].b64_jsonStringThe image, base64-encoded.
data[].urlString or nullAlways null on this API; images are inline only.
sizeStringImage dimensions, 1024x1024.
output_formatStringpng or jpeg.
usage.input_tokensIntegerPrompt text tokens plus input image tokens (edits and variations).
usage.output_tokensIntegerGenerated image tokens: 1,024 per 1024x1024 image, scaling with size.

The response body lands in response; the vector is data[0].embedding in the JSON:

Billing follows the usage counts, and the counts scale with image size: a 1024x1024 image is 1,024 tokens, a 512x512 image is 256. A generated image bills 1,024 output tokens at the model's output price (about €0.00026 at €0.25 per 1M); an edit also bills input tokens for the image you send, at the same scale. Edits and variations return an image the same size as the one you send; generation always produces 1024x1024.

Write prompts with specifics

Name the subject, the setting, the lighting, and the style. "A photorealistic portrait of a cat sitting on a windowsill at sunset, soft golden lighting, shallow depth of field" beats "a cat": the model has something concrete to honor.

For reading images instead of creating them, send them to a vision model as content parts: see Examples. Current model specs live in the Model Catalog.

On this page