API / use-files-api-as-imagine-inputs

API

Use Files API file IDs as Imagine inputs

Use Files API file IDs as Imagine inputs

Anywhere an Imagine endpoint accepts a public URL or base64 image/video, you can pass a Files API file_id instead. xAI fetches the file from your private storage. The file stays private, you avoid re-uploading bytes on each edit, and you can chain earlier Imagine outputs that were saved with storage_options. Images: PNG, JPEG, WebP. Videos: MP4. The file must be fully uploaded before you reference it.

Edit a stored image

curl -s -X POST https://api.x.ai/v1/images/edits \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-imagine-image-2.0",
    "prompt": "Add a party hat to the dog",
    "image": { "file_id": "file_7de029f4-eb66-42ee-87f8-b2a9d9e7466a" },
    "response_format": "url"
  }'
import os
import xai_sdk

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

response = client.image.sample(
    prompt="Add a party hat to the dog",
    model="grok-imagine-image-2.0",
    image_file_id="file_7de029f4-eb66-42ee-87f8-b2a9d9e7466a",
)
print(response.url)

Multiple images (mix file_id and URL)

curl -s -X POST https://api.x.ai/v1/images/edits \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-imagine-image-2.0",
    "prompt": "Blend these two scenes into one cohesive composition",
    "images": [
      { "file_id": "file_7de029f4-eb66-42ee-87f8-b2a9d9e7466a" },
      { "url": "https://example.com/scene-b.jpg" }
    ],
    "response_format": "url"
  }'

In the xAI SDK, use image_file_ids=[...] for multiple stored sources.

Image-to-video from a stored frame

curl -s -X POST https://api.x.ai/v1/videos/generations \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-imagine-video-1.5",
    "prompt": "Pan across the scene as the sky darkens",
    "duration": 5,
    "image": { "file_id": "file_7de029f4-eb66-42ee-87f8-b2a9d9e7466a" }
  }'

SDK: image_file_id=... on client.video.generate. For video edits use video: { "file_id": "..." } / video_file_id. For reference-to-video use reference_images entries with file_id or url, or SDK reference_image_file_ids.

Chain without leaving Files

Generate with storage_options={"filename": "city.jpg"}, then pass file_output.file_id into the next edit or video call. Pair with Persist an Imagine output with a public URL when you also need a shareable CDN link.

Pitfalls

  • Referencing a file that is still uploading or the wrong MIME type for the endpoint.
  • Publishing a file just to use it as input — private file_id is enough.
  • Re-downloading and re-uploading between steps when storage_options already gave you a file_id.