API / read-imagine-video-progress-while-polling

API

Read Imagine video progress while polling

Surface approximate completion while a video job is still pending so your queue UI, worker logs, or operator dashboard can show percent done instead of a silent wait. Official REST reference for GET https://api.x.ai/v1/videos/{request_id} documents an optional progress field: while status is pending, progress sits between 0 and 99; when status is done, progress is 100; when status is failed, progress is omitted. Pair this with the same start-and-poll flow covered in Poll Imagine video manually with start and get. Create a key and load credits at console.x.ai before you bill a generation that you will monitor.

What you need

An XAI_API_KEY with Console balance, a generation or edit request that already returns a request_id, and a place to print or store the percent between polls. The xAI Python SDK's blocking generate() hides status checks for you; read progress when you poll REST yourself or when you call start() / get() and inspect the raw deferred result. Sleep a few seconds between checks — official examples use about five seconds — so you do not hammer the status endpoint.

Poll and print progress

  1. Export the key locally and keep it out of chat logs and public repos:
export XAI_API_KEY="your_api_key"
  1. Start a generation and capture request_id:
REQUEST_ID=$(curl -s -X POST https://api.x.ai/v1/videos/generations \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -d '{
    "model": "grok-imagine-video-1.5",
    "prompt": "A cat lounging in a sunbeam, tail gently swishing",
    "duration": 5,
    "aspect_ratio": "16:9",
    "resolution": "720p"
  }' | jq -r '.request_id')

echo "Request ID: $REQUEST_ID"
  1. Loop on the status endpoint and read both status and progress:
while true; do
  RESULT=$(curl -s "https://api.x.ai/v1/videos/$REQUEST_ID" \
    -H "Authorization: Bearer $XAI_API_KEY")
  STATUS=$(echo "$RESULT" | jq -r '.status')
  PROGRESS=$(echo "$RESULT" | jq -r '.progress // empty')
  echo "status=$STATUS progress=${PROGRESS:-n/a}"
  if [ "$STATUS" = "done" ]; then
    echo "$RESULT" | jq -r '.video.url'
    break
  elif [ "$STATUS" = "failed" ] || [ "$STATUS" = "expired" ]; then
    echo "$RESULT" | jq .
    break
  fi
  sleep 5
done
  1. Treat progress as approximate completion for UX only — gate retries and downloads on status, not on a specific percent.
  2. When generation fails, read the error.code / error.message object instead of waiting for progress; see Handle Imagine video generation errors.

After the generate

Log request_id with the final progress line so support can correlate a slow job. If you need a longer wait or calmer interval on the SDK's blocking helpers, use Customize Imagine video SDK poll timeout and interval. Download the temporary video.url promptly once status is done, and confirm Check respect_moderation on Imagine video before you publish the file.

Pitfalls

Driving business logic off progress alone fails when the field is missing on failed or briefly unset. Polling every few hundred milliseconds wastes quota and still will not finish the encode faster. Ignoring expired and failed while staring at a stuck percent leaves workers looping forever. Mixing Console API spend with SuperGrok weekly Imagine quotas on grok.com confuses two meters. Pasting keys into tickets or committing them to git forces a rotate.