Generate Videos
November 17, 2025 (November 26, 2025)
Table of contents
Generate videos using Google Flow AI models (Veo 3.1 Quality, Veo 3.1 Fast, Veo 3.1 Fast Relaxed) 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 $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 Qualityveo-3.1-quality | Veo 3.1 Fastveo-3.1-fast (default) | Veo 3.1 Fast Relaxedveo-3.1-fast-relaxed |
|---|---|---|---|
| T2V (text-to-video) | β | β | β |
| I2V (start frame) | β | β | β |
| I2V-FL (start + end) | β | β | β |
| R2V (reference images 1-3) | β | β (landscape only) | β (landscape only) |
| Aspect ratios | all | all | all |
count | β (1-4) | β (1-4) | β (1-4) |
seed | β | β | β |
| Subscription | all | all | Ultra only |
| Cost | 100 credits / $0.50 | 10 credits / $0.05 | free (lower priority) |
https://api.useapi.net/v1/google-flow/videos
Request Headers
Authorization: Bearer {API token}
Content-Type: application/json
# Alternatively you can use multipart/form-data
# Content-Type: multipart/form-data
API tokenis required, see Setup useapi.net for details.
Request Body
{
"prompt": "A serene mountain landscape at sunset with camera slowly panning right",
"model": "veo-3.1-fast",
"aspectRatio": "landscape",
"count": 2,
"seed": 123456
}
-
emailis optional. The email address of the Google Flow account to use.When only one account is configured, the API will automatically use that account.
With multiple accounts configured, omitting the email parameter triggers automatic load balancing based on video generation job statistics to select the healthiest account.
If reference images (
startImage,endImage, orreferenceImage_1to_3) are provided, theemailparameter can be omittedβthe API will automatically use the same account where the images were uploaded. promptis required, text description for video generation.modelis optional, the AI model to use for video generation (default:veo-3.1-fast).
Supported values:veo-3.1-quality,veo-3.1-fast,veo-3.1-fast-relaxed(Ultra only, no credits, lower priority).aspectRatiois optional, output video aspect ratio (default:landscape).
Supported values:landscapeandportrait.countis optional, number of video variations to generate (1-4, default:1).seedis optional, random seed for reproducible results (integer β₯ 0).startImageis optional, mediaGenerationId from POST /assets/emailfor I2V mode (video starts with this frame).endImageis optional, mediaGenerationId from POST /assets/emailfor I2V-FL mode (video ends with this frame, requiresstartImage).referenceImage_1toreferenceImage_3are optional, mediaGenerationId from POST /assets/emailfor R2V mode (1-3 reference images for style/composition). Only works withveo-3.1-fastmodel andlandscapeaspect ratio.asyncis optional, enables fire-and-forget mode (default:false). Whentrue, returns immediately with201 Createdand job metadata. Poll GET /jobs/jobIdfor completion status. Useful for avoiding long request timeouts since video generation takes 60-180 seconds.replyUrlis 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/jobIdresponse.replyRefis optional, custom reference string passed back in webhook callbacks. Useful for tracking jobs on your end.
Important:
- Cannot use both reference images (R2V) and start/end frames (I2V) in the same request
- End frame only (without start frame) is not supported
- R2V mode only supports landscape aspect ratio and works with
veo-3.1-fastandveo-3.1-fast-relaxedmodels
Responses
-
Videos generated successfully. Returns job ID and operations array with video URLs and metadata.
{ "jobId": "j1731859234567v-u12345-email:jo***@gmail.com-bot:google-flow", "operations": [ { "operation": { "name": "d00af...redacted...6f7a", "metadata": { "@type": "type.googleapis.com/google.internal.labs.aisandbox.v1.Media", "name": "CAUSJ...redacted...OWQ5ZA", "video": { "seed": 123456, "mediaGenerationId": "CAUSJ...redacted...OWQ5ZA", "prompt": "A serene mountain landscape at sunset with camera slowly panning right", "fifeUrl": "https://storage.googleapis.com/ai-sandbox-videofx/video/...redacted...", "mediaVisibility": "PRIVATE", "servingBaseUri": "https://storage.googleapis.com/ai-sandbox-videofx/image/...redacted...", "model": "veo_3_1_t2v", "isLooped": false, "aspectRatio": "VIDEO_ASPECT_RATIO_LANDSCAPE" } } }, "sceneId": "323c0...redacted...3ebf6", "mediaGenerationId": "CAUSJ...redacted...OWQ5ZA", "status": "MEDIA_GENERATION_STATUS_SUCCESSFUL" } ], "remainingCredits": 18760 } -
Job created in async mode (
async: true). Video generation is processing in the background.Use GET /jobs/
jobIdto poll for completion status.{ "jobid": "j1731859234567v-u12345-email:jo***@gmail.com-bot:google-flow", "type": "video", "status": "created", "created": "2025-11-17T12:34:56.789Z", "request": { "async": true, "prompt": "A serene mountain landscape at sunset with camera slowly panning right", "email": "jo***@gmail.com", "model": "veo-3.1-fast", "aspectRatio": "landscape", "count": 2, "seed": 123456, "replyUrl": "https://your-domain.com/webhook", "replyRef": "custom-reference-123" }, "response": { "operations": [ { "operation": { "name": "1450903d...redacted...9c86f0" }, "sceneId": "1450903d...redacted...9c86f0", "status": "MEDIA_GENERATION_STATUS_PENDING" }, { "operation": { "name": "f2eec9bd...redacted...e16f7a" }, "sceneId": "f2eec9bd...redacted...e16f7a", "status": "MEDIA_GENERATION_STATUS_PENDING" } ] } } -
Invalid request (validation error, mode conflict, email mismatch, or content policy violation).
General errors:
{ "error": "Reference-to-video only supports landscape aspect ratio" }Content policy error:
{ "error": { "code": 400, "message": "Request contains an invalid argument.", "status": "INVALID_ARGUMENT", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "PUBLIC_ERROR_UNSAFE_GENERATION" } ] } } -
Invalid API token.
{ "error": "Unauthorized" } -
Subscription expired or insufficient credits.
{ "error": "Account has no subscription or subscription expired" } -
Unauthorized access to reference images from another user.
{ "error": "Unauthorized access to user:123 detected in reference user:123-email:...-image:..." } -
Account not found or not configured.
{ "error": "Google Flow account [email protected] not found" } -
Video generation polling timeout (after 10 minutes).
{ "error": "Video generation polling timeout after 120 attempts (600s)" } -
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.
{ "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" } ] } } -
Google session refresh failed. The account needs to be reconfigured. Delete the account using DELETE /accounts/
emailand add it again by strictly following the procedure in Setup Google Flow.{ "error": "Failed to refresh session: 500 Internal Server Error" }
Model
-
Video generation completed. Returns full video data with signed URLs.
{ 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_0_r2v isLooped: boolean aspectRatio: string // VIDEO_ASPECT_RATIO_LANDSCAPE | PORTRAIT } } } sceneId: string mediaGenerationId: string status: string // MEDIA_GENERATION_STATUS_SUCCESSFUL | FAILED }> remainingCredits?: number } -
Job created and processing in background. Structure matches GET /jobs/
jobIdresponse.{ 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' }> } } -
Error response structure (applies to both sync and async modes).
{ error: string | { // String (useapi.net) or object (Google API) code: number message: string status: string details: Array<{ '@type': string reason: string }> } }
Examples
-
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 -
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)); } -
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)