=== URL: https://useapi.net/docs/start-here/setup-google-flow === Document URL: https://useapi.net/docs/start-here/setup-google-flow --- layout: default title: Setup Google Flow parent: Start Here nav_order: 205 --- # Google Flow {: .no_toc } November 17, 2025 (January 2, 2026) ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} Approximately 15 minutes to complete setup steps. --- [Google Flow](https://labs.google/fx/tools/flow) creates cinematic AI clips with [Veo](https://aistudio.google.com/models/veo-3), images with [Imagen 4](https://deepmind.google/technologies/imagen-3/) and [Nano Banana / Gemini 2.5 Flash Image](https://deepmind.google/technologies/gemini/flash/). ### Create a dedicated Gmail account ⚠️ **Use a dedicated Gmail account for this API - do NOT use your personal Gmail account.** If you already have a dedicated Gmail account for AI/API services, you can use that. Otherwise, create a new one. When creating a new account: 1. Enable [2-Step Verification](https://support.google.com/accounts/answer/185839) 2. Use [Google Authenticator](https://support.google.com/accounts/answer/1066447) for verification codes ### Clear all browser cookies ⚠️ **Do NOT use Google Chrome.** Google's integration with Chrome will interfere with cookie extraction. **Use one of these browsers instead:** - [Opera](https://www.opera.com/) ← Recommended (has built-in VPN) - [Brave](https://brave.com/) - [Ungoogled Chromium](https://github.com/ungoogled-software/ungoogled-chromium) If using Opera, enable VPN and set region to Americas. **You must clear ALL cookies before proceeding** to start with a fresh session. Open browser settings and select `Delete browsing data...` `1` ![](../../assets/images/google-flow-setup-1.jpg) Select time range to be `All time` `1` and check `Cookies and other site data` `2`, click `Delete data` `3` ![](../../assets/images/google-flow-setup-2.jpg) ### Navigate to Google Flow and login with your Gmail account Navigate to [https://labs.google/fx/tools/flow](https://labs.google/fx/tools/flow) and click on `Sign in with Google` button `1` ![](../../assets/images/google-flow-setup-3.jpg) Enter your Google email created earlier `1` ![](../../assets/images/google-flow-setup-4.jpg) Enter 2-Step Verification code `1` ⚠️ **You MUST check `Don't ask again on this device`** `2` - skipping this will break the API session. ![](../../assets/images/google-flow-setup-5.jpg) Once successfully logged in you should see `New project` button ![](../../assets/images/google-flow-setup-6.jpg) ### Navigate to Google Account Navigate to [https://myaccount.google.com/](https://myaccount.google.com/) ![](../../assets/images/google-flow-setup-7.jpg) ### Copy `https://accounts.google.com/` cookies 1. **Open Developer Tools:** right-click anywhere on page → select `Inspect` (or press `F12`) ![](../../assets/images/google-flow-setup-8.jpg) 2. **Go to Application tab** `1` 3. **Select Cookies** → `https://accounts.google.com/` `2` 4. **Select all cookies** in the right panel (`Ctrl+A`) and **copy** (`Ctrl+C`) `3` ![](../../assets/images/google-flow-setup-9.jpg) Your copied cookies will look similar to this (values redacted): ![](../../assets/images/google-flow-setup-10.jpg) ### Verify `cookies` value Paste your cookies below and click **Go** to verify. You should receive HTTP `200` if successful. ⚠️ **This step only VERIFIES your cookies - it does NOT add your account!** After successful verification, you **MUST** proceed to [POST /accounts](../api-google-flow-v1/post-google-flow-accounts) to actually add and configure your Google Flow API account. ⚠️ **CRITICAL - Do this immediately after successful verification:** 1. Open a new empty tab 2. Close all other tabs 3. [Clear all browser cookies](#clear-all-browser-cookies) 4. **Do NOT restart the browser** ⚠️ **The API now manages this Google account session.** Do NOT access this Google account via AI Studio or Google Flow directly (browser or any other means). Using the same account through both the API and direct access will break the session and require you to redo this entire setup.
### Configure Captcha Providers Image and video generation requires reCAPTCHA v3 Enterprise solving. **Users receive 100 free captcha credits** when adding their first Google Flow account. These credits are used automatically, so you can start generating images and videos right away without configuring any provider. Check your remaining credits via [GET /accounts/captcha-providers](../api-google-flow-v1/get-google-flow-accounts-captcha-providers). After free credits are exhausted, you must configure at least one provider's API key before using [POST /images](../api-google-flow-v1/post-google-flow-images), [POST /images/upscale](../api-google-flow-v1/post-google-flow-images-upscale), or [POST /videos](../api-google-flow-v1/post-google-flow-videos). **Supported Providers:** | Provider | Cost | Website | |----------|------|---------| | **EzCaptcha** | ~$2.50 per 1,000 solves | [ez-captcha.com](https://www.ez-captcha.com/) | | **CapSolver** | ~$3.00 per 1,000 solves | [capsolver.com](https://www.capsolver.com/) — use promo code `useapi` for 8% discount | | **YesCaptcha** | varies | [yescaptcha.com](https://yescaptcha.com/) | **Setup Steps:** 1. Create an account with one or more providers above 2. Purchase credits and obtain your API key from the provider's dashboard 3. Configure your API key(s) using [POST /accounts/captcha-providers](../api-google-flow-v1/post-google-flow-accounts-captcha-providers) **Tips:** - Use [GET /accounts/captcha-stats?anonymized=true](../api-google-flow-v1/get-google-flow-accounts-captcha-stats) to compare success rates across providers and choose the best one for your needs. Note that provider performance may vary over time. - Configure multiple providers for redundancy (if one fails or returns rejected tokens, the API automatically retries with the next provider) - Each image/video generation attempt requires one captcha solve (~$2.50-$3.00 per 1,000 generations) === URL: https://useapi.net/docs/api-google-flow-v1/delete-google-flow-accounts-email === Document URL: https://useapi.net/docs/api-google-flow-v1/delete-google-flow-accounts-email --- layout: default title: DELETE accounts/email parent: Google Flow API v1 nav_order: 400 --- ## Delete Account Configuration {: .no_toc } November 17, 2025 ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Delete a configured Google Flow account. This removes the account from your configuration and cancels any scheduled refresh operations. **Warning:** This action cannot be undone. You will need to reconfigure the account using [POST /accounts](https://useapi.net/docs/api-google-flow-v1/post-google-flow-accounts) if you want to use it again. {: .delete } > **https://api.useapi.net/v1/google-flow/accounts/`email`** ### Request Headers ``` yaml Authorization: Bearer {API token} ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Path Parameters - `email` is **required**. The email address of the Google Flow account to delete (URL-encoded if necessary). ### Responses {% tabs v1_delete_accounts_response %} {% tab v1_delete_accounts_response 200 %} 200 OK Account deleted successfully. ```json { "message": "Google Flow account john@gmail.com deleted" } ``` {% endtab %} {% tab v1_delete_accounts_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% tab v1_delete_accounts_response 404 %} 404 Not Found Account not found or not configured. ```json { "error": "Google Flow account john@gmail.com not found" } ``` {% endtab %} {% endtabs %} ### Examples {% tabs v1_delete_accounts_example %} {% tab v1_delete_accounts_example Curl %} ``` bash curl -X DELETE \ -H "Authorization: Bearer YOUR_API_TOKEN" \ "https://api.useapi.net/v1/google-flow/accounts/john%40gmail.com" ``` {% endtab %} {% tab v1_delete_accounts_example JavaScript %} ``` javascript const token = 'YOUR_API_TOKEN'; const email = 'john@gmail.com'; const response = await fetch( `https://api.useapi.net/v1/google-flow/accounts/${encodeURIComponent(email)}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${token}` } } ); const result = await response.json(); console.log('Delete result:', result); ``` {% endtab %} {% tab v1_delete_accounts_example Python %} ``` python import requests from urllib.parse import quote token = 'YOUR_API_TOKEN' email = 'john@gmail.com' headers = {'Authorization': f'Bearer {token}'} response = requests.delete( f'https://api.useapi.net/v1/google-flow/accounts/{quote(email)}', headers=headers ) print('Delete result:', response.json()) ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts-captcha-providers === Document URL: https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts-captcha-providers --- layout: default title: GET …/captcha-providers parent: Google Flow API v1 nav_order: 420 --- ## Get Captcha Providers {: .no_toc } December 23, 2025 (January 2, 2026) ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Retrieve configured captcha provider API keys (masked for security). {: .get } > **https://api.useapi.net/v1/google-flow/accounts/captcha-providers** ### Request Headers ``` yaml Authorization: Bearer {API token} ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Responses {% tabs v1_get_captcha_providers_response %} {% tab v1_get_captcha_providers_response 200 %} 200 OK Returns masked keys for all configured providers. **With providers configured:** ```json { "EzCaptcha": "abc12…", "CapSolver": "def34…" } ``` **No providers configured (shows free credits if available):** ```json { "freeCaptchaCredits": 100 } ``` {% endtab %} {% tab v1_get_captcha_providers_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% endtabs %} ### Model ```typescript { // TypeScript, all fields are optional EzCaptcha?: string // Masked API key or omitted if not configured CapSolver?: string // Masked API key or omitted if not configured YesCaptcha?: string // Masked API key or omitted if not configured freeCaptchaCredits?: number // Remaining free credits (only shown when no providers configured) } ``` **Note:** `freeCaptchaCredits` is only included in the response when: - No captcha providers are configured, AND - The user has remaining free credits (> 0) ### Examples {% tabs v1_get_captcha_providers_example %} {% tab v1_get_captcha_providers_example Curl %} ``` bash curl -H "Accept: application/json" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ "https://api.useapi.net/v1/google-flow/accounts/captcha-providers" ``` {% endtab %} {% tab v1_get_captcha_providers_example JavaScript %} ``` javascript const apiUrl = 'https://api.useapi.net/v1/google-flow/accounts/captcha-providers'; const token = 'YOUR_API_TOKEN'; const response = await fetch(apiUrl, { headers: { 'Authorization': `Bearer ${token}` } }); const result = await response.json(); console.log('Configured providers:', result); ``` {% endtab %} {% tab v1_get_captcha_providers_example Python %} ``` python import requests apiUrl = 'https://api.useapi.net/v1/google-flow/accounts/captcha-providers' token = 'YOUR_API_TOKEN' headers = { 'Authorization': f'Bearer {token}' } response = requests.get(apiUrl, headers=headers) print(response.status_code, response.json()) ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts-captcha-stats === Document URL: https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts-captcha-stats --- layout: default title: GET …/captcha-stats parent: Google Flow API v1 nav_order: 425 --- ## Get Captcha Statistics {: .no_toc } February 4, 2026 ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Query captcha solving statistics for your account. Returns detailed information about captcha token requests and their success/failure rates. Compare success rates across all configured providers to help decide which one works best for your use case. Use `anonymized=true` for a quick summary without downloading individual data rows. **Note:** - Data latency is at least 5 minutes, but should not exceed 15 minutes. - Data is retained for 3 months. - Results are cached for 5 minutes. {: .get } > **https://api.useapi.net/v1/google-flow/accounts/captcha-stats** ### Request Headers ``` yaml Authorization: Bearer {API token} ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Query Parameters | Parameter | Required | Description | |:----------|:---------|:------------| | `date` | No | Date in `YYYY-MM-DD` format.
Defaults to today if `limit` is not specified. | | `limit` | No | Number of records to return (max: 50000).
If specified, `date` filter is ignored and returns last N records across all dates. | | `provider` | No | Filter by captcha provider.
Supported: `EzCaptcha`, `CapSolver`, `YesCaptcha` | | `anonymized` | No | Set to `true` to return summary only without individual data rows.
Useful for comparing success rates across providers.
Uses last 3000 records, ignores `date`/`limit` filters. | ### Responses {% tabs v1_get_captcha_stats_response %} {% tab v1_get_captcha_stats_response 200 %} 200 OK Returns captcha statistics for the specified filters. ```json { "date": "2026-02-03", "total": 42, "summary": { "from": "2026-02-03T00:05:23.000Z", "to": "2026-02-03T23:58:47.000Z", "time_span": "23 hours 53 minutes", "success_rate_by_provider": { "EzCaptcha": 96.67, "CapSolver": 91.67 }, "by_status_code_images": { "200": 85.71, "403": 14.29 }, "by_status_code_videos": { "200": 94.29, "403": 5.71 }, "avg_captcha_ms": 8500, "avg_api_ms": 1200, "avg_attempt": 1.2 }, "data": [ { "timestamp": "2026-02-03T10:30:00.000Z", "jobId": "20260203103000123-user:123-bot:google-flow", "provider": "EzCaptcha", "taskId": "abc123-task-id", "route": "post-videos", "statusText": "OK", "pageAction": "VIDEO_GENERATION", "error": "", "statusCode": 200, "captchaDurationMs": 8500, "apiDurationMs": 1200, "attemptNumber": 1 } ] } ``` The `summary` object provides aggregated statistics (omitted if no data). {% endtab %} {% tab v1_get_captcha_stats_response 400 %} 400 Bad Request Missing or invalid parameters. ```json { "error": "" } ``` {% endtab %} {% tab v1_get_captcha_stats_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% endtabs %} ### Model ```typescript // Response structure { date?: string // Date filter applied (YYYY-MM-DD) limit?: number // Limit filter applied provider?: string // Provider filter applied total: number // Total records returned summary?: { // Aggregated statistics (omitted if no data) from: string // Earliest timestamp (ISO 8601) to: string // Latest timestamp (ISO 8601) time_span: string // Human readable duration (e.g., "2 days 5 hours") success_rate_by_provider: Record // Success rate % per provider (excludes 503) by_status_code_images: Record // Status code % for IMAGE actions by_status_code_videos: Record // Status code % for VIDEO actions avg_captcha_ms: number // Average captcha solve time in ms avg_api_ms: number // Average API call time in ms avg_attempt: number // Average attempt number } data: Array<{ timestamp: string // ISO 8601 timestamp jobId: string // Job identifier provider: string // Captcha provider used (EzCaptcha, CapSolver, YesCaptcha) taskId: string // Provider's task ID route: string // API route (post-videos, post-images, etc.) statusText: string // HTTP status text (OK, Forbidden, NetworkError) pageAction: string // reCAPTCHA action (VIDEO_GENERATION, IMAGE_GENERATION) error: string // Error message (empty on success) statusCode: number // HTTP status code (200, 403, 0 for network errors) captchaDurationMs: number // Captcha solve duration in ms apiDurationMs: number // API call duration in ms attemptNumber: number // Attempt number (1 = first try, 2+ = retry) }> } ``` ### Examples {% tabs v1_get_captcha_stats_example %} {% tab v1_get_captcha_stats_example Curl %} ``` bash # Today's stats curl -H "Authorization: Bearer YOUR_API_TOKEN" \ "https://api.useapi.net/v1/google-flow/accounts/captcha-stats" # Specific date curl -H "Authorization: Bearer YOUR_API_TOKEN" \ "https://api.useapi.net/v1/google-flow/accounts/captcha-stats?date=2026-02-01" # Last 1000 records curl -H "Authorization: Bearer YOUR_API_TOKEN" \ "https://api.useapi.net/v1/google-flow/accounts/captcha-stats?limit=1000" # Filter by provider curl -H "Authorization: Bearer YOUR_API_TOKEN" \ "https://api.useapi.net/v1/google-flow/accounts/captcha-stats?provider=EzCaptcha" # Summary only (no data rows) curl -H "Authorization: Bearer YOUR_API_TOKEN" \ "https://api.useapi.net/v1/google-flow/accounts/captcha-stats?anonymized=true" ``` {% endtab %} {% tab v1_get_captcha_stats_example JavaScript %} ``` javascript const apiUrl = 'https://api.useapi.net/v1/google-flow/accounts/captcha-stats'; const token = 'YOUR_API_TOKEN'; const response = await fetch(apiUrl, { headers: { 'Authorization': `Bearer ${token}` } }); const stats = await response.json(); console.log(`Total records: ${stats.total}`); console.log(`Success rates:`, stats.summary?.success_rate_by_provider); console.log('Data:', stats.data); ``` {% endtab %} {% tab v1_get_captcha_stats_example Python %} ``` python import requests apiUrl = 'https://api.useapi.net/v1/google-flow/accounts/captcha-stats' token = 'YOUR_API_TOKEN' headers = { 'Authorization': f'Bearer {token}' } # Today's stats response = requests.get(apiUrl, headers=headers) stats = response.json() print(f"Total records: {stats['total']}") print(f"Success rates: {stats.get('summary', {}).get('success_rate_by_provider')}") # Filter by provider response = requests.get( apiUrl, params={'provider': 'EzCaptcha'}, headers=headers ) ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts-email === Document URL: https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts-email --- layout: default title: GET accounts/email parent: Google Flow API v1 nav_order: 350 --- ## Get Account Configuration {: .no_toc } November 17, 2025 (December 1, 2025) ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Get configuration details for a specific Google Flow account, including health status, credits information, and available video models. {: .get } > **https://api.useapi.net/v1/google-flow/accounts/`email`** ### Request Headers ``` yaml Authorization: Bearer {API token} ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Path Parameters - `email` is **required**. The email address of the Google Flow account to query (URL-encoded if necessary). ### Responses {% tabs v1_get_accounts_email_response %} {% tab v1_get_accounts_email_response 200 %} 200 OK Account configuration found and returned with health status. ```json { "created": "2025-11-10T12:00:00.000Z", "accountCookies": [ { "name": "HSID", "value": "AYQ...(redacted)", "domain": ".google.com", "path": "/", "expires": "2027-11-10T12:00:00.000Z", "httpOnly": true, "secure": false, "sameSite": "Lax" } ], "sessionCookies": [ { "name": "__Host-GAPS", "value": "1:eJy...(redacted)", "domain": "labs.google", "path": "/", "expires": "2025-12-10T12:00:00.000Z", "httpOnly": true, "secure": true, "sameSite": "Lax" } ], "sessionData": { "user": { "name": "John Doe", "email": "jo***@gmail.com", "image": "https://lh3.googleusercontent.com/a/..." }, "expires": "2025-11-11T12:00:00.000Z", "access_token": "ya29.a0A...(redacted)" }, "project": { "projectId": "3b1c0e9d-7a6f-4592-8d38-7f9e1b4c6a5d", "projectTitle": "Nov 11 - 02:56" }, "nextRefresh": { "messageId": "msg-abc123", "scheduledFor": "2025-11-11T11:00:00.000Z" }, "health": "OK", "credits": { "credits": 1250, "userPaygateTier": "PAYGATE_TIER_TWO" }, "models": { "videoModels": [ { "key": "veo_3_1_t2v_fast_ultra", "displayName": "Veo 3.1 - Fast", "supportedAspectRatios": ["VIDEO_ASPECT_RATIO_LANDSCAPE"], "capabilities": ["VIDEO_MODEL_CAPABILITY_TEXT", "VIDEO_MODEL_CAPABILITY_AUDIO"], "videoLengthSeconds": 8, "videoGenerationTimeSeconds": 100, "framesPerSecond": 24, "paygateTier": "PAYGATE_TIER_TWO", "accessType": "MODEL_ACCESS_TYPE_GENERAL", "modelAccessInfo": {}, "modelMetadata": { "veoModelName": "Beta Audio" } }, { "key": "veo_3_1_t2v", "displayName": "Veo 3.1 - Quality", "supportedAspectRatios": ["VIDEO_ASPECT_RATIO_LANDSCAPE"], "capabilities": ["VIDEO_MODEL_CAPABILITY_TEXT", "VIDEO_MODEL_CAPABILITY_AUDIO"], "videoLengthSeconds": 8, "videoGenerationTimeSeconds": 210, "creditCost": 100, "framesPerSecond": 24, "paygateTier": "PAYGATE_TIER_TWO", "accessType": "MODEL_ACCESS_TYPE_GENERAL", "modelAccessInfo": {}, "modelMetadata": { "veoModelName": "Beta Audio" } } ] } } ``` **Note:** Sensitive values (cookie values, access tokens) are redacted for security. Email addresses are partially masked. The `credits` and `models` fields are only included when `health` is `"OK"`. **Ultra Plan Models:** For accounts with Google AI Ultra subscription ([PAYGATE_TIER_TWO](https://one.google.com/ai)), video models with keys ending in `_ultra` do not include a `creditCost` field, indicating unlimited generation for these models. {% endtab %} {% tab v1_get_accounts_email_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% tab v1_get_accounts_email_response 404 %} 404 Not Found Account not found or not configured. ```json { "error": "Google Flow account email@example.com not found" } ``` {% endtab %} {% endtabs %} ### Model ```typescript { created: string // ISO 8601 timestamp accountCookies: Array<{ name: string value: string // Redacted domain: string path: string expires: string | number httpOnly: boolean secure: boolean sameSite: 'Lax' | 'Strict' | 'None' }> sessionCookies: Array<{ // Same structure name: string value: string // Redacted domain: string path: string expires: string | number httpOnly: boolean secure: boolean sameSite: 'Lax' | 'Strict' | 'None' }> sessionData: { user: { name: string email: string // Partially masked image: string } expires: string // ISO 8601 timestamp access_token: string // Redacted } project: { projectId: string projectTitle: string } nextRefresh: { messageId: string scheduledFor: string // ISO 8601 timestamp } health: string // "OK" | "" credits?: { // Only present when health is "OK" credits: number userPaygateTier: string // "PAYGATE_TIER_ONE" | "PAYGATE_TIER_TWO" } models?: { // Only present when health is "OK" videoModels: Array<{ key: string // Model identifier (e.g., "veo_3_1_t2v_fast_ultra") displayName: string // "Veo 3.1 - Fast" | "Veo 3.1 - Quality" supportedAspectRatios: string[] capabilities: string[] // e.g., ["VIDEO_MODEL_CAPABILITY_TEXT", "VIDEO_MODEL_CAPABILITY_AUDIO"] videoLengthSeconds: number videoGenerationTimeSeconds?: number creditCost?: number // Absent for unlimited Ultra models (keys ending in _ultra) framesPerSecond: number paygateTier: string // "PAYGATE_TIER_ONE" | "PAYGATE_TIER_TWO" accessType: string modelAccessInfo: object modelMetadata: object }> } error?: string // Error message } ``` ### Examples {% tabs v1_get_accounts_email_example %} {% tab v1_get_accounts_email_example Curl %} ``` bash curl -H "Authorization: Bearer YOUR_API_TOKEN" \ "https://api.useapi.net/v1/google-flow/accounts/john%40gmail.com" ``` {% endtab %} {% tab v1_get_accounts_email_example JavaScript %} ``` javascript const token = 'YOUR_API_TOKEN'; const email = 'john@gmail.com'; const response = await fetch( `https://api.useapi.net/v1/google-flow/accounts/${encodeURIComponent(email)}`, { headers: { 'Authorization': `Bearer ${token}` } } ); const accountConfig = await response.json(); console.log('Account config:', accountConfig); console.log('Health:', accountConfig.health); console.log('Credits:', accountConfig.credits); ``` {% endtab %} {% tab v1_get_accounts_email_example Python %} ``` python import requests from urllib.parse import quote token = 'YOUR_API_TOKEN' email = 'john@gmail.com' headers = {'Authorization': f'Bearer {token}'} response = requests.get( f'https://api.useapi.net/v1/google-flow/accounts/{quote(email)}', headers=headers ) account_config = response.json() print('Account config:', account_config) print('Health:', account_config.get('health')) print('Credits:', account_config.get('credits')) ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts === Document URL: https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts --- layout: default title: GET accounts parent: Google Flow API v1 nav_order: 300 --- ## List All Configured Accounts {: .no_toc } November 17, 2025 (December 1, 2025) ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- List all configured Google Flow accounts. To get a specific account use [GET /accounts/`email`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts-email). {: .get } > **https://api.useapi.net/v1/google-flow/accounts** ### Request Headers ``` yaml Authorization: Bearer {API token} ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Responses {% tabs v1_get_accounts_response %} {% tab v1_get_accounts_response 200 %} 200 OK Returns a map of all configured accounts, keyed by email address. ```json { "a***@gmail.com": { "created": "2025-11-09T22:02:04.802Z", "health": "OK", "nextRefresh": { "scheduledFor": "2025-12-01T11:46:01.000Z" }, "project": { "projectId": "a7e08e13-a6ea-4945-9841-cb4147e4f024", "projectTitle": "Nov 11 - 02:56" }, "sessionData": { "expires": "2025-12-01T12:46:01.000Z" } }, "b***@gmail.com": { "created": "2025-11-10T02:56:58.864Z", "health": "OK", "nextRefresh": { "scheduledFor": "2025-12-01T09:13:16.000Z" }, "project": { "projectId": "47050a10-06f4-4469-8ab0-6d294c703508", "projectTitle": "Nov 11 - 02:56" }, "sessionData": { "expires": "2025-12-01T10:13:16.000Z" } } } ``` If no accounts are configured, returns an empty object `{}`. {% endtab %} {% tab v1_get_accounts_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% endtabs %} ### Model ```typescript // Map of email to account summary { [email: string]: { health: string // "OK" | "" error?: string // Error message if health check failed created?: string // ISO 8601 timestamp sessionData?: { expires: string // ISO 8601 timestamp } project?: { projectId: string projectTitle: string } nextRefresh?: { scheduledFor: string // ISO 8601 timestamp } } } ``` ### Examples {% tabs v1_get_accounts_example %} {% tab v1_get_accounts_example Curl %} ``` bash curl -H "Authorization: Bearer YOUR_API_TOKEN" \ "https://api.useapi.net/v1/google-flow/accounts" ``` {% endtab %} {% tab v1_get_accounts_example JavaScript %} ``` javascript const token = 'YOUR_API_TOKEN'; const response = await fetch('https://api.useapi.net/v1/google-flow/accounts', { headers: { 'Authorization': `Bearer ${token}` } }); const accounts = await response.json(); console.log('Configured accounts:', accounts); ``` {% endtab %} {% tab v1_get_accounts_example Python %} ``` python import requests token = 'YOUR_API_TOKEN' headers = {'Authorization': f'Bearer {token}'} response = requests.get('https://api.useapi.net/v1/google-flow/accounts', headers=headers) print('All accounts:', response.json()) ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid === Document URL: https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid --- layout: default title: GET jobs/jobid parent: Google Flow API v1 nav_order: 800 --- ## Retrieve Job Status {: .no_toc } November 17, 2025 (December 23, 2025) ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Retrieve the status and details of a specific image or video generation job by its job ID. This endpoint is particularly useful when using [async mode](https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos#async-mode) for video generation, or when tracking job progress via webhooks using the `replyUrl` parameter. To get load balancing statistics across all jobs, use [GET /jobs](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs). {: .get } > **https://api.useapi.net/v1/google-flow/jobs/`jobId`** ### Request Headers ``` yaml Authorization: Bearer {API token} ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Path Parameters - `jobId` is **required**, the unique job identifier returned from [POST /images](https://useapi.net/docs/api-google-flow-v1/post-google-flow-images) or [POST /videos](https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos). ### Responses {% tabs v1_get_jobs_jobid_response %} {% tab v1_get_jobs_jobid_response 200 %} 200 OK Returns the job record with current status and details. **Video job (completed):** ```json { "jobid": "j1731859234567v-u12345-email:jo***@gmail.com-bot:google-flow", "type": "video", "status": "completed", "created": "2025-11-17T12:34:56.789Z", "updated": "2025-11-17T12:37:23.456Z", "request": { "email": "jo***@gmail.com", "prompt": "A serene mountain landscape at sunset with camera slowly panning right", "model": "veo-3.1-fast", "aspectRatio": "landscape", "count": 2, "seed": 123456, "async": true, "replyUrl": "https://your-domain.com/webhook" }, "response": { "operations": [ { "operation": { "name": "d00af...redacted...6f7a" }, "sceneId": "abc123...", "status": "VIDEO_GENERATION_STATUS_SUCCEEDED", "video": { "uri": "https://storage.googleapis.com/...", "seed": 123456, "mediaGenerationId": "CAUSJ...redacted...OWQ5ZA", "fifeUrl": "https://storage.googleapis.com/...", "servingBaseUri": "https://lh3.googleusercontent.com/..." } } ], "captcha": { "service": "EzCaptcha", "taskId": "abc123...", "durationMs": 3500, "attempts": [ { "service": "EzCaptcha", "taskId": "abc123...", "durationMs": 3500, "success": true } ] } } } ``` **Image job (completed):** ```json { "jobid": "j1731859345678i-u12345-email:an***@gmail.com-bot:google-flow", "type": "image", "status": "completed", "created": "2025-11-17T12:45:12.345Z", "updated": "2025-11-17T12:45:34.678Z", "request": { "email": "an***@gmail.com", "prompt": "A serene mountain landscape at sunset with vibrant colors", "model": "imagen-4", "aspectRatio": "landscape", "count": 4, "replyUrl": "https://your-domain.com/webhook", "replyRef": "custom-reference-123" }, "response": { "media": [ { "name": "…redacted…", "image": { "generatedImage": { "seed": 987654, "mediaGenerationId": "user:12345…redacted…", "fifeUrl": "https://storage.googleapis.com/...", "prompt": "A serene mountain landscape at sunset with vibrant colors" } } } ], "captcha": { "service": "EzCaptcha", "taskId": "abc123...", "durationMs": 3200, "attempts": [ { "service": "EzCaptcha", "taskId": "abc123...", "durationMs": 3200, "success": true } ] } } } ``` **Job failed:** ```json { "jobid": "j1731859567890i-u12345-email:an***@gmail.com-bot:google-flow", "type": "image", "status": "failed", "created": "2025-11-17T13:00:12.345Z", "updated": "2025-11-17T13:00:45.678Z", "request": { "email": "an***@gmail.com", "prompt": "Generate an image", "model": "nano-banana" }, "error": "API error: 500", "code": 500, "response": { "error": { "code": 500, "message": "Internal error encountered.", "status": "INTERNAL" } } } ``` {% endtab %} {% tab v1_get_jobs_jobid_response 400 %} 400 Bad Request Invalid job ID format. ```json { "error": "Invalid job ID format" } ``` {% endtab %} {% tab v1_get_jobs_jobid_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% tab v1_get_jobs_jobid_response 403 %} 403 Forbidden Job belongs to a different user. ```json { "error": "Access denied - job belongs to different user" } ``` {% endtab %} {% tab v1_get_jobs_jobid_response 404 %} 404 Not Found Job not found in database. ```json { "error": "Job not found" } ``` {% endtab %} {% tab v1_get_jobs_jobid_response 410 %} 410 Gone Job has expired (jobs are retained for 7 days). ```json { "error": "Job has expired" } ``` {% endtab %} {% endtabs %} ### Model {% tabs v1_get_jobs_jobid_model %} {% tab v1_get_jobs_jobid_model Video Job %} Video generation job structure. ```typescript { jobid: string // Unique job identifier type: 'video' // Job type status: 'created' | 'started' | 'completed' | 'failed' created: string // ISO 8601 creation timestamp updated?: string // ISO 8601 last update timestamp request: { email?: string prompt: string model?: 'veo-3.1-quality' | 'veo-3.1-fast' aspectRatio?: 'landscape' | 'portrait' | 'square' count?: number // 1-4 seed?: number startImage?: string // mediaGenerationId for I2V mode endImage?: string // mediaGenerationId for I2V-FL mode referenceImage_1?: string // mediaGenerationId for R2V mode referenceImage_2?: string // mediaGenerationId for R2V mode referenceImage_3?: string // mediaGenerationId for R2V mode async?: boolean // Fire-and-forget mode replyUrl?: string // Webhook URL for callbacks replyRef?: string // Custom reference for callbacks } response?: { operations: Array<{ operation: { name: string error?: { // Present when operation failed code: number message: string } metadata?: { // Present when completed '@type': string name: string video: { seed: number mediaGenerationId: string prompt: string fifeUrl: string // Signed video URL (MP4, valid ~24h) mediaVisibility: string servingBaseUri: string // Signed thumbnail URL (JPEG, valid ~24h) model: string // veo_3_1_t2v | veo_3_1_i2v | veo_3_1_i2v_fl | veo_3_0_r2v isLooped: boolean aspectRatio: string // VIDEO_ASPECT_RATIO_LANDSCAPE | PORTRAIT } } } sceneId: string mediaGenerationId?: string // Present when completed status: string // MEDIA_GENERATION_STATUS_PENDING | PROCESSING | SUCCESSFUL | FAILED }> remainingCredits?: number captcha?: { // Captcha metadata (for debugging/research) service: string // "EzCaptcha" | "CapSolver" | "YesCaptcha" taskId: string durationMs: number attempts: Array<{ service: string taskId?: string durationMs: number success: boolean error?: string }> } } error?: string // Error message (if failed) errorDetails?: string // Additional error details code?: number // HTTP status code (if failed) } ``` {% endtab %} {% tab v1_get_jobs_jobid_model Image Job %} Image generation job structure. ```typescript { jobid: string // Unique job identifier type: 'image' // Job type status: 'created' | 'started' | 'completed' | 'failed' created: string // ISO 8601 creation timestamp updated?: string // ISO 8601 last update timestamp request: { email?: string prompt: string model?: 'imagen-4' | 'nano-banana' aspectRatio?: 'landscape' | 'portrait' count?: number // 1-4 seed?: number reference_1?: string // mediaGenerationId reference_2?: string // mediaGenerationId reference_3?: string // mediaGenerationId replyUrl?: string // Webhook URL for callbacks replyRef?: string // Custom reference for callbacks } response?: { media: Array<{ name: string image: { generatedImage: { seed: number mediaGenerationId: string fifeUrl: string // Signed image URL (valid ~24h) prompt: string } } }> captcha?: { // Captcha metadata (for debugging/research) service: string // "EzCaptcha" | "CapSolver" | "YesCaptcha" taskId: string durationMs: number attempts: Array<{ service: string taskId?: string durationMs: number success: boolean error?: string }> } } error?: string // Error message (if failed) errorDetails?: string // Additional error details code?: number // HTTP status code (if failed) } ``` {% endtab %} {% endtabs %} ### Examples {% tabs v1_get_jobs_jobid_examples %} {% tab v1_get_jobs_jobid_examples Curl %} ```bash # Get job status curl "https://api.useapi.net/v1/google-flow/jobs/j1731859234567v-u12345-email:jo***@gmail.com-bot:google-flow" \ -H "Authorization: Bearer {API token}" # Poll for completion (check every 5 seconds) while true; do STATUS=$(curl -s "https://api.useapi.net/v1/google-flow/jobs/j1731859234567v-u12345-email:jo***@gmail.com-bot:google-flow" \ -H "Authorization: Bearer {API token}" | jq -r '.status') echo "Status: $STATUS" if [[ "$STATUS" == "completed" || "$STATUS" == "failed" ]]; then break fi sleep 5 done ``` {% endtab %} {% tab v1_get_jobs_jobid_examples JavaScript %} ```javascript const apiToken = 'your-api-token' const jobId = 'j1731859234567v-u12345-email:jo***@gmail.com-bot:google-flow' // Get job status async function getJobStatus(jobId) { const response = await fetch(`https://api.useapi.net/v1/google-flow/jobs/${jobId}`, { headers: { 'Authorization': `Bearer ${apiToken}` } }) if (!response.ok) { throw new Error(`HTTP ${response.status}: ${await response.text()}`) } return await response.json() } // Poll until completion async function waitForCompletion(jobId, intervalMs = 5000) { while (true) { const job = await getJobStatus(jobId) console.log(`Status: ${job.status}`) if (job.status === 'completed') { console.log('Job completed!', job.response) return job } if (job.status === 'failed') { console.error('Job failed:', job.error) throw new Error(job.error) } await new Promise(resolve => setTimeout(resolve, intervalMs)) } } // Usage const job = await waitForCompletion(jobId) ``` {% endtab %} {% tab v1_get_jobs_jobid_examples Python %} ```python import requests import time api_token = 'your-api-token' job_id = 'j1731859234567v-u12345-email:jo***@gmail.com-bot:google-flow' # Get job status def get_job_status(job_id: str) -> dict: response = requests.get( f'https://api.useapi.net/v1/google-flow/jobs/{job_id}', headers={'Authorization': f'Bearer {api_token}'} ) response.raise_for_status() return response.json() # Poll until completion def wait_for_completion(job_id: str, interval_sec: int = 5) -> dict: while True: job = get_job_status(job_id) print(f"Status: {job['status']}") if job['status'] == 'completed': print("Job completed!", job['response']) return job if job['status'] == 'failed': raise Exception(f"Job failed: {job.get('error')}") time.sleep(interval_sec) # Usage job = wait_for_completion(job_id) # Access video URLs (for video jobs) if job['type'] == 'video': for op in job['response']['operations']: if 'video' in op and 'fifeUrl' in op['video']: print(f"Video URL: {op['video']['fifeUrl']}") # Access image URLs (for image jobs) if job['type'] == 'image': for media in job['response']['media']: if 'image' in media and 'generatedImage' in media['image']: print(f"Image URL: {media['image']['generatedImage']['fifeUrl']}") ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs === Document URL: https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs --- layout: default title: GET jobs parent: Google Flow API v1 nav_order: 810 --- ## Get Load Balancing Statistics {: .no_toc } November 17, 2025 (November 19, 2025) ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Get load balancing statistics across all configured Google Flow accounts. This endpoint provides real-time visibility into job distribution, account health, and performance metrics for both image and video generation. To retrieve a specific job, use [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid). {: .get } > **https://api.useapi.net/v1/google-flow/jobs/?options=`options`** ### Request Headers ``` yaml Authorization: Bearer {API token} ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Query Parameters - `options` is optional, controls the level of detail in the response (default: `summary`). Supported values: - `summary`: Returns aggregated stats per account (executing, completed, failed, rate limited counts) - `executing`: Adds details of currently executing jobs with elapsed time - `history`: Includes top 10 most recent completed jobs from the last 15 minutes ### Load Balancing Algorithm When you have multiple Google Flow accounts configured and don't specify an `email` parameter in [POST /images](https://useapi.net/docs/api-google-flow-v1/post-google-flow-images) or [POST /videos](https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos), the API automatically selects the best account using a scoring algorithm: **Formula:** `score = executing + (failed × 10) + (rateLimited × 20)` **Lower scores are better.** The account with the lowest score receives the next job. **Components:** - `executing`: Number of jobs currently running on this account Weight: **1×** (each executing job adds 1 point) Purpose: Distribute load evenly across accounts - `failed`: Number of failed jobs (non-429 4xx/5xx responses) in last 15 minutes Weight: **10×** (each failure adds 10 points) Purpose: Heavily penalize unreliable accounts - `rateLimited`: Number of 429 rate limit responses in last 15 minutes Weight: **20×** (each rate limit adds 20 points) Purpose: Most heavily penalize rate-limited accounts to avoid hitting limits **Example scores:** - Idle account: `0 executing + 0 failed + 0 rateLimited = 0` (best) - 2 jobs running: `2 executing + 0 failed + 0 rateLimited = 2` - 1 recent failure: `0 executing + 1 failed + 0 rateLimited = 10` - 1 rate limit hit: `0 executing + 0 failed + 1 rateLimited = 20` - Rate limited account: `0 executing + 0 failed + 2 rateLimited = 40` (worst) **Randomization:** When multiple accounts have the same score, one is selected randomly. **Stats expiration:** Job statistics older than 15 minutes are automatically removed from load balancing calculations. ### Responses {% tabs v1_get_jobs_response %} {% tab v1_get_jobs_response 200 %} 200 OK Returns load balancing statistics categorized by job type. **With `options=summary` (default):** ```json { "emails": [ "jo***@gmail.com", "an***@gmail.com" ], "videos": { "summary": { "jo***@gmail.com": { "executing": 2, "completed": 15, "failed": 0, "rateLimited": 0, "avgResponseTime": 125340.50, "score": 2 }, "an***@gmail.com": { "executing": 0, "completed": 8, "failed": 1, "rateLimited": 0, "avgResponseTime": 98234.75, "score": 10 } } }, "images": { "summary": { "jo***@gmail.com": { "executing": 1, "completed": 42, "failed": 0, "rateLimited": 0, "avgResponseTime": 12456.30, "score": 1 }, "an***@gmail.com": { "executing": 0, "completed": 38, "failed": 0, "rateLimited": 1, "avgResponseTime": 15234.80, "score": 20 } } }, "combined": { "summary": { "jo***@gmail.com": { "executing": 3, "completed": 57, "failed": 0, "rateLimited": 0, "avgResponseTime": 32145.60, "score": 3 }, "an***@gmail.com": { "executing": 0, "completed": 46, "failed": 1, "rateLimited": 1, "avgResponseTime": 42367.25, "score": 30 } } } } ``` **With `options=executing`:** Adds `executing` object with currently running jobs and their elapsed time in `MM:SS` format: ```json { "emails": [ "jo***@gmail.com", "an***@gmail.com" ], "videos": { "summary": { "..." }, "executing": { "j1731...redacted...v-u12345-email:jo***@gmail.com-bot:google-flow": { "email": "jo***@gmail.com", "timestamp": 1731859234567, "elapsed": "1:23" }, "j1731...redacted...v-u12345-email:jo***@gmail.com-bot:google-flow-http:200": { "email": "jo***@gmail.com", "timestamp": 1731859123456, "elapsed": "3:45" } } }, "images": { "summary": { "..." }, "executing": { "j1731...redacted...i-u12345-email:jo***@gmail.com-bot:google-flow": { "email": "jo***@gmail.com", "timestamp": 1731859345678, "elapsed": "0:15" } } }, "combined": { "summary": { "..." } } } ``` **With `options=history`:** Adds both `executing` and `history` objects with top 10 most recent completed jobs from last 15 minutes: ```json { "emails": [ "jo***@gmail.com", "an***@gmail.com" ], "videos": { "summary": { "..." }, "executing": { "..." }, "history": { "j1731...redacted...v-u12345-email:jo***@gmail.com-bot:google-flow": { "email": "jo***@gmail.com", "timestamp": 1731858123456, "httpStatus": 200, "responseTime": 125340 }, "j1731...redacted...v-u12345-email:an***@gmail.com-bot:google-flow": { "email": "an***@gmail.com", "timestamp": 1731858234567, "httpStatus": 500, "responseTime": 98234 } } }, "images": { "summary": { "..." }, "executing": { "..." }, "history": { "..." } }, "combined": { "summary": { "..." } } } ``` {% endtab %} {% tab v1_get_jobs_response 400 %} 400 Bad Request Invalid `options` parameter value. ```json { "error": "Invalid options parameter. Use: summary, executing, or history" } ``` {% endtab %} {% tab v1_get_jobs_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% endtabs %} ### Model ```typescript { emails: string[] // List of all configured healthy account emails videos: { summary: { [email: string]: { executing: number // Currently running jobs completed: number // Successfully completed (2xx) in last 15min failed: number // Failed (4xx/5xx except 429) in last 15min rateLimited: number // Rate limited (429) in last 15min avgResponseTime: number // Average response time in milliseconds score: number // Load balancing score (lower is better) } } executing?: { // Only with options=executing or history [jobId: string]: { email: string // Account email timestamp: number // Unix timestamp (milliseconds) elapsed: string // Elapsed time in MM:SS format } } history?: { // Only with options=history [jobId: string]: { email: string // Account email timestamp: number // Unix timestamp (milliseconds) httpStatus: number // HTTP status code (200, 429, 500, etc.) responseTime: number // Response time in milliseconds } } } images: { summary: { [email: string]: { executing: number // Currently running jobs completed: number // Successfully completed (2xx) in last 15min failed: number // Failed (4xx/5xx except 429) in last 15min rateLimited: number // Rate limited (429) in last 15min avgResponseTime: number // Average response time in milliseconds score: number // Load balancing score (lower is better) } } executing?: { // Only with options=executing or history [jobId: string]: { email: string // Account email timestamp: number // Unix timestamp (milliseconds) elapsed: string // Elapsed time in MM:SS format } } history?: { // Only with options=history [jobId: string]: { email: string // Account email timestamp: number // Unix timestamp (milliseconds) httpStatus: number // HTTP status code (200, 429, 500, etc.) responseTime: number // Response time in milliseconds } } } combined: { summary: { [email: string]: { executing: number // Currently running jobs completed: number // Successfully completed (2xx) in last 15min failed: number // Failed (4xx/5xx except 429) in last 15min rateLimited: number // Rate limited (429) in last 15min avgResponseTime: number // Average response time in milliseconds score: number // Load balancing score (lower is better) } } } } ``` ### Examples {% tabs v1_get_jobs_examples %} {% tab v1_get_jobs_examples Curl %} ```bash # Get summary stats (default) curl "https://api.useapi.net/v1/google-flow/jobs" \ -H "Authorization: Bearer {API token}" # Get executing jobs with elapsed time curl "https://api.useapi.net/v1/google-flow/jobs/?options=executing" \ -H "Authorization: Bearer {API token}" # Get full history (last 15 minutes) curl "https://api.useapi.net/v1/google-flow/jobs/?options=history" \ -H "Authorization: Bearer {API token}" ``` {% endtab %} {% tab v1_get_jobs_examples JavaScript %} ```javascript const apiToken = 'your-api-token' // Get summary stats (default) const response = await fetch('https://api.useapi.net/v1/google-flow/jobs', { headers: { 'Authorization': `Bearer ${apiToken}` } }) const stats = await response.json() // Check which account has lowest score for images const imagesSummary = stats.images.summary const bestAccount = Object.entries(imagesSummary) .sort(([, a], [, b]) => a.score - b.score)[0] console.log('Best account for images:', bestAccount[0], 'score:', bestAccount[1].score) // Get executing jobs const execResponse = await fetch('https://api.useapi.net/v1/google-flow/jobs/?options=executing', { headers: { 'Authorization': `Bearer ${apiToken}` } }) const execStats = await execResponse.json() console.log('Currently executing videos:', Object.keys(execStats.videos.executing || {}).length) ``` {% endtab %} {% tab v1_get_jobs_examples Python %} ```python import requests api_token = 'your-api-token' headers = {'Authorization': f'Bearer {api_token}'} # Get summary stats (default) response = requests.get( 'https://api.useapi.net/v1/google-flow/jobs', headers=headers ) stats = response.json() # Check which account has lowest score for videos videos_summary = stats['videos']['summary'] best_account = min(videos_summary.items(), key=lambda x: x[1]['score']) print(f"Best account for videos: {best_account[0]}, score: {best_account[1]['score']}") # Get full history history_response = requests.get( 'https://api.useapi.net/v1/google-flow/jobs/?options=history', headers=headers ) history_stats = history_response.json() print(f"Image job history entries: {len(history_stats['images'].get('history', {}))}") ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/index === Document URL: https://useapi.net/docs/api-google-flow-v1/index --- layout: default title: Google Flow API v1 nav_order: 2000 has_children: true permalink: /docs/api-google-flow-v1 --- # Google Flow API v1 November 17, 2025 (February 4, 2026) This is the [experimental](../../docs/legal) API for [Google Flow](https://labs.google/fx/tools/flow) by [Google Labs](https://labs.google). [Google Flow](https://labs.google/fx/tools/flow) creates cinematic AI clips with [Veo](https://aistudio.google.com/models/veo-3), images with [Imagen 4](https://deepmind.google/technologies/imagen-3/), [Nano Banana / Gemini 2.5 Flash Image](https://deepmind.google/technologies/gemini/flash/), and [Nano Banana Pro / Gemini 3 Pro Image](https://deepmind.google/models/gemini-image/pro/). **Image generation:** Works with any [Google AI](https://one.google.com/ai) subscription or **free** account. **Video generation:** Requires [Google AI Pro](https://one.google.com/ai) ($20/month) or [Ultra](https://one.google.com/ai) ($125/month): - `Veo 3.1 Fast` — 5¢ per video - `Veo 3.1 Quality` — 50¢ per video - `Veo 3.1 Fast Relaxed` — free, Ultra only (lower priority) Official Google AI Pro and Google AI Ultra [credits table](https://support.google.com/googleone/answer/16287445). **Captcha:** Image and video generation requires reCAPTCHA solving ([POST /images](https://useapi.net/docs/api-google-flow-v1/post-google-flow-images), [POST /images/upscale](https://useapi.net/docs/api-google-flow-v1/post-google-flow-images-upscale), [POST /videos](https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos), [POST /videos/upscale](https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-upscale), [POST /videos/extend](https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-extend)). [POST /videos/gif](https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-gif) and [POST /videos/concatenate](https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-concatenate) do not require captcha. - **Users receive 100 free captcha credits** when adding their first Google Flow account - After free credits are exhausted, configure provider API keys via [POST /accounts/captcha-providers](https://useapi.net/docs/api-google-flow-v1/post-google-flow-accounts-captcha-providers) - Cost: $2.5-$3.0 per 1,000 solves depending on provider - Compare provider success rates with [GET /accounts/captcha-stats?anonymized=true](https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts-captcha-stats) - See [Setup Google Flow - Captcha Providers](../../docs/start-here/setup-google-flow#configure-captcha-providers) for details ⚙️ [Setup Google Flow](../../docs/start-here/setup-google-flow) 📦 [Postman collection](https://www.postman.com/useapinet/useapi-net/collection) (February 4, 2026) 🤖 [LLM-friendly API spec](https://useapi.net/assets/aibot/api-google-flow-v1.txt) Feed this to your LLM to build integrations Examples: * [Video Extend and Concatenate](/blog/260129) * [Video Upscale and GIF](/blog/260120) * [Nano Banana Pro with 5 references](/blog/251201) * [Nano Banana Pro](/blog/251120) * [Imagen 4, Nano Banana and Veo 3.1 Fast](/blog/251117) Developer Community: * Discord Server * Telegram Channel * r/GoogleFlowAPI === URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-accounts-captcha-providers === Document URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-accounts-captcha-providers --- layout: default title: POST …/captcha-providers parent: Google Flow API v1 nav_order: 410 --- ## Configure Captcha Providers {: .no_toc } December 23, 2025 (January 2, 2026) ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Configure captcha provider API keys for image and video generation. Google Flow requires reCAPTCHA v3 Enterprise tokens for API calls - these third-party services solve the captcha automatically. **Supported Providers:** | Provider | Cost | Website | |----------|------|---------| | **EzCaptcha** | ~$2.50 per 1,000 solves | [ez-captcha.com](https://www.ez-captcha.com/) | | **CapSolver** | ~$3.00 per 1,000 solves | [capsolver.com](https://www.capsolver.com/) — use promo code `useapi` for 8% discount | | **YesCaptcha** | varies | [yescaptcha.com](https://yescaptcha.com/) | Use [GET /accounts/captcha-stats?anonymized=true](https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts-captcha-stats) to compare success rates across providers. Configure multiple providers for redundancy - the API will automatically retry with different providers if one fails or returns a rejected token. {: .post } > **https://api.useapi.net/v1/google-flow/accounts/captcha-providers** ### Request Headers ``` yaml Authorization: Bearer {API token} Content-Type: application/json # Alternatively you can use multipart/form-data # Content-Type: multipart/form-data ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Request Body ```json { "EzCaptcha": "", "CapSolver": "", "YesCaptcha": "" } ``` - `EzCaptcha` is optional. API key from [ez-captcha.com](https://www.ez-captcha.com/). - `CapSolver` is optional. API key from [capsolver.com](https://www.capsolver.com/). - `YesCaptcha` is optional. API key from [yescaptcha.com](https://yescaptcha.com/). **Notes:** - All fields are optional - only include providers you want to configure - Set a field to empty string `""` to remove that provider - Users receive **100 free captcha credits** when adding their first Google Flow account. These credits are used automatically when no provider API keys are configured. - Once free credits are exhausted, at least one provider must be configured to use [POST /images](https://useapi.net/docs/api-google-flow-v1/post-google-flow-images), [POST /images/upscale](https://useapi.net/docs/api-google-flow-v1/post-google-flow-images-upscale), or [POST /videos](https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos) ### Responses {% tabs v1_post_captcha_providers_response %} {% tab v1_post_captcha_providers_response 200 %} 200 OK Captcha providers configured successfully. Returns masked keys for all configured providers. **With providers configured:** ```json { "EzCaptcha": "abc...***...xyz", "CapSolver": "def...***...uvw" } ``` **All providers removed (shows free credits if available):** ```json { "freeCaptchaCredits": 100 } ``` {% endtab %} {% tab v1_post_captcha_providers_response 400 %} 400 Bad Request Invalid provider name specified. ```json { "error": "Invalid captcha provider(s): InvalidProvider. Valid providers: EzCaptcha, CapSolver, YesCaptcha" } ``` {% endtab %} {% tab v1_post_captcha_providers_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% endtabs %} ### Model ```typescript { // TypeScript, all fields are optional EzCaptcha?: string // Masked API key or omitted if not configured CapSolver?: string // Masked API key or omitted if not configured YesCaptcha?: string // Masked API key or omitted if not configured freeCaptchaCredits?: number // Remaining free credits (only shown when no providers configured) } ``` **Note:** `freeCaptchaCredits` is only included in the response when: - No captcha providers are configured (all removed), AND - The user has remaining free credits (> 0) ### Examples {% tabs v1_post_captcha_providers_example %} {% tab v1_post_captcha_providers_example Curl %} ``` bash curl -H "Accept: application/json" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -X POST "https://api.useapi.net/v1/google-flow/accounts/captcha-providers" \ -d '{ "EzCaptcha": "", "CapSolver": "" }' ``` {% endtab %} {% tab v1_post_captcha_providers_example JavaScript %} ``` javascript const apiUrl = 'https://api.useapi.net/v1/google-flow/accounts/captcha-providers'; const token = 'YOUR_API_TOKEN'; const response = await fetch(apiUrl, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ EzCaptcha: '', CapSolver: '' }) }); const result = await response.json(); console.log('Captcha providers configured:', result); ``` {% endtab %} {% tab v1_post_captcha_providers_example Python %} ``` python import requests apiUrl = 'https://api.useapi.net/v1/google-flow/accounts/captcha-providers' token = 'YOUR_API_TOKEN' headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {token}' } body = { 'EzCaptcha': '', 'CapSolver': '' } response = requests.post(apiUrl, headers=headers, json=body) print(response.status_code, response.json()) ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-accounts === Document URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-accounts --- layout: default title: POST accounts parent: Google Flow API v1 nav_order: 200 --- ## Configure Google Flow Account {: .no_toc } November 17, 2025 ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Configure your Google Flow account for API access using cookies from your authenticated Google account. {: .post } > **https://api.useapi.net/v1/google-flow/accounts** ### Request Headers ``` yaml Authorization: Bearer {API token} Content-Type: application/json # Alternatively you can use multipart/form-data # Content-Type: multipart/form-data ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Request Body ```json { "cookies": "Name\tValue\tDomain\tPath\tExpires\t..." } ``` - `cookies` is **required**. Cookies copied from Chrome DevTools in table format. See [Setup Google Flow](../start-here/setup-google-flow) for detailed instructions on how to obtain these cookies. ### Responses {% tabs v1_post_accounts_response %} {% tab v1_post_accounts_response 201 %} 201 Created New account configuration created successfully. ```json { "accountCookies": [ { "name": "HSID", "value": "AYQ...(redacted)", "domain": ".google.com", "path": "/", "expires": "2027-11-10T12:00:00.000Z", "httpOnly": true, "secure": false, "sameSite": "Lax" } ], "sessionCookies": [ { "name": "__Host-GAPS", "value": "1:eJy...(redacted)", "domain": "labs.google", "path": "/", "expires": "2025-12-10T12:00:00.000Z", "httpOnly": true, "secure": true, "sameSite": "Lax" } ], "sessionData": { "user": { "name": "John Doe", "email": "jo***@gmail.com", "image": "https://lh3.googleusercontent.com/a/..." }, "expires": "2025-11-11T12:00:00.000Z", "access_token": "ya29.a0A...(redacted)" }, "created": "2025-11-10T12:00:00.000Z", "project": { "projectId": "3b1c0e9d-7a6f-4592-8d38-7f9e1b4c6a5d", "projectTitle": "Nov 11 - 02:56" }, "nextRefresh": { "messageId": "msg-abc123", "scheduledFor": "2025-11-11T11:00:00.000Z" } } ``` {% endtab %} {% tab v1_post_accounts_response 200 %} 200 OK Existing account configuration updated successfully. ```json { "accountCookies": [ { "name": "HSID", "value": "AYQ...(redacted)", "domain": ".google.com", "path": "/", "expires": "2027-11-10T12:00:00.000Z", "httpOnly": true, "secure": false, "sameSite": "Lax" } ], "sessionCookies": [ { "name": "__Host-GAPS", "value": "1:eJy...(redacted)", "domain": "labs.google", "path": "/", "expires": "2025-12-10T12:00:00.000Z", "httpOnly": true, "secure": true, "sameSite": "Lax" } ], "sessionData": { "user": { "name": "John Doe", "email": "jo***@gmail.com", "image": "https://lh3.googleusercontent.com/a/..." }, "expires": "2025-11-11T12:00:00.000Z", "access_token": "ya29.a0A...(redacted)" }, "created": "2025-11-10T12:00:00.000Z", "project": { "projectId": "3b1c0e9d-7a6f-4592-8d38-7f9e1b4c6a5d", "projectTitle": "Nov 11 - 02:56" }, "nextRefresh": { "messageId": "msg-abc123", "scheduledFor": "2025-11-11T11:00:00.000Z" } } ``` {% endtab %} {% tab v1_post_accounts_response 400 %} 400 Bad Request Validation error (missing/invalid parameters or cookies). ```json { "error": "Failed to validate cookies: 401 Unauthorized" } ``` {% endtab %} {% tab v1_post_accounts_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% tab v1_post_accounts_response 402 %} 402 Payment Required Subscription expired or insufficient credits. ```json { "error": "Account has no subscription or subscription expired" } ``` {% endtab %} {% endtabs %} ### Model - `created` - ISO 8601 timestamp when the account was first configured - `accountCookies` - Google account cookies - `sessionCookies` - Session cookies for Google Flow - `sessionData` - User session information with access token - `project` - Auto-created Google Flow project for this session - `nextRefresh` - Scheduled refresh details (refreshes automatically 1 hour before expiry) ```typescript { // TypeScript, all fields are optional created: string // ISO 8601 timestamp accountCookies: Array<{ name: string value: string domain: string path: string expires: string | number httpOnly: boolean secure: boolean sameSite: 'Lax' | 'Strict' | 'None' }> sessionCookies: Array<{ name: string value: string domain: string path: string expires: string | number httpOnly: boolean secure: boolean sameSite: 'Lax' | 'Strict' | 'None' }> sessionData: { user: { name: string email: string image: string } expires: string // ISO 8601 timestamp access_token: string } project: { projectId: string projectTitle: string } nextRefresh: { messageId: string scheduledFor: string // ISO 8601 timestamp } health?: string // "OK" | "Error information" error?: string // Error message } ``` ### Examples {% tabs v1_post_accounts_example %} {% tab v1_post_accounts_example Curl %} ``` bash curl -H "Accept: application/json" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -X POST "https://api.useapi.net/v1/google-flow/accounts" \ -d '{ "cookies": "HSID\tAYQ...\t.google.com\t/\t2027-11-10...\nSSID\tAbc...\t.google.com\t/\t2027-11-10..." }' ``` {% endtab %} {% tab v1_post_accounts_example JavaScript %} ``` javascript const apiUrl = 'https://api.useapi.net/v1/google-flow/accounts'; const token = 'YOUR_API_TOKEN'; const cookies = `HSID\tAYQ...\t.google.com\t/\t2027-11-10... SSID\tAbc...\t.google.com\t/\t2027-11-10...`; const response = await fetch(apiUrl, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ cookies: cookies }) }); const result = await response.json(); console.log('Account configured:', result); ``` {% endtab %} {% tab v1_post_accounts_example Python %} ``` python import requests apiUrl = 'https://api.useapi.net/v1/google-flow/accounts' token = 'YOUR_API_TOKEN' cookies = """HSID\tAYQ...\t.google.com\t/\t2027-11-10... SSID\tAbc...\t.google.com\t/\t2027-11-10...""" headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {token}' } body = { 'cookies': cookies } response = requests.post(apiUrl, headers=headers, json=body) print(response.status_code, response.json()) ``` {% endtab %} {% endtabs %} ### Try It See [Setup Google Flow](../start-here/setup-google-flow#verify-cookies-value) page.
=== URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-assets-email === Document URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-assets-email --- layout: default title: POST assets/email parent: Google Flow API v1 nav_order: 500 --- ## Upload Assets {: .no_toc } November 17, 2025 ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Upload assets to Google Flow. Currently supported formats are PNG and JPEG with a maximum file size of 20 MB. | Content-Type | File Extension | | ------------ | -------------- | | image/png | png | | image/jpeg | jpeg | [POST raw content using Make.com and similar nocode tools.](../questions-and-answers.html#how-post-raw-content-to-runwaymlassets-and-minimaxfiles-using-makecom-and-similar-nocode-tools) {: .post } > **https://api.useapi.net/v1/google-flow/assets/`email`** ### Request Headers ``` yaml Authorization: Bearer {API token} Content-Type: select from the table above ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. - `Content-Type` is **required**, see table above. ### Path Parameters - `email` is optional. The email address of the Google Flow account to use (URL-encoded if necessary). When only one [account](https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts) is configured, the API will automatically use that account. With multiple [accounts](https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts) configured, omitting the email parameter triggers automatic [load balancing](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs#load-balancing-algorithm) based on **image generation** job statistics to select the healthiest account. **Note:** The endpoint can be called as either `POST /assets` (no email) or `POST /assets/:email` (explicit email). ### Request Body Binary image content (raw bytes). ### Responses {% tabs v1_post_assets_email_response %} {% tab v1_post_assets_email_response 200 %} 200 OK Image uploaded successfully. Returns the media generation ID with reference ID, image dimensions, and the account email used. ```json { "mediaGenerationId": { "mediaGenerationId": "...redacted..." }, "width": 685, "height": 900, "email": "jo***@gmail.com" } ``` - `mediaGenerationId.mediaGenerationId` - Reference ID for use in subsequent API calls (format: `user:{userid}-email:{hex_encoded_email}-image:{internal_media_id}`) - `width` - Image width in pixels - `height` - Image height in pixels - `email` - Account email that was used for the upload (useful when email was omitted and auto-selected via load balancing) {% endtab %} {% tab v1_post_assets_email_response 400 %} 400 Bad Request Invalid request (empty content, unsupported content type, file too large, or content policy violation). **General error:** ```json { "error": "File size (25165824) is over 20971520 bytes" } ``` **Content policy error:** ```json { "error": { "code": 400, "message": "Request contains an invalid argument.", "status": "INVALID_ARGUMENT", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "PUBLIC_ERROR_TRUMP_FACE_DETECTED" } ] } } ``` {% endtab %} {% tab v1_post_assets_email_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% tab v1_post_assets_email_response 404 %} 404 Not Found Account not found or not configured. ```json { "error": "Google Flow account john@gmail.com not found" } ``` {% endtab %} {% tab v1_post_assets_email_response 429 %} 429 Too Many Requests Rate limit or quota exhausted (concurrency limit or account quota reached). Wait 5-10 seconds and retry. If this persists, you may need to cool this account off for a few hours before trying again. ```json { "error": { "code": 429, "message": "Resource has been exhausted (e.g. check quota).", "status": "RESOURCE_EXHAUSTED", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "PUBLIC_ERROR_USER_REQUESTS_THROTTLED" } ] } } ``` {% endtab %} {% tab v1_post_assets_email_response 596 %} 596 Session Error Google session refresh failed. The account needs to be reconfigured. Delete the account using [DELETE /accounts/email](https://useapi.net/docs/api-google-flow-v1/delete-google-flow-accounts-email) and add it again by strictly following the procedure in [Setup Google Flow](../start-here/setup-google-flow). ```json { "error": "Failed to refresh session: 500 Internal Server Error" } ``` {% endtab %} {% endtabs %} ### Model ```typescript { mediaGenerationId: { mediaGenerationId: string // Reference ID: user:{userid}-email:{hex_encoded_email}-image:{internal_media_id} } width: number // Image width in pixels height: number // Image height in pixels email: string // Account email used for upload error?: string | { // Error: string (useapi.net) or object (Google API) code: number message: string status: string details: Array<{ '@type': string reason: string }> } } ``` ### Examples {% tabs v1_post_assets_email_example %} {% tab v1_post_assets_email_example Curl %} ``` bash # Option 1: Without email (auto-selection/load balancing) curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: image/jpeg" \ --data-binary @/path/to/your/image.jpeg \ "https://api.useapi.net/v1/google-flow/assets" # Option 2: With specific email curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: image/jpeg" \ --data-binary @/path/to/your/image.jpeg \ "https://api.useapi.net/v1/google-flow/assets/john%40gmail.com" ``` {% endtab %} {% tab v1_post_assets_email_example JavaScript %} ``` javascript const token = 'YOUR_API_TOKEN'; // Option 1: Without email (auto-selection/load balancing) const apiUrl = 'https://api.useapi.net/v1/google-flow/assets'; // Option 2: With specific email // const email = 'john@gmail.com'; // const apiUrl = `https://api.useapi.net/v1/google-flow/assets/${encodeURIComponent(email)}`; // Load image - Example 1: Fetch from URL const imageUrl = "https://upload.wikimedia.org/wikipedia/commons/7/7d/Mona_Lisa_color_restoration.jpg"; const responseImage = await fetch(imageUrl); const blob = await responseImage.blob(); // Load image - Example 2: From local file (Node.js) // const fsp = require('fs').promises; // const imageFileName = "./cat.png"; // const blob = new Blob([await fsp.readFile(imageFileName)]); // Load image - Example 3: From file input element // // // const imageFile = document.getElementById('image-file'); // const blob = imageFile.files[0]; const response = await fetch(apiUrl, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': blob.type || 'image/jpeg' }, body: blob }); const result = await response.json(); console.log('Upload result:', result); console.log('Reference ID:', result.mediaGenerationId.mediaGenerationId); console.log('Account used:', result.email); ``` {% endtab %} {% tab v1_post_assets_email_example Python %} ``` python import requests from urllib.parse import quote token = 'YOUR_API_TOKEN' # Option 1: Without email (auto-selection/load balancing) api_url = 'https://api.useapi.net/v1/google-flow/assets' # Option 2: With specific email # email = 'john@gmail.com' # api_url = f'https://api.useapi.net/v1/google-flow/assets/{quote(email)}' # Load image - Example 1: Fetch from URL # image_url = "https://upload.wikimedia.org/wikipedia/commons/7/7d/Mona_Lisa_color_restoration.jpg" # response_image = requests.get(image_url) # file_content = response_image.content # Load image - Example 2: From local file # image_file_path = "./image.jpg" # with open(image_file_path, 'rb') as image_file: # file_content = image_file.read() headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'image/jpeg' } response = requests.post( api_url, headers=headers, data=file_content ) result = response.json() print('Upload result:', result) print('Reference ID:', result.get('mediaGenerationId', {}).get('mediaGenerationId')) print('Account used:', result.get('email')) ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-images-upscale === Document URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-images-upscale --- layout: default title: POST images/upscale parent: Google Flow API v1 nav_order: 650 --- ## Upscale Images {: .no_toc } January 2, 2026 ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Upscale a previously generated image to 2K or 4K resolution. This endpoint uses Google Flow's native image upscaling capabilities. **Important:** - Upscaling is only supported for images generated with `nano-banana-pro` model. Other models (`imagen-4`, `nano-banana`) will return a `429` error. - `4k` resolution requires a paid Google account with an active subscription. Free accounts can only use `2k` resolution. {: .post } > **https://api.useapi.net/v1/google-flow/images/upscale** ### Request Headers ``` yaml Authorization: Bearer {API token} Content-Type: application/json # Alternatively you can use multipart/form-data # Content-Type: multipart/form-data ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Request Body ```json { "mediaGenerationId": "user:12345-email:6a6f...-image:CAMaJDMx...", "resolution": "2k" } ``` - `mediaGenerationId` is **required**. The `mediaGenerationId` from a previously generated image via [POST /images](https://useapi.net/docs/api-google-flow-v1/post-google-flow-images). - `resolution` is optional. Target resolution for upscaling (default: `2k`). Supported values: `2k`, `4k`. - `captchaRetry` is optional, number of captcha retry attempts (1-10, default: 3). Cycles through configured [captcha providers](https://useapi.net/docs/api-google-flow-v1/post-google-flow-accounts-captcha-providers) starting with EzCaptcha if available. - `captchaOrder` is optional, explicit captcha provider sequence as comma-separated string (e.g., `"EzCaptcha,EzCaptcha,CapSolver"`). Maximum 10 entries. Each provider must have an API key configured. **Note:** `captchaRetry` and `captchaOrder` are mutually exclusive - only one can be specified per request. ### Responses {% tabs v1_post_images_upscale_response %} {% tab v1_post_images_upscale_response 200 %} 200 OK Image upscaled successfully. Returns base64-encoded image data. ```json { "encodedImage": "/9j/4AAQSkZJRgABAQAAAQ...base64 encoded image data...", "captcha": { "service": "EzCaptcha", "taskId": "abc123...", "durationMs": 3500, "attempts": [ { "service": "EzCaptcha", "taskId": "abc123...", "durationMs": 3500, "success": true } ] } } ``` {% endtab %} {% tab v1_post_images_upscale_response 400 %} 400 Bad Request Invalid request (missing or invalid mediaGenerationId). ```json { "error": "mediaGenerationId is required" } ``` {% endtab %} {% tab v1_post_images_upscale_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% tab v1_post_images_upscale_response 403 %} 403 Forbidden Request rejected by Google. **Recommendations:** - Ensure `captchaRetry` is set to at least 3 (default). Try increasing to a higher value (e.g., 5) to see if that helps - If issues persist, contact [useapi.net support](../support) ```json { "error": { "code": 403, "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "PUBLIC_ERROR_SOMETHING_WENT_WRONG" } ], "message": "reCAPTCHA evaluation failed", "status": "PERMISSION_DENIED" }, "captcha": { "service": "EzCaptcha", "taskId": "ab0251dc-6930-4a82-966a-71fe6ab6aa42", "durationMs": 5789, "attempts": [ { "service": "EzCaptcha", "taskId": "ab0251dc-6930-4a82-966a-71fe6ab6aa42", "durationMs": 5789, "success": true } ] } } ``` {% endtab %} {% tab v1_post_images_upscale_response 404 %} 404 Not Found Account not found or image not found. ```json { "error": "Google Flow account john@gmail.com not found" } ``` {% endtab %} {% tab v1_post_images_upscale_response 429 %} 429 Too Many Requests Upscaling not supported for this image. Only images generated with `nano-banana-pro` model can be upscaled. ```json { "error": { "code": 429, "message": "Resource has been exhausted (e.g. check quota).", "status": "RESOURCE_EXHAUSTED", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "PUBLIC_ERROR_PER_MODEL_DAILY_QUOTA_REACHED_UPGRADEABLE", "metadata": { "canUpgradeForQuota": "true" } } ] }, "captcha": { "service": "EzCaptcha", "taskId": "e07eb626-a824-40e1-ae03-51a631fbe6ef", "durationMs": 3519, "attempts": [ { "service": "EzCaptcha", "taskId": "e07eb626-a824-40e1-ae03-51a631fbe6ef", "durationMs": 3519, "success": true } ] } } ``` {% endtab %} {% endtabs %} ### Model - `encodedImage` - Base64-encoded upscaled image data (JPEG format) - `captcha` - Captcha metadata for debugging/research - `captcha.service` - Provider that returned the successful token - `captcha.taskId` - Task ID from the captcha service - `captcha.durationMs` - Total time for all captcha attempts - `captcha.attempts` - Array of all captcha attempts (including failures) ```typescript { encodedImage: string // Base64-encoded image (decode and save as .jpg) captcha?: { // Captcha metadata service: string // "EzCaptcha" | "CapSolver" | "YesCaptcha" 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 }> } } ``` ### Examples {% tabs v1_post_images_upscale_example %} {% tab v1_post_images_upscale_example Curl %} ``` bash # First generate an image curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"prompt": "A beautiful sunset over mountains"}' \ "https://api.useapi.net/v1/google-flow/images" > generate.json # Extract mediaGenerationId from the response MEDIA_ID=$(jq -r '.media[0].image.generatedImage.mediaGenerationId' generate.json) # Upscale the image to 2K curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"mediaGenerationId\": \"$MEDIA_ID\", \"resolution\": \"2k\"}" \ "https://api.useapi.net/v1/google-flow/images/upscale" > upscale.json # Decode base64 and save as image jq -r '.encodedImage' upscale.json | base64 -d > upscaled_image.jpg ``` {% endtab %} {% tab v1_post_images_upscale_example JavaScript %} ``` javascript const token = 'YOUR_API_TOKEN'; // First generate an image const generateResponse = await fetch('https://api.useapi.net/v1/google-flow/images', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt: 'A beautiful sunset over mountains' }) }); const generated = await generateResponse.json(); const mediaGenerationId = generated.media[0].image.generatedImage.mediaGenerationId; // Upscale the image const upscaleResponse = await fetch('https://api.useapi.net/v1/google-flow/images/upscale', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ mediaGenerationId, resolution: '2k' }) }); const upscaled = await upscaleResponse.json(); // Decode base64 and save const buffer = Buffer.from(upscaled.encodedImage, 'base64'); require('fs').writeFileSync('upscaled_image.jpg', buffer); console.log('Upscaled image saved!'); ``` {% endtab %} {% tab v1_post_images_upscale_example Python %} ``` python import requests import base64 token = 'YOUR_API_TOKEN' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } # First generate an image generate_response = requests.post( 'https://api.useapi.net/v1/google-flow/images', headers=headers, json={'prompt': 'A beautiful sunset over mountains'} ) generated = generate_response.json() media_generation_id = generated['media'][0]['image']['generatedImage']['mediaGenerationId'] # Upscale the image upscale_response = requests.post( 'https://api.useapi.net/v1/google-flow/images/upscale', headers=headers, json={ 'mediaGenerationId': media_generation_id, 'resolution': '2k' } ) upscaled = upscale_response.json() # Decode base64 and save image_data = base64.b64decode(upscaled['encodedImage']) with open('upscaled_image.jpg', 'wb') as f: f.write(image_data) print('Upscaled image saved!') ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-images === Document URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-images --- layout: default title: POST images parent: Google Flow API v1 nav_order: 600 --- ## Generate Images {: .no_toc } November 17, 2025 (January 2, 2026) ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Generate images using AI models [Imagen 4](https://deepmind.google/technologies/imagen-3/), [Nano Banana / Gemini 2.5 Flash Image](https://deepmind.google/technologies/gemini/flash/), and [Nano Banana Pro / Gemini 3 Pro Image](https://deepmind.google/models/gemini-image/pro/) from text prompts with optional reference images. Use any [Google AI](https://one.google.com/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. If you receive a `429 Too Many Requests` or `503 Service Unavailable` response, simply wait 5-10 seconds before retrying—both status codes indicate temporary capacity constraints and are safe to retry. If you consistently receive 429 errors, you may need to execute a cool-off period of at least a few hours before trying again. Image generation typically completes within 10-20 seconds. **Important notes:** - **Content moderation:** If your generation is moderated, retrying with the same prompt often succeeds on subsequent attempts as moderation decisions can vary between requests. Alternatively, switching between `imagen-4`, `nano-banana`, and `nano-banana-pro` models may help, as they have different content moderation behaviors. {: .post } > **https://api.useapi.net/v1/google-flow/images** ### Request Headers ``` yaml Authorization: Bearer {API token} Content-Type: application/json # Alternatively you can use multipart/form-data # Content-Type: multipart/form-data ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Request Body ```json { "prompt": "A serene mountain landscape at sunset with vibrant colors", "model": "imagen-4", "aspectRatio": "landscape", "count": 4, "seed": 123456 } ``` - `email` is optional. The email address of the Google Flow account to use. When only one [account](https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts) is configured, the API will automatically use that account. With multiple [accounts](https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts) configured, omitting the email parameter triggers automatic [load balancing](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs#load-balancing-algorithm) based on **image generation** job statistics to select the healthiest account. If reference images (`reference_1` to `_10`) are provided, the `email` parameter can be omitted—the API will automatically use the same account where the images were uploaded. - `prompt` is **required**, text description for image generation. - `model` is optional, the AI model to use for image generation (default: `imagen-4`). Supported values: `imagen-4`, `nano-banana`, `nano-banana-pro` (Ultra accounts only). - `aspectRatio` is optional, output image aspect ratio (default: `landscape`). Supported values: `landscape`, `portrait`. - `count` is optional, number of image variations to generate (1-4, default: `4`). - `seed` is optional, random seed for reproducible results (integer ≥ 0). - `reference_1` to `reference_10` are optional, use `mediaGenerationId` from [POST /assets/`email`](https://useapi.net/docs/api-google-flow-v1/post-google-flow-assets-email) for reference images. `imagen-4` and `nano-banana` support max 3 references, `nano-banana-pro` supports up to 10. - `replyUrl` is optional, webhook URL for job status callbacks. Receives POST requests with job status updates (`created`, `completed`, `failed`). The JSON payload shape matches [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid) response. Callbacks timeout after 5 seconds. - `replyRef` is optional, custom reference string passed back in webhook callbacks. Useful for tracking jobs on your end. - `captchaRetry` is optional, number of captcha retry attempts (1-10, default: 3). Cycles through configured [captcha providers](https://useapi.net/docs/api-google-flow-v1/post-google-flow-accounts-captcha-providers) starting with EzCaptcha if available. - `captchaOrder` is optional, explicit captcha provider sequence as comma-separated string (e.g., `"EzCaptcha,EzCaptcha,CapSolver"`). Maximum 10 entries. Each provider must have an API key configured. **Note:** `captchaRetry` and `captchaOrder` are mutually exclusive - only one can be specified per request. **Auto-detection:** If `model` is not specified: >3 references selects `nano-banana-pro`, 1-3 references selects `nano-banana`, no references defaults to `imagen-4`. ### Responses {% tabs v1_post_images_response %} {% tab v1_post_images_response 200 %} 200 OK Images generated successfully. Returns job ID and media array with generated image data. ```json { "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": "EzCaptcha", "taskId": "abc123...", "durationMs": 3500, "attempts": [ { "service": "EzCaptcha", "taskId": "abc123...", "durationMs": 3500, "success": true } ] } } ``` {% endtab %} {% tab v1_post_images_response 400 %} 400 Bad Request Invalid request (validation error, reference count exceeded, email mismatch, or content policy violation). **General error:** ```json { "error": "Invalid request parameters" } ``` **Content policy error:** ```json { "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" } ] } } ``` {% endtab %} {% tab v1_post_images_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% tab v1_post_images_response 402 %} 402 Payment Required Subscription expired or insufficient credits. ```json { "error": "Account has no subscription or subscription expired" } ``` {% endtab %} {% tab v1_post_images_response 403 %} 403 Forbidden Request rejected by Google. **Recommendations:** - Ensure `captchaRetry` is set to at least 3 (default). Try increasing to a higher value (e.g., 5) to see if that helps - If issues persist, contact [useapi.net support](../support) ```json { "code": 403, "created": "2025-12-23T21:54:26.393Z", "error": "API error: 403", "jobid": "j1223215426393445325i-u12345-email:us***@gmail.com-bot:google-flow", "request": { "aspectRatio": "portrait", "count": 4, "email": "us***@gmail.com", "model": "nano-banana-pro", "prompt": "A serene mountain landscape at sunset", "reference_1": { "email": "us***@gmail.com", "id": "CAMaJDMxZGNl...***...YmUwMmM", "referenceId": "user:12345-email:***-image:CAMaJDMxZGNl...***...YmUwMmM", "type": "image", "user": 12345 } }, "response": { "captcha": { "attempts": [ { "service": "EzCaptcha", "taskId": "14af1dbb-885c-4e25-8121-7a79489dfd0e", "durationMs": 5357, "success": true }, { "service": "EzCaptcha", "taskId": "fd044078-0a4a-4303-a585-26fd5d2acb00", "durationMs": 5376, "success": true }, { "service": "EzCaptcha", "taskId": "ab0251dc-6930-4a82-966a-71fe6ab6aa42", "durationMs": 5789, "success": true } ], "durationMs": 18091, "service": "EzCaptcha", "taskId": "ab0251dc-6930-4a82-966a-71fe6ab6aa42" }, "error": { "code": 403, "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "PUBLIC_ERROR_SOMETHING_WENT_WRONG" } ], "message": "reCAPTCHA evaluation failed", "status": "PERMISSION_DENIED" } }, "status": "failed", "type": "image", "updated": "2025-12-23T21:54:45.319Z" } ``` {% endtab %} {% tab v1_post_images_response 404 %} 404 Not Found Account not found or not configured. ```json { "error": "Google Flow account john@gmail.com not found" } ``` {% endtab %} {% tab v1_post_images_response 429 %} 429 Too Many Requests Rate limit or quota exhausted (concurrency limit or account quota reached). Wait 5-10 seconds and retry. If this persists, you may need to cool this account off for a few hours before trying again. **Concurrency/rate limit error:** ```json { "error": { "code": 429, "message": "Resource has been exhausted (e.g. check quota).", "status": "RESOURCE_EXHAUSTED", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "PUBLIC_ERROR_USER_REQUESTS_THROTTLED" } ] } } ``` **Per-model daily quota reached (e.g., using `nano-banana-pro` on non-Ultra account):** ```json { "error": { "code": 429, "message": "Resource has been exhausted (e.g. check quota).", "status": "RESOURCE_EXHAUSTED", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "PUBLIC_ERROR_PER_MODEL_DAILY_QUOTA_REACHED", "metadata": { "canUpgradeForQuota": "true" } } ] } } ``` {% endtab %} {% tab v1_post_images_response 500 %} 500 Internal Server Error One or more generated images were moderated by Google's content policy. Try one of the following: - Switch to `imagen-4` model (often successfully processes prompts rejected by `nano-banana`) - Modify your prompt or remove/change reference images - Retry the same request (moderation decisions can vary between attempts) ```json { "error": { "code": 500, "message": "Internal error encountered.", "status": "INTERNAL" } } ``` {% endtab %} {% tab v1_post_images_response 503 %} 503 Service Unavailable Service temporarily unavailable. Wait 5-10 seconds and retry. ```json { "error": { "code": 503, "message": "Service temporarily unavailable.", "status": "UNAVAILABLE", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "SERVICE_UNAVAILABLE" } ] } } ``` {% endtab %} {% tab v1_post_images_response 596 %} 596 Session Error Google session refresh failed. The account cookies needs to be updated following the instructions in [Setup Google Flow](../start-here/setup-google-flow). ```json { "error": "Failed to refresh session." } ``` {% endtab %} {% endtabs %} ### Model - `jobId` - Unique job identifier (for use with [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid)) - `media` - Array of generated images (1-4 images based on `count`) - `media[].image.generatedImage` - Generated image data object - **`generatedImage.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 calls - `generatedImage.prompt` - The prompt used for generation - `generatedImage.modelNameType` - Model variant used (`IMAGEN_3_5`, `R2I`, `GEM_PIX`) - `generatedImage.aspectRatio` - Generated image aspect ratio (`IMAGE_ASPECT_RATIO_LANDSCAPE` or `IMAGE_ASPECT_RATIO_PORTRAIT`) - `generatedImage.mediaVisibility` - Visibility setting (always "PRIVATE") - `generatedImage.workflowId` - Unique workflow identifier - `generatedImage.requestData` - Request data used for this generation including prompt inputs and reference images - `media[].name` - Internal identifier for the media item - `media[].workflowId` - Unique workflow identifier for this generation - `captcha` - Captcha metadata for debugging/research - `captcha.service` - Provider that returned the successful token - `captcha.taskId` - Task ID from the captcha service - `captcha.durationMs` - Total time for all captcha attempts - `captcha.attempts` - Array of all captcha attempts (including failures) ```typescript { 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" workflowId: string fifeUrl: string // Direct signed URL to generated image aspectRatio: string // "IMAGE_ASPECT_RATIO_LANDSCAPE" | "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 // "EzCaptcha" | "CapSolver" | "YesCaptcha" 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 } }> } } ``` ### Examples {% tabs v1_post_images_example %} {% tab v1_post_images_example Curl %} ``` bash 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": "landscape", "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... ``` {% endtab %} {% tab v1_post_images_example JavaScript %} ``` javascript 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: 'landscape', 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 element // const url = URL.createObjectURL(imageBlob); // document.querySelector('img').src = url; } ``` {% endtab %} {% tab v1_post_images_example Python %} ``` python 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': 'landscape', '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) ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-concatenate === Document URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-concatenate --- layout: default title: POST videos/concatenate parent: Google Flow API v1 nav_order: 740 --- ## Concatenate Videos {: .no_toc } January 29, 2026 ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Concatenate multiple previously generated videos into a single video. This is a synchronous operation that returns base64-encoded video data. - Combines 2-10 videos into a single video file. - All videos must have the same aspect ratio (all landscape or all portrait). - No captcha required - this endpoint doesn't require reCAPTCHA solving. - Optional trimming allows removing frames from the start/end of each video for smoother transitions. - Returns large base64-encoded video data (~7MB per input video). - Concatenation typically completes within 15-20 seconds. {: .post } > **https://api.useapi.net/v1/google-flow/videos/concatenate** ### Request Headers ``` yaml Authorization: Bearer {API token} Content-Type: application/json ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Request Body ```json { "media": [ { "mediaGenerationId": "user:12345-email:6a6f...-video:CAMaJDMx..." }, { "mediaGenerationId": "user:12345-email:6a6f...-video:CAMaJDMy...", "trimStart": 0.5 }, { "mediaGenerationId": "user:12345-email:6a6f...-video:CAMaJDMz...", "trimEnd": 1 } ] } ``` - `media` is **required**. Array of 2-10 video references to concatenate. Each item contains: - `mediaGenerationId` is **required**. The `mediaGenerationId` from a previously generated or extended video. - `trimStart` is optional. Seconds to trim from the start of this video (0-8, default: 0). When concatenating extended videos, use `trimStart: 1` to remove the ~1 second overlap with the source video. - `trimEnd` is optional. Seconds to trim from the end of this video (0-8, default: 0). **Notes:** - All videos must belong to the same Google Flow account (same email). - All videos must have the same aspect ratio. - Videos are concatenated in the order provided. ### Responses {% tabs v1_post_videos_concatenate_response %} {% tab v1_post_videos_concatenate_response 200 %} 200 OK Videos concatenated successfully. Returns job ID and base64-encoded video data. ```json { "jobId": "j1737312345678v-u12345-email:jo***@gmail.com-bot:google-flow", "status": "MEDIA_GENERATION_STATUS_SUCCESSFUL", "inputsCount": 3, "encodedVideo": "AAAAIGZ0eXBpc29t...~21MB base64..." } ``` {% endtab %} {% tab v1_post_videos_concatenate_response 400 %} 400 Bad Request Invalid request. ```json { "error": "Error message", "code": 400 } ``` {% endtab %} {% tab v1_post_videos_concatenate_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% tab v1_post_videos_concatenate_response 404 %} 404 Not Found Account not found or video not found. ```json { "error": "Google Flow account john@gmail.com not found" } ``` {% endtab %} {% tab v1_post_videos_concatenate_response 408 %} 408 Request Timeout Concatenation polling timeout (after 3 minutes). ```json { "error": "Polling timeout" } ``` {% endtab %} {% endtabs %} ### Model ```typescript { jobId: string // Job identifier status: string // MEDIA_GENERATION_STATUS_SUCCESSFUL | FAILED inputsCount: number // Number of input videos encodedVideo: string // Base64-encoded MP4 (~7MB per input, decode and save as .mp4) error?: string | { // Error: string (useapi.net) or object (Google API) code: number message: string status: string details?: Array<{ '@type': string reason: string }> } } ``` ### Examples {% tabs v1_post_videos_concatenate_example %} {% tab v1_post_videos_concatenate_example Curl %} ``` bash # Generate first video curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"prompt": "A serene mountain landscape at sunrise"}' \ "https://api.useapi.net/v1/google-flow/videos" > video1.json # Generate second video (or extend the first) curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"prompt": "The sun rises higher, birds fly across the sky"}' \ "https://api.useapi.net/v1/google-flow/videos" > video2.json # Extract mediaGenerationIds VIDEO1_ID=$(jq -r '.operations[0].mediaGenerationId' video1.json) VIDEO2_ID=$(jq -r '.operations[0].mediaGenerationId' video2.json) # Concatenate videos curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"media\": [{\"mediaGenerationId\": \"$VIDEO1_ID\"}, {\"mediaGenerationId\": \"$VIDEO2_ID\", \"trimStart\": 0.5}]}" \ "https://api.useapi.net/v1/google-flow/videos/concatenate" > concat.json # Decode base64 and save as MP4 jq -r '.encodedVideo' concat.json | base64 -d > concatenated_video.mp4 ``` {% endtab %} {% tab v1_post_videos_concatenate_example JavaScript %} ``` javascript const token = 'YOUR_API_TOKEN'; // Assume you have two video mediaGenerationIds const videoId1 = 'user:12345-email:6a6f...-video:CAMaJDMx...'; const videoId2 = 'user:12345-email:6a6f...-video:CAMaJDMy...'; // Concatenate videos const concatResponse = await fetch('https://api.useapi.net/v1/google-flow/videos/concatenate', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ media: [ { mediaGenerationId: videoId1 }, { mediaGenerationId: videoId2, trimStart: 0.5 } // Trim 0.5s from start for smooth transition ] }) }); const result = await concatResponse.json(); // Decode base64 and save (Node.js) const buffer = Buffer.from(result.encodedVideo, 'base64'); require('fs').writeFileSync('concatenated_video.mp4', buffer); console.log('Concatenated video saved!'); // Or use in browser as data URL for preview const dataUrl = `data:video/mp4;base64,${result.encodedVideo}`; document.getElementById('video-player').src = dataUrl; ``` {% endtab %} {% tab v1_post_videos_concatenate_example Python %} ``` python import requests import base64 token = 'YOUR_API_TOKEN' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } # Assume you have two video mediaGenerationIds video_id_1 = 'user:12345-email:6a6f...-video:CAMaJDMx...' video_id_2 = 'user:12345-email:6a6f...-video:CAMaJDMy...' # Concatenate videos concat_response = requests.post( 'https://api.useapi.net/v1/google-flow/videos/concatenate', headers=headers, json={ 'media': [ {'mediaGenerationId': video_id_1}, {'mediaGenerationId': video_id_2, 'trimStart': 0.5} # Trim 0.5s for smooth transition ] } ) result = concat_response.json() # Decode base64 and save video_data = base64.b64decode(result['encodedVideo']) with open('concatenated_video.mp4', 'wb') as f: f.write(video_data) print(f'Concatenated video saved! ({len(video_data)} bytes)') ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-extend === Document URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-extend --- layout: default title: POST videos/extend parent: Google Flow API v1 nav_order: 730 --- ## Extend Videos {: .no_toc } January 29, 2026 ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Extend a previously generated video with a new prompt. Creates an additional 8-second segment that continues from the last ~1 second of the source video. - Video extension requires a paid [Google AI](https://one.google.com/ai) subscription with remaining credits. - The extended video inherits the aspect ratio from the source video (landscape or portrait). - Extended videos have ~1 second overlap with the source video's last frame. Use `trimStart` in [POST /videos/concatenate](https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-concatenate) to remove overlap when combining clips. {: .post } > **https://api.useapi.net/v1/google-flow/videos/extend** ### Request Headers ``` yaml Authorization: Bearer {API token} Content-Type: application/json ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Request Body ```json { "mediaGenerationId": "user:12345-email:6a6f...-video:CAMaJDMx...", "prompt": "The camera slowly pans right revealing a majestic waterfall" } ``` - `mediaGenerationId` is **required**. The `mediaGenerationId` from a previously generated or extended video via [POST /videos](https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos) or [POST /videos/extend](https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-extend). - `prompt` is **required**. Text description for the video extension (what happens next). - `model` is optional. Video generation model (default: `veo-3.1-fast`). Supported values: `veo-3.1-fast`, `veo-3.1-fast-relaxed` (Ultra only), `veo-3.1-quality`. - `count` is optional. Number of video variations to generate (1-4, default: 1). Each variation uses a different seed. - `seed` is optional. Random seed for reproducible results. If not specified, a random seed is generated. When `count` > 1, seeds are incremented (seed, seed+1, seed+2, ...). - `async` is optional, enables fire-and-forget mode (default: `false`). When `true`, returns immediately with `201 Created` and job metadata. Poll [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid) for completion status. - `replyUrl` is optional, webhook URL for job status callbacks. Receives POST requests with job status updates (`created`, `started`, `completed`, `failed`). The JSON payload shape matches [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid) response. - `replyRef` is optional, custom reference string passed back in webhook callbacks. - `captchaRetry` is optional, number of captcha retry attempts (1-10, default: 3). Cycles through configured [captcha providers](https://useapi.net/docs/api-google-flow-v1/post-google-flow-accounts-captcha-providers) starting with EzCaptcha if available. - `captchaOrder` is optional, explicit captcha provider sequence as comma-separated string (e.g., `"EzCaptcha,EzCaptcha,CapSolver"`). Maximum 10 entries. Each provider must have an API key configured. **Note:** `captchaRetry` and `captchaOrder` are mutually exclusive - only one can be specified per request. ### Responses {% tabs v1_post_videos_extend_response %} {% tab v1_post_videos_extend_response 200 %} 200 OK Video extended successfully. Returns job ID and operations array with extended video URLs. ```json { "jobId": "j1737312345678v-u12345-email:jo***@gmail.com-bot:google-flow", "operations": [ { "operation": { "name": "d00af...redacted...6f7a", "metadata": { "@type": "type.googleapis.com/google.internal.labs.aisandbox.v1.Media", "name": "CAUSJ...redacted...OWQ5ZA", "video": { "seed": 987654321, "mediaGenerationId": "user:12345-email:6a6f...-video:CAUSJ...redacted", "prompt": "The camera slowly pans right revealing a majestic waterfall", "fifeUrl": "https://storage.googleapis.com/ai-sandbox-videofx/video/...redacted...", "mediaVisibility": "PRIVATE", "servingBaseUri": "https://storage.googleapis.com/ai-sandbox-videofx/image/...redacted...", "model": "veo_3_1_t2v", "isLooped": false, "aspectRatio": "VIDEO_ASPECT_RATIO_LANDSCAPE" } } }, "sceneId": "323c0...redacted...3ebf6", "mediaGenerationId": "user:12345-email:6a6f...-video:CAUSJ...redacted", "status": "MEDIA_GENERATION_STATUS_SUCCESSFUL" } ], "captcha": { "service": "EzCaptcha", "taskId": "abc123...", "durationMs": 3500, "attempts": [ { "service": "EzCaptcha", "taskId": "abc123...", "durationMs": 3500, "success": true } ] } } ``` {% endtab %} {% tab v1_post_videos_extend_response 201 %} 201 Created Job created in async mode (`async: true`). Video extension is processing in the background. Use [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid) to poll for completion status. ```json { "jobid": "j1737312345678v-u12345-email:jo***@gmail.com-bot:google-flow", "type": "video", "status": "created", "created": "2026-01-29T12:34:56.789Z", "request": { "async": true, "prompt": "The camera slowly pans right revealing a majestic waterfall", "mediaGenerationId": "user:12345-email:6a6f...-video:CAMaJDMx..." }, "response": { "operations": [ { "operation": { "name": "1450903d...redacted...9c86f0" }, "sceneId": "1450903d...redacted...9c86f0", "status": "MEDIA_GENERATION_STATUS_PENDING" } ], "captcha": { "service": "EzCaptcha", "taskId": "14af1dbb-885c-4e25-8121-7a79489dfd0e", "durationMs": 5357 } } } ``` {% endtab %} {% tab v1_post_videos_extend_response 400 %} 400 Bad Request Invalid request. ```json { "error": "Error message", "code": 400 } ``` {% endtab %} {% tab v1_post_videos_extend_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% tab v1_post_videos_extend_response 403 %} 403 Forbidden Request rejected by Google. **Recommendations:** - Ensure `captchaRetry` is set to at least 3 (default). Try increasing to a higher value (e.g., 5) to see if that helps - If issues persist, contact [useapi.net support](../support) ```json { "error": { "code": 403, "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "PUBLIC_ERROR_SOMETHING_WENT_WRONG" } ], "message": "reCAPTCHA evaluation failed", "status": "PERMISSION_DENIED" } } ``` {% endtab %} {% tab v1_post_videos_extend_response 404 %} 404 Not Found Account not found or video not found. ```json { "error": "Google Flow account john@gmail.com not found" } ``` {% endtab %} {% tab v1_post_videos_extend_response 408 %} 408 Request Timeout Video extension polling timeout (after 10 minutes). ```json { "error": "Polling timeout" } ``` {% endtab %} {% endtabs %} ### Model {% tabs v1_post_videos_extend_model %} {% tab v1_post_videos_extend_model 200 OK (Sync) %} Video extension completed. Returns extended video data with signed URLs. ```typescript { jobId: string // Job identifier operations: Array<{ operation?: { name: string metadata: { '@type': string name: string video: { seed: number mediaGenerationId: string // Reference ID for the extended video prompt: string // Extension prompt fifeUrl: string // Signed video URL (MP4, valid ~24h) mediaVisibility: string servingBaseUri: string // Signed thumbnail URL (JPEG, valid ~24h) model: string // veo_3_1_t2v isLooped: boolean aspectRatio: string // VIDEO_ASPECT_RATIO_LANDSCAPE | PORTRAIT } } } sceneId: string mediaGenerationId: string status: string // MEDIA_GENERATION_STATUS_SUCCESSFUL | FAILED }> captcha?: { // Captcha metadata service: string // "EzCaptcha" | "CapSolver" | "YesCaptcha" taskId: string durationMs: number attempts: Array<{ service: string taskId?: string durationMs: number success: boolean error?: string }> } } ``` {% endtab %} {% tab v1_post_videos_extend_model 201 Created (Async) %} Job created and processing in background. Structure matches [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid) response. ```typescript { jobid: string // Job identifier type: 'video' // Job type status: 'created' // Job status created: string // ISO 8601 timestamp request: { async: true prompt: string // Extension prompt mediaGenerationId: string // Source video reference model?: string // "veo-3.1-fast" seed?: number replyUrl?: string replyRef?: string } response: { operations: Array<{ operation: { name: string // Operation identifier } sceneId: string // Scene identifier status: 'MEDIA_GENERATION_STATUS_PENDING' }> captcha?: { // Present when captcha was used service: string taskId: string durationMs: number } } } ``` {% endtab %} {% tab v1_post_videos_extend_model Error %} Error response structure. ```typescript { jobId?: string // Present for job-related errors error: string // Error summary message code?: number // HTTP status code response?: { // API response with error details error?: { code: number message: string status: string details?: Array<{ '@type': string reason: string }> } } } ``` {% endtab %} {% endtabs %} ### Examples {% tabs v1_post_videos_extend_example %} {% tab v1_post_videos_extend_example Curl %} ``` bash # First generate a video curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"prompt": "A serene mountain landscape at sunset"}' \ "https://api.useapi.net/v1/google-flow/videos" > generate.json # Extract mediaGenerationId from the response MEDIA_ID=$(jq -r '.operations[0].mediaGenerationId' generate.json) # Extend the video curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"mediaGenerationId\": \"$MEDIA_ID\", \"prompt\": \"The camera slowly pans right revealing a majestic waterfall\"}" \ "https://api.useapi.net/v1/google-flow/videos/extend" > extend.json # Extract extended video URL and download VIDEO_URL=$(jq -r '.operations[0].operation.metadata.video.fifeUrl' extend.json) curl "$VIDEO_URL" --output extended_video.mp4 ``` {% endtab %} {% tab v1_post_videos_extend_example JavaScript %} ``` javascript const token = 'YOUR_API_TOKEN'; // First generate a video const generateResponse = await fetch('https://api.useapi.net/v1/google-flow/videos', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt: 'A serene mountain landscape at sunset' }) }); const generated = await generateResponse.json(); const mediaGenerationId = generated.operations[0].mediaGenerationId; // Extend the video const extendResponse = await fetch('https://api.useapi.net/v1/google-flow/videos/extend', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ mediaGenerationId, prompt: 'The camera slowly pans right revealing a majestic waterfall' }) }); const extended = await extendResponse.json(); const videoUrl = extended.operations[0].operation.metadata.video.fifeUrl; // Download extended video (Node.js) const videoResponse = await fetch(videoUrl); const videoBuffer = await videoResponse.arrayBuffer(); require('fs').writeFileSync('extended_video.mp4', Buffer.from(videoBuffer)); console.log('Extended video saved!'); ``` {% endtab %} {% tab v1_post_videos_extend_example Python %} ``` python import requests token = 'YOUR_API_TOKEN' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } # First generate a video generate_response = requests.post( 'https://api.useapi.net/v1/google-flow/videos', headers=headers, json={'prompt': 'A serene mountain landscape at sunset'} ) generated = generate_response.json() media_generation_id = generated['operations'][0]['mediaGenerationId'] # Extend the video extend_response = requests.post( 'https://api.useapi.net/v1/google-flow/videos/extend', headers=headers, json={ 'mediaGenerationId': media_generation_id, 'prompt': 'The camera slowly pans right revealing a majestic waterfall' } ) extended = extend_response.json() video_url = extended['operations'][0]['operation']['metadata']['video']['fifeUrl'] # Download extended video video_response = requests.get(video_url) with open('extended_video.mp4', 'wb') as f: f.write(video_response.content) print('Extended video saved!') ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-gif === Document URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-gif --- layout: default title: POST videos/gif parent: Google Flow API v1 nav_order: 720 --- ## Generate Video GIF {: .no_toc } January 20, 2026 ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Generate an animated GIF preview from a previously generated video. This is a synchronous operation that returns base64-encoded GIF data. - No captcha required - this endpoint doesn't require reCAPTCHA solving. - GIF generation can take up to 90 seconds. {: .post } > **https://api.useapi.net/v1/google-flow/videos/gif** ### Request Headers ``` yaml Authorization: Bearer {API token} Content-Type: application/json # Alternatively you can use multipart/form-data # Content-Type: multipart/form-data ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Request Body ```json { "mediaGenerationId": "user:12345-email:6a6f...-video:CAMaJDMx..." } ``` - `mediaGenerationId` is **required**. The `mediaGenerationId` from a previously generated video via [POST /videos](https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos). ### Responses {% tabs v1_post_videos_gif_response %} {% tab v1_post_videos_gif_response 200 %} 200 OK GIF generated successfully. Returns base64-encoded GIF data. ```json { "encodedGif": "R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7...base64 encoded GIF data..." } ``` {% endtab %} {% tab v1_post_videos_gif_response 400 %} 400 Bad Request Invalid request (missing or invalid mediaGenerationId). ```json { "error": "mediaGenerationId is required" } ``` **Invalid reference type:** ```json { "error": "mediaGenerationId type must be 'video', got 'image'" } ``` {% endtab %} {% tab v1_post_videos_gif_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% tab v1_post_videos_gif_response 404 %} 404 Not Found Account not found or video not found. ```json { "error": "Google Flow account john@gmail.com not found" } ``` {% endtab %} {% endtabs %} ### Model ```typescript { encodedGif: string // Base64-encoded GIF data (decode and save as .gif) error?: string | { // Error: string (useapi.net) or object (Google API) code: number message: string status: string details?: Array<{ '@type': string reason: string }> } } ``` ### Examples {% tabs v1_post_videos_gif_example %} {% tab v1_post_videos_gif_example Curl %} ``` bash # First generate a video curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"prompt": "A serene mountain landscape at sunset"}' \ "https://api.useapi.net/v1/google-flow/videos" > generate.json # Extract mediaGenerationId from the response MEDIA_ID=$(jq -r '.operations[0].mediaGenerationId' generate.json) # Generate GIF preview curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"mediaGenerationId\": \"$MEDIA_ID\"}" \ "https://api.useapi.net/v1/google-flow/videos/gif" > gif.json # Decode base64 and save as GIF jq -r '.encodedGif' gif.json | base64 -d > video_preview.gif ``` {% endtab %} {% tab v1_post_videos_gif_example JavaScript %} ``` javascript const token = 'YOUR_API_TOKEN'; // First generate a video const generateResponse = await fetch('https://api.useapi.net/v1/google-flow/videos', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt: 'A serene mountain landscape at sunset' }) }); const generated = await generateResponse.json(); const mediaGenerationId = generated.operations[0].mediaGenerationId; // Generate GIF preview const gifResponse = await fetch('https://api.useapi.net/v1/google-flow/videos/gif', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ mediaGenerationId }) }); const gifResult = await gifResponse.json(); // Decode base64 and save (Node.js) const buffer = Buffer.from(gifResult.encodedGif, 'base64'); require('fs').writeFileSync('video_preview.gif', buffer); console.log('GIF preview saved!'); // Or use in browser as data URL const dataUrl = `data:image/gif;base64,${gifResult.encodedGif}`; document.getElementById('preview').src = dataUrl; ``` {% endtab %} {% tab v1_post_videos_gif_example Python %} ``` python import requests import base64 token = 'YOUR_API_TOKEN' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } # First generate a video generate_response = requests.post( 'https://api.useapi.net/v1/google-flow/videos', headers=headers, json={'prompt': 'A serene mountain landscape at sunset'} ) generated = generate_response.json() media_generation_id = generated['operations'][0]['mediaGenerationId'] # Generate GIF preview gif_response = requests.post( 'https://api.useapi.net/v1/google-flow/videos/gif', headers=headers, json={'mediaGenerationId': media_generation_id} ) gif_result = gif_response.json() # Decode base64 and save gif_data = base64.b64decode(gif_result['encodedGif']) with open('video_preview.gif', 'wb') as f: f.write(gif_data) print('GIF preview saved!') ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-upscale === Document URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos-upscale --- layout: default title: POST videos/upscale parent: Google Flow API v1 nav_order: 710 --- ## Upscale Videos {: .no_toc } January 20, 2026 ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Upscale a previously generated video to 1080p or 4K resolution. - Currently, video upscaling requires a paid [Google AI](https://one.google.com/ai) subscription or remaining credits. - Currently, `4K` resolution requires a [Google AI Ultra](https://one.google.com/ai) subscription. Other paid accounts can only use `1080p` resolution. - `1080p` upscaling is free. `4K` upscaling currently costs 50 credits. - Video upscaling typically completes within 30-60 seconds, with 4K taking a few minutes. - Upscaling the same video twice returns a cached result (no additional credits consumed). Use the video URL from the first upscale response. {: .post } > **https://api.useapi.net/v1/google-flow/videos/upscale** ### Request Headers ``` yaml Authorization: Bearer {API token} Content-Type: application/json # Alternatively you can use multipart/form-data # Content-Type: multipart/form-data ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Request Body ```json { "mediaGenerationId": "user:12345-email:6a6f...-video:CAMaJDMx...", "resolution": "1080p" } ``` - `mediaGenerationId` is **required**. The `mediaGenerationId` from a previously generated video via [POST /videos](https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos). - `resolution` is optional. Target resolution for upscaling (default: `1080p`). Supported values: `1080p`, `4K`. - `async` is optional, enables fire-and-forget mode (default: `false`). When `true`, returns immediately with `201 Created` and job metadata. Poll [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid) for completion status. - `replyUrl` is optional, webhook URL for job status callbacks. Receives POST requests with job status updates (`created`, `started`, `completed`, `failed`). The JSON payload shape matches [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid) response. - `replyRef` is optional, custom reference string passed back in webhook callbacks. - `captchaRetry` is optional, number of captcha retry attempts (1-10, default: 3). Cycles through configured [captcha providers](https://useapi.net/docs/api-google-flow-v1/post-google-flow-accounts-captcha-providers) starting with EzCaptcha if available. - `captchaOrder` is optional, explicit captcha provider sequence as comma-separated string (e.g., `"EzCaptcha,EzCaptcha,CapSolver"`). Maximum 10 entries. Each provider must have an API key configured. **Note:** `captchaRetry` and `captchaOrder` are mutually exclusive - only one can be specified per request. ### Responses {% tabs v1_post_videos_upscale_response %} {% tab v1_post_videos_upscale_response 200 %} 200 OK Video upscaled successfully. Returns job ID and operations array with upscaled video URLs. ```json { "jobId": "j1737312345678v-u12345-email:jo***@gmail.com-bot:google-flow", "operations": [ { "operation": { "name": "d00af...redacted...6f7a", "metadata": { "@type": "type.googleapis.com/google.internal.labs.aisandbox.v1.Media", "name": "CAUSJ...redacted...OWQ5ZA", "video": { "seed": 987654321, "mediaGenerationId": "user:12345-email:6a6f...-video:CAUSJ...redacted", "prompt": "Original video prompt", "fifeUrl": "https://storage.googleapis.com/ai-sandbox-videofx/video/...redacted...", "mediaVisibility": "PRIVATE", "servingBaseUri": "https://storage.googleapis.com/ai-sandbox-videofx/image/...redacted...", "model": "veo_3_1_upsampler_1080p", "isLooped": false, "aspectRatio": "VIDEO_ASPECT_RATIO_LANDSCAPE" } } }, "sceneId": "323c0...redacted...3ebf6", "mediaGenerationId": "user:12345-email:6a6f...-video:CAUSJ...redacted", "status": "MEDIA_GENERATION_STATUS_SUCCESSFUL" } ], "captcha": { "service": "EzCaptcha", "taskId": "abc123...", "durationMs": 3500, "attempts": [ { "service": "EzCaptcha", "taskId": "abc123...", "durationMs": 3500, "success": true } ] } } ``` {% endtab %} {% tab v1_post_videos_upscale_response 201 %} 201 Created Job created in async mode (`async: true`). Video upscaling is processing in the background. Use [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid) to poll for completion status. ```json { "jobid": "j1737312345678v-u12345-email:jo***@gmail.com-bot:google-flow", "type": "video", "status": "created", "created": "2026-01-19T12:34:56.789Z", "request": { "async": true, "mediaGenerationId": "user:12345-email:6a6f...-video:CAMaJDMx...", "resolution": "1080p" }, "response": { "operations": [ { "operation": { "name": "1450903d...redacted...9c86f0" }, "sceneId": "1450903d...redacted...9c86f0", "status": "MEDIA_GENERATION_STATUS_PENDING" } ], "captcha": { "service": "EzCaptcha", "taskId": "14af1dbb-885c-4e25-8121-7a79489dfd0e", "durationMs": 5357 } } } ``` {% endtab %} {% tab v1_post_videos_upscale_response 400 %} 400 Bad Request Invalid request. ```json { "error": "Error message" } ``` {% endtab %} {% tab v1_post_videos_upscale_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% tab v1_post_videos_upscale_response 403 %} 403 Forbidden Request rejected by Google. **Recommendations:** - Ensure `captchaRetry` is set to at least 3 (default). Try increasing to a higher value (e.g., 5) to see if that helps - If issues persist, contact [useapi.net support](../support) ```json { "error": { "code": 403, "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "PUBLIC_ERROR_SOMETHING_WENT_WRONG" } ], "message": "reCAPTCHA evaluation failed", "status": "PERMISSION_DENIED" }, "captcha": { "service": "EzCaptcha", "taskId": "ab0251dc-6930-4a82-966a-71fe6ab6aa42", "durationMs": 5789, "attempts": [ { "service": "EzCaptcha", "taskId": "ab0251dc-6930-4a82-966a-71fe6ab6aa42", "durationMs": 5789, "success": true } ] } } ``` {% endtab %} {% tab v1_post_videos_upscale_response 404 %} 404 Not Found Account not found or video not found. ```json { "error": "Google Flow account john@gmail.com not found" } ``` {% endtab %} {% tab v1_post_videos_upscale_response 408 %} 408 Request Timeout Video upscaling polling timeout (after 10 minutes). ```json { "error": "Polling timeout" } ``` {% endtab %} {% endtabs %} ### Model {% tabs v1_post_videos_upscale_model %} {% tab v1_post_videos_upscale_model 200 OK (Sync) %} Video upscaling completed. Returns upscaled video data with signed URLs. Re-upscaling the same video returns `rawBytes` (base64 video data) instead of URLs. ```typescript { jobId: string // Job identifier operations: Array<{ operation?: { name: string metadata: { '@type': string name: string video: { seed: number mediaGenerationId: string // Reference ID for the upscaled video prompt: string // Original video prompt fifeUrl: string // Signed video URL (MP4, valid ~24h) mediaVisibility: string servingBaseUri: string // Signed thumbnail URL (JPEG, valid ~24h) model: string // veo_3_1_upsampler_1080p | veo_3_1_upsampler_4k isLooped: boolean aspectRatio: string // VIDEO_ASPECT_RATIO_LANDSCAPE | PORTRAIT } } } rawBytes?: string // Base64 video data (present when re-upscaling same video) sceneId: string mediaGenerationId: string status: string // MEDIA_GENERATION_STATUS_SUCCESSFUL | FAILED }> captcha?: { // Captcha metadata service: string // "EzCaptcha" | "CapSolver" | "YesCaptcha" taskId: string durationMs: number attempts: Array<{ service: string taskId?: string durationMs: number success: boolean error?: string }> } } ``` {% endtab %} {% tab v1_post_videos_upscale_model 201 Created (Async) %} Job created and processing in background. Structure matches [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid) response. ```typescript { jobid: string // Job identifier type: 'video' // Job type status: 'created' // Job status created: string // ISO 8601 timestamp request: { async: true mediaGenerationId: string // Original video reference resolution?: string // "1080p" | "4K" replyUrl?: string replyRef?: string } response: { operations: Array<{ operation: { name: string // Operation identifier } sceneId: string // Scene identifier status: 'MEDIA_GENERATION_STATUS_PENDING' }> captcha?: { // Present when captcha was used service: string taskId: string durationMs: number } } } ``` {% endtab %} {% tab v1_post_videos_upscale_model Error %} Error response structure. ```typescript { jobId?: string // Present for job-related errors error: string // Error summary message code?: number // HTTP status code response?: { // API response with error details error?: { code: number message: string status: string details?: Array<{ '@type': string reason: string }> } } } ``` {% endtab %} {% endtabs %} ### Examples {% tabs v1_post_videos_upscale_example %} {% tab v1_post_videos_upscale_example Curl %} ``` bash # First generate a video curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"prompt": "A serene mountain landscape at sunset"}' \ "https://api.useapi.net/v1/google-flow/videos" > generate.json # Extract mediaGenerationId from the response MEDIA_ID=$(jq -r '.operations[0].mediaGenerationId' generate.json) # Upscale the video to 1080p curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d "{\"mediaGenerationId\": \"$MEDIA_ID\", \"resolution\": \"1080p\"}" \ "https://api.useapi.net/v1/google-flow/videos/upscale" > upscale.json # Extract upscaled video URL and download VIDEO_URL=$(jq -r '.operations[0].operation.metadata.video.fifeUrl' upscale.json) curl "$VIDEO_URL" --output upscaled_video.mp4 ``` {% endtab %} {% tab v1_post_videos_upscale_example JavaScript %} ``` javascript const token = 'YOUR_API_TOKEN'; // First generate a video const generateResponse = await fetch('https://api.useapi.net/v1/google-flow/videos', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt: 'A serene mountain landscape at sunset' }) }); const generated = await generateResponse.json(); const mediaGenerationId = generated.operations[0].mediaGenerationId; // Upscale the video const upscaleResponse = await fetch('https://api.useapi.net/v1/google-flow/videos/upscale', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ mediaGenerationId, resolution: '1080p' }) }); const upscaled = await upscaleResponse.json(); const videoUrl = upscaled.operations[0].operation.metadata.video.fifeUrl; // Download upscaled video (Node.js) const videoResponse = await fetch(videoUrl); const videoBuffer = await videoResponse.arrayBuffer(); require('fs').writeFileSync('upscaled_video.mp4', Buffer.from(videoBuffer)); console.log('Upscaled video saved!'); ``` {% endtab %} {% tab v1_post_videos_upscale_example Python %} ``` python import requests token = 'YOUR_API_TOKEN' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } # First generate a video generate_response = requests.post( 'https://api.useapi.net/v1/google-flow/videos', headers=headers, json={'prompt': 'A serene mountain landscape at sunset'} ) generated = generate_response.json() media_generation_id = generated['operations'][0]['mediaGenerationId'] # Upscale the video upscale_response = requests.post( 'https://api.useapi.net/v1/google-flow/videos/upscale', headers=headers, json={ 'mediaGenerationId': media_generation_id, 'resolution': '1080p' } ) upscaled = upscale_response.json() video_url = upscaled['operations'][0]['operation']['metadata']['video']['fifeUrl'] # Download upscaled video video_response = requests.get(video_url) with open('upscaled_video.mp4', 'wb') as f: f.write(video_response.content) print('Upscaled video saved!') ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos === Document URL: https://useapi.net/docs/api-google-flow-v1/post-google-flow-videos --- layout: default title: POST videos parent: Google Flow API v1 nav_order: 700 --- ## Generate Videos {: .no_toc } November 17, 2025 (January 13, 2026) ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- Generate videos using Google Flow AI models ([Veo 3.1 Quality](https://deepmind.google/technologies/veo/), [Veo 3.1 Fast](https://deepmind.google/technologies/veo/), [Veo 3.1 Fast Relaxed](https://deepmind.google/technologies/veo/)) from text prompts with optional start/end frames or reference images. Videos are returned as signed URLs ready for download. This endpoint features dynamic concurrency management. If you receive a `429 Too Many Requests` or `503 Service Unavailable` response, simply wait 5-10 seconds before retrying—both status codes indicate temporary capacity constraints and are safe to retry. If you consistently receive 429 errors, you may need to execute a cool-off period of at least a few hours before trying again. Video generation typically completes within 60-180 seconds depending on the model and mode. The endpoint automatically polls for completion and returns the final result. Use a [Google AI Ultra](https://one.google.com/ai) $125/m special subscription plan for `Veo 3.1 Fast` $5cents/video and `Veo 3.1 Quality` $50cents/video generations. `Veo 3.1 Fast Relaxed` is available for Ultra subscribers with no credit cost but lower generation priority. ### Model Capabilities | Parameter | [Veo 3.1 Quality](https://deepmind.google/technologies/veo/)
`veo-3.1-quality` | [Veo 3.1 Fast](https://deepmind.google/technologies/veo/)
`veo-3.1-fast` (default) | [Veo 3.1 Fast Relaxed](https://deepmind.google/technologies/veo/)
`veo-3.1-fast-relaxed` | |-----------|:---:|:---:|:---:| | T2V (text-to-video) | ✓ | ✓ | ✓ | | I2V (start frame) | ✓ | ✓ | ✓ | | I2V-FL (start + end) | ✓ | ✓ | ✓ | | R2V (reference images 1-3) | ✗ | ✓ | ✓ | | Aspect ratios | all | all | all | | `count` | ✓ (1-4) | ✓ (1-4) | ✓ (1-4) | | `seed` | ✓ | ✓ | ✓ | | Subscription | all | all | Ultra only | | Cost | 100 credits / $0.50 | 10 credits / $0.05 | free (lower priority) | {: .post } > **https://api.useapi.net/v1/google-flow/videos** ### Request Headers ``` yaml Authorization: Bearer {API token} Content-Type: application/json # Alternatively you can use multipart/form-data # Content-Type: multipart/form-data ``` - `API token` is **required**, see [Setup useapi.net](../start-here/setup-useapi) for details. ### Request Body ```json { "prompt": "A serene mountain landscape at sunset with camera slowly panning right", "model": "veo-3.1-fast", "aspectRatio": "landscape", "count": 2, "seed": 123456 } ``` - `email` is optional. The email address of the Google Flow account to use. When only one [account](https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts) is configured, the API will automatically use that account. With multiple [accounts](https://useapi.net/docs/api-google-flow-v1/get-google-flow-accounts) configured, omitting the email parameter triggers automatic [load balancing](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs#load-balancing-algorithm) based on **video generation** job statistics to select the healthiest account. If reference images (`startImage`, `endImage`, or `referenceImage_1` to `_3`) are provided, the `email` parameter can be omitted—the API will automatically use the same account where the images were uploaded. - `prompt` is **required**, text description for video generation. - `model` is optional, the AI model to use for video generation (default: `veo-3.1-fast`). Supported values: `veo-3.1-quality`, `veo-3.1-fast`, `veo-3.1-fast-relaxed` (Ultra only, no credits, lower priority). - `aspectRatio` is optional, output video aspect ratio (default: `landscape`). Supported values: `landscape` and `portrait`. - `count` is optional, number of video variations to generate (1-4, default: `1`). - `seed` is optional, random seed for reproducible results (integer ≥ 0). - `startImage` is optional, mediaGenerationId from [POST /assets/`email`](https://useapi.net/docs/api-google-flow-v1/post-google-flow-assets-email) for I2V mode (video starts with this frame). - `endImage` is optional, mediaGenerationId from [POST /assets/`email`](https://useapi.net/docs/api-google-flow-v1/post-google-flow-assets-email) for I2V-FL mode (video ends with this frame, requires `startImage`). - `referenceImage_1` to `referenceImage_3` are optional, mediaGenerationId from [POST /assets/`email`](https://useapi.net/docs/api-google-flow-v1/post-google-flow-assets-email) for R2V mode (1-3 reference images for style/composition). Only works with `veo-3.1-fast` and `veo-3.1-fast-relaxed` models. - `async` is optional, enables fire-and-forget mode (default: `false`). When `true`, returns immediately with `201 Created` and job metadata. Poll [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid) for completion status. Useful for avoiding long request timeouts since video generation takes 60-180 seconds. - `replyUrl` is optional, webhook URL for job status callbacks. Receives POST requests with job status updates (`created`, `started`, `completed`, `failed`). The JSON payload shape matches [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid) response. - `replyRef` is optional, custom reference string passed back in webhook callbacks. Useful for tracking jobs on your end. - `captchaRetry` is optional, number of captcha retry attempts (1-10, default: 3). Cycles through configured [captcha providers](https://useapi.net/docs/api-google-flow-v1/post-google-flow-accounts-captcha-providers) starting with EzCaptcha if available. - `captchaOrder` is optional, explicit captcha provider sequence as comma-separated string (e.g., `"EzCaptcha,EzCaptcha,CapSolver"`). Maximum 10 entries. Each provider must have an API key configured. **Note:** `captchaRetry` and `captchaOrder` are mutually exclusive - only one can be specified per request. **Important:** - Cannot use both reference images (R2V) and start/end frames (I2V) in the same request - End frame only (without start frame) is not supported - R2V mode works with `veo-3.1-fast` and `veo-3.1-fast-relaxed` models only ### Responses {% tabs v1_post_videos_response %} {% tab v1_post_videos_response 200 %} 200 OK Videos generated successfully. Returns job ID and operations array with video URLs and metadata. ```json { "jobId": "j1731859234567v-u12345-email:jo***@gmail.com-bot:google-flow", "operations": [ { "operation": { "name": "d00af...redacted...6f7a", "metadata": { "@type": "type.googleapis.com/google.internal.labs.aisandbox.v1.Media", "name": "CAUSJ...redacted...OWQ5ZA", "video": { "seed": 123456, "mediaGenerationId": "CAUSJ...redacted...OWQ5ZA", "prompt": "A serene mountain landscape at sunset with camera slowly panning right", "fifeUrl": "https://storage.googleapis.com/ai-sandbox-videofx/video/...redacted...", "mediaVisibility": "PRIVATE", "servingBaseUri": "https://storage.googleapis.com/ai-sandbox-videofx/image/...redacted...", "model": "veo_3_1_t2v", "isLooped": false, "aspectRatio": "VIDEO_ASPECT_RATIO_LANDSCAPE" } } }, "sceneId": "323c0...redacted...3ebf6", "mediaGenerationId": "CAUSJ...redacted...OWQ5ZA", "status": "MEDIA_GENERATION_STATUS_SUCCESSFUL" } ], "remainingCredits": 18760, "captcha": { "service": "EzCaptcha", "taskId": "abc123...", "durationMs": 3500, "attempts": [ { "service": "EzCaptcha", "taskId": "abc123...", "durationMs": 3500, "success": true } ] } } ``` {% endtab %} {% tab v1_post_videos_response 201 %} 201 Created Job created in async mode (`async: true`). Video generation is processing in the background. Use [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid) to poll for completion status. ```json { "jobid": "j1731859234567v-u12345-email:jo***@gmail.com-bot:google-flow", "type": "video", "status": "created", "created": "2025-11-17T12:34:56.789Z", "request": { "async": true, "prompt": "A serene mountain landscape at sunset with camera slowly panning right", "email": "jo***@gmail.com", "model": "veo-3.1-fast", "aspectRatio": "landscape", "count": 2, "seed": 123456, "replyUrl": "https://your-domain.com/webhook", "replyRef": "custom-reference-123" }, "response": { "operations": [ { "operation": { "name": "1450903d...redacted...9c86f0" }, "sceneId": "1450903d...redacted...9c86f0", "status": "MEDIA_GENERATION_STATUS_PENDING" }, { "operation": { "name": "f2eec9bd...redacted...e16f7a" }, "sceneId": "f2eec9bd...redacted...e16f7a", "status": "MEDIA_GENERATION_STATUS_PENDING" } ], "captcha": { "service": "EzCaptcha", "taskId": "14af1dbb-885c-4e25-8121-7a79489dfd0e", "durationMs": 5357 } } } ``` {% endtab %} {% tab v1_post_videos_response 400 %} 400 Bad Request Invalid request (validation error, mode conflict, email mismatch, or content policy violation). **Validation error:** ```json { "error": "Reference-to-video mode requires veo-3.1-fast or veo-3.1-fast-relaxed model" } ``` **Content policy error:** ```json { "jobId": "j1731859234567v-u12345-email:jo***@gmail.com-bot:google-flow", "error": "API error: 400", "code": 400, "response": { "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" } ] } } } ``` **Content policy error (direct):** ```json { "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" } ] } } ``` **All operations failed (during polling):** ```json { "jobId": "j1731859234567v-u12345-email:jo***@gmail.com-bot:google-flow", "error": "All operations failed", "code": 400, "response": { "operations": [ { "operation": { "name": "a789f1...redacted", "error": { "code": 3, "message": "PUBLIC_ERROR_MINOR" } }, "sceneId": "a629a9...redacted", "status": "MEDIA_GENERATION_STATUS_FAILED" } ] } } ``` {% endtab %} {% tab v1_post_videos_response 401 %} 401 Unauthorized Invalid API token. ```json { "error": "Unauthorized" } ``` {% endtab %} {% tab v1_post_videos_response 402 %} 402 Payment Required Subscription expired or insufficient credits. ```json { "error": "Account has no subscription or subscription expired" } ``` {% endtab %} {% tab v1_post_videos_response 403 %} 403 Forbidden Request rejected by Google. **Recommendations:** - Ensure `captchaRetry` is set to at least 3 (default). Try increasing to a higher value (e.g., 5) to see if that helps - If issues persist, contact [useapi.net support](../support) ```json { "code": 403, "created": "2025-12-23T21:54:26.393Z", "error": "API error: 403", "jobid": "j1223215426393445325v-u12345-email:us***@gmail.com-bot:google-flow", "request": { "aspectRatio": "landscape", "count": 1, "duration": 8, "email": "us***@gmail.com", "model": "veo-3.1-fast", "prompt": "A cinematic shot of a sunset over the ocean..." }, "response": { "captcha": { "attempts": [ { "service": "EzCaptcha", "taskId": "14af1dbb-885c-4e25-8121-7a79489dfd0e", "durationMs": 5357, "success": true }, { "service": "EzCaptcha", "taskId": "fd044078-0a4a-4303-a585-26fd5d2acb00", "durationMs": 5376, "success": true }, { "service": "EzCaptcha", "taskId": "ab0251dc-6930-4a82-966a-71fe6ab6aa42", "durationMs": 5789, "success": true } ], "durationMs": 18091, "service": "EzCaptcha", "taskId": "ab0251dc-6930-4a82-966a-71fe6ab6aa42" }, "error": { "code": 403, "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "PUBLIC_ERROR_SOMETHING_WENT_WRONG" } ], "message": "reCAPTCHA evaluation failed", "status": "PERMISSION_DENIED" } }, "status": "failed", "type": "video", "updated": "2025-12-23T21:54:45.319Z" } ``` {% endtab %} {% tab v1_post_videos_response 404 %} 404 Not Found Account not found or not configured. ```json { "error": "Google Flow account john@gmail.com not found" } ``` {% endtab %} {% tab v1_post_videos_response 408 %} 408 Request Timeout Video generation polling timeout (after 10 minutes). ```json { "error": "Video generation polling timeout after 120 attempts (600s)" } ``` {% endtab %} {% tab v1_post_videos_response 429 %} 429 Too Many Requests Rate limit or quota exhausted (concurrency limit or account quota reached). Wait 5-10 seconds and retry. If this persists, you may need to cool this account off for a few hours before trying again. ```json { "error": { "code": 429, "message": "Resource has been exhausted (e.g. check quota).", "status": "RESOURCE_EXHAUSTED", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "PUBLIC_ERROR_USER_REQUESTS_THROTTLED" } ] } } ``` {% endtab %} {% tab v1_post_videos_response 596 %} 596 Session Error Google session refresh failed. The account needs to be reconfigured. Delete the account using [DELETE /accounts/email](https://useapi.net/docs/api-google-flow-v1/delete-google-flow-accounts-email) and add it again by strictly following the procedure in [Setup Google Flow](../start-here/setup-google-flow). ```json { "error": "Failed to refresh session: 500 Internal Server Error" } ``` {% endtab %} {% endtabs %} ### Model {% tabs v1_post_videos_model %} {% tab v1_post_videos_model 200 OK (Sync) %} Video generation completed. Returns full video data with signed URLs. ```typescript { jobId: string // Job identifier operations: Array<{ operation: { name: string metadata: { '@type': string name: string video: { seed: number mediaGenerationId: string prompt: string fifeUrl: string // Signed video URL (MP4, valid ~24h) mediaVisibility: string servingBaseUri: string // Signed thumbnail URL (JPEG, valid ~24h) model: string // veo_3_1_t2v | veo_3_1_i2v | veo_3_1_i2v_fl | veo_3_1_r2v isLooped: boolean aspectRatio: string // VIDEO_ASPECT_RATIO_LANDSCAPE | PORTRAIT } } } sceneId: string mediaGenerationId: string status: string // MEDIA_GENERATION_STATUS_SUCCESSFUL | FAILED }> remainingCredits?: number captcha?: { // Captcha metadata service: string // "EzCaptcha" | "CapSolver" | "YesCaptcha" taskId: string durationMs: number attempts: Array<{ service: string taskId?: string durationMs: number success: boolean error?: string }> } } ``` {% endtab %} {% tab v1_post_videos_model 201 Created (Async) %} Job created and processing in background. Structure matches [GET /jobs/`jobId`](https://useapi.net/docs/api-google-flow-v1/get-google-flow-jobs-jobid) response. ```typescript { jobid: string // Job identifier type: 'video' // Job type status: 'created' // Job status created: string // ISO 8601 timestamp request: { async: true prompt: string email?: string model?: string aspectRatio?: string count?: number seed?: number startImage?: string endImage?: string referenceImage_1?: string referenceImage_2?: string referenceImage_3?: string replyUrl?: string replyRef?: string } response: { operations: Array<{ operation: { name: string // Operation identifier } sceneId: string // Scene identifier status: 'MEDIA_GENERATION_STATUS_PENDING' }> captcha?: { // Present when captcha was used service: string // Provider that generated final token taskId: string // Task ID from provider durationMs: number // Total captcha solving time attempts?: Array<{ // All captcha attempts (if retries occurred) service: string taskId: string durationMs: number success: boolean }> } } } ``` {% endtab %} {% tab v1_post_videos_model Error %} Error response structure (applies to both sync and async modes). ```typescript { jobId?: string // Present for job-related errors error: string // Error summary message code?: number // HTTP status code response?: { // API response with error details operations?: Array<{ // Present when operations failed operation: { name: string error?: { code: number; message: string } } sceneId: string status: string }> error?: { // Present for direct API errors code: number message: string status: string details?: Array<{ '@type': string reason: string }> } } } ``` {% endtab %} {% endtabs %} ### Examples {% tabs v1_post_videos_example %} {% tab v1_post_videos_example Curl %} ``` bash curl -X POST \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "prompt": "A serene mountain landscape at sunset with camera slowly panning right", "model": "veo-3.1-fast", "aspectRatio": "landscape", "count": 2, "seed": 123456 }' \ "https://api.useapi.net/v1/google-flow/videos" > response.json # Extract video URLs using jq cat response.json | jq -r '.operations[0].operation.metadata.video.fifeUrl' cat response.json | jq -r '.operations[1].operation.metadata.video.fifeUrl' # Download videos using curl curl "$(cat response.json | jq -r '.operations[0].operation.metadata.video.fifeUrl')" --output video_1.mp4 curl "$(cat response.json | jq -r '.operations[1].operation.metadata.video.fifeUrl')" --output video_2.mp4 ``` {% endtab %} {% tab v1_post_videos_example JavaScript %} ``` javascript const token = 'YOUR_API_TOKEN'; const apiUrl = 'https://api.useapi.net/v1/google-flow/videos'; 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 camera slowly panning right', model: 'veo-3.1-fast', aspectRatio: 'landscape', count: 2, seed: 123456 }) }); const result = await response.json(); console.log('Generated videos:', result.operations.length); // Download videos for (const [index, op] of result.operations.entries()) { const video = op.operation.metadata.video; console.log(`Video ${index + 1} seed:`, video.seed); console.log(`mediaGenerationId:`, video.mediaGenerationId); console.log(`Video URL:`, video.fifeUrl); // Download video (Node.js) const videoResponse = await fetch(video.fifeUrl); const videoBuffer = await videoResponse.arrayBuffer(); const fs = require('fs'); fs.writeFileSync(`generated_video_${index + 1}.mp4`, Buffer.from(videoBuffer)); // Download thumbnail (Node.js) const thumbResponse = await fetch(video.servingBaseUri); const thumbBuffer = await thumbResponse.arrayBuffer(); fs.writeFileSync(`generated_video_${index + 1}_thumb.jpg`, Buffer.from(thumbBuffer)); } ``` {% endtab %} {% tab v1_post_videos_example Python %} ``` python import requests token = 'YOUR_API_TOKEN' api_url = 'https://api.useapi.net/v1/google-flow/videos' headers = { 'Authorization': f'Bearer {token}', 'Content-Type': 'application/json' } data = { 'prompt': 'A serene mountain landscape at sunset with camera slowly panning right', 'model': 'veo-3.1-fast', 'aspectRatio': 'landscape', 'count': 2, 'seed': 123456 } response = requests.post(api_url, headers=headers, json=data) result = response.json() print(f"Generated {len(result['operations'])} videos") # Download videos for index, op in enumerate(result['operations']): video = op['operation']['metadata']['video'] print(f"Video {index + 1} seed:", video['seed']) print(f"mediaGenerationId:", video['mediaGenerationId']) # Download video video_response = requests.get(video['fifeUrl']) with open(f'generated_video_{index + 1}.mp4', 'wb') as f: f.write(video_response.content) # Download thumbnail thumb_response = requests.get(video['servingBaseUri']) with open(f'generated_video_{index + 1}_thumb.jpg', 'wb') as f: f.write(thumb_response.content) ``` {% endtab %} {% endtabs %} ### Try It
=== URL: https://useapi.net/docs/questions-and-answers === Document URL: https://useapi.net/docs/questions-and-answers --- title: Q&A nav_order: 110000 layout: home --- # Questions and Answers {: .no_toc } 4 min read • September 2023 (January 14, 2026) ## Table of contents {: .no_toc .text-delta } 1. TOC {:toc} --- ### How to avoid Midjourney bans? Using automation is against Discord and Midjourney's Terms of Service, so you need to plan accordingly and have backup account(s) ready. * The best practice is to create several new Discord accounts and join the Midjourney Discord server. These accounts should be used exclusively for API work and nothing else. We strongly recommend using a VPN to prevent your personal data/IP addresses from being leaked. You can use the [Opera](https://www.opera.com/download) browser with built-in VPN or the [Brave](https://brave.com/download) browser with [Tor support](https://support.brave.com/hc/en-us/articles/360018121491-What-is-a-Private-Window-with-Tor-Connectivity). * Brand new/fresh Discord accounts have a significantly higher chance of being banned when running high Midjourney generation loads. Consider purchasing aged Discord accounts (2-3 years old) from marketplaces like [z2u.com](https://www.z2u.com/) for around $1-3 each. Aged accounts appear more legitimate and are less likely to trigger automated bans. * When creating accounts in bulk, make sure to restart Opera/Brave so that your IP is different every time, since Discord tracks and records the IP addresses used to create new accounts. Make sure to log in to the Discord accounts designated for API use through a VPN. When creating new email and Discord accounts, use names closely resembling real names - something that does not look suspicious. * Once a Discord account is created, join the Midjourney Discord [server](https://discord.com/invite/midjourney) and follow the [instructions](https://useapi.net/docs/start-here/setup-midjourney) to create your own server and invite the Midjourney bot. If you're planning to use this account, you can proceed with a Midjourney subscription. It's a good idea to create several Discord accounts with the Midjourney setup, as described above early on, this will *"age"* them and make them less suspicious later on when you need to subscribe to Midjourney. * When paying for a Midjourney subscription use a virtual credit card number (provided by most major credit card companies) or services like [Privacy.com](https://privacy.com). Make sure to use a credit card name and address that resemble an actual address and name. Use a *different name and address* for every new Midjourney subscription. Midjourney has access to all payment details and will cross-check banned accounts' payment information to ban newly created accounts if a match is found. * If your account gets banned, file a charge dispute with your credit card company. Since Midjourney cannot produce any evidence of you violating the ToS, the bank will fully refund your payment. Our customers have reported a 100% success rate of getting their money back, though it may take some time. * When using the API, try to simulate real users. Avoid running generations 24/7 by establishing quiet hours (for example, you can use two or three accounts and rotate them every 12/8 hours). Midjourney seems to specifically target accounts with a large number of `--relax` usage, so try to limit those generations to a reasonable number (<300 generations/day). If you heavily rely on `--relax`, execute at least one fast generation for every NN relax generations. * Do not post public links to Discord/Midjourney CDN attachments, they contain your Discord account number and can be used to trace back to your account. * Sharing cross-account `--p` codes is not safe. You risk all accounts using the same `--p` codes being banned by Midjourney. * Do not run multiple requests with the same or similar prompts (e.g., "My test prompt 1", "My test prompt 2", and so on). Midjourney analyzes prompts and will force your Discord account token to expire when this kind of situation is detected. You will have to reset your Discord password manually before you can continue operating. * Adjust [maxJobs](../docs/api-v2/post-account-midjourney) parameter to be one less than the maximum possible. For example, for the [Pro Plan](https://docs.midjourney.com/docs/plans) with a maximum of 12 concurrent jobs, set `maxJobs` to 11 or even 10. * If you ever receive a [504](../docs/api-v2/post-jobs-imagine#responses) response code, it means your `maxJobs` is set to a value higher than your account plan supports. Adjust it accordingly. * Finally, monitor for [596](../docs/api-v2/post-jobs-imagine#responses) response codes and ensure you check your API email. The API will proactively warn you if you have pending moderation messages or if Midjourney issues a CAPTCHA request. ### How to avoid Runway account suspension? Using automation is against Runway's Terms of Service, so you need to plan accordingly and have backup account(s) ready. * The best practice is to create several stand-by Runway accounts. These accounts should be used exclusively for API work and nothing else. We strongly recommend using a VPN to prevent your personal data/IP addresses from being leaked. You can use the [Opera](https://www.opera.com/download) browser with a built-in VPN or the [Brave](https://brave.com/download) browser with [Tor support](https://support.brave.com/hc/en-us/articles/360018121491-What-is-a-Private-Window-with-Tor-Connectivity). * When creating accounts in bulk, make sure to restart Opera/Brave so that your IP is different every time. When creating new emails and Runway accounts, use names that closely resemble real names—something that does not look suspicious. * Once a new Runway account is created, you will have a few free credits with which you can test the API. After testing, log out and leave the account alone until you are ready to activate the [Unlimited plan](https://runwayml.com/pricing) (the only subscription plan that makes sense to pay for). * When paying for a Runway subscription, use a virtual credit card number (provided by most major credit card companies) or services like [Privacy.com](https://privacy.com). Make sure to use a credit card name and address that resemble an actual name and address. Use a *different name and address* for every new Runway subscription. Runway has access to all payment details and can cross-check banned accounts' payment information to ban newly created accounts if a match is found. * If your account gets suspended, file a charge dispute with your credit card company. Since Runway cannot produce any evidence of you violating the ToS, the bank will fully refund your payment. Our customers have reported a 100% success rate of getting their money back, though it may take some time. * When using the API, try to simulate real users. Avoid running generations 24/7 by establishing quiet hours (for example, you can use two or three accounts and rotate them every 12 to 8 hours). Avoid calling API endpoints too frequently, and consider using the `replyUrl` webhook to retrieve results, as this will ensure the least intrusive operation. * Finally, monitor your API email—the one you used to subscribe to useapi.net services. The API will proactively warn you if your Runway account has any issues. ### Do you validate a user's text/image prompts to ensure they are passing AI services' safety requirements? It is common practice for AI services to ban users for violating prompt guidelines (for example, see Midjourney PG13 [requirements](https://docs.midjourney.com/docs/community-guidelines)). Our API does not perform any prompt pre-validations, it will return a [422](../docs/api-v2/post-jobs-imagine#responses) status code if the job is moderated by Midjourney, and similar checks apply for the other AI APIs we offer. Generally speaking, if you're planning to use the API for a public Telegram bot (which is one of the popular use cases) or in similar scenarios where you do not control the quality of the prompt, it might be a good idea to use a combination of a ban/stop word list along with [OpenAI ChatGPT](https://openai.com/api/pricing) or [Google Gemini](https://ai.google.dev/pricing) to check if the prompts meet safety requirements. [Gemini](https://ai.google.dev/pricing) offers a free tier with some RPM (requests per minute) limitations. We also offer LLM models, specifically `MiniMax-Text-01`, a fast instructional multimodal model that is free to use and can validate both text and images for safety. Please see [POST minimax/llm](../docs/api-minimax-v1/post-minimax-llm). ### How is your experimental Runway API different from the official Runway API? Official [Runway API](https://docs.dev.runwayml.com) currently only supports Gen-3 Alpha Turbo. The cost for Gen-3 Alpha Turbo 10-second generation is [$0.50](https://docs.dev.runwayml.com/usage/billing). Our [experimental Runway API](https://useapi.net/docs/api-runwayml-v1) is a reverse-engineered version of [runwayml.com](https://runwayml.com). It fully supports **all** features of Gen-3 Alpha, Gen-3 Alpha Turbo, Act-One, Video to Video, Super-Slow Motion, Gen-2, the LipSync feature, and [more](https://useapi.net/docs/api-runwayml-v1). When used along with the Runway [Unlimited plan](https://runwayml.com/pricing), it allows you to run several hundred generations each day. On average, you can expect the following numbers for Gen-3 Alpha Turbo 10-second generation: - 1 generation is completed within 25 seconds - 10 generations take about 4 minutes to complete - 30 generations take about 12 minutes to complete - 150 generations take about one hour to complete If you generate 200+ videos, the official API will cost you $0.50 per generation, so 200 generations cost about $100. This means the $95 [Unlimited plan](https://runwayml.com/pricing), combined with our $15/month subscription, will pay for itself by the **first day**, most often within the first few hours. We provide an API for all the features available at [runwayml.com](https://runwayml.com), including Gen-3 Alpha, Act-One, video-to-video (with extend and expand), Frames, and many more. The official Runway API only supports [Gen-3 Alpha Turbo](https://docs.dev.runwayml.com/). ### How is your experimental MiniMax API different from the official MiniMax API? Official [MiniMax API](https://intl.minimaxi.com/document/video_generation) costs $0.43…$0.65 [link](https://www.minimaxi.com/en/price) per single 6-second-long generation. Our [experimental MiniMax API](https://useapi.net/docs/api-minimax-v1) is a reverse-engineered version of the MiniMax/HailuoAI websites. It does not cost you anything to generate as many videos as you wish, thanks to a flat monthly [subscription](https://useapi.net/docs/subscription) fee. You can link as many [paid](https://hailuoai.video/subscribe) or free MiniMax/HailuoAI accounts to our API as you wish. With [Unlimited](https://hailuoai.video/subscribe) Hailuo AI plan or [Standard](https://hailuoai.video/subscribe) plan for first day, you can expect the following numbers: - 1 generation completed within 2 minutes - 10 generations take about 20 minutes to complete - 30 generations take about an hour to complete If you generate 250+ videos, the official API will cost you $0.43 per generation, so 250 generations total about $107.50. This means the $95 [Unlimited](https://hailuoai.video/subscribe) plan, combined with our $15/month subscription, will pay for itself by the **first day**. When using free [hailuoai.video](https://hailuoai.video) account, it costs one credit to generate a single image, and you can generate up to four images at once. With a daily free top-up of 100 credits, a free hailuoai.video account can generate 100 images per day – up to 3K images per month. ### Do you support [n8n](https://n8n.io) workflow automation? Please consider the [n8n-nodes-useapi](https://github.com/lvalics/n8n-nodes-useapi) package by [lvalics](https://github.com/lvalics). ### How POST raw content to [runwayml/assets](https://useapi.net/docs/api-runwayml-v1/post-runwayml-assets) and [minimax/files](https://useapi.net/docs/api-minimax-v1/post-minimax-files) using Make.com and similar nocode tools? We recommend using module called [0codekit](https://www.make.com/en/integrations/onesaas) to run JavaScript and return a result.
0codekit JavaScript example ```js async function fetchFromURLandPOST(imageURL, name) { const apiToken = ""; // https://useapi.net/docs/start-here/setup-useapi // Runway https://useapi.net/docs/api-runwayml-v1/post-runwayml-assets const apiUrl = `https://api.useapi.net/v1/runwayml/assets/?name=${name}`; // MiniMax https://useapi.net/docs/api-minimax-v1/post-minimax-files // const apiUrl = `https://api.useapi.net/v1/minimax/files/`; try { // Fetch the image from the URL const responseImage = await fetch(imageURL); if (!responseImage.ok) throw new Error(`Failed to fetch ${imageURL}: ${responseImage.statusText}`); // Convert the response to a Blob const blob = await responseImage.blob(); // Prepare headers for the POST request const headers = { "Authorization": `Bearer ${apiToken}`, "Content-Type": blob.type, }; // Make the POST request with the blob as the body const response = await fetch(apiUrl, { method: "POST", headers: headers, body: blob, }); const result = await response.json(); return { data: result }; } catch (error) { return { error: error.message }; } } // Calling the function result = await fetchFromURLandPOST("https:\\website.com\image.jpeg", "my_image"); ```