Edit a video

October 7, 2026

Table of contents

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

Change a clip with a prompt, for example “Make the paper boat bright yellow”. The result is a new clip with a new mediaId, and the job runs on the account that holds the source.

Edit works on clips Google made: pass a video mediaId from POST /videos, POST /videos/extend or POST /videos/upscale. In our tests 7 of 7 edits of generated clips worked, including a colour change, an added object, a restyle, an extended 8-second clip and a 1080p portrait clip.

The API also accepts an uploaded video, an assetId from POST /assets, but Google refuses those at once with 422. That happened to every upload we tried, even a clip this API had generated and we uploaded again. A refusal uses nothing.

Cost

An edit uses the clip’s length in seconds from the account’s monthly Vids video allowance, the same as generating a clip of that length. A request Google refuses uses nothing.

Sync, async and webhooks

  • Every generation runs as a job on our side, with up to 15 minutes for Google’s answer, so a slow answer is never lost.
  • Sync (the default): the POST waits for the job and answers 200 with the finished job record, or the job’s error code. A video usually takes 20 to 100 seconds, an image about 10. If the job is still running after about 100 seconds, the POST answers 202 with the job as it stands: fetch the result with GET /jobs/jobid. Always check status: only completed has a result.
  • Async: pass async: true or a replyUrl. The POST answers 202 at once with the job in status: "pending". Poll GET /jobs/jobid or wait for the webhook.
  • replyUrl receives one POST of the final job record, as JSON, when the job completes or fails.
  • Each account runs at most maxJobs jobs at a time (default 3, range 1 to 10, set with POST /accounts). GET /jobs shows what is running. Job records are kept for 30 days.

https://api.useapi.net/v1/google-vids/videos/edit

Request Headers
Authorization: Bearer {API token}
Content-Type: application/json
# Alternatively you can use multipart/form-data
# Content-Type: multipart/form-data
Request Body
{
  "video": "user:[email protected]:eyJ1IjoiaHR0…",
  "prompt": "Make the paper boat bright yellow",
  "async": true,
  "replyUrl": "https://your-domain.com/webhook",
  "replyRef": "boat-yellow"
}
  • video is required, the video mediaId of the clip to edit, from a finished job’s result. An assetId of an uploaded MP4 is accepted, but Google refuses it.
  • prompt is required, the change to make.
    Maximum length: 5000 characters.
  • duration is optional for a mediaId, where it defaults to the clip’s length, and required for an assetId, where it is the uploaded video’s length in seconds.
    Range: 3 to 10.
  • aspectRatio is optional.
    Supported values: landscape, portrait. Default: the source clip’s (landscape for an assetId).
  • resolution is optional.
    Supported values: 720p, 1080p. Default: the source clip’s (720p for an assetId).
  • async is optional, true to answer 202 at once and run the job in the background. Default: false.
  • replyUrl is optional, a public http(s) URL that receives one POST of the job record when the job completes or fails. Setting it also makes the request async.
    Callback body has the same JSON shape as GET /jobs/jobid response.
    Maximum length: 1024 characters.
  • replyRef is optional, your own reference echoed back in the job record.
    Maximum length: 1024 characters.
