Skip to main content
Each thread has isolated file storage accessible via these endpoints. Files are stored in the thread’s SQLite database with support for external references (URLs, S3, R2).

List Directory / Query Files

threadId
string
required
The thread identifier
stats
boolean
Return storage statistics instead of file list
grep
string
Full-text search pattern
find
string
Glob pattern for path matching (e.g., *.jpg)
# List root directory
GET /api/threads/{threadId}/fs

# Get storage stats
GET /api/threads/{threadId}/fs?stats=1

# Full-text search
GET /api/threads/{threadId}/fs?grep=searchterm

# Find by pattern
GET /api/threads/{threadId}/fs?find=*.jpg
{
  "files": [
    {
      "path": "/attachments/photo.jpg",
      "name": "photo.jpg",
      "mimeType": "image/jpeg",
      "storage": "local",
      "size": 245123,
      "isDirectory": false,
      "createdAt": 1704067200000,
      "width": 2048,
      "height": 1536
    }
  ],
  "path": "/"
}

Get File

threadId
string
required
The thread identifier
path
string
required
File path (e.g., attachments/photo.jpg)
thumbnail
boolean
Return image thumbnail instead of full file
format
string
Set to json to return metadata only
# Get file content
GET /api/threads/{threadId}/fs/{path}

# Get thumbnail
GET /api/threads/{threadId}/fs/{path}?thumbnail=1

# Get metadata only
GET /api/threads/{threadId}/fs/{path}?format=json
Returns binary file data with appropriate Content-Type header, or JSON metadata when format=json.

Write File

threadId
string
required
The thread identifier
path
string
required
File path to write
data
string
Base64-encoded file data
mimeType
string
MIME type of the file
metadata
object
Optional custom metadata
width
number
Image width in pixels (for images)
height
number
Image height in pixels (for images)
thumbnail
string
Base64-encoded thumbnail for images
type
string
Set to "directory" to create a directory
location
string
External URL for linked files (instead of data)
# Write file (JSON)
POST /api/threads/{threadId}/fs/{path}
Content-Type: application/json
{
  "data": "base64...",
  "mimeType": "image/jpeg"
}

# Create directory
POST /api/threads/{threadId}/fs/{path}
Content-Type: application/json
{ "type": "directory" }

# Link external file
POST /api/threads/{threadId}/fs/{path}
Content-Type: application/json
{
  "location": "https://example.com/file.pdf",
  "mimeType": "application/pdf",
  "size": 1024000
}

# Raw binary upload (auto-chunks large files)
POST /api/threads/{threadId}/fs/{path}
Content-Type: application/octet-stream
[binary data]
Large files (>1.75MB) are automatically chunked server-side. No special client handling is required—just send a normal POST request with the binary data.
{
  "id": "/attachments/photo.jpg",
  "type": "file",
  "path": "/attachments/photo.jpg",
  "name": "photo.jpg",
  "mimeType": "image/jpeg",
  "size": 245123,
  "width": 2048,
  "height": 1536
}

Delete File

threadId
string
required
The thread identifier
path
string
required
File or directory path to delete
DELETE /api/threads/{threadId}/fs/{path}
Returns 204 No Content on success. Directories must be empty to delete.

FileRecord Schema

interface FileRecord {
  path: string;           // Full path (e.g., "/attachments/photo.jpg")
  name: string;           // Filename
  mimeType: string;       // MIME type
  storage: 'local' | 'url' | 's3' | 'r2';
  location?: string;      // External URL (if storage !== 'local')
  size: number;           // Size in bytes
  metadata?: object;      // Custom metadata
  isDirectory: boolean;
  createdAt: number;      // Unix timestamp (ms)
  width?: number;         // Image width in pixels (images only)
  height?: number;        // Image height in pixels (images only)
  isChunked?: boolean;    // True if file is stored in chunks (>1.75MB)
  chunkCount?: number;    // Number of chunks (if chunked)
}