Image Generations
Minimum-discount routing: Prefix the path with a min{N} segment (e.g. /min30/v1/images/generations) to require marketplace seller offers to meet a minimum estimated buyer discount before routing. Buyer-owned providers are not covered. See Minimum-Discount Routing.
OpenAI-compatible image generation via the marketplace. One synchronous request returns the image(s); the marketplace routes to the cheapest healthy seller for the model and settles USDC to that seller.
The marketplace also supports image-to-image editing via POST /v1/images/edits - or this same endpoint when the body carries a source image. See Image-to-Image below.
Generating an image is not the same as showing one to a model. To have a text model look at an image you already have, send an image content part to /v1/chat/completions instead. See Media Inputs.
Request
Auth: API key (Authorization: Bearer inf_***), or pay-per-request via x402 (PAYMENT-SIGNATURE). With no auth, the endpoint returns 402 advertising x402. See Buyer endpoints.
modelstringrequiredModel ID, e.g.venice-z-image-turbo,seedream-4.5,venice-flux-2-pro,gpt-5.4-image-2. Query/v1/modelsfor the live catalogpromptstringrequiredText promptnintegerNumber of images (1–10, default 1). Token-metered models served over the chat wire return a single imagesizestringe.g.1024x1024. Drives per-megapixel billing and the per-token output estimateresolutionstring1K,2K, or4K. Selects the pricing tier for resolution-tiered models; when omitted, the tier is derived fromsizequalitystringe.g.low,medium,high. Drives the per-token output estimate where the provider doesn't report usageresponse_formatstringb64_jsonorurl(passed through to the provider)
Headers include X-Request-Id. With response_format=url, items are { "url": "https://..." }.
{
"created": 1713200000,
"data": [
{ "b64_json": "iVBORw0KGgo..." }
]
}Image-to-Image (editing)
Edit an existing image with a text prompt. Send a JSON body with the source image(s) and an edit-capable model; the marketplace routes to the cheapest healthy seller that supports image input. You can also send an edit to POST /v1/images/generations - including a source image in the body runs the edit flow there too. The min{N} prefix works on both paths.
Auth: same as generations - API key, or pay-per-request via x402.
modelstringrequiredAn edit-capable model, e.g.nano-banana-2-edit,qwen-image-2-edit,seedream-v4-edit,flux-2-max-edit(most carry an-editsuffix). Query/v1/modelsfor the live catalogpromptstringrequiredThe edit instructionimagestringSource image - anhttps://URL or adata:URI (e.g.data:image/png;base64,...).image_urlis accepted as an alias. URLs are passed to the provider as-is; the marketplace never fetches theminput_imagesarrayMultiple source images. The first entry is the base (start) image; the rest are reference layers. Each entry is anhttps/data:URI string, or an object{ "url": "...", "role": "start" | "reference" }. Max 8 images per requestimagesarrayOpenAI-compatible source images, as the OpenAI SDKs send them on a JSON edit: entries of{ "image_url": "..." }or bare strings, each anhttps://URL or adata:URI. The first entry is the base image; the rest are reference layers. Max 8.file_identries are not supported (400 invalid_image_input- passimage_url). When bothinput_imagesandimagesare sent,input_imagesis used
size, quality, resolution, and response_format apply as on generations. Bare base64 (without the data: prefix) and http:// URLs are rejected.
Masked edits (inpaint) are not supported yet - sending a mask/mask_url returns 400 mask_not_supported.
Response: the standard image response (above). The default b64_json returns the edited image inline; response_format: "url" returns short-lived download URLs instead. Editing is synchronous and returns one edited image per request.
curl $SURPLUS_BASE_URL/images/edits \ -H "Authorization: Bearer inf_***" \ -H "Content-Type: application/json" \ -d '{ "model": "nano-banana-2-edit", "prompt": "make the sky a dramatic sunset", "image": "https://example.com/skyline.png" }'
{
"model": "qwen-image-2-edit",
"prompt": "apply the style of the second image to the first",
"input_images": [
{ "url": "https://example.com/photo.jpg", "role": "start" },
{ "url": "https://example.com/style.jpg", "role": "reference" }
]
}{
"model": "gpt-image-2-edit",
"prompt": "make the sky a dramatic sunset",
"images": [{ "image_url": "https://example.com/skyline.png" }]
}Pricing - canonical price × discount
Each image model has a canonical reference price (OpenRouter-first, then Venice, then the SI registry). A seller's offer is a discount off that canonical, and the marketplace routes to the deepest discount. You always pay the canonical × the winning offer's discount - never an arbitrary per-seller price.
Canonical follows the model's native metering unit:
| Unit | Models (examples) | Canonical | Buyer charge |
|---|---|---|---|
| per-token | Nano Banana, GPT-image, Gemini image | $/1M input + output | usage_tokens × canonical/1M × discount |
| per-image | Z-Image, SDXL, Seedream, Lustify, … | $/image | canonical/image × n × discount |
| per-megapixel | FLUX.2 Pro/Max/Flex, Grok Imagine | $/MP | canonical/MP × (w×h/1e6 × n) × discount |
$/1M input + outputBuyer charge · usage_tokens × canonical/1M × discount$/imageBuyer charge · canonical/image × n × discount$/MPBuyer charge · canonical/MP × (w×h/1e6 × n) × discount- Per-token models bill on actual usage the provider reports; when a provider returns none (e.g. Venice serving a token-canonical model), usage is derived from
size/qualityso the buyer sees true per-1M pricing and the seller isn't underpaid. - Per-image and per-megapixel are deterministic from the request (
n,size) - no provider usage needed. - Image-to-image bills the same way - the model's canonical price × the winning discount, per edited image (an edit returns one image). For models with resolution-tiered pricing, the rate follows the output resolution (
resolution, or derived fromsize). - See the live canonical and effective discounts at
/api/markets/:modeland/v1/prices: token-image models show$/1Minput/output, diffusion models$/image, FLUX/Grok$/MP.
All costs are USDC microdollars (1 USD = 1,000,000 microdollars), drawn from your balance per completed request.
Errors
| Status | Meaning |
|---|---|
400 | Invalid request (bad JSON, validation, unknown model). Image-to-image adds: too_many_input_images (more than 8), invalid_image_input (a source that isn't an https URL or data: URI, or an images entry carrying a file_id), image_required (an edit request with no usable image), mask_not_supported (inpaint is not supported yet) |
402 | Insufficient balance (API key), or payment required (no auth - x402 challenge) |
404 | No available sellers for the model |
5xx | Provider error (sanitized; the marketplace retries the next healthy seller before failing) |
400Meaning · Invalid request (bad JSON, validation, unknown model). Image-to-image adds: too_many_input_images (more than 8), invalid_image_input (a source that isn't an https URL or data: URI, or an images entry carrying a file_id), image_required (an edit request with no usable image), mask_not_supported (inpaint is not supported yet)402Meaning · Insufficient balance (API key), or payment required (no auth - x402 challenge)404Meaning · No available sellers for the model5xxMeaning · Provider error (sanitized; the marketplace retries the next healthy seller before failing)