Responses
  • 200 OK — sync mode, a 3-second clip edited, charged 3 seconds.

    {
      "jobid": "user:[email protected]:cb856ace-5b20-4bad-8476-70a03c492cb8",
      "type": "video",
      "mode": "edit",
      "email": "[email protected]",
      "status": "completed",
      "created": "2026-10-07T06:28:21.680Z",
      "request": {
        "video": "user:[email protected]:eyJ1IjoiaHR0…",
        "prompt": "Make the paper boat bright yellow"
      },
      "updated": "2026-10-07T06:28:59.896Z",
      "completed": "2026-10-07T06:28:59.896Z",
      "result": {
        "mediaId": "user:[email protected]:eyJ1IjoiaHR0…",
        "width": 1280,
        "height": 720,
        "duration": 3,
        "resolution": "720p",
        "aspectRatio": "landscape",
        "model": "/flix/generate_videos_omni_edit_psq/v1",
        "quota": {
          "video": {
            "limit": 10000,
            "left": 9621,
            "resetAt": "2026-11-01T07:00:00.000Z"
          }
        },
        "elapsedMs": 38167
      }
    }
    
  • 202 Accepted — the job is running: with async: true or replyUrl at once, in sync mode after about 100 seconds of waiting. Fetch the result with GET /jobs/jobid (or wait for the webhook).

  • 400 Bad Request — a parameter is missing or invalid.

    {
      "error": "duration (the uploaded video's length in seconds, 3–10) is required when video is an asset id",
      "code": 400
    }
    
    {
      "error": "Parameter video is not a valid video / asset id",
      "code": 400
    }
    
  • 401 Unauthorized

    Invalid API token.

    {
      "error": "useapi.net ⁝ Unauthorized",
      "code": 401
    }
    
  • 403 Forbidden — the video id was issued to a different API token.

    {
      "error": "video id does not belong to this API token",
      "code": 403
    }
    
  • 404 Not Found — the account that holds the source is no longer connected.

    {
      "error": "Account [email protected] (from the video id) is not configured",
      "code": 404
    }
    
  • 422 Unprocessable Content — Google refused the edit. Every uploaded video gets this answer. Nothing was charged.

    {
      "jobid": "user:[email protected]:db97658a-1240-4eee-a9dc-75f7c5123d2e",
      "type": "video",
      "mode": "edit",
      "email": "[email protected]",
      "status": "failed",
      "created": "2026-10-07T06:36:31.478Z",
      "request": {
        "video": "user:[email protected]:AVL_0qh2dWHI…",
        "duration": 4,
        "prompt": "Make the sky stormy and dark"
      },
      "updated": "2026-10-07T06:36:41.176Z",
      "completed": "2026-10-07T06:36:41.176Z",
      "error": {
        "code": 422,
        "message": "Google refused this request (\"That request looks like it goes against our terms. Try asking something else.\"). Change the prompt or the inputs and try again."
      }
    }
    
  • 429 Too Many Requests — the account is running maxJobs jobs, the month’s video allowance is used up (error.retryAt is the reset time), or Google is limiting the account for a minute.

    {
      "error": "Account [email protected] is running 3 of 3 jobs (maxJobs). Wait for one to finish, or raise maxJobs with POST /accounts",
      "code": 429
    }
    
  • 504 Gateway Timeout — Google did not answer within 15 minutes, or the connection to Google was cut. Google may still finish the job and charge it, but the result cannot be retrieved: run it again.

  • 596 Account Error

    Google reported the account as signed out. While we re-check it, the answer is the first message below. Retry in about a minute. If it stays signed out, the account is paused, you receive an email, and the answer becomes the second message until you re-add it via Setup Google Vids.

    {
      "error": "Google reported this account as signed out. We are re-checking it — please retry in about a minute. If it stays signed out, you will receive a re-add email.",
      "code": 596
    }
    
    {
      "error": "Account [email protected]: Google signed this account out. Re-add it at https://useapi.net/docs/start-here/setup-google-vids",
      "code": 596
    }
    
Model

The job record, mode: "edit". GET /jobs/jobid and the replyUrl webhook return the same shape.

{ // TypeScript, all fields are optional
  jobid: string                  // user:<id>-<email>-job:<uuid>
  type: 'video' | 'image'
  mode?: 'text' | 'image' | 'ingredients' | 'extend' | 'upscale' | 'edit'   // video jobs only
  email: string                  // the account the job runs on
  status: 'pending' | 'processing' | 'completed' | 'failed'
  created: string                // ISO 8601, when the job was accepted
  updated?: string               // ISO 8601, the last status change
  completed?: string             // ISO 8601, when the job completed or failed
  request: Record<string, unknown>   // your request body as sent (ids as strings)
  replyUrl?: string
  replyRef?: string
  error?: {                      // status 'failed'
    code: number                 // 400 | 403 | 404 | 422 | 429 | 500 | 502 | 503 | 504 | 596, see GET /jobs/{jobid}
    message: string
    retryAt?: string             // code 429: ISO 8601, when to try again
  }
  result?: {                     // status 'completed'
    mediaId: string              // download it with GET /media/{mediaId}. A video: extend / upscale / edit it. An image: use it as startImage, referenceImage_N or avatar image
    width: number
    height: number
    duration?: number            // video: length of the whole clip in seconds
    resolution?: '720p' | '1080p'              // video
    aspectRatio?: 'landscape' | 'portrait'     // video
    model: string | null         // Google's backend path, e.g. /flix/generate_videos_omni_t2v_psq/v1
    quota: {                     // what the account has left after this job
      video?: { limit: number, left: number, resetAt: string }   // seconds, video jobs
      image?: { limit: number, left: number, resetAt: string }   // images, image jobs
    }
    elapsedMs: number            // how long Google took
  }
}
Examples
  • curl -X POST "https://api.useapi.net/v1/google-vids/videos/edit" \
       -H "Content-Type: application/json" \
       -H "Authorization: Bearer …" \
       -d '{
         "video": "user:[email protected]:eyJ1IjoiaHR0…",
         "prompt": "Make the paper boat bright yellow"
       }'
    
  • const token = "API token";
    const video = "mediaId of a clip made by this API";
    const apiUrl = "https://api.useapi.net/v1/google-vids/videos/edit";
    const response = await fetch(apiUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": `Bearer ${token}`,
      },
      body: JSON.stringify({ video, prompt: "Make the paper boat bright yellow" })
    });
    const job = await response.json();
    console.log("response", response.status, job.result ?? job.error ?? job);
    
  • import requests
    token = "API token"
    video = "mediaId of a clip made by this API"
    apiUrl = "https://api.useapi.net/v1/google-vids/videos/edit"
    headers = {
        "Content-Type": "application/json",
        "Authorization" : f"Bearer {token}"
    }
    data = {
        "video": video,
        "prompt": "Make the paper boat bright yellow"
    }
    response = requests.post(apiUrl, headers=headers, json=data)
    print(response, response.json())
    
Try It