Edit a video
October 7, 2026
Table of contents
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
200with 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 answers202with the job as it stands: fetch the result with GET /jobs/jobid. Always checkstatus: onlycompletedhas aresult. - Async: pass
async: trueor areplyUrl. The POST answers202at once with the job instatus: "pending". Poll GET /jobs/jobidor wait for the webhook. replyUrlreceives onePOSTof the final job record, as JSON, when the job completes or fails.- Each account runs at most
maxJobsjobs at a time (default3, range1to10, 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
API tokenis required, see Setup useapi.net for details.
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"
}
videois required, the videomediaIdof the clip to edit, from a finished job’sresult. AnassetIdof an uploaded MP4 is accepted, but Google refuses it.promptis required, the change to make.
Maximum length:5000characters.durationis optional for amediaId, where it defaults to the clip’s length, and required for anassetId, where it is the uploaded video’s length in seconds.
Range:3to10.aspectRatiois optional.
Supported values:landscape,portrait. Default: the source clip’s (landscapefor anassetId).resolutionis optional.
Supported values:720p,1080p. Default: the source clip’s (720pfor anassetId).asyncis optional,trueto answer202at once and run the job in the background. Default:false.replyUrlis optional, a publichttp(s)URL that receives onePOSTof 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/jobidresponse.
Maximum length:1024characters.replyRefis optional, your own reference echoed back in the job record.
Maximum length:1024characters.
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: trueorreplyUrlat 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 } -
Invalid API token.
{ "error": "useapi.net ⁝ Unauthorized", "code": 401 } -
403 Forbidden — the
videoid 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
maxJobsjobs, the month’s video allowance is used up (error.retryAtis 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())