API / poll-imagine-video-manually

API

Poll Imagine video manually with start and get

Poll Imagine video manually with start and get

client.video.generate() blocks until the clip is ready. When you need the request_id up front, custom retry logic, or to interleave other work, call start() then get() yourself. REST callers already do this: POST /v1/videos/generations then GET /v1/videos/{request_id}.

Python SDK

Import DeferredStatus from xai_sdk.proto.deferred_pb2. start() returns a request_id. Loop on get() until the status leaves PENDING.

import os
import time
import xai_sdk
from xai_sdk.proto import deferred_pb2

client = xai_sdk.Client(api_key=os.getenv("XAI_API_KEY"))

start_response = client.video.start(
    prompt="A cat lounging in a sunbeam, tail gently swishing",
    model="grok-imagine-video-1.5",
    duration=5,
)
print(f"Request ID: {start_response.request_id}")

while True:
    result = client.video.get(start_response.request_id)
    if result.status == deferred_pb2.DeferredStatus.DONE:
        print(f"Video URL: {result.response.video.url}")
        break
    elif result.status == deferred_pb2.DeferredStatus.EXPIRED:
        print("Request expired")
        break
    elif result.status == deferred_pb2.DeferredStatus.FAILED:
        print("Video generation failed")
        break
    elif result.status == deferred_pb2.DeferredStatus.PENDING:
        print("Still processing...")
        time.sleep(5)
Proto value Meaning
PENDING Still generating
DONE Ready; read result.response.video.url
EXPIRED Request expired
FAILED Generation failed

For extensions, use extend_start() with the same get() poll. The blocking generate() / extend() helpers still accept timeout and interval when you do not need the raw lifecycle. See Customize Imagine video SDK poll timeout and interval.

REST

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
  }' | jq -r '.request_id')

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')
  if [ "$STATUS" = "done" ]; then
    echo "$RESULT" | jq -r '.video.url'
    break
  elif [ "$STATUS" = "failed" ] || [ "$STATUS" = "expired" ]; then
    echo "Request $STATUS"; echo "$RESULT" | jq .
    break
  fi
  sleep 5
done

REST statuses are lowercase strings: pending, done, expired, failed. On failure the body can include error.code and error.message. See Handle Imagine video generation errors.

Pitfalls

  • Temporary vidgen.x.ai URLs expire; download promptly if you need a lasting copy.
  • Sleeping under a few seconds burns rate limit without finishing the model faster.
  • Auth, missing models, and rate limits fail synchronously on start / POST before a job exists, so they never appear as deferred FAILED.