Skip to main content
API referenceImage generations

Image Generations

POST/v1/images/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.

  • modelstringrequired
    Model ID, e.g. venice-z-image-turbo, seedream-4.5, venice-flux-2-pro, gpt-5.4-image-2. Query /v1/models for the live catalog
  • promptstringrequired
    Text prompt
  • ninteger
    Number of images (1–10, default 1). Token-metered models served over the chat wire return a single image
  • sizestring
    e.g. 1024x1024. Drives per-megapixel billing and the per-token output estimate
  • resolutionstring
    1K, 2K, or 4K. Selects the pricing tier for resolution-tiered models; when omitted, the tier is derived from size
  • qualitystring
    e.g. low, medium, high. Drives the per-token output estimate where the provider doesn't report usage
  • response_formatstring
    b64_json or url (passed through to the provider)

Headers include X-Request-Id. With response_format=url, items are { "url": "https://..." }.

Response - 200 OKjson
{
  "created": 1713200000,
  "data": [
    { "b64_json": "iVBORw0KGgo..." }
  ]
}
Three metering units, one discount
per tokensome multimodal models
per imagefixed price per output
per megapixelscales with resolution
Image models are not all priced the same way. Whichever unit applies, the seller's discount is applied to it identically - the unit changes, the arithmetic does not.

Image-to-Image (editing)

POST/v1/images/edits

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.

  • modelstringrequired
    An edit-capable model, e.g. nano-banana-2-edit, qwen-image-2-edit, seedream-v4-edit, flux-2-max-edit (most carry an -edit suffix). Query /v1/models for the live catalog
  • promptstringrequired
    The edit instruction
  • imagestring
    Source image - an https:// URL or a data: URI (e.g. data:image/png;base64,...). image_url is accepted as an alias. URLs are passed to the provider as-is; the marketplace never fetches them
  • input_imagesarray
    Multiple source images. The first entry is the base (start) image; the rest are reference layers. Each entry is an https/data: URI string, or an object { "url": "...", "role": "start" | "reference" }. Max 8 images per request
  • imagesarray
    OpenAI-compatible source images, as the OpenAI SDKs send them on a JSON edit: entries of { "image_url": "..." } or bare strings, each an https:// URL or a data: URI. The first entry is the base image; the rest are reference layers. Max 8. file_id entries are not supported (400 invalid_image_input - pass image_url). When both input_images and images are sent, input_images is 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.

Single-image editbash
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"
  }'
Multi-image edit (base + reference)json
{
  "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" }
  ]
}
OpenAI SDK shapejson
{
  "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:

per-tokenModels (examples) · Nano Banana, GPT-image, Gemini imageCanonical · $/1M input + outputBuyer charge · usage_tokens × canonical/1M × discount
per-imageModels (examples) · Z-Image, SDXL, Seedream, Lustify, …Canonical · $/imageBuyer charge · canonical/image × n × discount
per-megapixelModels (examples) · FLUX.2 Pro/Max/Flex, Grok ImagineCanonical · $/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/quality so 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 from size).
  • See the live canonical and effective discounts at /api/markets/:model and /v1/prices: token-image models show $/1M input/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

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 model
5xxMeaning · Provider error (sanitized; the marketplace retries the next healthy seller before failing)