Storage Operations File and folder operations, locking, previews, and transforms
Storage endpoints are available on both workspaces and shares. The API patterns are identical — replace workspace/{workspace_id} with share/{share_id} in any path below unless noted as workspace-only or share-only.
All endpoints require JWT authentication unless otherwise noted. Include the header Authorization: Bearer {jwt_token} with every request.
Conventions
- Root folder: Use the literal string
"root"as the path parameter (e.g.,/storage/root/list/) - Trash folder: Use
"trash"to list trashed items (e.g.,/storage/trash/list/) - Node IDs: OpaqueIds — 30-character alphanumeric strings displayed with hyphens (e.g.,
f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4). Use as-is in API calls. - Node ID prefixes:
f= file,d= folder,n= note - Node types in responses:
"file","folder","note","link"(lowercase strings) - Parent field: Nodes at the storage root have
"parent": "root"; nested nodes show the parent's OpaqueId - Delete vs purge:
DELETE .../storage/{node_id}/delete/moves to trash.DELETE .../storage/trash/delete/empties the entire trash.DELETE .../storage/{node_id}/purge/permanently deletes a single trashed item. - Workspace folder shares: Shares that reference a workspace folder have their
rootmapped to the designated folder. All operations are scoped to that subtree.
Node Object Schema
All endpoints that return node data use this format. Fields vary by node type.
| Field | Type | Present On | Description |
|---|---|---|---|
id | string | all | OpaqueId of the node |
name | string | all | File, folder, or note name |
type | string | all | "file", "folder", "note", or "link" |
parent | string | all | Parent folder OpaqueId or "root" |
size | integer | file | File size in bytes |
hash | string | file | Content hash of the file |
hash_algo | string | file | Hash algorithm (e.g., "md5") |
mimetype | string | file | MIME type (e.g., "application/pdf") |
mimecategory | string | file | MIME category (e.g., "document", "image") |
version | string | file, note | Current version identifier (e.g., "v1") |
created | string | all | ISO 8601 creation timestamp |
modified | string | all | ISO 8601 last-modified timestamp |
restricted | boolean | all | Whether the file has been restricted |
dmca | boolean | all | Whether the file has a DMCA flag |
locked | boolean | all | Whether the node has an active lock |
lock_info | object/null | all | Lock details when locked; null otherwise |
virus | object | file | Virus scan status: {"status": "scanned", "infected": false} |
file_attributes | object | file | Media metadata: width, height, duration (where applicable) |
summary | object | file | AI-generated summary: {"title": "...", "short": "...", "long": "..."} |
metadata | object/null | file | User-defined custom title and description overrides |
previews | object | file | Preview generation state per type (e.g., {"thumbnail": {"state": "ready"}}) |
ai | object | file | AI processing state: {"state": "...", "attach": true/false} |
origin | object | file | Origin info: {"type": "upload", "creator": "{user_id}"} |
AI States
| Value | Description |
|---|---|
disabled | AI processing is disabled for this file |
pending | Queued for AI processing |
inprogress | AI processing is running |
ready | AI processing complete |
failed | AI processing failed |
indexed | File has been indexed for search and RAG |
Keyset Pagination (Storage List)
Storage listing endpoints (list and recent) use cursor-based pagination, not offset-based.
Request Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| sort_by | string | name | One of: name, updated, created, type |
| sort_dir | string | asc | One of: asc, desc |
| page_size | int | 100 | One of: 100, 250, 500 (snapped to nearest) |
| cursor | string | — | Opaque cursor string from previous response |
Response Pagination Fields
| Field | Type | Description |
|---|---|---|
pagination.has_more | boolean | Whether more pages exist |
pagination.next_cursor | string/null | Cursor for the next page; null if last page |
pagination.page_size | integer | Effective page size used |
Notes:
- Cursors are HMAC-signed; tampered cursors are rejected with an error.
- When using a cursor, the page size from the cursor takes precedence over the request parameter.
- Only the first page of each sort configuration is cached (30-second TTL).
- The
recentendpoint ignoressort_byandsort_dir(always sorted byupdateddescending).
List Folder Contents
/current/workspace/{workspace_id}/storage/{parent_id}/list/
/current/share/{share_id}/storage/{parent_id}/list/
List the contents of a folder. Uses keyset pagination.
Auth required. Permission: View (workspace), Guest+ (share). Share list on public shares may not require JWT.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {parent_id} | string | Yes | Folder OpaqueId, "root", or "trash" |
Query parameters: See Keyset Pagination section above.
curl Example
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/root/list/?sort_by=name&sort_dir=asc&page_size=100" \
-H "Authorization: Bearer {jwt_token}"
Response
{
"result": "yes",
"response": {
"nodes": {
"items": [
{
"id": "d1abc-defgh-ijklm-nopqr-stuvw-xyz123",
"type": "folder",
"name": "Documents",
"parent": "root",
"created": "2025-01-01T00:00:00Z",
"modified": "2025-01-20T14:45:00Z"
},
{
"id": "f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4",
"type": "file",
"name": "photo.jpg",
"parent": "root",
"size": 2048000,
"mimetype": "image/jpeg",
"created": "2025-01-10T09:00:00Z",
"modified": "2025-01-10T09:00:00Z"
}
],
"path": "/",
"parent": null
},
"pagination": {
"has_more": true,
"next_cursor": "eyJwIjoiMmFiYzEyMy4uLiIsInMi...",
"page_size": 100
}
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
nodes.items | array | Array of node objects for current page |
nodes.path | string | Current folder path |
nodes.parent | string/null | Parent folder ID or null for root |
pagination.has_more | boolean | true if more pages exist |
pagination.next_cursor | string/null | Cursor for next page |
pagination.page_size | integer | Actual page size used |
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Folder not found |
APP_ERROR_INPUT_INVALID | 400 | Node is not a folder |
APP_ERROR_INPUT_INVALID | 400 | Invalid pagination cursor (tampered or mismatched) |
Node Details
/current/workspace/{workspace_id}/storage/{node_id}/details/
/current/share/{share_id}/storage/{node_id}/details/
Get full details for a single node (file, folder, or note).
Auth required. Permission: View (workspace), View (share).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {node_id} | string | Yes | Node OpaqueId |
curl Example
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/details/" \
-H "Authorization: Bearer {jwt_token}"
Response
{
"result": "yes",
"response": {
"node": {
"id": "f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4",
"type": "file",
"name": "document.pdf",
"parent": "d1abc-defgh-ijklm-nopqr-stuvw-xyz123",
"size": 5242880,
"hash": "d41d8cd98f00b204e9800998ecf8427e",
"hash_algo": "md5",
"mimetype": "application/pdf",
"mimecategory": "document",
"version": "v1",
"created": "2025-01-15T10:30:00Z",
"modified": "2025-01-20T14:45:00Z",
"restricted": false,
"dmca": false,
"locked": false,
"lock_info": null,
"virus": { "status": "scanned", "infected": false },
"file_attributes": { "width": null, "height": null, "duration": null },
"summary": {
"title": "Quarterly Report",
"short": "Q4 financial summary",
"long": "Comprehensive financial report covering revenue and expenses."
},
"metadata": null,
"previews": {
"thumbnail": { "state": "ready" },
"pdf": { "state": "ready" }
},
"ai": { "state": "indexed", "attach": true },
"origin": { "type": "upload", "creator": "98765432109876543210" }
}
}
}
Response fields: See Node Object Schema above for complete field reference.
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Node not found |
APP_DENIED | 403 | No permission to view details (share only) |
Add File from Upload
/current/workspace/{workspace_id}/storage/{parent_id}/addfile/
/current/share/{share_id}/storage/{parent_id}/addfile/
Add a previously uploaded file to storage.
Auth required. Permission: Guest (workspace), file creation permission (share).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {parent_id} | string | Yes | Parent folder OpaqueId or "root" |
Request Body (form-encoded)
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Filename for the new file |
| from | string | Yes | JSON-encoded source object (see below) |
from format (workspace):
{"type": "upload", "upload": {"id": "{upload_id}"}}
from format (share — also supports hash source):
{"from_type": "upload", "upload": {"upload_id": "{upload_id}"}}
{"from_type": "hash", "hash": {"hash": "{file_hash}", "hash_type": "sha256"}}
curl Example
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/root/addfile/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'name=document.pdf' \
-d 'from={"type":"upload","upload":{"id":"abc123opaqueid"}}'
Response
{
"result": "yes",
"response": {
"node": {
"id": "f4kn6-arybw-qxes3-ey9z6-cwoc4-sglhn5",
"type": "file",
"name": "document.pdf",
"parent": "root",
"size": 5242880,
"hash": "d41d8cd98f00b204e9800998ecf8427e",
"hash_algo": "md5",
"mimetype": "application/pdf",
"mimecategory": "document",
"version": "v1",
"created": "2025-01-15T10:30:00Z",
"modified": "2025-01-15T10:30:00Z",
"restricted": false,
"dmca": false,
"locked": false
}
}
}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_INPUT_INVALID | 400 | Duplicate filename in parent folder |
APP_ERROR_INPUT_INVALID | 400 | Upload session not found or not associated with your account |
APP_ERROR_INPUT_INVALID | 400 | Upload is not complete |
APP_ERROR_NOT_FOUND | 404 | Parent folder not found |
APP_ERROR_INPUT_INVALID | 400 | Parent node is not a folder |
APP_ERROR_NOT_FOUND | 404 | Parent folder is in trash |
Notes:
- The upload session must be in COMPLETE status before adding the file.
- Virus scanning occurs during upload assembly, not at this stage.
Add Link (Workspace Only)
/current/workspace/{workspace_id}/storage/{parent_id}/addlink/
Add a share link node to workspace storage. Link nodes represent references to shares within the workspace tree.
Auth required. Permission: Guest.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} | string | Yes | 20-digit workspace profile ID |
| {parent_id} | string | Yes | Parent folder OpaqueId or "root" |
Request Body (form-encoded)
| Parameter | Type | Required | Description |
|---|---|---|---|
| link_target_type | string | Yes | Must be "share" |
| share | string | Yes | Share identifier to link |
curl Example
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/root/addlink/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'link_target_type=share' \
-d 'share=my-share-name'
Response
{"result": "yes"}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_MISSING | 404 | Share not found or not accessible |
APP_ERROR_INPUT_INVALID | 400 | Share does not belong to this workspace |
APP_ERROR_INPUT_INVALID | 400 | A link to this share already exists (only one per share) |
Create Folder
/current/workspace/{workspace_id}/storage/{parent_id}/createfolder/
/current/share/{share_id}/storage/{parent_id}/createfolder/
Create a new folder.
Auth required. Permission: Guest (workspace), folder creation permission (share).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {parent_id} | string | Yes | Parent folder OpaqueId or "root" |
Request Body (form-encoded)
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Folder name |
curl Example
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/root/createfolder/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'name=Documents'
Response
{
"result": "yes",
"response": {
"node": {
"id": "d2bcd-efghi-jklmn-opqrs-tuvwx-yz1234",
"type": "folder",
"name": "Documents",
"parent": "root",
"created": "2025-01-15T10:30:00Z",
"modified": "2025-01-15T10:30:00Z",
"restricted": false,
"dmca": false,
"locked": false
}
}
}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_INPUT_INVALID | 400 | Duplicate name in parent folder |
APP_ERROR_NOT_FOUND | 404 | Parent folder not found |
APP_ERROR_INPUT_INVALID | 400 | Parent node is not a folder |
APP_ERROR_NOT_FOUND | 404 | Parent folder is in trash |
APP_DENIED | 403 | No folder creation permission (share only) |
Create Note (Workspace Only)
/current/workspace/{workspace_id}/storage/{parent_id}/createnote/
Create a markdown note. Notes are auto-indexed for AI when workspace intelligence is enabled.
Auth required. Permission: Guest.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} | string | Yes | 20-digit workspace profile ID |
| {parent_id} | string | Yes | Parent folder OpaqueId or "root" |
Request Body (form-encoded)
| Parameter | Type | Required | Constraints | Description |
|---|---|---|---|---|
| name | string | Yes | Must end in .md | Note name |
| content | string | Yes | Max 100 KB | Markdown content |
curl Example
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/root/createnote/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'name=meeting-notes.md' \
-d 'content=# Meeting Notes\n\nDiscussed project timeline.'
Response
{
"result": "yes",
"response": {
"note": {
"id": "n5mno-pqrst-uvwxy-z1234-abcde-fghij6",
"type": "note",
"name": "meeting-notes.md",
"parent": "root",
"mimetype": "text/markdown",
"created": "2025-01-15T10:30:00Z",
"modified": "2025-01-15T10:30:00Z"
}
}
}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_INPUT_INVALID | 400 | Filename must end with .md |
APP_ERROR_INPUT_INVALID | 400 | Duplicate name in parent folder |
APP_ERROR_NOT_FOUND | 404 | Parent folder not found |
Update Note (Workspace Only)
/current/workspace/{workspace_id}/storage/{node_id}/updatenote/
Update an existing note's name and/or content. Updating content creates a new version.
Auth required. Permission: Guest.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} | string | Yes | 20-digit workspace profile ID |
| {node_id} | string | Yes | Note OpaqueId |
Request Body (form-encoded)
| Parameter | Type | Required | Constraints | Description |
|---|---|---|---|---|
| name | string | No | Must end in .md | New note name |
| content | string | No | Max 100 KB | New markdown content |
At least one of name or content is required.
curl Example
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/n5mno-pqrst-uvwxy-z1234-abcde-fghij6/updatenote/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'content=# Updated Notes\n\nRevised content here.'
Response
{
"result": "yes",
"response": {
"note": {
"id": "n5mno-pqrst-uvwxy-z1234-abcde-fghij6",
"type": "note",
"name": "meeting-notes.md",
"parent": "root",
"mimetype": "text/markdown",
"created": "2025-01-15T10:30:00Z",
"modified": "2025-01-20T14:45:00Z"
}
}
}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Note not found |
APP_ERROR_INPUT_INVALID | 400 | Node is not a note |
APP_ERROR_NOT_FOUND | 404 | Note is in trash |
APP_ERROR_INPUT_INVALID | 400 | No content or name provided |
APP_ERROR_INPUT_INVALID | 400 | Duplicate name in parent folder |
Update Node
/current/workspace/{workspace_id}/storage/{node_id}/update/
/current/share/{share_id}/storage/{node_id}/update/
Update a node: rename, replace content with a new upload, and/or update custom metadata. Cannot be used on Note nodes (use updatenote instead).
Auth required. Permission: Guest (workspace), file modification permission (share).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {node_id} | string | Yes | Node OpaqueId |
Request Body (form-encoded)
| Parameter | Type | Required | Constraints | Description |
|---|---|---|---|---|
| name | string | No | — | New node name |
| from | string | No | JSON-encoded | New file content source (same format as addfile) |
| metadata_title | string | No | Max 50 chars | Custom title override |
| metadata_short | string | No | Max 2048 chars | Custom short description override |
At least one field should be provided.
curl Example (rename)
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/update/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'name=new-document-name.pdf'
curl Example (replace content and update metadata)
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/update/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'from={"type":"upload","upload":{"id":"upload_opaque_id"}}' \
-d 'metadata_title=Updated Report' \
-d 'metadata_short=Q1 2025 revision'
Response
{
"result": "yes",
"response": {
"node": {
"id": "f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4",
"type": "file",
"name": "new-document-name.pdf",
"parent": "root",
"size": 5242880,
"version": "v2",
"modified": "2025-01-22T11:00:00Z"
}
}
}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Node not found |
APP_ERROR_INPUT_INVALID | 400 | Cannot update a Note with this endpoint |
APP_ERROR_NOT_FOUND | 404 | Node is in trash |
Notes:
- Replacing content creates a new version.
- Renaming a link node propagates the rename to the linked share.
- Custom metadata overrides AI-generated summary values for display.
Move Node
/current/workspace/{workspace_id}/storage/{node_id}/move/
/current/share/{share_id}/storage/{node_id}/move/
Move a node to a different folder within the same storage instance.
Auth required. Permission: Guest (workspace), file modification permission (share).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {node_id} | string | Yes | Node OpaqueId to move |
Request Body (form-encoded)
| Parameter | Type | Required | Description |
|---|---|---|---|
| parent | string | Yes | Destination folder OpaqueId or "root" |
curl Example
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/move/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'parent=d1abc-defgh-ijklm-nopqr-stuvw-xyz123'
Response
{"result": "yes"}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Source or destination node not found |
APP_ERROR_NOT_FOUND | 404 | Source or destination is in trash |
APP_ERROR_INPUT_INVALID | 400 | Cannot move a folder into itself or its subfolders |
APP_DENIED | 403 | No move permission (share only) |
Copy Node
/current/workspace/{workspace_id}/storage/{node_id}/copy/
/current/share/{share_id}/storage/{node_id}/copy/
Copy a node to another folder within the same storage instance. Folder copies are recursive.
Auth required. Permission: Guest (workspace), file/folder creation permission (share).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {node_id} | string | Yes | Node OpaqueId to copy |
Request Body (form-encoded)
| Parameter | Type | Required | Description |
|---|---|---|---|
| parent | string | Yes | Destination folder OpaqueId or "root" |
curl Example
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/copy/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'parent=d1abc-defgh-ijklm-nopqr-stuvw-xyz123'
Response
{
"result": "yes",
"response": {
"node": {
"id": "f6qrs-tuvwx-yz123-abcde-fghij-klmno7",
"type": "file",
"name": "document.pdf",
"parent": "d1abc-defgh-ijklm-nopqr-stuvw-xyz123"
},
"job": null
}
}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Source or destination not found |
APP_ERROR_INPUT_INVALID | 400 | Destination is not a folder |
APP_ERROR_NOT_FOUND | 404 | Source or destination is in trash |
Notes:
- Creates a deep copy for folders (all children are copied recursively).
- The copied node gets a new OpaqueId.
Transfer Node
/current/workspace/{workspace_id}/storage/{node_id}/transfer/
/current/share/{share_id}/storage/{node_id}/transfer/
Copy a node to a different storage instance (e.g., from workspace to share, share to workspace, or share to share). The original node remains in place.
Auth required. Permission: Guest on source + write access on destination.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | Source profile ID |
| {node_id} | string | Yes | Node OpaqueId to transfer, or "root" for all |
Request Body (form-encoded)
| Parameter | Type | Required | Description |
|---|---|---|---|
| instance | string | Yes | 20-digit destination workspace or share profile ID |
| parent | string | Yes | Destination parent folder OpaqueId or "root" |
curl Example
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/transfer/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'instance=98765432109876543210' \
-d 'parent=root'
Response
{
"result": "yes",
"response": {
"node": {
"id": "f7stu-vwxyz-12345-abcde-fghij-klmno8",
"type": "file",
"name": "document.pdf",
"parent": "root"
},
"job": null
}
}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Source node not found or outside scope |
APP_DENIED | 403 | No write access to destination |
Notes:
- Folder transfers are recursive.
- The user must have write access to both source and destination.
Delete Node (Move to Trash)
/current/workspace/{workspace_id}/storage/{node_id}/delete/
/current/share/{share_id}/storage/{node_id}/delete/
Move a node to trash. Pass "trash" as the {node_id} to empty the entire trash bin.
Auth required. Permission: Guest (workspace), file modification permission (share). Emptying trash on shares requires admin permission.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {node_id} | string | Yes | Node OpaqueId, or "trash" to empty the entire trash |
curl Examples
# Delete a specific node
curl -X DELETE "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/delete/" \
-H "Authorization: Bearer {jwt_token}"
# Empty the trash
curl -X DELETE "https://api.fast.io/current/workspace/12345678901234567890/storage/trash/delete/" \
-H "Authorization: Bearer {jwt_token}"
Response
{
"result": "yes",
"response": {
"job": null
}
}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Node not found |
APP_ERROR_NOT_FOUND | 404 | Node already in trash |
APP_DENIED | 403 | No delete permission (share only) |
APP_DENIED | 403 | No permission to empty trash (share, non-admin) |
Notes:
- Deleting a folder moves it and all children to trash recursively.
- Share delete permissions may be restricted to files the user created.
Purge Node (Permanent Delete)
/current/workspace/{workspace_id}/storage/{node_id}/purge/
/current/share/{share_id}/storage/{node_id}/purge/
Permanently delete a node that is already in trash. Irreversible.
Auth required. Permission: Member (workspace), admin (share).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {node_id} | string | Yes | OpaqueId of the trashed node |
curl Example
curl -X DELETE "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/purge/" \
-H "Authorization: Bearer {jwt_token}"
Response
{
"result": "yes",
"response": {
"job": null
}
}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Node not found |
APP_ERROR_INPUT_INVALID | 400 | Node is not in trash |
APP_DENIED | 403 | Insufficient permission (share, non-admin) |
Restore from Trash
/current/workspace/{workspace_id}/storage/{node_id}/restore/
/current/share/{share_id}/storage/{node_id}/restore/
Restore a trashed node to its original location.
Auth required. Permission: Guest (workspace), file modification + admin (share).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {node_id} | string | Yes | OpaqueId of the trashed node |
curl Example
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/restore/" \
-H "Authorization: Bearer {jwt_token}"
Response
{
"result": "yes",
"response": {
"job": null
}
}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Node not found |
APP_ERROR_INPUT_INVALID | 400 | Node is not in trash |
APP_DENIED | 403 | No restore permission (share only) |
List Versions
/current/workspace/{workspace_id}/storage/{node_id}/versions/
/current/share/{share_id}/storage/{node_id}/versions/
List all versions of a file or note.
Auth required. Permission: View (workspace), file view permission (share).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {node_id} | string | Yes | Node OpaqueId |
curl Example
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/versions/" \
-H "Authorization: Bearer {jwt_token}"
Response
{
"result": "yes",
"response": {
"versions": [
{
"id": "v8abc-defgh-ijklm-nopqr-stuvw-xyz901",
"version_number": 2,
"created": "2025-01-20T14:45:00Z",
"operation": "update",
"size": 5242880,
"hash": "abc123def456789..."
},
{
"id": "v9bcd-efghi-jklmn-opqrs-tuvwx-yz0123",
"version_number": 1,
"created": "2025-01-15T10:30:00Z",
"operation": "create",
"size": 4194304,
"hash": "def456abc789012..."
}
]
}
}
Response Fields (per version)
| Field | Type | Description |
|---|---|---|
id | string | Version OpaqueId |
version_number | integer | Incrementing version number |
created | string | ISO 8601 timestamp of this version |
operation | string | How this version was created: "create", "update", "restore" |
size | integer | File size in bytes for this version |
hash | string | Content hash for this version |
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Node not found |
APP_ERROR_INPUT_INVALID | 400 | Unsupported node type |
APP_ERROR_OBJECT_INIT | 500 | Node data is corrupted |
Restore Version
/current/workspace/{workspace_id}/storage/{node_id}/restore-version/
/current/share/{share_id}/storage/{node_id}/restore-version/
Restore a file to a previous version. Creates a new version pointing to the historical version's content. Both filename and content are restored.
Auth required. Permission: Guest (workspace), file modification permission (share).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {node_id} | string | Yes | File OpaqueId |
Request Body (form-encoded)
| Parameter | Type | Required | Description |
|---|---|---|---|
| version_id | string | Yes | OpaqueId of the version to restore |
curl Example
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/restore-version/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'version_id=v9bcd-efghi-jklmn-opqrs-tuvwx-yz0123'
Response
{
"result": "yes",
"response": {
"new_version": {
"id": "v0cde-fghij-klmno-pqrst-uvwxy-z12345",
"version_number": 3,
"created": "2025-01-25T09:00:00Z",
"operation": "restore"
},
"node": {
"id": "f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4",
"type": "file",
"name": "original-name.pdf",
"version": "v3"
}
}
}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Node not found |
APP_ERROR_INPUT_INVALID | 400 | Can only restore file versions (not folders) |
APP_ERROR_INPUT_INVALID | 400 | Cannot restore version of trashed file |
APP_ERROR_NOT_FOUND | 404 | Version not found |
APP_ERROR_INPUT_INVALID | 400 | Version does not belong to this file |
APP_ERROR_NOT_FOUND | 404 | Version data no longer available |
APP_DENIED | 403 | No permission to restore versions (share only) |
Notes:
- Original versions are preserved; a new version with operation type
"restore"is created. - Both filename and content are restored to the historical version's state.
Download File (Read)
/current/workspace/{workspace_id}/storage/{node_id}/read/
/current/share/{share_id}/storage/{node_id}/read/
Download file content as binary. For notes, returns raw markdown. Supports byte-range requests for partial downloads and video streaming.
Auth: JWT or download token. Permission: View (workspace), download permission (share). With a valid token query parameter, no JWT is required.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {node_id} | string | Yes | File or note OpaqueId |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| token | string | No | Download token from requestread (bypasses JWT auth) |
| version_id | string | No | Specific version OpaqueId to download |
curl Examples
# Download with JWT auth
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/read/" \
-H "Authorization: Bearer {jwt_token}" \
-o output.pdf
# Download with token (no JWT needed)
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/read/?token={download_token}" \
-o output.pdf
# Download specific version
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/read/?version_id=v9bcd-efghi-jklmn-opqrs-tuvwx-yz0123" \
-H "Authorization: Bearer {jwt_token}" \
-o output_v1.pdf
# Byte-range request (streaming)
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/read/" \
-H "Authorization: Bearer {jwt_token}" \
-H "Range: bytes=0-1023"
Response: Binary file content streamed directly.
- Status
200 OKfor full file,206 Partial Contentfor range requests. - Headers:
Content-Type,Content-Length,Content-Disposition,Accept-Ranges: bytes.
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | File not found |
APP_ERROR_INPUT_INVALID | 400 | Can only read file or note (not folder) |
APP_ERROR_NOT_FOUND | 404 | File is in trash |
APP_ERROR_NOT_FOUND | 404 | Version not found |
APP_ERROR_INPUT_INVALID | 400 | Version does not belong to this file |
APP_ERROR_NOT_FOUND | 404 | Version data no longer available |
APP_DENIED | 403 | File flagged as virus-infected (share only) |
Request Download Token
/current/workspace/{workspace_id}/storage/{node_id}/requestread/
/current/share/{share_id}/storage/{node_id}/requestread/
Generate a temporary auth-free download token.
Auth required. Permission: View (workspace), download permission (share).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {node_id} | string | Yes | File or note OpaqueId |
curl Example
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/requestread/" \
-H "Authorization: Bearer {jwt_token}"
Response
{
"result": "yes",
"response": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}
Usage: Append ?token={token} to the read endpoint to download without an Authorization header. Useful for opening files in browser tabs.
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | File not found |
APP_ERROR_INPUT_INVALID | 400 | Can only read file or note |
APP_ERROR_NOT_FOUND | 404 | File is in trash |
APP_DENIED | 403 | No download permission (share only) |
Download Folder as ZIP
/current/workspace/{workspace_id}/storage/{folder_id}/zip/
/current/share/{share_id}/storage/{folder_id}/zip/
Download an entire folder as a streaming ZIP archive.
Auth required. Permission: View (workspace), download permission (share).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} or {share_id} | string | Yes | 20-digit profile ID |
| {folder_id} | string | Yes | Folder OpaqueId, or "root" for entire storage |
curl Example
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/root/zip/" \
-H "Authorization: Bearer {jwt_token}" \
-o workspace.zip
Response: Binary ZIP archive streamed directly with Content-Type and Content-Disposition headers.
Notes:
- The archive is streamed; it is not buffered in memory.
- Rate limited more aggressively than other endpoints due to resource cost.
Recent Files
/current/workspace/{workspace_id}/storage/recent/
/current/share/{share_id}/storage/recent/
List recently modified nodes across all folders, sorted by updated descending. Unlike list which is scoped to a single folder, this endpoint returns nodes from the entire storage tree.
Auth required. Permission: View (workspace), Guest+ (share). Public shares may allow password-only access.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| page_size | int | 100 | One of: 100, 250, 500 (snapped to nearest) |
| cursor | string | — | Opaque cursor string from previous response |
| type | string | — | Filter by node type: file, folder, link, note |
curl Example
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/recent/?type=file&page_size=250" \
-H "Authorization: Bearer {jwt_token}"
Response
{
"result": "yes",
"nodes": {
"count": 3,
"items": [
{
"id": "f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4",
"name": "report.pdf",
"type": "file",
"parent": "d1abc-defgh-ijklm-nopqr-stuvw-xyz123",
"size": 2048576,
"updated": "2025-02-18T14:30:00Z",
"created": "2025-02-17T10:00:00Z"
}
]
},
"pagination": {
"has_more": true,
"next_cursor": "eyJsYXN0X3VwZGF0ZWQiOiIyMDI1LTAyLTE4...",
"page_size": 100
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
nodes.count | integer | Number of nodes in this page |
nodes.items | array | Array of node resources |
pagination.has_more | boolean | Whether more pages exist |
pagination.next_cursor | string/null | Cursor for the next page |
pagination.page_size | integer | Effective page size used |
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_INPUT_INVALID | 406 | Invalid pagination cursor |
APP_DENIED | 401 | Insufficient permissions to view files (share only) |
APP_ERROR_NOT_FOUND | 404 | Orphaned workspace folder share |
Notes:
- Sort order is always
updated DESCand is not configurable. - Uses cursor-based (keyset) pagination, same as the
listendpoint. - For workspace folder shares, results are post-filtered to the share's subtree.
Search
/current/workspace/{workspace_id}/storage/search/
/current/share/{share_id}/storage/search/
Search files by keyword. Uses keyword and semantic search.
Auth required. Permission: View (workspace), search + file view permissions (share).
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| search | string | Yes | Search query string |
curl Example
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/search/?search=quarterly+report" \
-H "Authorization: Bearer {jwt_token}"
Response
{
"result": "yes",
"response": {
"files": {
"f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4": {
"name": "Q4 Report.pdf",
"parent_id": "d1abc-defgh-ijklm-nopqr-stuvw-xyz123",
"type": "file"
},
"f6qrs-tuvwx-yz123-abcde-fghij-klmno7": {
"name": "Quarterly Summary.docx",
"parent_id": "root",
"type": "file"
}
}
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
files | object | Map of node OpaqueIds to file info |
files.{id}.name | string | File name |
files.{id}.parent_id | string | Parent folder node ID |
files.{id}.type | string | Node type |
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Search not available for workspace folder shares (share only) |
APP_DENIED | 403 | No search permission (share only) |
Notes:
- Share search is not available for workspace-backed shares (shared folders).
- Search results are filtered by the user's file view permissions.
QuickShare (Workspace Only)
/current/workspace/{workspace_id}/storage/{node_id}/quickshare/
/current/workspace/{workspace_id}/storage/{node_id}/quickshare/
/current/workspace/{workspace_id}/storage/{node_id}/quickshare/
Create, retrieve, or delete a temporary public link for a single file.
Auth required. Permission: Member.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {workspace_id} | string | Yes | 20-digit workspace profile ID |
| {node_id} | string | Yes | File OpaqueId |
POST — Create or Update QuickShare
Request Body (form-encoded)
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| expires | string (digits) | No | Platform default | Expiration in seconds from now |
curl Example
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/quickshare/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'expires=604800'
Response
{
"result": "yes",
"response": {
"quickshare": {
"id": "qs_abc123def456",
"node": {
"id": "f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4",
"type": "file",
"name": "presentation.pdf",
"size": 5242880,
"mimetype": "application/pdf"
},
"creator_uid": {
"id": "12345678901234567890",
"email_address": "john@example.com",
"first_name": "John",
"last_name": "Doe"
},
"limit_exceeded": false,
"expires": "2025-01-22 10:30:00",
"created": "2025-01-15 10:30:00"
}
}
}
Error Responses (POST)
| Error Code | HTTP Status | Description |
|---|---|---|
APP_DENIED | 403 | File too large for quickshare |
APP_ERROR_INPUT_INVALID | 400 | Expiration too far in the future |
GET — Get QuickShare Details
Returns the same format as POST. Returns APP_ERROR_NOT_FOUND (404) if no quickshare exists.
DELETE — Delete QuickShare
Returns {"result": "yes"}. Returns APP_ERROR_NOT_FOUND (404) if no quickshare exists.
Public Access Endpoints (No Auth Required)
Once a quickshare is created, these endpoints are accessible without authentication:
GET /current/quickshare/{quickshare_id}/details/ -- metadata and file info
GET /current/quickshare/{quickshare_id}/storage/read/ -- download the file
GET /current/quickshare/{quickshare_id}/storage/preview/{preview_type}/read/ -- preview
GET /current/quickshare/{quickshare_id}/storage/preview/{preview_type}/read/file/{filename} -- preview sub-file
List QuickShares in Workspace
/current/workspace/{workspace_id}/storage/quickshares/list/
Returns an array of all active quickshares in the workspace.
Auth required. Permission: Member.
curl Example
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/quickshares/list/" \
-H "Authorization: Bearer {jwt_token}"
Response
{
"result": "yes",
"response": {
"quickshares": [
{
"id": "qs_abc123def456",
"node": { "id": "...", "type": "file", "name": "presentation.pdf" },
"creator_uid": { "id": "...", "email_address": "john@example.com" },
"limit_exceeded": false,
"expires": "2025-01-22 10:30:00",
"created": "2025-01-15 10:30:00"
}
]
}
}
File Locking
Lock a file to prevent concurrent edits. Locks expire automatically if not renewed via heartbeat. Available on both workspace and share storage.
Acquire Lock
/current/workspace/{workspace_id}/storage/{node_id}/lock/
/current/share/{share_id}/storage/{node_id}/lock/
Acquire a lock on a file.
Auth required. Permission: Guest (workspace), file modification permission (share).
Request Body (form-encoded)
| Parameter | Type | Required | Constraints | Description |
|---|---|---|---|---|
| duration | integer | No | 60-3600 seconds | Lock duration (default varies) |
| client_info | string | No | JSON object | Client metadata: device_name (max 255), client_version (max 50) |
curl Example
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/lock/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'duration=300' \
-d 'client_info={"device_name":"My Laptop","client_version":"2.1.0"}'
Response
{
"result": "yes",
"response": {
"lock_token": "unique_lock_token_string",
"locked_at": "2025-01-28T10:00:00+00:00",
"expires_at": "2025-01-28T10:05:00+00:00",
"node_id": "f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4"
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
lock_token | string | Token required for heartbeat and release operations |
locked_at | string | ISO 8601 lock acquisition time |
expires_at | string | ISO 8601 lock expiration time |
node_id | string | OpaqueId of the locked node |
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Node does not exist |
APP_ERROR_NOT_FOUND | 404 | Cannot lock a deleted node |
APP_CONFLICT | 409 | Node already locked by another user |
Heartbeat (Extend Lock)
/current/workspace/{workspace_id}/storage/{node_id}/lock/heartbeat/
/current/share/{share_id}/storage/{node_id}/lock/heartbeat/
Extend the lock duration.
Auth required.
Request Body (form-encoded)
| Parameter | Type | Required | Description |
|---|---|---|---|
| lock_token | string | Yes | Token from acquire response |
curl Example
curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/lock/heartbeat/" \
-H "Authorization: Bearer {jwt_token}" \
-d 'lock_token=unique_lock_token_string'
Response
{
"result": "yes",
"response": {
"expires_at": "2025-01-28T10:10:00+00:00",
"time_remaining": 300
}
}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | No lock exists on this node |
APP_ERROR_NOT_FOUND | 404 | Lock has expired |
APP_DENIED | 403 | Lock token does not match |
Notes:
- Send heartbeats well before the lock expires (e.g., at 50% of lock duration).
- Heartbeats can recreate an expired lock if the token and user match.
Release Lock
/current/workspace/{workspace_id}/storage/{node_id}/lock/
/current/share/{share_id}/storage/{node_id}/lock/
Release a lock on a file.
Auth required.
Request Body/Query
| Parameter | Type | Required | Description |
|---|---|---|---|
| lock_token | string | Yes | Token from acquire response |
Response
{
"result": "yes",
"response": {
"released": true
}
}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | No lock exists on this node |
APP_DENIED | 403 | Lock token does not match |
Lock Status
/current/workspace/{workspace_id}/storage/{node_id}/lock/
/current/share/{share_id}/storage/{node_id}/lock/
Check the lock status of a node.
Auth required.
Response (locked)
{
"result": "yes",
"response": {
"locked": true,
"locked_at": "2025-01-28T10:00:00+00:00",
"expires_at": "2025-01-28T10:05:00+00:00",
"node_id": "f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4",
"time_remaining": 245,
"locker_uid": "12345678901234567890"
}
}
Response (unlocked)
{
"result": "yes",
"response": {
"locked": false
}
}
Previews
File previews provide rendered views of documents, images, video, and other content without downloading the original file.
Preview Types
| Value | Description |
|---|---|
thumbnail | Small thumbnail image |
image | Full-size image preview |
hlsstream | HLS video/audio stream |
pdf | PDF document preview |
spreadsheet | Spreadsheet preview |
Preview States
Returned in node details responses under previews.{type}.state:
| State | Description |
|---|---|
unknown | Preview status not yet determined |
not possible | File type cannot be previewed |
not generated | Preview not yet generated |
error | Preview generation failed |
in progress | Preview is being generated |
ready | Preview is available |
Preauthorize Preview
/current/workspace/{workspace_id}/storage/{node_id}/preview/{preview_type}/preauthorize/
/current/share/{share_id}/storage/{node_id}/preview/{preview_type}/preauthorize/
Get a preview download URL with an embedded token.
Auth required. Permission: View (workspace), file view permission (share).
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {preview_type} | string | Yes | One of: thumbnail, image, hlsstream, pdf, spreadsheet |
curl Example
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/preview/thumbnail/preauthorize/" \
-H "Authorization: Bearer {jwt_token}"
Response
{
"result": "yes",
"response": {
"downloadToken": "eyJhbGciOiJIUzI1NiJ9...",
"path": "/current/workspace/.../preview/thumbnail/read/eyJhbGci.../file/preview.png",
"primaryFilename": "preview.png"
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
downloadToken | string | JWT token for preview access |
path | string | Full API path to read the preview file |
primaryFilename | string | Name of the primary preview file |
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | File not found |
APP_ERROR_INPUT_INVALID | 400 | Can only preview file or note |
APP_ERROR_NOT_FOUND | 404 | File is in trash |
APP_RESOURCE_NOT_FOUND | 404 | Preview not available |
Read Preview
/current/workspace/{workspace_id}/storage/{node_id}/preview/{preview_type}/read/
/current/share/{share_id}/storage/{node_id}/preview/{preview_type}/read/
Read or redirect to a preview. For single-file previews, streams content directly. For multi-file previews, returns a 307 Temporary Redirect to the file-specific endpoint with a generated token.
Auth required.
Token-Based Preview Read
/current/workspace/{workspace_id}/storage/{node_id}/preview/{preview_type}/read/{token}/file/{filename}
/current/share/{share_id}/storage/{node_id}/preview/{preview_type}/read/{download_token}/file/{filename}
Read a specific preview file using a token (from preauthorize). Token-based auth — no Authorization header needed.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| {token} | string | Yes | Download token from preauthorize |
| {filename} | string | Yes | Preview filename |
Transforms
Image transforms allow on-the-fly resizing, cropping, rotating, and format conversion.
Get Transform Status
/current/workspace/{workspace_id}/storage/{node_id}/transform/{transform_name}/
/current/share/{share_id}/storage/{node_id}/transform/{transform_name}/
Check if a transformation is available without triggering it.
Auth required. Currently the supported {transform_name} is image.
curl Example
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/transform/image/" \
-H "Authorization: Bearer {jwt_token}"
Response
{
"result": "yes",
"response": {
"state": "rendered"
}
}
Transformation States
| State | Description |
|---|---|
rendered | Transform is ready |
rendering | Transform in progress |
unrendered | Transform not yet requested |
unable to render | Transform failed or unsupported |
Request Transform
/current/workspace/{workspace_id}/storage/{node_id}/transform/{transform_name}/request/
/current/share/{share_id}/storage/{node_id}/transform/{transform_name}/request/
Request a transformation. If not yet rendered, triggers the transformation. If already rendered, returns immediately.
Auth required.
Response
{
"result": "yes",
"response": {
"state": "rendered"
}
}
Error Responses
| Error Code | HTTP Status | Description |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Unknown transformation name |
APP_ERROR_NOT_FOUND | 404 | Unable to transform (failed or unsupported) |
Read Transformed File
/current/workspace/{workspace_id}/storage/{node_id}/transform/{transform_name}/read/
/current/share/{share_id}/storage/{node_id}/transform/{transform_name}/read/
Download the transformed file. Supports byte-range requests and token auth.
Auth: JWT or download token.
Image Transform Parameters
Pass as query parameters on transform read endpoints:
| Parameter | Type | Values |
|---|---|---|
| output-format | string | png, jpg |
| width | int | Target width in pixels |
| height | int | Target height in pixels |
| cropwidth | int | Crop region width |
| cropheight | int | Crop region height |
| cropx | int | Crop region X offset |
| cropy | int | Crop region Y offset |
| rotate | int | 0, 90, 180, 270 |
| size | string | Predefined: IconSmall, IconMedium, Preview |
curl Example
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4/transform/image/read/?width=200&height=200&output-format=jpg" \
-H "Authorization: Bearer {jwt_token}" \
-o thumbnail.jpg
Request Transform Download Token (Workspace Only)
/current/workspace/{workspace_id}/storage/{node_id}/transform/{transform_name}/requestread/
Get a temporary download token for the transformed file.
Auth required.
Response
{
"result": "yes",
"response": {
"token": "eyJhbGciOiJIUzI1NiJ9..."
}
}
Download Tokens Pattern
The requestread endpoint generates temporary, auth-free download tokens for files, previews, and transforms.
Flow:
GET .../storage/{node_id}/requestread/— returns{"token": "..."}GET .../storage/{node_id}/read/?token={token}— download without Authorization header
Useful for opening files in browser tabs or embedding in pages without exposing auth headers.
Workspace-Only Features
These endpoints are only available on workspaces, not shares:
addlink— add a share link to storagecreatenote/updatenote— markdown notesquickshare— temporary public file linksquickshares/list— list all quicksharestransform/.../requestread/— transform download tokens
Share-Specific Notes
- Share storage follows identical patterns to workspace storage for all common operations
- Shares support file locking (acquire, heartbeat, release, status)
- Shares support previews and transforms (status, request, read)
- Share permissions are granular: separate permissions for file view, download, creation, modification, and administration
- Shares may restrict operations to files the user created (creator-only restrictions)
- Workspace folder shares map
rootto the designated folder and scope all operations to that subtree - Search is not available for workspace folder shares (files are indexed by workspace, not share)
- Public shares may allow listing and downloading without JWT authentication