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
Return storage statistics instead of file list
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
List Directory
Storage Stats
{
"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
File path (e.g., attachments/photo.jpg)
Return image thumbnail instead of full file
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
Image width in pixels (for images)
Image height in pixels (for images)
Base64-encoded thumbnail for images
Set to "directory" to create a directory
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
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)
}