ARTICLE

xAI Batch API: image, edit, video and 1-hour signed URLs—ingest Bubble catalog bulk assets via BIAIG before links expire

Imagine batch rows ship signed media URLs that expire in about an hour while the batch itself may take up to a day. My pipeline: API Connector → BIAIG → immediate Bubble Storage, with separate paths for stills, edits, and video.

Why this is a different risk class

The digest flagged xAI Batch API for Imagine—image generation, image editing, video generation/editing/extension—alongside chat/Responses. Official docs are blunt: image and video batch results use signed URLs that expire after one hour and must be downloaded promptly. That is not the same problem I covered in earlier OpenAI/Google batch pieces (pricing, async without blocking WU). Here the catalog killer is media URL TTL, not batch discount alone. Same topic: gpt-image-2 batch discount: unit economics.

Second layer: batch metadata has expires_at. After that, batch results are gone. That is separate from the one-hour signed URL on each asset.

What the API returns (essentials)

  • Lifecycle: POST /v1/batches, add lines via POST /v1/batches/{batch_id}/requests, or JSONL through the Files API (input_file_id; max 200 MB / 50,000 requests; file-based batches are sealed—no late AddBatchRequests).
  • Poll GET /v1/batches/{batch_id}; fetch GET .../results with pagination (limit up to 1000, pagination_token). Each row maps to your batch_request_id / custom_id.
  • Images: image_response with .url, .base64, .usage, .model. Docs document base64 as an alternative to fetching the URL.
  • Video: video_response with .url, .duration, .usage, .model; batch docs do not document .base64 for video—plan on URL + fast download.
  • JSONL endpoints include /v1/images/generations, /v1/images/edits, /v1/videos/generations (or /v1/videos), /v1/videos/edits, /v1/videos/extensions. Example models such as grok-imagine-image-2.0 and grok-imagine-video-1.5; batch support is per-model.
  • Batch completion is best-effort, typically within 24 hours, but you can read results incrementally as individual requests finish—you do not have to wait for num_pending to hit zero before ingesting ready rows.

The catalog trap: the batch may still be running while each finished row’s signed URL is already on a ~1-hour clock. I store the xAI URL in a Bubble field without copying the file once—and I get broken PDP links after expiry. I do not leave it there.

Ingest pipeline for a Bubble catalog

Publication context (not vendor-spec): API Connector for xAI REST plus BIAIG as a bulk orchestrator over backend workflows—poll, map, persist.

1. API Connector (contract boundaries)

  • Calls for create batch, poll status, and paginated results—I do not gate media ingest on “batch completed.”
  • I map custom_id to a stable SKU/variant/job key for idempotent replays.
  • I do not treat the xAI URL as the long-lived catalog field; mapping feeds a save step, not the final product image URL.

2. BIAIG batch job: poll → ingest before expiry

How I wire it (methodology, not an xAI SLA guarantee):

  1. After batch submit, I run a recurring backend workflow (cadence depends on volume; not specified in the Scout brief).
  2. On each poll, I walk GET .../results pages; for every new batch_request_id:
    • Image (flat still for PDP): if image_response.base64 is present, I prefer base64 into Bubble Workflow/Data API file objects { filename, contents, private?, attach_to? } to reduce TTL race. If URL-only, I immediately use File/Image “save to Bubble storage” (community/docs pattern via API Connector).
    • Image edit leg: same ingest on outputs; inputs (image.url) must be reachable by xAI—private Bubble assets may need a fetchable staging URL or Files API (batch file_id inputs not confirmed on the batch-api page I reviewed).
    • Video / edit / extension: I plan download and upload to Storage as soon as the row appears; large files raise timeout/partial-transfer risk inside the one-hour window. I do not assume base64.
  3. After a successful save, I store Bubble file URLs or attachments in the catalog, not xAI signed URLs. Job state: ingested / failed for replay.
  4. I watch batch expires_at; missed rows are gone unless I submit a new batch (sealed JSONL mistakes can mean duplicate spend). Worth reading next: FLUX 3 Image and Vercel.

3. PDP vs bulk: stills separate from edit/video legs

Leg Typical output Bubble ingest
Image generation url + optional base64 base64 or immediate still save
Image edit url (+ base64?) output ingest; input URL staging
Video gen/edit/extension url only immediate download → Storage; separate WU/timeout budget

Product detail pages often need flat stills for me; video sits on a different asset path with different limits—not the same workflow unchanged.

OpenAI batch (comparison context, not full parity)

OpenAI batch image jobs often return base64 inside output JSONL; DALL·E URL outputs are also documented as short-lived (~60 minutes). xAI batch emphasizes signed media URLs (one hour) with optional inline base64 for images only. A working OpenAI batch ingest pattern does not transfer 1:1 to xAI video legs—I learned that at the contract level, not by hoping. Worth reading next: OpenAI Images API: up to.

Comparison point OpenAI batch xAI batch
Image job output Often base64 inside output JSONL Signed media URLs (one hour); optional inline base64 for images only
URL outputs DALL·E URLs documented as short-lived (~60 minutes) Signed media URLs (one hour)
Ingest / parity Working batch ingest pattern Does not transfer 1:1 to xAI video legs (contract-level, not full parity)

Open questions (explicit)

The Scout packet leaves these unsettled:

  • Whether the one-hour clock starts at request completion, first GET results, or first URL access.
  • Whether storage_options / Files API persistence on sync Imagine (June 2026 release notes) applies to batch payloads—not documented on the batch page I reviewed.
  • Whether image_response.base64 is always populated in batch results.
  • BIAIG-specific orchestration (poll cadence, concurrency, WU limits, error replay) remains publication context.

Risk checklist

  • Dual expiry: signed media URLs and batch expires_at.
  • ~24h batch latency vs 1h URL TTL—ingest as rows complete.
  • Signed URLs are bearer links; I treat them as temporary exposure until copied to owned storage.
  • Video is URL-only and can be large.
  • Edit/extension jobs need inputs xAI can fetch.
  • I never use xAI URLs as the catalog source of truth.
Risk What it covers What it is not for
Dual expiry Signed media URLs and batch expires_at Relying on a single expiry mechanism
Batch latency vs URL TTL ~24h batch latency vs 1h URL TTL; ingest as rows complete Waiting for the full batch before ingest
Signed URLs Bearer links; temporary exposure until copied to owned storage Long-lived or owned catalog assets
Video URL-only delivery; can be large —
Edit/extension jobs Inputs xAI can fetch Jobs whose inputs xAI cannot fetch
xAI URLs Temporary media access Catalog source of truth

Sources (scope of this article)

Official: Batch API | xAI Docs, Batches REST reference, Release Notes, Imagine image/video generation pages. Bubble: The Bubble API (files), forum pattern for saving a public URL to storage. Comparison: OpenAI Batch API guide.

← All articles