API / upload-files-from-bytes

API

Upload Files API content from bytes or a file handle

Upload Files API content from bytes or a file handle

client.files.upload accepts a path string, raw bytes, a BytesIO, or an open file handle. Use bytes or a handle when the payload already lives in memory or came from another stream and you do not want a temp file on disk. Max size is 512 MB. Get a key at console.x.ai.

From bytes

Pass the bytes and a filename so the Files object has a usable name downstream.

import os
from xai_sdk import Client

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

content = b"This is my document content.\nIt can span multiple lines."
file = client.files.upload(content, filename="document.txt")

print(f"File ID: {file.id}")
print(f"Filename: {file.filename}")
print(f"Size: {file.size} bytes")

From an open file handle

import os
from xai_sdk import Client

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

with open("document.pdf", "rb") as f:
    file = client.files.upload(f, filename="document.pdf")

print(f"File ID: {file.id}")

Path uploads still work: client.files.upload("/path/to/document.pdf"). Attach the returned id in chat with Attach files to a Grok chat request, or feed Imagine with Use Files API as Imagine inputs.

REST / OpenAI SDK

Multipart POST https://api.x.ai/v1/files with purpose=assistants (stored for compatibility; xAI does not enforce it) and file=@.... OpenAI SDK: client.files.create(file=..., purpose="assistants") against base_url="https://api.x.ai/v1".

Pitfalls

  • Omitting filename on bytes uploads leaves a vague name in list/get responses.
  • Putting expires_after after file in multipart returns 400; TTL fields must come first.
  • Collections uploads cap at 100 MB per file; the standalone Files API allows 512 MB.