Retrieve a job

October 7, 2026

Table of contents

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

Fetch a job record by its jobid. Every generation is a job: POST /videos, POST /videos/extend, POST /videos/upscale, POST /videos/edit and POST /images all return one. After an async request, poll this endpoint until status is completed or failed.

A video takes about 20 to 100 seconds and an image about 10, so polling every 10 seconds is enough. A job may run for up to 15 minutes, and a sync POST that answered 202 hands you a job that is still running. A job still not finished about 16 minutes after it was created is failed with 504 when it is read.

Instead of polling, pass replyUrl (and optionally replyRef) with the POST: when the job completes or fails, the API sends one POST of this same job record, as JSON, to that URL. See Model.

Job records are kept for 30 days.

https://api.useapi.net/v1/google-vids/jobs/jobid

  • jobid is URL-encoded in the path (it contains : and @), for example user%3A12345-user%40example.com-job%3A4aa24347-8099-4624-80ec-fb758db74419.
Request Headers
Authorization: Bearer {API token}
Responses
  • 200 OK

    Completed (an async text-to-video job):

    {
      "jobid": "user:[email protected]:4aa24347-8099-4624-80ec-fb758db74419",
      "type": "video",
      "mode": "text",
      "email": "[email protected]",
      "status": "completed",
      "created": "2026-10-07T06:29:01.204Z",
      "request": {
        "prompt": "A hot air balloon rising over a misty valley at sunrise",
        "duration": 3,
        "async": true
      },
      "updated": "2026-10-07T06:29:27.207Z",
      "completed": "2026-10-07T06:29:27.207Z",
      "result": {
        "mediaId": "user:[email protected]:eyJ1IjoiaHR0…",
        "width": 1280,
        "height": 720,
        "duration": 3,
        "resolution": "720p",
        "aspectRatio": "landscape",
        "model": "/flix/generate_videos_omni_t2v_psq/v1",
        "quota": {
          "video": {
            "limit": 10000,
            "left": 9615,
            "resetAt": "2026-11-01T07:00:00.000Z"
          }
        },
        "elapsedMs": 24611
      }
    }
    

    Running:

    {
      "jobid": "user:[email protected]:4aa24347-8099-4624-80ec-fb758db74419",
      "type": "video",
      "mode": "text",
      "email": "[email protected]",
      "status": "processing",
      "created": "2026-10-07T06:29:01.204Z",
      "request": {
        "prompt": "A hot air balloon rising over a misty valley at sunrise",
        "duration": 3,
        "async": true
      },
      "updated": "2026-10-07T06:29:02.461Z"
    }
    

    Failed (Google refused an edit of an uploaded video):

    {
      "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]:…",
        "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."
      }
    }
    
  • 400 Bad Request

    The path value is not a Google Vids jobid.

    {
      "error": "Path parameter jobid (…) is not a valid job id",
      "code": 400
    }
    
  • 401 Unauthorized

    Invalid API token.

    {
      "error": "useapi.net ⁝ Unauthorized",
      "code": 401
    }
    
  • 403 Forbidden

    {
      "error": "This job does not belong to this API token",
      "code": 403
    }
    
  • 404 Not Found

    No such job, or its record is older than 30 days.

    {
      "error": "Job user:[email protected]:00000000-0000-4000-8000-000000000000 not found (records are kept 30 days)",
      "code": 404
    }
    
Model

The job record. POST /videos, POST /videos/extend, POST /videos/upscale, POST /videos/edit and POST /images return it too, and it is the body of the replyUrl webhook.

{ // 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
  }
}
status Meaning
pending Async only: the job is queued and has not started.
processing Google is generating. A sync job starts here.
completed Done. result.mediaId downloads the file with GET /media/mediaId.
failed Done without a file. error says why.

A job sent without email and without input ids can change email while it runs: when Google refuses it because that account’s allowance is used up, it moves to another of your accounts.

error.code Meaning
400 Google rejected the request as invalid. message has Google’s reason.
403 The account’s Google plan has no Vids allowance for this kind of job (a monthly limit of 0).
404 The account was removed with DELETE /accounts/email before the async job ran.
422 Google refused the prompt or the inputs (“That request looks like it goes against our terms”). Nothing was charged. Change the prompt or the inputs. In our tests every edit of an uploaded video ended here.
429 The account’s monthly allowance is used up, and retryAt is the reset time. Or Google is limiting the account for a short while, and retryAt is about a minute away.
500 An unexpected error on our side.
502 Google answered without a file, or with an unexpected error.
503 Google answered with a server error or could not be reached, or the async job could not be queued. Retry.
504 Google did not answer within 15 minutes, or the connection to Google was cut, or the job did not finish within its time budget. Google may still finish the file and charge it.
596 Google reported the account as signed out. While we re-check it, retry in about a minute. If it stays signed out, re-add it via Setup Google Vids.

A sync POST whose job fails answers with the HTTP status in error.code and the failed job record as the body.

The replyUrl webhook is one POST with Content-Type: application/json and this record as the body, sent once when the job completes or fails (a 10-second timeout, no retries, redirects are not followed). Use replyRef to match the callback to your own records.

Examples
  • JOBID="user:[email protected]:4aa24347-8099-4624-80ec-fb758db74419"
    curl -H "Authorization: Bearer …" \
         "https://api.useapi.net/v1/google-vids/jobs/$(python3 -c "import urllib.parse,sys;print(urllib.parse.quote(sys.argv[1],safe=''))" "$JOBID")"
    
  • const token = "API token";
    const jobid = "user:[email protected]:4aa24347-8099-4624-80ec-fb758db74419";
    const apiUrl = `https://api.useapi.net/v1/google-vids/jobs/${encodeURIComponent(jobid)}`;
    let job;
    do {
      await new Promise(resolve => setTimeout(resolve, 10000));
      const response = await fetch(apiUrl, {
        headers: {
          "Authorization": `Bearer ${token}`,
        },
      });
      job = await response.json();
      console.log(job.status);
    } while (job.status === "pending" || job.status === "processing");
    console.log("job", job);
    
  • import requests, time, urllib.parse
    token = "API token"
    jobid = "user:[email protected]:4aa24347-8099-4624-80ec-fb758db74419"
    apiUrl = "https://api.useapi.net/v1/google-vids/jobs/" + urllib.parse.quote(jobid, safe="")
    headers = {
        "Authorization" : f"Bearer {token}"
    }
    while True:
        time.sleep(10)
        job = requests.get(apiUrl, headers=headers).json()
        print(job.get("status"))
        if job.get("status") not in ("pending", "processing"):
            break
    print(job)
    
Try It