Guides
Image generation API and agent images on camelRun
Generate and edit images with POST /v1/images, or let an agent make them with the generate_image built-in. Billed per token at OpenAI prices.
View as Markdown · Docs index for coding agents
POST /v1/images makes images from a prompt, or edits images you give it, with
no agent. An agent makes them with the generate_image built-in.
Images are made with OpenAI's gpt-image-2.5-flare, on the OpenAI key a model
call of yours would use: a key scope's,
your own (PUT /v1/providers/openai/key), else the platform's. On the
platform's key, a prepaid account pays per token at OpenAI's prices (see
Billing).
Make an image
const { images: [image], costUsd } = await agents.images.generate("A watercolor camel crossing dunes at dawn", { size: "1536x1024" });
await writeFile("camel.png", Buffer.from(image.data!, "base64"));{
"images": [{ "contentType": "image/png", "width": 1536, "height": 1024, "data": "iVBORw0KGgo…" }],
"model": "openai/gpt-image-2.5-flare", "usage": { "inputTokens": 16, "outputTokens": 343 }, "costUsd": 0.01037
}| Field | |
|---|---|
prompt | What to make, or how to change the images given (at most 32,000 characters) |
size | 1024x1024 (default), 1536x1024 (landscape) or 1024x1536 (portrait) |
quality | low, medium (default) or high |
format | png (default), jpeg or webp |
background | transparent (with png or webp) or opaque; the model chooses when left out |
n | How many images, 1 to 4 (default 1) |
keyScope | A key scope whose OpenAI key goes first |
volumeId, path | Save the images in a volume of yours instead (see Save to a volume) |
subject, context, actor | Who it is for and who asked, carried to its usage.recorded event, as an agent's identity is |
bucket | With end-user credits on: which of the subject's buckets pays |
The answer comes when the images are ready: about 10 seconds for one at low
or medium, longer at high (OpenAI allows up to two minutes for a complex
prompt). The images come back as base64 and nothing is kept.
- A retry makes (and bills) new images. Requests take no
Idempotency-Key. - API tokens and OAuth tokens may make images; browser tokens may not.
- Runs-per-minute limits count each request as a run.
Edit images
Give up to 4 images (PNG, JPEG or WebP) in images, and the prompt says how to
change or combine them:
const { images } = await agents.images.edit("Put this camel on a beach", [await readFile("camel.png")], { quality: "high" });- In JSON, each image is
{"data": "<base64>"}or{"url": "https://…"}, which camelRun fetches from the public internet (three redirects at most). - As multipart, each image is a file part named
image, and the other fields are form fields (contextas JSON). - A
mask(a part, or{data}/{url}) says where the first image may change: transparent there. It is an image with an alpha channel, in the first image's format and size.
Save to a volume
With volumeId (one of your volumes), the images
are saved there, under path (a directory, /images by default), and the
answer gives their paths instead of their bytes:
{ "images": [{ "contentType": "image/png", "width": 1024, "height": 1024, "volumeId": "vol_…", "path": "/images/image-20261009T104512-3fa9c1.png", "size": 1316554, "version": 1 }], … }Read them with GET /v1/volumes/{id}/files/{path}, or hand a browser a signed
link to one (POST /v1/volumes/{id}/links). They count toward your storage
like any file.
In an agent
Give an agent (or its definition, or a stateless run)
the generate_image built-in:
const agent = await agents.upsert("illustrator", { builtins: ["generate_image"] });
const run = await agent.run("Draw a camel crossing dunes at dawn, as a watercolor, and show it to me");The model calls generate_image with a prompt, and optionally images
(paths of images in its files, such as an attachment or one it made before, to
edit or combine), size, quality (medium by default), format and
background.
- Each call makes one image, saved to the agent's workspace under
tool-outputs/generate_image/<call>/, and answers with its path, size and cost. - The model is shown the image, so it can check it or describe it. It presents
it to the user with
present_file, which emits afile_presentedevent with a signed link. - A stateless run with
generate_imagegets a workspace for its images.
Each image is billed as a request to POST /v1/images is, with the run's facts
on its usage.recorded event (agentId, requestId, actor, the agent's
identity and key scope). It counts against the agent's spend limit and the
run's own spendLimit: a call whose estimate is more than what is left fails
before anything is sent, and the model is told why. The run's
usage.imageCostUsd says what its images cost.
Saving a definition or an agent with generate_image when the account has no
OpenAI key to use answers with a warning, and a call then fails with how to add
one.
Safety and errors
OpenAI's safety system checks the prompt, the images given and the image made.
A request it refuses is a 400 IMAGE_REFUSED, which names the stage (input:
the prompt or images given; output: the image made) and the categories it
gives, never the prompt:
{ "type": "error", "error": "OpenAI's safety system refused this request (violence)", "code": "IMAGE_REFUSED", "stage": "input", "categories": ["violence"] }A refused request is not charged. In an agent, the model is told it was refused and why.
| Error | |
|---|---|
| 400 | A request OpenAI cannot take, with its reason |
400 IMAGE_UNAVAILABLE | No OpenAI key to use |
413 IMAGE_TOO_LARGE | An image to edit is too large |
415 UNSUPPORTED_IMAGE | An image to edit is not PNG, JPEG or WebP |
502 IMAGE_FAILED | The provider failed |
Limits
| Prompt | 32,000 characters |
| Images to edit | 4, PNG, JPEG or WebP, 25 MB each, 50 MB in all, at most 8,000 pixels a side |
| Images made | 4 per request |
| Time | 3 minutes for the provider to answer |
Billing
On the platform's key, images cost what OpenAI charges for
gpt-image-2.5-flare, with no camelRun markup: $5 per million text tokens in,
$8 per million image tokens in (images given to edit) and $30 per million image
tokens out. The tokens are those OpenAI reports for the request. One image
costs:
| Quality | 1024x1024 | 1536x1024 or 1024x1536 |
|---|---|---|
low | $0.0059 (196 tokens) | $0.0047 (158 tokens) |
medium | $0.0132 (439 tokens) | $0.0103 (343 tokens) |
high | $0.0527 (1,756 tokens) | $0.0412 (1,372 tokens) |
Add the prompt (a few hundredths of a cent), and about $0.008 to $0.012 for each image given to edit (1,024 tokens for a square one, 1,536 for a wide one). A spend limit refuses a request whose estimate (the most it can cost) is more than what is left of it, before anything is sent. On your own key or a key scope's, OpenAI bills you and camelRun charges nothing.
Either way it is recorded:
- In
GET /v1/usage, a row per day withkind: "image"and modelopenai/gpt-image-2.5-flare(responsescounts images). - In the hour's ledger entry, as
image(micro-USD) andimages. - As a
usage.recordedevent withkind: "image",images, and its tokens (input: text and images in,output: images out). Made with no agent, it hasagentId: nulland thesubject,contextandactoryou sent. The older usage webhook (/v1/usage-webhook) carries model responses only.
Images count toward your monthly cap and prepaid credit, as a model response does. See Pricing.
Privacy
Prompts and images are never written to camelRun's logs, which carry sizes,
quality, tokens and timings. A request without volumeId keeps nothing; with
one, the images are kept in your volume until you delete them. OpenAI processes
the prompt and images under its API data policy (not used for training).