Upscale Videos

January 20, 2026

Table of contents

  1. Request Headers
  2. Request Body
  3. Responses
  4. Model
  5. Examples
  6. Try It

Upscale a previously generated video to 1080p or 4K resolution.

  • Currently, video upscaling requires a paid Google AI subscription or remaining credits.
  • Currently, 4K resolution requires a Google AI Ultra 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.

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

Request Body

{
  "mediaGenerationId": "user:12345-email:6a6f...-video:CAMaJDMx...",
  "resolution": "1080p"
}
  • mediaGenerationId is required. The mediaGenerationId from a previously generated video via POST /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 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 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 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

  • 200 OK

    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
          }
        ]
      }
    }
    
  • 201 Created

    Job created in async mode (async: true). Video upscaling is processing in the background.

    Use GET /jobs/jobId to 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
        }
      }
    }
    
  • 400 Bad Request

    Invalid request.

    {
      "error": "Error message"
    }
    
  • 401 Unauthorized

    Invalid API token.

    {
      "error": "Unauthorized"
    }
    
  • 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
    {
      "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
          }
        ]
      }
    }
    
  • 404 Not Found

    Account not found or video not found.

    {
      "error": "Google Flow account [email protected] not found"
    }
    
  • 408 Request Timeout

    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/jobId response.

    {
      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!')
    

Try It