文件与集合

Public URL

通过 Files API 上传的每个文件默认都存储在 private storage 中,获取文件需要 API key。Public URL 可将已存储文件转换为 xAI CDN 上永久、可分享的链接,任何人无需 API key 即可打开。

创建后仍可完全控制:

  • 随时 revoke,只需一次 API 调用即可立即使 URL 失效。

  • 自动过期,设置 expires_after(1 小时至 30 天),或让 URL 继承文件自身的过期时间,使二者同时失效。

创建 public URL 不会修改底层 private file,revoke URL 也不会删除文件,二者的 lifecycle 相互独立。

如果需要控制访问权限(例如仅限已登录用户),请保持文件为 private,并通过自己的 backend 使用经过身份验证的 GET /v1/files/{file_id}/content endpoint 提供文件。

快速入门

import os
from xai_sdk import Client

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

# 1. Upload (or reference an existing) file
file = client.files.upload("/path/to/diagram.png")

# 2. Create the public URL
resp = client.files.create_public_url(file.id)

print(resp.public_url)
# https://files-cdn.x.ai/<token>/file_abc123.png

# 3. When you're done sharing, revoke it
client.files.revoke_public_url(file.id)

过期行为

创建 public URL 时,可以选择通过 expires_after(单位为秒)设置过期时间。超过 deadline 后,URL 会自动 revoke,后续请求返回 404,无需额外调用 API 进行清理。底层文件不受影响,仍可通过经过身份验证的 Files API 访问。

URL 的实际过期时间取决于两个输入:创建时是否传入 expires_after,以及底层文件是否 有自己的过期时间

  • 文件没有过期时间,expires_after 被省略,URL 永不过期,直到明确调用 revoke_public_url 或删除底层文件。

  • 文件没有过期时间,expires_after 设置为 N,URL 会从现在起在 N 秒后自动 revoke,文件本身不受影响。

  • 文件在时间 Texpires_after 被省略,URL 会继承文件的过期时间,二者都在 T

  • 文件在时间 Texpires_after 设置为 N,URL 会从现在起在 N 秒后消失。N 必须小于或等于文件的剩余 lifetime,否则请求会被拒绝。

expires_after 必须介于 3600 秒(1 小时)2592000 秒(30 天) 之间。Public URL 绝不能比文件存在更久;请求的 expires_after 大于文件剩余 lifetime 时会被拒绝。

import os
from datetime import timedelta
from xai_sdk import Client

client = Client(api_key=os.getenv("XAI_API_KEY"))
file = client.files.upload("/path/to/photo.png")

# 1. Indefinite: omit expires_after on a file with no expiry.
# Must call revoke_public_url to explicitly revoke the public URL.
resp = client.files.create_public_url(file.id)
assert not resp.HasField("expires_at")

# 2. URL-bound: pass expires_after as int seconds or a timedelta
resp = client.files.create_public_url(file.id, expires_after=timedelta(hours=24))
print(f"Expires at: {resp.expires_at.seconds}")

# 3. Inherited: file has its own expiration, omit expires_after on the URL
ttl_file = client.files.upload(
    b"\\x89PNG\\r\\n\\x1a\\n" + b"\\x00" * 32,
    filename="short-lived.png",
    expires_after=timedelta(hours=2),
)
resp = client.files.create_public_url(ttl_file.id)
# resp.expires_at matches the file's expires_at

Idempotency

一个文件在同一时间最多只能有一个 active public URL。对已有 active URL 的文件调用 create_public_url 会返回现有 URL,而不会生成新 URL,因此可安全地重复调用。

如果在后续调用中传入不同的 expires_after,现有 URL 的过期时间会原地更新,URL 中的 token 保持不变。

Python

import os
from xai_sdk import Client

client = Client(api_key=os.getenv("XAI_API_KEY"))
file_id = "file_abc123"

# First call creates the URL
resp1 = client.files.create_public_url(file_id, expires_after=86400)  # 1 day

# Second call returns the same URL, no re-upload
resp2 = client.files.create_public_url(file_id, expires_after=86400)
assert resp1.public_url == resp2.public_url

# Calling again with a different expires_after extends/shortens the expiry
# while keeping the same URL
resp3 = client.files.create_public_url(file_id, expires_after=604800)  # 7 days
assert resp1.public_url == resp3.public_url
assert resp3.expires_at.seconds > resp1.expires_at.seconds

Revoke Public URL

Revoke 会使 URL 失效,并从文件 metadata 中清除该 URL。原始文件不受影响,仍可通过经过身份验证的 endpoint 访问。

import os
from xai_sdk import Client

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

# Revoke a public URL
resp = client.files.revoke_public_url("file_abc123")
print(f"Revoked: {resp.revoked}")    # True
print(f"Was URL: {resp.public_url}") # the URL that just stopped working

# The file itself is still available via authenticated endpoints
file = client.files.get("file_abc123")
print(file.filename)

# Revoke is idempotent and safe to call on:
# - files that never had a public URL (returns revoked=False)
# - files whose URL was already revoked (returns revoked=False)
# - files that have been deleted
client.files.revoke_public_url("file_abc123")  # no-op, no error

Revocation 是全有或全无的。一个文件同一时间只能有一个 public URL,因此 revoke 会使所有持有该链接的人都无法访问。如果链接泄露给错误对象,唯一的补救方法是 revoke 并创建新 URL;新 URL 会使用全新的 token,旧 URL 将永久失效。

查找具有 Public URL 的文件

get_filelist_files 始终返回文件当前的 public URL 状态。public_urlpublic_url_expires_at 会填充在每个具有 active public URL 的文件上。

还可以在 filter 上使用 list_files 参数,查找具有或不具有 active public URL 的文件:

import os
from xai_sdk import Client

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

# All files that currently have a public URL
with_url = client.files.list(filter="public_url != null")
for f in with_url.data:
    print(f.id, f.filename)

# All files that do not currently have a public URL
without_url = client.files.list(filter="public_url = null")

限制

  • 最大文件大小:50 MiB。更大的文件仍可通过经过身份验证的 Files API 访问,但不能设为 public。

  • 受限的 content type。仅以下类型符合条件:

    • image/png.png

    • image/jpeg.jpg

    • video/mp4.mp4

    • application/pdf.pdf

  • 过期时间必须介于 1 小时和 30 天之间,且 public URL 绝不能比文件存在更久。

  • 删除文件会 revoke public URL。文件被删除后(手动删除或过期),无法继续保留 public URL。

  • 每个文件同一时间只能有一个 public URL。 create_public_url 具有 idempotency,重复调用会返回相同 URL。Revoke 后,下一次 create_public_url 会签发新 token,之前分享的所有 URL 都将永久失效。

  • 每个 team 最多有 1,000 个 active public URL。创建新 URL 前,请 revoke 不再需要的 URL。