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
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
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
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
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
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:

Upload a file
xeroctl files upload --purpose batch requests.jsonl
List files
xeroctl files list
Get file info
xeroctl files get file-abc123def456
Download file content
xeroctl files download file-abc123def456 -o output.jsonl
Delete a file
xeroctl files delete file-abc123def456

Client Examples

Python (requests)

Python
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)

JavaScript
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.