Generate Images
November 17, 2025 (June 15, 2026)
Table of contents
Generate images using AI models Imagen 4, Nano Banana / Gemini 2.5 Flash Image, Nano Banana 2 / Gemini 3.1 Flash Image, and Nano Banana Pro / Gemini 3 Pro Image from text prompts with optional reference images. Use any Google AI subscription or even free account for image generations.
This endpoint features dynamic concurrency management, allowing anywhere from 3 to 20 parallel generations depending on real-time capacity. Image generation typically completes within 10-20 seconds.
Model Capabilities
| Parameter | Imagen 4imagen-4 (default) | Nano Banana 2nano-banana-2 | Nano Banana Pronano-banana-pro |
|---|---|---|---|
| T2I (text-to-image) | ✓ | ✓ | ✓ |
| I2I (reference images) | ✓ (max 3) | ✓ (max 10) | ✓ (max 10) |
| Aspect ratios | 16:9, 4:3, 1:1, 3:4, 9:16 | 16:9, 4:3, 1:1, 3:4, 9:16, auto† | 16:9, 4:3, 1:1, 3:4, 9:16, auto† |
| Default aspect ratio | 16:9 | 16:9 (T2I) / auto (I2I) | 16:9 (T2I) / auto (I2I) |
count | ✓ (1-4) | ✓ (1-4) | ✓ (1-4) |
seed | ✓ | ✓ | ✓ |
| Subscription | all | all | all |
† auto is only valid in image-to-image mode (at least one reference_* provided) — the backend derives the aspect ratio from the first reference image.
Legacy alias nano-banana is still accepted and maps to nano-banana-2.
Content Moderation
If your generation is moderated, retrying with the same prompt often succeeds on subsequent attempts — moderation decisions can vary between requests. Alternatively, switching between imagen-4, nano-banana-2, and nano-banana-pro models may help, as each has different content-moderation behavior.
https://api.useapi.net/v1/google-flow/images
Request Headers
Authorization: Bearer {API token}
Content-Type: application/json
# Alternatively you can use multipart/form-data
# Content-Type: multipart/form-data
API tokenis required, see Setup useapi.net for details.
Request Body
{
"prompt": "A serene mountain landscape at sunset with vibrant colors",
"model": "imagen-4",
"aspectRatio": "16:9",
"count": 4,
"seed": 123456
}
-
emailis optional. The email address of the Google Flow account to use.When only one account is configured, the API will automatically use that account.
With multiple accounts configured, omitting the email parameter triggers automatic load balancing based on image generation job statistics to select the healthiest account.
If reference images (
reference_1to_10) are provided, theemailparameter can be omitted—the API will automatically use the same account where the images were uploaded. promptis required, text description for image generation.modelis optional, the AI model to use for image generation (default:imagen-4).
Supported values:imagen-4,nano-banana-2,nano-banana-pro. Legacy aliasnano-bananais still accepted and maps tonano-banana-2.aspectRatiois optional, output image aspect ratio. Supported values:16:9,4:3,1:1,3:4,9:16,auto. Legacy aliaseslandscape(→16:9) andportrait(→9:16) are still accepted.autois only valid withnano-banana-2ornano-banana-prowhen at least onereference_*is provided — the backend derives the aspect ratio from the first reference image. Default:- text-to-image (no references):
16:9 imagen-4image-to-image:16:9nano-banana-2/nano-banana-proimage-to-image:auto
- text-to-image (no references):
countis optional, number of image variations to generate (1-4, default:4).seedis optional, random seed for reproducible results (integer ≥ 0).reference_1toreference_10are optional, usemediaGenerationIdfrom POST /assets/emailfor reference images.imagen-4supports max 3 references,nano-banana-2andnano-banana-prosupport up to 10.character_1tocharacter_7are optional, character reference-ids from POST /characters. Characters mix freely withreference_*— they share the same per-model image-ref budget on Google’s side (per-character image counts roll into the total). Imagen models that don’t accept reference images also don’t accept characters.replyUrlis optional, webhook URL for job status callbacks. Receives POST requests with job status updates (created,completed,failed). The JSON payload shape matches GET /jobs/jobIdresponse. Callbacks timeout after 5 seconds.replyRefis optional, custom reference string passed back in webhook callbacks. Useful for tracking jobs on your end.captchaToken,captchaRetry,captchaOrderare optional, mutually exclusive captcha parameters. See Captcha Parameters for details.
Auto-detection: If model is not specified: with references selects nano-banana-2, without references defaults to imagen-4.
Inline @-mention markers (optional)
You can place @-markers inside prompt that resolve to the body parameters you supply. Markers are case-insensitive and opt-in — a prompt with no markers behaves exactly like before.
Supported markers:
| Marker | Resolves to |
|---|---|
@character_1..7 | matching character_N body param |
@reference_1..10 | matching reference_N body param |
Rules:
- Each marker MUST have a matching body slot supplied. Otherwise the API returns 400 with
'character_N' was not provided in the request body. - A slot referenced inline still goes into the upstream reference array — markers are positional/grounding info, not a replacement for the body params.
- Same slot may be inlined multiple times; the upstream reference array de-duplicates by id.
- Body params supplied but NOT inlined still flow to the upstream reference array (unchanged behavior).
- Unknown strings like
@gmail.comor@anyword_1(no_<digit>after a recognized slot name) pass through as literal prompt text.
Example:
{
"model": "nano-banana-pro",
"prompt": "@character_1 standing next to @reference_1, golden hour light",
"character_1": "user:123-email:...-character:...-imgs:1",
"reference_1": "user:123-email:...-image:..."
}
Responses
-
Images generated successfully. Returns job ID and media array with generated image data.
{ "jobId": "j1731859345678i-u12345-email:jo***@gmail.com-bot:google-flow", "media": [ { "name": "…redacted…", "workflowId": "…redacted…", "image": { "generatedImage": { "seed": 123456, "mediaGenerationId": "user:12345…redacted…", "mediaVisibility": "PRIVATE", "prompt": "A serene mountain landscape at sunset with vibrant colors", "modelNameType": "IMAGEN_3_5", "workflowId": "…redacted…", "fifeUrl": "https://storage.googleapis.com/…redacted…", "aspectRatio": "IMAGE_ASPECT_RATIO_LANDSCAPE", "requestData": { "promptInputs": [ { "textInput": "A serene mountain landscape at sunset with vibrant colors" } ], "imageGenerationRequestData": { "imageGenerationImageInputs": [] } } } } } ], "captcha": { "service": "AntiCaptcha", "taskId": "abc123...", "durationMs": 3500, "attempts": [ { "service": "AntiCaptcha", "taskId": "abc123...", "durationMs": 3500, "success": true } ] } } -
Invalid request (validation error, reference count exceeded, email mismatch, or content policy violation).
General error:
{ "error": "Invalid request parameters" }Content policy error:
{ "error": { "code": 400, "message": "Request contains an invalid argument.", "status": "INVALID_ARGUMENT", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "PUBLIC_ERROR_UNSAFE_GENERATION" } ] } } -
Invalid API token.
{ "error": "Unauthorized" } -
Subscription expired or insufficient credits.
{ "error": "Account has no subscription or subscription expired" } -
Request rejected by Google — the reCAPTCHA token was outright rejected (not just scored low). After internal retries with fresh tokens, the worker returns this. The top-level
errorfield carries acaptcha_quality:prefix so tooling can detect this failure class. IncreasecaptchaRetry(default 3) in the request body to 5 or higher, and configure additional providers via POST /accounts/captcha-providers socaptchaOrdercan cycle across them. If issues persist, contact your reCAPTCHA provider(s) support. -
Account not found or not configured.
{ "error": "Google Flow account [email protected] not found" } -
Google returns several
RESOURCE_EXHAUSTED429 variants. Check thereasonfield and respond accordingly:Reason Meaning Scope What to do Cooldown PUBLIC_ERROR_USER_REQUESTS_THROTTLEDPer-user concurrency limit (the token was fine) All models on the account Run fewer parallel requests, retry later ~30 min PUBLIC_ERROR_USER_QUOTA_REACHEDAccount’s overall Flow quota cap All models on the account Add accounts, or omit emailto load-balance~30 min PUBLIC_ERROR_PER_MODEL_DAILY_QUOTA_REACHEDPer-model daily quota Only that model, on that account Switch model, or wait Next UTC midnight PUBLIC_ERROR_UNUSUAL_ACTIVITY_TOO_MUCH_TRAFFICCaptcha-provider issue — low reCAPTCHA score (worker already auto-retried) Per request Add more captcha providers + captchaOrder, or raisecaptchaRetry60s Every
429returns the cooldown two ways — an HTTPRetry-After: <seconds>header and a bodyretryAfter: <ISO timestamp>field. Honor it before retrying.When
emailis omitted, the first three reasons quarantine the account and the load balancer routes around it. If every account is quarantined for the model you get429witherror: "no_eligible_account". Routing details: GET /jobs › Load Balancing Algorithm.Captcha-quality failures prefix the top-level
errorwithcaptcha_quality:(e.g."captcha_quality: PUBLIC_ERROR_UNUSUAL_ACTIVITY_TOO_MUCH_TRAFFIC after 3 attempts") so you can detect them without parsing the nested body. -
One or more generated images were moderated by Google’s content policy. Try one of the following:
- Switch to
imagen-4model (often successfully processes prompts rejected bynano-banana) - Modify your prompt or remove/change reference images
- Retry the same request (moderation decisions can vary between attempts)
{ "error": { "code": 500, "message": "Internal error encountered.", "status": "INTERNAL" } } - Switch to
-
503has two distinct causes — check the response body to tell them apart.A transient Google-side outage. Wait 5-10 seconds and retry.
{ "error": { "code": 503, "message": "Service temporarily unavailable.", "status": "UNAVAILABLE" } }A captcha-provider failure — the top-level
erroris prefixedCaptcha service failed:. The problem is your captcha provider (check its API key and balance), not Google. Don’t retry until the provider is back.{ "error": "Captcha service failed: ERROR_ZERO_BALANCE", "code": 503 } -
596 Session Error
Google session refresh failed. The account cookies needs to be updated following the instructions in Setup Google Flow.
{ "error": "Failed to refresh session." }
Model
jobId- Unique job identifier (for use with GET /jobs/jobId)media- Array of generated images (1-4 images based oncount)media[].image.generatedImage- Generated image data objectgeneratedImage.fifeUrl- Direct signed URL to access the generated image (valid for limited time)generatedImage.seed- Seed used for this generation (for reproducibility)generatedImage.mediaGenerationId- mediaGenerationId for use in subsequent API callsgeneratedImage.prompt- The prompt used for generationgeneratedImage.modelNameType- Model variant used (IMAGEN_3_5,R2I,GEM_PIX,GEM_PIX_2,NARWHAL)generatedImage.aspectRatio- Generated image aspect ratio (IMAGE_ASPECT_RATIO_LANDSCAPE,IMAGE_ASPECT_RATIO_LANDSCAPE_FOUR_THREE,IMAGE_ASPECT_RATIO_SQUARE,IMAGE_ASPECT_RATIO_PORTRAIT_THREE_FOUR, orIMAGE_ASPECT_RATIO_PORTRAIT)generatedImage.mediaVisibility- Visibility setting (always “PRIVATE”)generatedImage.workflowId- Unique workflow identifiergeneratedImage.requestData- Request data used for this generation including prompt inputs and reference imagesmedia[].name- Internal identifier for the media itemmedia[].workflowId- Unique workflow identifier for this generationcaptcha- Captcha metadata for debugging/researchcaptcha.service- Provider that returned the successful tokencaptcha.taskId- Task ID from the captcha servicecaptcha.durationMs- Total time for all captcha attemptscaptcha.attempts- Array of all captcha attempts (including failures)
{
jobId: string // Job identifier
media: Array<{
name: string // Internal media identifier
workflowId: string // Unique workflow ID
image: {
generatedImage: {
seed: number
mediaGenerationId: string // Format: user:{userid}-email:{hex}-image:{id}
mediaVisibility: string // "PRIVATE"
prompt: string
modelNameType: string // "IMAGEN_3_5" | "R2I" | "GEM_PIX" | "GEM_PIX_2" | "NARWHAL"
workflowId: string
fifeUrl: string // Direct signed URL to generated image
aspectRatio: string // "IMAGE_ASPECT_RATIO_LANDSCAPE" | "IMAGE_ASPECT_RATIO_LANDSCAPE_FOUR_THREE" | "IMAGE_ASPECT_RATIO_SQUARE" | "IMAGE_ASPECT_RATIO_PORTRAIT_THREE_FOUR" | "IMAGE_ASPECT_RATIO_PORTRAIT"
requestData: {
promptInputs: Array<{
textInput: string
}>
imageGenerationRequestData: {
imageGenerationImageInputs: Array<{
mediaGenerationId: string
imageInputType: string // "IMAGE_INPUT_TYPE_REFERENCE"
}>
}
}
}
}
}>
captcha?: { // Captcha metadata
service: string // "CapSolver" | "AntiCaptcha" | "YesCaptcha" | "CapMonster" | "SolveCaptcha" | "2Captcha" | "EzCaptcha" | "UserProvided"
taskId?: string
durationMs: number
attempts: Array<{
service: string
taskId?: string
durationMs: number
success: boolean
error?: string
}>
}
error?: string | { // Error: string (useapi.net) or object (Google API)
code: number
message: string
status: string
details: Array<{
'@type': string
reason: string
metadata?: {
canUpgradeForQuota: boolean
}
}>
}
// The following siblings appear only on the load-balancer empty-set 429,
// i.e. when error === "no_eligible_account" (see 429 response tab).
message?: string // Customer-facing explanation
retryAfter?: string // ISO-8601 timestamp of earliest retry
skipReasons?: Array<{ // Per-account filter rationale
email: string
reason: string // Google 429 reason that triggered the quarantine
model: string // Quarantined model, or "*" for account-wide
}>
}
Examples
-
curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "prompt": "A serene mountain landscape at sunset with vibrant colors", "model": "imagen-4", "aspectRatio": "16:9", "count": 4, "seed": 123456 }' \ "https://api.useapi.net/v1/google-flow/images" > response.json # Download images using fifeUrl curl -o image_1.jpg "$(cat response.json | jq -r '.media[0].image.generatedImage.fifeUrl')" curl -o image_2.jpg "$(cat response.json | jq -r '.media[1].image.generatedImage.fifeUrl')" # Continue for remaining images... -
const token = 'YOUR_API_TOKEN'; const apiUrl = 'https://api.useapi.net/v1/google-flow/images'; const response = await fetch(apiUrl, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt: 'A serene mountain landscape at sunset with vibrant colors', model: 'imagen-4', aspectRatio: '16:9', count: 4, seed: 123456 }) }); const result = await response.json(); console.log('Generated images:', result.media.length); // Download and save images for (const [index, item] of result.media.entries()) { const img = item.image.generatedImage; console.log(`Image ${index + 1} seed:`, img.seed); console.log(`mediaGenerationId:`, img.mediaGenerationId); // Download image from fifeUrl const imageResponse = await fetch(img.fifeUrl); const imageBlob = await imageResponse.blob(); // In Node.js with fs: // const buffer = Buffer.from(await imageBlob.arrayBuffer()); // require('fs').writeFileSync(`generated_image_${index + 1}.jpg`, buffer); // In browser: create download link or display in <img> element // const url = URL.createObjectURL(imageBlob); // document.querySelector('img').src = url; } -
import requests token = 'YOUR_API_TOKEN' api_url = 'https://api.useapi.net/v1/google-flow/images' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } data = { 'prompt': 'A serene mountain landscape at sunset with vibrant colors', 'model': 'imagen-4', 'aspectRatio': '16:9', 'count': 4, 'seed': 123456 } response = requests.post(api_url, headers=headers, json=data) result = response.json() print(f"Generated {len(result['media'])} images") # Download and save images for index, item in enumerate(result['media']): img = item['image']['generatedImage'] print(f"Image {index + 1} seed:", img['seed']) print(f"mediaGenerationId:", img['mediaGenerationId']) # Download image from fifeUrl image_response = requests.get(img['fifeUrl']) with open(f'generated_image_{index + 1}.jpg', 'wb') as f: f.write(image_response.content)