Technical docs
Storage
Overview
Support reference for the org Storage page (`/storage`) and the org storage APIs behind it.
For the organization private API surface under `/api/private`, see `private-api.md`.
What users can do in `/storage`
- Browse folders with URL-backed navigation via `?path=...`.
- Switch between list and grid views.
- Search the current folder, sort, hide/show columns, and filter by file type and modified date.
- Select multiple items and bulk delete.
- Create folders.
- Upload by file picker, drag-and-drop, or folder upload.
- Download files.
- Copy file or folder paths.
- Share folders with AI teammates.
- Open non-folder items in Cowork via `/cowork?path=...`.
Current file actions in the UI
- Files: `Download`, `Copy Path`, `Delete`.
- Folders: `Share`, `Copy Path`, `Delete`.
- The Storage UI does not currently expose rename, copy, or move actions, even though org APIs exist for them.
- The code still contains an unused details panel, but `/storage` does not currently expose a working details action.
Upload rules
- Allowed upload types: `png`, `jpg`, `jpeg`, `gif`, `webp`, `svg`, `pdf`, `docx`, `xlsx`, `pptx`, `txt`, `htm`, `html`, `md`, `csv`, `json`, `yaml`, `yml`.
- Max upload size: `10 MB` per file.
- In the `/storage` UI, individual files cannot be uploaded to root (`/`).
- The org and private upload APIs still allow root uploads when `path` is omitted.
- Root-level folder uploads are allowed.
- Duplicate handling offers `Skip existing` and `Replace`.
- Upload UI supports pause, resume, retry, cancel, and persistent progress.
Sharing behavior
- Only folders can be shared.
- Root (`/`) cannot be shared.
- Sharing uses a dedicated dialog with AI teammates in the org, but Ally is not presented as a normal editable row there.
- The dialog always shows an `Ally` row with both `Read` and `Write` checked and disabled.
- The dialog text for Ally says `Full storage access is automatic.`
- Ally is the only special system-backed teammate in this share list.
- Permissions are `read` and `write`.
- In the current dialog, enabling `write` also enables `read`.
- If `write` is removed, `read` remains checked unless it is inherited from a parent share.
- `read` is disabled when it is inherited or when `write` is checked, so the dialog never allows write-only access.
- Parent-folder permissions appear as inherited (`from_parent: true`) and cannot be toggled from the child folder.
- Deleting a folder or file path removes matching share records for that path and nested paths.
Indexing and search
- Storage rows can show indexing states: `Indexed`, `Queued for indexing`, `Indexing…`, `Indexing failed`, `Not indexable`.
- Vector indexing currently supports `.txt`, `.md`, `.docx`, `.pdf`, and `.pptx`.
- Exact storage search is broader and can extract text from formats such as `docx`, `xlsx`, `pptx`, and `pdf`.
- Valid uploads can still show `Not indexable`.
Org API routes
- `GET /api/organizations/{orgId}/storage?path=...`
- `GET /api/organizations/{orgId}/storage/stats?path=...`
- `POST /api/organizations/{orgId}/storage/upload`
- `GET /api/organizations/{orgId}/storage/download?path=...`
- `DELETE /api/organizations/{orgId}/storage/file?path=...`
- `POST /api/organizations/{orgId}/storage/folder`
- `POST /api/organizations/{orgId}/storage/folder/rename`
- `POST /api/organizations/{orgId}/storage/folder/copy`
- `POST /api/organizations/{orgId}/storage/folder/move`
- `GET /api/organizations/{orgId}/storage/file/content?path=...`
- `PUT /api/organizations/{orgId}/storage/file/content`
- `GET /api/organizations/{orgId}/storage/folder/share?path=...`
- `POST /api/organizations/{orgId}/storage/folder/share`
- `DELETE /api/organizations/{orgId}/storage/folder/share`
Cowork edit endpoints
- `GET/PUT /storage/file/content` only allow existing `.txt` and `.md` files.
- Upload is capped at `10 MB` by the API upload route. The cowork content route is existing-file only; current code does not show a separate content-endpoint size rule beyond file handling in the caller.
AI teammate storage permissions
- Non-system AI teammates are still limited to folders explicitly shared with them.
- `storage.list` returns only content inside shared folders for non-system AI teammates.
- `storage.semantic_search` searches indexed documents inside readable shared folders for non-system AI teammates.
- `storage.search`, `storage.read_file`, `storage.read_image`, and `storage.stat_file` require readable shared-folder access for non-system AI teammates.
- `storage.get_temp_file_url` also requires readable shared-folder access for non-system AI teammates.
- `storage.write_file` and `storage.edit_file` require writable shared-folder access for non-system AI teammates.
- `storage.write_file` and `storage.edit_file` only support `.txt`, `.md`, `.htm`, `.html`, `.csv`, `.json`, `.yaml`, and `.yml`.
- `storage.rename` requires the target path to be inside a writable shared folder for non-system AI teammates.
- `storage.copy` requires readable source access and writable destination access for non-system AI teammates.
- `storage.move` requires writable access to both source and destination for non-system AI teammates.
- `storage.get_temp_file_url` returns a temporary HTTPS link for a readable file and is meant for external systems that need a URL instead of inline bytes.
- Current temporary-link format is `{API_DOMAIN}/shared/files/{organization_id}/{run_id}/{document_id}`.
- The temporary link only works while the workflow run that created it is still active; once the run completes or is aborted, the link expires.
- `storage.get_temp_file_url` currently returns `File not found` when the file does not yet have an `OrganizationDocument` record.
- Ally uses system-level storage access.
Realtime behavior
- The backend emits `storage_file.created`, `storage_file.updated`, `storage_file.deleted`, `storage_file.renamed`, `storage_file.copied`, and `storage_file.moved`.
- The current Storage file-list hook auto-refreshes on all six events.
- Cowork document state also listens to rename and move events so an open document can follow its new path.
Private storage API (HTTPS)
- The canonical private API reference now lives in `private-api.md`.
- Private storage routes are under `{api_url}/api/private/storage`.
- Current auth is `api-key: <TOKEN>` only.