Codex Image Generation With a Custom Provider: imagegen Setup
Two lines in config.toml turn on Codex's built-in image tool on a relay. Here is the setup we ran on October 29, 2026, where the images are saved, and what the relay must send back.
On this page
- Why imagegen disappears on a custom provider
- The config.toml that turns it on
- Run one image and find the file
- Edit an existing image
- Transparent background
- What your relay must return (gpt-image-2, b64_json)
- Errors and fixes
- Codex says it has no image tool
- Codex asks for OPENAI_API_KEY
- failed to decode image generation response: missing field b64_json
- The image request fails with model_not_found
- Reconnecting... 1/5 (stream disconnected before completion)
- FAQ
- Do I need OPENAI_API_KEY for imagegen?
- Can I choose another image model, size or quality?
- Do I have to type $imagegen?
- Does this work in the Codex desktop app?
- Sources checked
Codex 0.165.0 hides its built-in image tool on a relay until the provider block adds an http_headers entry named x-openai-actor-authorization, with any non-empty value, and keeps requires_openai_auth = false, the default. Then Codex sends image requests to the relay's /images/generations with the model gpt-image-2 and saves the PNG under ~/.codex/generated_images/. On October 29, 2026 that gave a 1024×1024 PNG in 29.0 seconds; the same config without the header gave no image tool.
We ran these tests with Codex CLI 0.165.0 on macOS, using OmniaKey, our own API gateway, as the custom provider.
Why imagegen disappears on a custom provider
Codex 0.165.0 decides whether the model gets an image tool from your provider block and the sign-in it has stored, in one function: image_generation_available.
requires_openai_auth = falsewith no actor header: no image tool. In our run with that config, Codex replied: "I don’t have a built-in image generation tool available in this session."requires_openai_auth = falseplus thex-openai-actor-authorizationheader: the tool appears. Our three runs with it (a new image, an edit and a transparent sticker) all called it.requires_openai_auth = truewith an API key sign-in: no image tool. Per Codex 0.165.0's code, the check wants a ChatGPT sign-in, and an API key sign-in does not count.
Two smaller conditions sit behind that gate, both in Codex 0.165.0's code: a stored free ChatGPT plan hides the tool even on a custom provider, and the chat model has to accept images, which Codex assumes for model names its own list does not know.
When the tool is missing, Codex either says it has no built-in image tool, as in our run without the header, or the imagegen skill offers its CLI fallback, which needs OPENAI_API_KEY.
The config.toml that turns it on
Open ~/.codex/config.toml. In the provider block for your relay, add the http_headers line and make sure requires_openai_auth is false, its default.
model = "gpt-6.1-sol" # a chat model your relay serves
model_provider = "relay"
[model_providers.relay]
name = "My relay"
base_url = "https://api.omniakey.com/v1"
env_key = "RELAY_API_KEY"
wire_api = "responses"
requires_openai_auth = false
http_headers = { "x-openai-actor-authorization" = "local-relay" }
[features]
image_generation = true # already on by default in Codex 0.165.0
model and model_provider are top-level keys, so they must sit above the first [section] line; TOML reads every line after a [section] header as part of that section.
requires_openai_auth = falsekeeps Codex on the key from your environment, the variable named inenv_key. OpenAI's auth page (checked October 29, 2026) says: "Whenrequires_openai_auth = true, Codex ignoresenv_key."http_headersholds the actor header. OpenAI's config reference calls it "Static HTTP headers added to provider requests", and Codex only checks that the value is not empty (the check in Codex's source), so "local-relay" is a placeholder, not a password.[features] image_generation = trueis optional in 0.165.0, where the feature is stable and on by default (codex features listprintsimage_generation stable true). Our runs left it out.wire_api = "responses"is the only value OpenAI's config reference supports.
Set the key and start Codex:
export RELAY_API_KEY="your-relay-key"
codex
If Codex was already running, quit it and open a new session so it reads the new config.
Run one image and find the file
Our October 29, 2026 runs went through a custom provider. Run 2, the check without the header, made no image. The other three each saved one 1024×1024 PNG. The times are the image call, not the whole turn.
| Run | What we asked | Image call |
|---|---|---|
| 1 | A new app icon | 29.0 s |
| 3 | Edit run 1's image | 37.6 s |
| 4 | A transparent sticker | 19.8 s |
Run 1 was a single prompt:
Create an app icon for a note-taking app called Inkwell: a fountain pen nib over a deep blue gradient, flat vector style, no text. Generate it with your image tool, then tell me where the file was saved.
Codex opened the imagegen skill by itself, without $imagegen in the prompt, then called the tool. The call took 29.0 seconds and the turn ended with one 1024×1024 PNG.
The file lands at ~/.codex/generated_images/<session id>/<call id>.png; ~/.codex is the default CODEX_HOME. Codex printed the path because the prompt asked. If the image belongs in your project, name the destination and the skill tells Codex to move or copy the file there.
Edit an existing image
Run 1's PNG went into the work folder as inkwell.png, and we asked:
Edit the image ./inkwell.png: change the background to a warm orange gradient and keep the pen nib as it is. Use your built-in image tool, then tell me where the edited file was saved.
Codex passed the file in referenced_image_paths, so the request went to /images/edits. The call took 37.6 seconds and the original inkwell.png stayed as it was. OpenAI's image generation page (checked October 29, 2026) says: "When editing an existing image, say exactly what should change and what must stay the same." The GPT-Image 2 prompt guide covers the rest.


Transparent background
Run 4 asked for a sticker:
Create a PNG sticker of a single fountain pen nib on a fully transparent background (no backdrop at all), flat vector style, no text. Generate it with your built-in image tool, then tell me where the file was saved.
Codex set transparent_background: true, the call took 19.8 seconds, and 85.0% of the pixels in the saved PNG are fully transparent. OpenAI's Images API reference lists transparent backgrounds for gpt-image-2 as "in preview": it worked in our run, but it is still a preview feature.

What your relay must return (gpt-image-2, b64_json)
Codex sends POST <base_url>/images/generations for a new image and POST <base_url>/images/edits for an edit, both as JSON with the model gpt-image-2, the id of GPT-Image 2, which your relay has to serve. Quality and size are "auto", background is "opaque" or "transparent", and the request leaves out both response_format and n. Both go to the same base URL, with the same key, as your chat requests. An edit carries its source image inside the JSON as a data URL rather than a file upload.
Codex reads a JSON reply with created and a data list whose first item holds b64_json; other fields are ignored, as images.rs shows. A parse failure starts with "failed to decode image generation response:".
You can check a relay without Codex. Save this as relay-check.sh:
curl -s https://api.omniakey.com/v1/images/generations \
-H "Authorization: Bearer $RELAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gpt-image-2", "prompt": "a red apple on a white table", "background": "opaque", "quality": "auto", "size": "auto"}' \
| python3 -c 'import json,sys; r=json.load(sys.stdin); print(r.get("error") or sorted(r["data"][0]))'
Point the base URL at your relay and export your key as RELAY_API_KEY. On October 29, 2026 the check against our gateway returned HTTP 200 after 25.0 seconds and printed:
['asset_id', 'b64_json', 'expires_at', 'revised_prompt', 'url']
If b64_json is missing from that list, Codex fails on the same reply. If the relay returns an error, the check prints the error instead.
Some relays break this because they store the image as a file. The same Images API reference (checked October 29, 2026) says response_format is a "Legacy response format parameter for retired image models. Unsupported for GPT image models, which always return base64-encoded images", and b64_json is "Returned by default for GPT image models". A relay that passes OpenAI's reply through unchanged works; one that sends back only a link breaks Codex.
OmniaKey's gateway had that problem until a fix on October 29, 2026. The fix note says Codex failed with "missing field b64_json", and the gateway now keeps b64_json unless the caller asks for a URL.
If your relay fails the check, OmniaKey serves gpt-image-2 and chat models such as gpt-6.1-sol with one key, and its image replies include b64_json, as the check shows. Set base_url = "https://api.omniakey.com/v1" in that provider block and put your OmniaKey key in the variable that env_key names; the Codex CLI guide covers the rest of the file, and current rates are on the pricing page.
Errors and fixes
Codex says it has no image tool
One of the conditions in the first section is not met. Add the http_headers line, keep requires_openai_auth = false with your env_key, and start a new session. Still missing? Run codex login status; with a free ChatGPT plan, codex logout removes the stored sign-in and the key from env_key is enough.
Codex asks for OPENAI_API_KEY
The built-in tool is unavailable, so the imagegen skill offers its CLI fallback, scripts/image_gen.py, which needs OPENAI_API_KEY. Fix the built-in tool with the config above instead; in built-in mode the key comes from env_key.
failed to decode image generation response: missing field b64_json
The relay replied without b64_json, usually with a link to a stored file. Run the check from the relay section against it and send the result to the operator; Codex wants the base64 string in the first item of data.
The image request fails with model_not_found
Your key has no gpt-image-2 on this relay, and Codex always sends that id with no setting to change it. Our gateway answered an image model it does not serve with HTTP 503 and the code model_not_found. Use a key and a relay that list gpt-image-2.
Reconnecting... 1/5 (stream disconnected before completion)
The chat request dropped and Codex retried it; the counter shows the attempt out of five. It appeared once in run 1 ("Concurrency limit exceeded for account, please retry later") and once in run 3 (a transport error), and both runs finished after the retry. If it keeps returning, check the relay's limits; the Codex compatibility kit covers chat trouble.
FAQ
Do I need OPENAI_API_KEY for imagegen?
No. In built-in mode the key comes from the variable named in env_key; only the skill's CLI fallback reads OPENAI_API_KEY.
Can I choose another image model, size or quality?
Not in Codex 0.165.0. The tool sends gpt-image-2 with quality and size "auto", config.toml has no key for any of them, and every image in our runs came back 1024×1024. For a different size or model, call your relay's image endpoint directly.
Do I have to type $imagegen?
No. In our runs Codex opened the imagegen skill on its own. OpenAI's docs say $imagegen in the prompt invokes the skill explicitly, which helps when Codex does not pick it up.
Does this work in the Codex desktop app?
We did not test the desktop app, only the CLI. The community fix repository says a running Codex Desktop does not pick up new environment variables: its macOS script installs a LaunchAgent, and you quit Codex completely and open a new task afterwards.
Sources checked
- OpenAI Codex docs: authentication for alternative model providers
- OpenAI Codex docs: configuration reference
- OpenAI Codex docs: image generation
- OpenAI API reference: create image
- Codex 0.165.0 source: when the image tool is offered
- Codex 0.165.0 source: the actor header check
- Codex 0.165.0 source: how the image reply is read
- xianyu110/codex-imagegen-relay-fix on GitHub
Models in this article
Related articles
Fix GPT-5.6 Model Not Found
Match the error first, then test model access, the API, and Codex separately.
GPT Image 2 Prompt Guide: Structure, Examples and Real Images
Eight prompts, nine real images: what GPT Image 2 got exactly right, what it added and how to fix it.
Best Model for Codex: GPT-6.1 Sol, GPT-6 Luna or GPT-5.6?
Start with GPT-6.1 Sol for complex coding, GPT-6 Luna for focused repeatable tasks, and the GPT-5.6 tiers for work that still runs on them.
