> ## Documentation Index
> Fetch the complete documentation index at: https://docs.standardagents.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# File System

> Per-thread file storage with SQLite backing

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

## File paths in URLs

`{path}` is the file's path in the thread file system without its leading `/`, with each path segment percent-encoded.
The `path` of an attachment is such a path, so encode each segment before placing it in a URL:

```ts theme={null}
const encoded = path.replace(/^\/+/, '').split('/').map(encodeURIComponent).join('/')
const url = `/api/threads/${threadId}/fs/${encoded}`
```

The file `/my dir/a file.txt` is served at `/api/threads/{threadId}/fs/my%20dir/a%20file.txt`.
`getFileUrl()` in `@standardagents/client`, `@standardagents/react`, and `@standardagents/vue` encodes paths this way.

The server decodes each segment separately, for reads, writes, and deletes.
An encoded slash (`%2F`) inside a segment is not a path separator, and no file name contains a slash.
A path with such a segment or with a malformed escape (for example a bare `%`) names no file: a read or delete returns `404`, and a write returns `400`.

## 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`)

```bash theme={null}
# 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
```

```json List Directory theme={null}
{
  "files": [
    {
      "path": "/attachments/photo.jpg",
      "name": "photo.jpg",
      "mimeType": "image/jpeg",
      "storage": "local",
      "size": 245123,
      "isDirectory": false,
      "createdAt": 1704067200000,
      "width": 2048,
      "height": 1536
    }
  ],
  "path": "/"
}
```

```json Storage Stats theme={null}
{
  "totalSize": 5242880,
  "fileCount": 12
}
```

***

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

```bash theme={null}
# 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`)

```bash theme={null}
# 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]
```

> [!NOTE]
>
> 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.

```json 201 theme={null}
{
  "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

```bash theme={null}
DELETE /api/threads/{threadId}/fs/{path}
```

Returns `204 No Content` on success. Directories must be empty to delete.

***

## FileRecord Schema

```typescript theme={null}
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)
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.