Inference Cheap

Image generation

Generate, edit, and stream images through the Inference Cheap API.

Use https://openai.inference.cheap/v1 with a key that allows image generation.

Choose an interface

InterfaceUse it for
POST /v1/images/generationsGenerate images from a prompt.
POST /v1/images/editsEdit images, optionally with a mask.
POST /v1/responses with an image_generation toolGenerate or edit images in a conversation.

All three interfaces support streaming.

Models

Only GPT Image 2.5 is available for now. Set model to gpt-image-2.5 in every request. Requests with another model, or without model, fail with 503 Service temporarily unavailable.

Generate an image

Install openai and set INFERENCE_CHEAP_API_KEY:

import base64
import os
from pathlib import Path
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["INFERENCE_CHEAP_API_KEY"],
    base_url="https://openai.inference.cheap/v1",
    timeout=300.0,
    max_retries=0,  # Avoid duplicate generations.
)

result = client.images.generate(
    model="gpt-image-2.5",
    prompt="A small red sailboat on a calm blue lake, watercolor illustration.",
    n=1,
    output_format="png",
)
Path("sailboat.png").write_bytes(base64.b64decode(result.data[0].b64_json))

Edit an image

Pass a local image file:

with open("sailboat.png", "rb") as source:
    result = client.images.edit(
        model="gpt-image-2.5",
        image=source,
        prompt="Change the sail to yellow. Keep the boat and lake composition.",
        output_format="png",
    )

Path("sailboat-edited.png").write_bytes(
    base64.b64decode(result.data[0].b64_json)
)

For JSON requests, use an HTTPS URL or a base64 data URL in images[].image_url. Add a mask with mask.image_url:

{
  "model": "gpt-image-2.5",
  "prompt": "Change the sail to yellow.",
  "images": [
    { "image_url": "data:image/png;base64,REPLACE_WITH_IMAGE_BASE64" }
  ]
}

Multipart fields: image / image[], optional mask. file_id is unsupported. Masks do not guarantee that areas outside the mask stay unchanged.

Parameters and output

The following parameters apply to /v1/images/generations and /v1/images/edits.

quality, style, and input_fidelity are not configurable and silently ignored.

ParameterCurrent behavior
promptRequired, non-empty.
modelRequired: gpt-image-2.5. See Models.
nPositive integer limiting returned images. Omit for all. The count is not guaranteed. All generated images are billed, including those not returned.
sizeSets only the aspect ratio, from 1:3 to 3:1; other values are ignored. Images are always about 1.57 megapixels, so 1024x1024 returns 1254x1254.
aspect_ratioW:H, for example 16:9. Not an OpenAI parameter: in the SDK, pass it in extra_body. Overrides size.
qualityIgnored. Always auto.
styleIgnored.
backgroundauto (default), opaque, or transparent. With auto, the model chooses from the prompt: an isolated object often comes back transparent. opaque always gives a solid background. transparent requires png or webp.
output_formatpng, jpeg, or webp.
output_compressionControls JPEG and WebP compression.
moderationDoes not disable safety checks.
streamfalse returns a final JSON response; true returns SSE events.
partial_imagesRequests streamed previews, which are not guaranteed.
response_formatb64_json by default. url returns inline data: URLs, not download links.
input_fidelityIgnored.

Stream images

Set stream: true to receive SSE events. Generation events include image_generation.partial_image and image_generation.completed; edits use the image_edit prefix. Handle error events; save only completed images.

Use the Responses image tool

Use a text model with the image_generation tool:

response = client.responses.create(
    model="gpt-5.6-sol",
    input="Draw a watercolor red sailboat on a calm blue lake.",
    tools=[{"type": "image_generation", "model": "gpt-image-2.5"}],
    tool_choice={"type": "image_generation"},
)

images = [
    item for item in response.output
    if item.type == "image_generation_call"
    and item.status == "completed" and item.result
]
if response.status != "completed" or not images:
    raise RuntimeError("The response did not contain a completed image.")
Path("sailboat.png").write_bytes(base64.b64decode(images[0].result))

For edits, include an input image and set action: "edit" in the tool. To add a mask, set input_image_mask: { image_url: "..." } in the tool.

With stream: true:

  • Previews arrive as response.image_generation_call.partial_image in partial_image_b64.
  • The completed image_generation_call.result contains the final image.
  • response.completed marks the end. Previews are not guaranteed.

API reference: Images and Responses image tool.

On this page