Skip to content
INFRO

Documentation

Image generation

Generate and edit images with POST /v1/images/generations and /v1/images/edits — parameters, sizes, response shape, and per-image billing.


Image generation is synchronous. You post a prompt, the request stays open while a provider renders, and the response carries the finished images. Expect a few seconds on fast models and up to a minute on the highest-quality ones.

Two endpoints share one request shape: /v1/images/generations creates images from text, /v1/images/edits modifies an image you upload. Both accept the universal routing, fallbacks, and logging extensions, and both report exact spend in usage.cost. Video works differently — it is asynchronous, see Video generation.

Endpoints
POST https://api.infro.io/v1/images/generations
POST https://api.infro.io/v1/images/edits

Request body

modelstringrequired
Image model ID in vendor/model-name form, e.g. bfl/flux-2-pro, ideogram/ideogram-3, or google/imagen-4-ultra. Browse IDs and per-image prices in the catalog.
promptstringrequired
What to render. Prompt conventions differ by model — recraft/recraft-v3 responds to style keywords, ideogram/ideogram-3 is the strongest at rendering text inside the image. Length limits are per model.
ninteger
How many images to return, 110. Defaults to 1. Models that can only render one image per upstream call are fanned out into parallel requests; you are billed per image either way.
sizestring
WIDTHxHEIGHT, e.g. 1024x1024. Defaults to the model's native square resolution. See the size table below.
qualitystring
standard (default) or high. high spends more compute per image and costs more. Models without a quality tier ignore it.
response_formatstring
url (default) returns a hosted link; b64_json returns the image inline as base64. Base64 payloads are several megabytes each — prefer url unless your runtime cannot make a second fetch.
seedinteger
Best-effort deterministic sampling. The same seed, prompt, and model reproduce the same image on providers that support it; providers that do not ignore the field.

INFRO extensions

The same top-level extensions available on chat completions apply here, with identical semantics.

routingobject
{"policy": "cheapest" | "fastest" | "balanced", "regions": ["us", "eu", "ap"]}. All fields optional. Full semantics in Smart routing.
fallbacksarray
Ordered model IDs to try if every provider of model fails, e.g. ["bfl/flux-2-dev", "qwen/qwen-image"]. See Failover & fallbacks.
loggingboolean
Set false to keep prompts and rendered images out of durable storage. Metadata is still metered for billing. See Privacy & data.

Example request

curl https://api.infro.io/v1/images/generations \
  -H "Authorization: Bearer $INFRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "bfl/flux-2-pro",
    "prompt": "An isometric cutaway of a small data center, soft studio lighting",
    "size": "1024x1024",
    "n": 1,
    "routing": {"policy": "balanced"},
    "fallbacks": ["ideogram/ideogram-3"]
  }'

Response

json
{
  "id": "img_5c3f9a21",
  "created": 1755950000,
  "model": "bfl/flux-2-pro",
  "provider": "fal",
  "data": [
    {
      "url": "https://cdn.infro.io/img/5c3f9a21-0.png",
      "b64_json": null
    }
  ],
  "usage": {
    "images": 1,
    "cost": 0.03
  }
}
data[].urlstring
Hosted PNG, or null when response_format is b64_json. Valid for 24 hours.
data[].b64_jsonstring
Base64-encoded image bytes, or null when response_format is url. Exactly one of the two fields is populated per entry.
providerstring
INFRO extension: the provider that actually rendered the images, as a bare lowercase slug. Useful when comparing latency or style drift between runs.
usage.imagesinteger
Number of images billed. Equals n on success.
usage.costnumber
INFRO extension: the exact USD amount charged for this request.

Image URLs expire 24 hours after the request and the file is then deleted. Download the bytes or copy them to your own storage if you need them longer — the same retention applies to async job outputs.

Editing an image

/v1/images/edits takes multipart/form-data rather than JSON, because it carries file uploads. model, prompt, n, size, response_format, and seed behave exactly as above and are sent as form fields.

imagefilerequired
The image to edit. PNG, JPEG, or WebP, up to 25 MB. Non-square images are accepted; the output keeps the input's aspect ratio unless you pass size.
maskfile
Optional PNG with an alpha channel, the same dimensions as image. Transparent pixels are the region to repaint; opaque pixels are preserved. Without a mask the model edits the whole image guided by the prompt.
promptstringrequired
What the edited region should contain. Describe the desired result, not the change — a walnut reading chair works better than replace the sofa.
curl https://api.infro.io/v1/images/edits \
  -H "Authorization: Bearer $INFRO_API_KEY" \
  -F model="bfl/flux-2-dev" \
  -F image=@room.png \
  -F mask=@room-mask.png \
  -F prompt="A walnut reading chair with a brass floor lamp beside it" \
  -F size="1024x1024"

Sizes and aspect ratios

Every model publishes the sizes it can render. These five cover most product work:

SizeRatioTypical use
1024x10241:1Avatars, product shots, grid thumbnails
1536x10243:2Blog headers and landscape hero images
1024x15362:3Posters, print, portrait cards
1792x102416:9Slides, video thumbnails, wide banners
1024x17929:16Stories and vertical mobile feeds

A size a model cannot render natively is snapped to its nearest supported resolution at the same ratio, so pixel dimensions in the response can differ slightly from what you asked for. Aspect ratio is never changed silently: a model that cannot produce the ratio you requested returns 400 invalid_request_error instead of cropping. Check the model page in the catalog before hardcoding a size.

Cost

Images are billed per image, never per token. The rate depends on the model, the resolution, and quality, and usage.cost on every response is the exact USD charged. n multiplies it linearly. Published rates live in the catalog and on pricing.

Failed renders are free. If a provider errors before producing an image, INFRO retries on another provider — and then on each model in fallbacks — and you are billed only for what came back. Failover is invisible to your code; only the provider field in the response changes.

Errors

  • 400 invalid_request_error — unsupported size or aspect ratio, a prompt over the model's limit, a mask whose dimensions differ from the image, or a malformed upload.
  • 402 insufficient_credits — the estimated cost of the request exceeds your balance. Nothing is rendered and nothing is charged.
  • 429 rate_limit_exceeded — retry with backoff; see Rate & spend limits.
  • 503 no_available_provider — every provider for model, and every entry in fallbacks, is unavailable. Widen fallbacks or retry.

Every status code and the full error body are documented in Errors.