Files API
Upload, manage, and download files for batch processing and other purposes. Files are project-global resources accessible across all endpoints.
Overview
The Files API manages file uploads used primarily for batch processing. Files are stored using the platform's two-tier storage architecture with per-project isolation and 30-day automatic expiration. For details on storage tiers, encryption, retention, and billing, see Storage.
Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /v1/files | Upload a file |
| GET | /v1/files | List files |
| GET | /v1/files/{file_id} | Get file metadata |
| GET | /v1/files/{file_id}/content | Download file content |
| DELETE | /v1/files/{file_id} | Delete a file |
Files are project-scoped. All paths are relative to your project base URL:
https://api.xerotier.ai/proj_ABC123
Upload Files
POST /v1/files
Upload a file using multipart/form-data:
| Field | Type | Description |
|---|---|---|
| filerequired | binary | File content. Maximum 500MB. |
| purposerequired | string | File purpose. See Supported Purposes. |
curl -X POST https://api.xerotier.ai/proj_ABC123/v1/files \
-H "Authorization: Bearer xero_myproject_your_api_key" \
-F "file=@requests.jsonl" \
-F "purpose=batch"
Response
{
"id": "file-abc123def456",
"object": "file",
"purpose": "batch",
"filename": "requests.jsonl",
"bytes": 1048576,
"status": "uploaded",
"created_at": 1709000000,
"expires_at": 1711592000
}
List Files
GET /v1/files
Returns a list of all files for the project.
curl https://api.xerotier.ai/proj_ABC123/v1/files \
-H "Authorization: Bearer xero_myproject_your_api_key"
Response
{
"object": "list",
"data": [
{
"id": "file-abc123def456",
"object": "file",
"purpose": "batch",
"filename": "requests.jsonl",
"bytes": 1048576,
"status": "uploaded",
"created_at": 1709000000
}
],
"has_more": false
}
Get File Metadata
GET /v1/files/{file_id}
curl https://api.xerotier.ai/proj_ABC123/v1/files/file-abc123def456 \
-H "Authorization: Bearer xero_myproject_your_api_key"
Download File Content
GET /v1/files/{file_id}/content
Downloads the raw file content. The response Content-Type is application/jsonl for JSONL files.
curl https://api.xerotier.ai/proj_ABC123/v1/files/file-abc123def456/content \
-H "Authorization: Bearer xero_myproject_your_api_key" \
-o output.jsonl
Delete Files
DELETE /v1/files/{file_id}
Deletes the file from storage. Files referenced by active batches cannot be deleted until the batch completes.
curl -X DELETE https://api.xerotier.ai/proj_ABC123/v1/files/file-abc123def456 \
-H "Authorization: Bearer xero_myproject_your_api_key"
Supported Purposes
| Purpose | Format | Max Size | Description |
|---|---|---|---|
batch |
JSONL | 500MB | Input/output files for batch processing. Consumed by the batch processor. |
assistants |
Various | 500MB | Accepted for OpenAI compatibility. Stored but not processed. |
vision |
Image | 20MB | Accepted for OpenAI compatibility. Stored but not processed. |
user_data |
Various | 500MB | Accepted for OpenAI compatibility. Stored but not processed. |
fine-tune |
JSONL | 500MB | Accepted for OpenAI compatibility. Stored but not processed. |
Note: Only batch purpose files are actively
consumed by the batch processor. All other purposes are accepted for API
compatibility but are stored without further processing.
Status Lifecycle
| Status | Description |
|---|---|
uploaded |
File has been uploaded and stored in object storage. |
processed |
File content has been validated and is ready for use (e.g., JSONL parsing succeeded). |
error |
File validation failed. Check the batch job's error details for specifics. |
deleted |
File has been deleted (terminal state). |
Files are validated when they are first used by a batch job. The status
transitions from uploaded to processed on success
or error on failure. Files automatically expire after 30 days.
CLI Commands
The xeroctl CLI provides file management commands:
xeroctl files upload --purpose batch requests.jsonl
xeroctl files list
xeroctl files get file-abc123def456
xeroctl files download file-abc123def456 -o output.jsonl
xeroctl files delete file-abc123def456
Client Examples
Python (requests)
import requests
headers = {"Authorization": "Bearer xero_myproject_your_api_key"}
base = "https://api.xerotier.ai/proj_ABC123/v1"
# Upload a file
with open("requests.jsonl", "rb") as f:
upload_resp = requests.post(
f"{base}/files",
headers=headers,
files={"file": ("requests.jsonl", f)},
data={"purpose": "batch"}
)
file_obj = upload_resp.json()
print(f"Uploaded: {file_obj['id']}")
# List files
files = requests.get(f"{base}/files", headers=headers).json()
for f in files["data"]:
print(f"{f['id']} - {f['filename']} ({f['status']})")
# Get file metadata
meta = requests.get(f"{base}/files/{file_obj['id']}", headers=headers).json()
print(f"File size: {meta['bytes']} bytes")
# Download file content
content = requests.get(
f"{base}/files/{file_obj['id']}/content",
headers=headers
)
with open("output.jsonl", "wb") as out:
out.write(content.content)
# Delete a file
requests.delete(f"{base}/files/{file_obj['id']}", headers=headers)
Node.js (fetch)
import { readFile, writeFile } from "node:fs/promises";
const base = "https://api.xerotier.ai/proj_ABC123/v1";
const headers = { "Authorization": "Bearer xero_myproject_your_api_key" };
// Upload a file
const fileData = await readFile("requests.jsonl");
const formData = new FormData();
formData.append("file", new Blob([fileData]), "requests.jsonl");
formData.append("purpose", "batch");
const uploadRes = await fetch(`${base}/files`, {
method: "POST",
headers: { "Authorization": headers.Authorization },
body: formData
});
const fileObj = await uploadRes.json();
console.log(`Uploaded: ${fileObj.id}`);
// List files
const listRes = await fetch(`${base}/files`, { headers });
const files = await listRes.json();
files.data.forEach(f => console.log(`${f.id} - ${f.filename}`));
// Get file metadata
const metaRes = await fetch(`${base}/files/${fileObj.id}`, { headers });
const meta = await metaRes.json();
console.log(`File size: ${meta.bytes} bytes`);
// Download file content
const contentRes = await fetch(`${base}/files/${fileObj.id}/content`, { headers });
const content = await contentRes.arrayBuffer();
await writeFile("output.jsonl", Buffer.from(content));
// Delete a file
await fetch(`${base}/files/${fileObj.id}`, {
method: "DELETE",
headers
});
Error Handling
| HTTP Status | Error Code | Description |
|---|---|---|
| 400 | invalid_request |
Missing file, invalid purpose, or file exceeds size limit. |
| 401 | authentication_error |
Invalid or missing API key. |
| 404 | not_found |
File not found. |
| 409 | conflict |
File is referenced by an active batch and cannot be deleted. |
| 429 | rate_limit_exceeded |
Too many requests. Check the Retry-After header. |