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.
POST https://api.infro.io/v1/images/generations
POST https://api.infro.io/v1/images/editsRequest body
modelstringrequired- Image model ID in
vendor/model-nameform, e.g.bfl/flux-2-pro,ideogram/ideogram-3, orgoogle/imagen-4-ultra. Browse IDs and per-image prices in the catalog. promptstringrequired- What to render. Prompt conventions differ by model —
recraft/recraft-v3responds to style keywords,ideogram/ideogram-3is the strongest at rendering text inside the image. Length limits are per model. ninteger- How many images to return,
1–10. Defaults to1. Models that can only render one image per upstream call are fanned out into parallel requests; you are billed per image either way. sizestringWIDTHxHEIGHT, e.g.1024x1024. Defaults to the model's native square resolution. See the size table below.qualitystringstandard(default) orhigh.highspends more compute per image and costs more. Models without a quality tier ignore it.response_formatstringurl(default) returns a hosted link;b64_jsonreturns the image inline as base64. Base64 payloads are several megabytes each — preferurlunless 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
modelfails, e.g.["bfl/flux-2-dev", "qwen/qwen-image"]. See Failover & fallbacks. loggingboolean- Set
falseto 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
{
"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
nullwhenresponse_formatisb64_json. Valid for 24 hours. data[].b64_jsonstring- Base64-encoded image bytes, or
nullwhenresponse_formatisurl. 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
non 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 chairworks better thanreplace 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:
| Size | Ratio | Typical use |
|---|---|---|
1024x1024 | 1:1 | Avatars, product shots, grid thumbnails |
1536x1024 | 3:2 | Blog headers and landscape hero images |
1024x1536 | 2:3 | Posters, print, portrait cards |
1792x1024 | 16:9 | Slides, video thumbnails, wide banners |
1024x1792 | 9:16 | Stories 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 formodel, and every entry infallbacks, is unavailable. Widenfallbacksor retry.
Every status code and the full error body are documented in Errors.