Image generation
Generate, edit, and stream images through the Inference Cheap API.
For agents — copy the image prompt.
Use https://openai.inference.cheap/v1 with a key that allows image generation.
Choose an interface
| Interface | Use it for |
|---|---|
POST /v1/images/generations | A prompt that produces image results. |
POST /v1/images/edits | A prompt plus source images, optionally with a mask. |
POST /v1/responses with an image_generation tool | Image generation inside a conversation or tool workflow. |
All three interfaces support streaming.
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,
)
result = client.images.generate(
model="gpt-image-2",
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))gpt-image-2 is the default. Image access is separate from /v1/models.
Edit an image
For local files, use a multipart upload through the SDK:
with open("sailboat.png", "rb") as source:
result = client.images.edit(
model="gpt-image-2",
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)
)JSON edits use images[].image_url (HTTPS or base64 data URL)
and optional mask.image_url:
{
"model": "gpt-image-2",
"prompt": "Change the sail to yellow.",
"images": [
{ "image_url": "data:image/png;base64,REPLACE_WITH_IMAGE_BASE64" }
]
}Multipart fields: image / image[], optional mask. Images file_id inputs
are unsupported. Masks do not guarantee pixel-perfect protection.
Parameters and output
Controls are forwarded to the model; supported values and limits vary.
| Parameter | Current behavior |
|---|---|
prompt | Required, non-empty. |
model | Defaults to gpt-image-2; the requested image model is used for routing. |
n | Positive integer; defaults to 1. Multiple-image requests depend on the model's limits. |
size, quality, background | Forwarded to the image tool. Omit for automatic choices; handle unsupported-option errors. |
output_format | Request png, jpeg, or webp; match the saved file extension to the output format. |
output_compression | Forwarded when supplied, for formats that support compression. |
moderation | Forwarded when supplied; do not assume it disables safety checks. |
stream | false returns a final JSON response; true returns SSE events. |
partial_images | Requests streamed previews; previews are optional and are not final outputs. |
response_format | Omit for data[].b64_json. url returns inline data: URLs on the current subscription-backed adapter, not hosted download links. |
input_fidelity | Does not control the current subscription-backed Images adapter; omit it. |
Decode data[].b64_json; response_format: "url" returns inline data: URLs.
Image requests can take minutes. Allow a suitable timeout, parse the final
JSON or stream outcome, and handle errors even after HTTP 200.
For 413, reduce the payload.
Stream images
Set stream: true on the Images request and use an SDK or SSE reader.
Generation events include image_generation.partial_image and
image_generation.completed; edits use the image_edit prefix. Handle error
events and only save a completed result as the final image.
Use the Responses image tool
Use a text model with image-tool access and specify the image model in the 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"}],
tool_choice={"type": "image_generation"},
)
images = [item for item in response.output if item.type == "image_generation_call"]
if not images:
raise RuntimeError("The response did not contain a completed image.")
Path("sailboat.png").write_bytes(base64.b64decode(images[0].result))Use action: "edit" with image input for edits. The Responses mask field is
input_image_mask: { image_url: "..." } inside the tool, unlike the Images
endpoint's mask field. Standard Responses streaming also delivers image-tool
progress and partial images when available.
For the underlying schemas, see OpenAI's Images API and Responses image tool. Apply the Inference Cheap differences documented on this page.
For agents
Copy this Markdown prompt to your agent.
# Use Inference Cheap images
- Base URL: https://openai.inference.cheap/v1. Read INFERENCE_CHEAP_API_KEY
from the project's secret store; never log it. The key needs image access.
- Use Images for standalone requests; Responses for conversation workflows.
Image model: gpt-image-2. Responses also needs an available text model.
- Start with n=1. Add options only as needed; allow several minutes per request.
- For edits, use the user's source image: multipart image/image[] or JSON
images: [{ image_url: "..." }]. Images file_id inputs are unsupported.
- Decode b64_json or inline data: URLs. Save with the matching extension.
Check the final result; previews and HTTP 200 alone do not mean completion.
- Show the output and report failures. Do not blindly repeat timed-out requests.
- Examples and options: https://docs.inference.cheap/images