Headline price per image is a poor first filter. Two models at the same nominal rate can differ in whether they accept reference images, whether they support masked edits, how output size is selected, and whether the charge is per request or per token. Filter candidates by capability first, then compare cost per accepted output on your own prompts.
This article is a selection framework for image generation APIs. It covers image generation, not video. Where a pipeline needs both, the same async and billing mechanics apply, but video is out of scope here.
Step 1: Match the supported operation
The first elimination round is operational. An endpoint that generates from text alone cannot do a masked edit, and a model built for inpainting is not a general prompt-to-image workhorse.
On TokenLab, generation and editing are usually different endpoints:
| What you need | Endpoint | Notes |
|---|---|---|
| Text-to-image | POST /v1/images/generations |
The request starts from a prompt only |
| Image-to-image / reference-driven generation | POST /v1/images/generations |
Models that accept operation: "image-to-image" plus reference URLs |
| Masked or multipart edit | POST /v1/images/edits |
Models that document an edit flow |
| Variation of an existing image | POST /v1/images/variations |
For integrations that already use the variations shape |
| Task status | GET /v1/tasks/{id} |
When a create response returns task_id, status: "pending", or poll_url |
See the image generation guide for the decision table and the Create Image and Edit Image references for request fields.
One routing rule causes a disproportionate number of failures: Nano Banana reference-image requests (nano-banana-2, nano-banana-pro) go to /v1/images/generations with operation: "image-to-image" and image_urls, not to /v1/images/edits. Conversely, gpt-image-2 edits belong on /v1/images/edits, where it accepts multipart image uploads, JSON image_url / image_urls, and images[] references with up to 16 source images.
Useful groupings from the current TokenLab catalog:
- Both generate and edit:
flux-2-klein-4b,flux-2-klein-9b,flux-2-pro,flux-2-flex,flux-2-max,flux-kontext-pro,flux-kontext-max,gemini-3-pro-image,gemini-3.1-flash-image,nano-banana-2,nano-banana-2-lite,nano-banana-pro,gpt-image-2,gpt-image-2.5-flare,gpt-image-2.5-sunburst,grok-imagine-image,grok-imagine-image-quality,grok-imagine-image-2.0,qwen-image-2.0,qwen-image-2.0-pro,qwen-image-3.0,seedream-4.0,seedream-4.5,seedream-5.0,seedream-5.0-lite,seedream-5.0-pro,vidu-image-lite,vidu-image-pro. - Text-to-image only:
flux-1-dev,flux-pro-1.1,flux-pro-1.1-ultra,sd3.5-medium,sd3.5-large,sd3.5-large-turbo,sd3.5-flash,stable-image-core,stable-image-ultra,z-image,z-image-turbo,kling-image,kling-omni-image,hy-image-lite. - Specialist edit tools:
stability-inpaint,stability-control-sketch,stability-control-structure,stability-style-guide,stability-upscale-fast,stability-upscale-conservative,image-upscaler,image-background-remover,flux-pro-1.0-fill,qwen-image-edit.
Verify operations per model rather than per family. GET /v1/models?recommended_for=image returns the current recommended set, and the Get a Model reference shows the supported_operations field that tells you what a specific ID accepts.
Step 2: Check how the model accepts reference images
Reference-image handling is where integrations break. The field names are not interchangeable:
image_url— a single reference image.image_urls— one or more references in JSON.reference_image_urls— additional references for models that separate primary inputs from references.image— a multipart file upload, for private or header-protected source images.images[]withimage_urlorfile_id— an edit-flow shape; not accepted on/v1/images/generations.
Constraints worth designing around, from the API reference:
- Remote references must be public
http/httpsURLs, without embedded credentials or fragments, and must not resolve to localhost, private, or reserved IP ranges. Each redirect is re-checked. - URL-fetched images: 50 MiB per image, 200 MiB aggregate per request (including the mask), 30s fetch timeout, up to 3 redirects. The fetched payload must be a real PNG, JPEG, or WebP.
- Source-image caps differ:
gpt-image-2accepts up to 16; the documented 3-input-image cap applies specifically togrok-imagine-imageandgrok-imagine-image-quality(which fail with400 too_many_imagesabove 3) and is not documented forgrok-imagine-image-2.0. - A
maskmust be a PNG smaller than 50 MiB with the same dimensions as the source image.
If your source images are private, plan for multipart upload or a /v1/files reference rather than passing an expiring signed URL. A signed URL that expires before processing starts is a rejected input, not a generation failure.
Step 3: Compare output controls, not just model names
Two models in the same tier can expose completely different size and quality controls. Confirm the selector contract before you build a UI around it.
| Control | What to check |
|---|---|
size |
OpenAI-style families accept auto or WIDTHxHEIGHT. For gpt-image-2, dimensions must be multiples of 16, the longest edge at most 3840px, the long/short ratio at most 3:1, and total pixels between 655,360 and 8,294,400 |
aspect_ratio |
Google image families and Grok Imagine use 1:1, 16:9, 9:16, 3:2, 2:3 and similar values |
resolution |
gemini-3.1-flash-image, gemini-3-pro-image, nano-banana-2, and nano-banana-pro support 1k, 2k, 4k, while nano-banana-2-lite only supports 1k. Grok Imagine supports 1k and 2k |
quality |
GPT Image models use auto, low, medium, high. Other models may use different values |
n |
Number of images per request, model dependent |
response_format |
url or b64_json. Async tasks return URLs regardless of the requested format |
background, output_format, output_compression |
Documented for gpt-image-2; transparent is not supported |
async |
Supported for gpt-image-2 and official FLUX/BFL image models |
Sending an undocumented field is not harmless. input_fidelity, for example, is not part of the current supported fields for gpt-image-2 and returns 400 unsupported_parameter. Unsupported fields on other models fail similarly. The full field list is in the Create Image reference.
Step 4: Identify the billing unit before comparing anything
Cost comparisons go wrong when a per-token model is compared against a per-image model as if they were the same unit.
gpt-image-2is token-priced. TokenLab follows the maker's usage breakdown for text input, image input, reported cached input, and image output tokens; it is not billed as a fixed per-image model.- Most other image models are priced per request, per image, or per other unit shown on the model page.
The practical consequence: for gpt-image-2, the same prompt at the same nominal settings can cost differently depending on resolution, quality, and the prompt itself, because output token volume changes. Measure before you commit to a routing rule.
Read the current billing unit and price at request time rather than hard-coding a table:
- Billing and pricing explains how charges, estimates, and async reservation work.
- Get a Model returns
tokenlab.pricingandtokenlab.pricing_unitfor a single model. - List Models returns the catalog with
tokenlab.pricing,tokenlab.capabilities, andtokenlab.deliveryAvailability. - The Models page shows the same information for browsing.
A dash in the TokenLab price column means no TokenLab Verified offer is currently available for that model, not that the model is free. Models with Official supply can still be reached through the Official or Auto delivery option.
Step 5: Decide synchronous versus task-based flow
High-resolution image requests can take close to a minute or longer. Set your HTTP client timeout to at least 120s for synchronous calls, or use the task flow.
- Send
async: truewithgpt-image-2or official FLUX/BFL image models to get atask_idandpoll_urlinstead of a finished image. - Do not hard-code a model as always synchronous or always asynchronous. Check the create response: if it contains
status: "pending",task_id, orpoll_url, follow the returnedpoll_url. - Statuses are
pending,processing,completed, andfailed. A successful status read returns HTTP 200 even when the task has failed; use thestatusfield, not the HTTP code. - Async image results are returned as URLs. If you need raw
b64_json, use a synchronous request. - Poll every few seconds and stop at a terminal status. Generated image HTTP(S) result URLs may be retained as media copies for 30 days; check
media_retention.itemsfor each item's status andexpires_at.
Details are in the async jobs and polling guide and the Get Image Status reference.
Retries are a billing risk, not just a latency risk. A create request retried after a timeout can produce a second task and a second charge. Store request_id, task_id, and any billing_transaction_id, and check whether a task was created before retrying.
Step 6: Evaluate on your own prompt set
No vendor-neutral quality ranking is included in this article, and none should be taken from marketing copy. Justify the choice with a measurement on your workload:
- Assemble a fixed prompt set that reflects your production distribution — the subjects, styles, and instruction shapes you actually receive. Generic demo prompts will not separate models for you.
- Run the same set across your candidate models at the same settings, and log generation time per request including retries.
- Score outputs with a fixed rubric, either automated or a human review panel, rather than eyeballing samples.
- Compute cost per accepted image, not cost per generated image. A cheaper model that needs two attempts per usable output is not cheaper.
- If your product is latency-sensitive, record percentiles rather than averages, since the tail is what users notice.
- Re-run the comparison when you change providers or resolution targets, because both pricing units and model behavior can change.
Cost per accepted image is the only number that answers whether a more expensive model is worth its rate for your workload.
Illustrative request
The following is an illustrative example of the generation call shape, not a measured result. It uses a model that exposes aspect_ratio and resolution.
curl https://api.tokenlab.sh/v1/images/generations \
-H "Authorization: Bearer $TOKENLAB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-3-pro-image",
"prompt": "A cinematic portrait of a white cat sitting on a rainy windowsill",
"aspect_ratio": "16:9",
"resolution": "2k"
}'
If that response comes back with status: "pending", poll the returned poll_url rather than treating it as a failure.
Model access is not uniform across API formats. TokenLab accepts Chat Completions, Responses, Anthropic Messages, and Gemini request shapes, and a given model may support only some of them. Check tokenlab.accepted_request_formats on the model before reusing an existing client — see API formats.
Limits of this article
- No independent quality benchmark, latency measurement, or throughput figure for any image model is included here. Vendor positioning about anatomy, text rendering, or photorealism is not reproduced as fact.
- No price is quoted. Image model pricing units differ and change; read the current value from the Models page or
GET /v1/models/{model}. - Model availability varies by delivery option and workspace.
tokenlab.deliveryAvailabilitydescribes configured support; it does not guarantee real-time availability, which is checked when a request runs. - Public region restrictions apply.
Related reading
- Image generation guide
- Create Image and Edit Image
- Async jobs and polling
- Billing and pricing
- List Models and Get a Model
- API formats
- Current model list and prices: Models page
Sources
- https://docs.tokenlab.sh/guides/image-generationSources checked 2026-09-27
- https://docs.tokenlab.sh/api-reference/images/create-imageSources checked 2026-09-27
- https://docs.tokenlab.sh/api-reference/images/edit-imageSources checked 2026-09-27
- https://docs.tokenlab.sh/api-reference/models/get-modelSources checked 2026-09-27
- https://docs.tokenlab.sh/guides/billingSources checked 2026-09-27
- https://docs.tokenlab.sh/api-reference/models/list-modelsSources checked 2026-09-27
- https://tokenlab.sh/models
- https://docs.tokenlab.sh/guides/async-jobs-pollingSources checked 2026-09-27



