=== 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`

Select time range to be `All time` `1` and check `Cookies and other site data` `2`, click `Delete data` `3`

### 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`

Enter your Google email created earlier `1`

Enter 2-Step Verification code `1`
⚠️ **You MUST check `Don't ask again on this device`** `2` - skipping this will break the API session.

Once successfully logged in you should see `New project` button

### Navigate to Google Account
Navigate to [https://myaccount.google.com/](https://myaccount.google.com/)

### Copy `https://accounts.google.com/` cookies
1. **Open Developer Tools:** right-click anywhere on page → select `Inspect` (or press `F12`)

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`

Your copied cookies will look similar to this (values redacted):

### 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.
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.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" | "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" | "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
---
# 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": "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 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/)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.