Upscale Videos
January 20, 2026
Table of contents
Upscale a previously generated video to 1080p or 4K resolution.
- Currently, video upscaling requires a paid Google AI subscription or remaining credits.
- Currently,
4Kresolution requires a Google AI Ultra subscription. Other paid accounts can only use1080presolution. 1080pupscaling is free.4Kupscaling 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.
https://api.useapi.net/v1/google-flow/videos/upscale
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
{
"mediaGenerationId": "user:12345-email:6a6f...-video:CAMaJDMx...",
"resolution": "1080p"
}
mediaGenerationIdis required. ThemediaGenerationIdfrom a previously generated video via POST /videos.resolutionis optional. Target resolution for upscaling (default:1080p).
Supported values:1080p,4K.asyncis optional, enables fire-and-forget mode (default:false).
Whentrue, returns immediately with201 Createdand job metadata. Poll GET /jobs/jobIdfor completion status.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.captchaRetryis optional, number of captcha retry attempts (1-10, default: 3). Cycles through configured captcha providers starting with EzCaptcha if available.captchaOrderis 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
-
Video upscaled successfully. Returns job ID and operations array with upscaled video URLs.
{ "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 } ] } } -
Job created in async mode (
async: true). Video upscaling is processing in the background.Use GET /jobs/
jobIdto poll for completion status.{ "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 } } } -
Invalid request.
{ "error": "Error message" } -
Invalid API token.
{ "error": "Unauthorized" } -
Request rejected by Google.
Recommendations:
- Ensure
captchaRetryis 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
{ "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 } ] } } - Ensure
-
Account not found or video not found.
{ "error": "Google Flow account [email protected] not found" } -
Video upscaling polling timeout (after 10 minutes).
{ "error": "Polling timeout" }
Model
-
Video upscaling completed. Returns upscaled video data with signed URLs. Re-upscaling the same video returns
rawBytes(base64 video data) instead of URLs.{ 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 }> } } -
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 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 } } } -
Error response structure.
{ 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 }> } } }
Examples
-
# 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 -
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!'); -
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!')