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 viaPOST /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}; fetchGET .../resultswith pagination (limit up to 1000,pagination_token). Each row maps to yourbatch_request_id/custom_id. - Images:
image_responsewith.url,.base64,.usage,.model. Docs document base64 as an alternative to fetching the URL. - Video:
video_responsewith.url,.duration,.usage,.model; batch docs do not document.base64for 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 asgrok-imagine-image-2.0andgrok-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_pendingto 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_idto 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):
- After batch submit, I run a recurring backend workflow (cadence depends on volume; not specified in the Scout brief).
- On each poll, I walk
GET .../resultspages; for every newbatch_request_id:- Image (flat still for PDP): if
image_response.base64is 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.
- Image (flat still for PDP): if
- After a successful save, I store Bubble file URLs or attachments in the catalog, not xAI signed URLs. Job state:
ingested/failedfor replay. - 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.base64is 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.