
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/vidgenURL as durable storage — usefile_idor the CDN URL. - Hitting the 1,000-URL cap and reading a missing
public_urlwithout checkingpublic_url_error.