API / set-imagine-storage-expiry-knobs

API

Set Imagine storage and public URL expiry knobs

Set Imagine storage and public URL expiry knobs

storage_options on an Imagine request can keep the asset in Files and optionally mint a CDN URL. Two clocks are independent: file expiry and public URL expiry. Both accept seconds from now in 3600–2592000 (1 hour–30 days). A public URL can never outlive its file. Minting a public URL without expiry knobs is covered in Persist an Imagine output with a public URL.

filename is always required inside storage_options.

Permanent file, short public URL

File stays. CDN link dies in 24 hours.

curl -s -X POST https://api.x.ai/v1/images/generations \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-imagine-image-quality",
    "prompt": "A futuristic city skyline at night",
    "response_format": "url",
    "storage_options": {
      "filename": "skyline.jpg",
      "public_url": {"expires_after": 86400}
    }
  }'

File and URL share one deadline

Omit public_url.expires_after. The URL inherits the file TTL.

curl -s -X POST https://api.x.ai/v1/images/generations \
  -H "Authorization: Bearer $XAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-imagine-image-quality",
    "prompt": "A futuristic city skyline at night",
    "response_format": "url",
    "storage_options": {
      "filename": "skyline.jpg",
      "expires_after": 7200,
      "public_url": true
    }
  }'

File longer than the URL

File lasts 24h. Public URL lasts 1h.

import os
import xai_sdk

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

response = client.image.sample(
    prompt="A futuristic city skyline at night",
    model="grok-imagine-image-quality",
    storage_options={
        "filename": "skyline.jpg",
        "expires_after": 86400,
        "public_url": {"expires_after": 3600},
    },
)
print(response.file_output.file_id)
print(response.public_url)
print(response.file_output.expires_at)
print(response.file_output.public_url_expires_at)

The same storage_options shape works on image edits and on video generate / edit / extend. For video, file_output (including public_url) lands on the completed poll response.

After generation

Revoke or re-mint with the Files API (create_public_url / revoke_public_url) using file_output.file_id. Team cap is 1,000 active public URLs. If minting fails, read public_url_error — the file can still be stored.

Pitfalls

  • Asking for a public URL TTL longer than the file TTL — rejected.
  • Treating the ephemeral imgen / vidgen URL as durable storage — use file_id or the CDN URL.
  • Hitting the 1,000-URL cap and reading a missing public_url without checking public_url_error.