Image Generation in Codex
Trigger image generation from inside the Codex CLI: a custom slash command /imagegen calls gpt-image-2 through Codex's built-in bash tool. Submission is asynchronous (submit task → poll for result), no extra software needed.
Prerequisites
- Codex CLI installed and
~/.codex/config.tomlconfigured per the Codex Quick Start (base_url = "https://relay.upthos.com"). - Your API Key belongs to a Codex / OpenAI tier group (Codex Lite / Codex Pro / Codex Max). Keys in Claude / Gemini groups cannot call the image API.
sandbox_mode = "danger-full-access"in~/.codex/config.toml— the Quick Start template no longer ships this line, so add it yourself; otherwise Codex cannot executecurl.
1. Expose your API key to Codex's bash tool
The key in ~/.codex/auth.json is only injected into Codex's connection to the upstream — it is not available to bash subprocesses, so curl won't see it. Pick one:
Option A: shell environment variable (recommended)
# macOS / Linux —— add to ~/.zshrc or ~/.bashrc
echo 'export OPENAI_API_KEY="sk-relay-YOUR_KEY"' >> ~/.zshrc
source ~/.zshrc
# Windows PowerShell
[Environment]::SetEnvironmentVariable("OPENAI_API_KEY", "sk-relay-YOUR_KEY", "User")
Option B: inject at launch
OPENAI_API_KEY=$(jq -r .OPENAI_API_KEY ~/.codex/auth.json) codex
Verify: in Codex, type
run echo $OPENAI_API_KEY. If you see the key prefix, you're good.
2. Create the slash command
In ~/.codex/prompts/ (create with mkdir -p ~/.codex/prompts if missing), create imagegen.md:
---
description: Generate an image via Upthos Relay (gpt-image-2)
---
The user wants to generate an image. Description: {{args}}
Use the bash tool to execute the following flow (**parse responses by exact field path — do not invent the structure**):
### Step 1: submit the task
curl -sS -X POST https://relay.upthos.com/v1/images/tasks \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"prompt": "<insert the user's description, escape double quotes>",
"size": "1:1",
"resolution": "1k"
}'
Response: `{"code":0,"data":[{"status":"submitted","task_id":"task_xxx"}]}`
Extract task ID from `data[0].task_id`.
### Step 2: poll for result
Call every 3 seconds (max 60 attempts, ~3 minutes):
curl -sS https://relay.upthos.com/v1/images/tasks/<task_id> \
-H "Authorization: Bearer $OPENAI_API_KEY"
Branch on `data.status`:
- `processing` → wait and retry
- `completed` → extract image URL from `data.result.images[0].url[0]` and present it
- `failed` → report `data.error.message` to the user, stop
### Step 3: output format
Render with markdown image syntax:

Followed by one line: resolution, elapsed time, expiry (convert unix timestamp to human-readable).
### Parameters (use defaults if user did not specify)
- `size`: `1:1` / `16:9` / `9:16` / `3:2` / `2:3` / `auto`
- `resolution`: `1k` (default) / `2k` / `4k`
- Multiple images: `n` supports 1..4 — a single task can generate multiple images (or you can submit multiple tasks in parallel)
### Error handling
- HTTP 402 / `INSUFFICIENT_BALANCE` → tell the user to top up at https://relay.upthos.com/dashboard
- HTTP 403 → current key's group doesn't support the image API; switch to a Codex-tier key
- HTTP 429 → rate limit hit, suggest retry later
{{args}}is replaced with whatever the user types after/imagegen.
3. Try it
cd into any project, run codex, then enter:
/imagegen a cyberpunk cat with neon backlight
With parameters:
/imagegen a cat, 2k, 16:9
Codex will submit the task, poll until completion, and render the result inline as markdown. Image URLs have a finite lifetime — download or re-host before they expire.
4. Pricing
gpt-image-2 is billed per image and is independent of your Codex subscription tier (subscription discounts apply only to text/code models, not images). Charged from balance — even subscription users pay from balance, image gen does not consume subscription quota.
| Resolution | Price per image | Best for |
|---|---|---|
| 1k | ¥0.041 | thumbnails, fast iteration |
| 2k | ¥0.082 | mainstream illustrations, social media |
| 4k | ¥0.123 | high-resolution, print assets |
low / medium / high quality cost the same — switch freely.
Swap model for gpt-image-2.5-flare or gpt-image-2.5-sunburst to use GPT Image 2.5 — prices are identical to the table above. Omitting model still defaults to gpt-image-2.
5. Advanced: image-to-image (reference images)
Pass an image_urls array to the submit request with 1–N publicly reachable image URLs:
{
"model": "gpt-image-2",
"prompt": "convert this image to watercolor style",
"size": "1:1",
"resolution": "1k",
"image_urls": ["https://example.com/source.png"]
}
If you need to upload a local file first, call POST /v1/images/uploads (multipart, single file) to get a short-lived public URL, then pass it via image_urls. You can chain this step into the same imagegen.md so Codex handles uploads automatically.
FAQ
Q: I got 404 / "Images API is not supported for this platform".
A: Your key is not in an OpenAI / Codex-tier group. Create a new key in the console and choose any of Codex Lite / Codex Pro / Codex Max.
Q: I got 402 INSUFFICIENT_BALANCE.
A: Image generation always charges balance, never subscription quota. Top up at the dashboard.
Q: Codex says OPENAI_API_KEY: unbound variable.
A: The env var didn't reach the bash subshell Codex spawned. Verify step 1 succeeded; run echo $OPENAI_API_KEY in your current shell to confirm it is exported.
Q: Can Codex generate images automatically in normal chat (without typing /imagegen)?
A: Yes. Move the prompt content into ~/.codex/AGENTS.md (Codex's global system prompt) and tell it "when the user mentions drawing / generating an image, follow this flow…". The model will trigger on its own without a slash command.
Q: How long do image URLs live?
A: The response contains expires_at (unix timestamp), typically a few days. Download or re-host before expiry.
Q: Can I call this from Python / Node SDK instead?
A: Yes — it's plain HTTP. The slash command is purely a convenience for in-Codex workflows; any HTTP client works.