Image API

Generating images over the API

Images go through the Responses endpoint: the mainline model reads your description and calls image generation as a tool, and the picture comes back as a Base64 result on a stream event. Same address and same key as a text call — no separate image service to wire up.

  1. 01

    Build the request body

    Four things matter: put image_generation in tools and name the image model; set tool_choice to the same type so it renders instead of replying in text; turn stream on, since image generation is far slower than text and streaming keeps events flowing and the connection alive; turn store off so the turn is not retained server-side. The image description goes into input as a user message, and instructions only states the job. The snippet below is bash — on Windows, jump to the Python example in the next step.

    curl https://api.xylemnode.com/v1/responses \
      -H "Authorization: Bearer sk-your-key" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "gpt-5.6-sol",
        "instructions": "Generate the requested image.",
        "input": [
          { "role": "user", "content": "A ginger cat in a spacesuit standing on the moon, blue Earth in the distance, cinematic lighting, photorealistic." }
        ],
        "tools": [{ "type": "image_generation", "model": "gpt-image-2" }],
        "tool_choice": { "type": "image_generation" },
        "stream": true,
        "store": false
      }'
  2. 02

    Pull the image out of the stream

    The response is SSE: read the JSON after each data: line, keep only events whose type is response.output_item.done, and find the one whose item.type is image_generation_call — its item.result is the finished image in Base64. Decode it and write it to a file. Note that result is a long string, not a URL, so don't treat it as an image address or print it to your terminal.

    import base64
    import json
    import requests
    
    PROMPT = "A ginger cat in a spacesuit standing on the moon, blue Earth in the distance, cinematic lighting, photorealistic."
    
    payload = {
        "model": "gpt-5.6-sol",
        "instructions": "Generate the requested image.",
        "input": [{"role": "user", "content": PROMPT}],
        "tools": [{"type": "image_generation", "model": "gpt-image-2"}],
        "tool_choice": {"type": "image_generation"},
        "stream": True,
        "store": False,
    }
    
    with requests.post(
        "https://api.xylemnode.com/v1/responses",
        headers={"Authorization": "Bearer sk-your-key"},
        json=payload,
        stream=True,
        timeout=600,
    ) as response:
        response.raise_for_status()
        for raw in response.iter_lines():
            if not raw:
                continue
            line = raw.decode("utf-8")
            if not line.startswith("data:"):
                continue
            chunk = line[5:].strip()
            if chunk == "[DONE]":
                break
            event = json.loads(chunk)
            if event.get("type") != "response.output_item.done":
                continue
            item = event.get("item") or {}
            if item.get("type") == "image_generation_call" and item.get("result"):
                with open("moon-cat.png", "wb") as file:
                    file.write(base64.b64decode(item["result"]))
                print("saved moon-cat.png")
  3. 03

    Swap models, tune the output

    Switch image models as needed: gpt-image-2.5-flare is faster, gpt-image-2.5-sunburst is more precise but slower — go by the model list in your console. Output options live on the same object inside tools: size sets the frame, quality the level of detail, background can request transparency (only png / webp support it) and output_format picks the file type. Add partial_images (1-3) and you'll receive a few preview drafts while it renders, as response.image_generation_call.partial_image events.

    "tools": [{
      "type": "image_generation",
      "model": "gpt-image-2.5-flare",
      "size": "1024x1536",
      "quality": "high",
      "background": "transparent",
      "output_format": "png",
      "partial_images": 2
    }]
Parameters
Endpoint
https://api.xylemnode.com/v1/responses
Method
POST (Bearer auth)
Mainline model
gpt-5.6-sol
Tool
image_generation
Image model
gpt-image-2
Result field
image_generation_call.result (Base64)

Two things that trip people up

First, the mainline model only reads the description and triggers the tool, so it has to be one that supports image_generation. If you get a tool-unavailable error, pick another mainline model from your console list. Second, one request produces one finished image. To keep editing the same image, turn store on and point previous_response_id at the earlier response on the next call — with store off the turn isn't retained, so there is nothing to continue from.