Storage Operations File and folder operations, locking, previews, and transforms

Base URL: https://api.fast.io/current/ Auth: Bearer JWT

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

Compact Responses (output=)

Every storage endpoint that returns node objects — folder listings, node details, search hits, metadata endpoints, trash listings, and quickshares — accepts an optional output query parameter that selects the shape of each node in the response. A single detail-level token may be combined with modifier tokens; specifying two detail levels (e.g. ?output=terse,standard) returns HTTP 400. When output= is omitted, responses are full and byte-for-byte unchanged.

LevelFields returned on each node (cumulative)
terseid, type, name, parent, mimetype, size, modified, recursive nodes for folders when the endpoint returns children, summary reduced to {title} only, previews reduced to a per-type {ready: bool} map (keys preserved: thumbnail, image, pdf, mp4, hlsstream, audio, spreadsheet), folder-only is_share_root/share_id
standardterse + version, created, restricted, dmca, locked, mimecategory, origin reduced to {creator, type}, ai reduced to {state}, metadata reduced to {title, short} (user-authored overrides), deleted, deleted_from, is_imported, link-only target_type/target_id
fullstandard + summary.short/summary.long, note-only summary.category, virus, full ai object, full file_attributes (including EXIF), all remaining origin.* fields, hash, hash_algo, lock_info, import_metadata, full previews state map

Use terse for list rows, tree rendering, pickers, breadcrumb navigation, and drag-and-drop targets — it carries modified (so list rows can render the date column and "sort by modified" without a follow-up fetch), a per-type previews readiness map (so the thumbnail selector can pick the best available source), and the summary title. Use standard for most detail views, file-browser main lists, and any UI that shows AI-processing state, lock/restricted chips, DMCA chips, import-provider chips, or trash state — it adds the ai.state that drives the "summarizing…" spinner, timestamps, origin creator plus type, the dmca flag for DMCA chip rendering, is_imported for import-provider chips, link-node target_type/target_id discriminators, and the metadata.title/metadata.short user overrides that list rows render when a custom title is set. Use full (or omit the parameter) for the node detail pane, virus/AI inspection, version history, and any workflow that reads long-form summaries, EXIF, import provider metadata, or content hashes. Unknown tokens are silently ignored. Add the markdown modifier (e.g. ?output=standard,markdown) to receive the response as GitHub-flavored Markdown (Content-Type: text/markdown; charset=UTF-8) instead of JSON — see the cross-cutting ?output= reference for the full contract.

Node Object Schema

All endpoints that return node data use this format. Fields vary by node type.

FieldTypePresent OnDescription
idstringallOpaqueId of the node
namestringallFile, folder, or note name
typestringall"file", "folder", "note", or "link"
parentstringallParent folder OpaqueId or "root"
sizeintegerfileFile size in bytes
hashstringfileContent hash of the file
hash_algostringfileHash algorithm (e.g., "md5")
mimetypestringfileMIME type (e.g., "application/pdf")
mimecategorystringfileMIME category (e.g., "document", "image")
versionstringfile, noteCurrent version identifier (e.g., "v1")
createdstringallCreation timestamp (YYYY-MM-DD HH:MM:SS)
modifiedstringallLast-modified timestamp (YYYY-MM-DD HH:MM:SS)
restrictedbooleanallWhether the file has been restricted
dmcabooleanallWhether the file has a DMCA flag
lockedbooleanallWhether the node has an active lock
lock_infoobject/nullallLock details when locked; null otherwise
virusobjectfileVirus scan status: {"status": "scanned", "infected": false}
file_attributesobjectfileMedia metadata: width, height, duration (where applicable)
summaryobjectfileAI-generated summary: {"title": "...", "short": "...", "long": "..."}
metadataobject/nullfileUser-defined custom title and description overrides
previewsobjectfilePreview generation state per type (e.g., {"thumbnail": {"state": "ready"}})
aiobjectfileAI processing state: {"state": "...", "attach": true/false}
originobjectfileOrigin info: {"type": "upload", "creator": "{user_id}"}

AI States

ValueDescription
disabledAI processing is disabled for this file
pendingQueued for AI processing
inprogressAI processing is running
readyAI processing complete
failedAI processing failed
indexedFile 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

ParameterTypeDefaultDescription
sort_bystringnameOne of: name, updated, created, type
sort_dirstringascOne of: asc, desc
page_sizeint100One of: 100, 250, 500 (snapped to nearest)
cursorstringOpaque cursor string from previous response

Response Pagination Fields

FieldTypeDescription
pagination.has_morebooleanWhether more pages exist
pagination.next_cursorstring/nullCursor for the next page; null if last page
pagination.page_sizeintegerEffective page size used

Notes:

List Folder Contents

GET /current/workspace/{workspace_id}/storage/{parent_id}/list/
GET /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

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{parent_id}stringYesFolder 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

FieldTypeDescription
nodes.itemsarrayArray of node objects for current page
nodes.pathstringCurrent folder path
nodes.parentstring/nullParent folder ID or null for root
pagination.has_morebooleantrue if more pages exist
pagination.next_cursorstring/nullCursor for next page
pagination.page_sizeintegerActual page size used

Error Responses

Error CodeHTTP StatusDescription
1609 (Not Found)404Folder not found
1605 (Invalid Input)400Node is not a folder
1605 (Invalid Input)400Invalid pagination cursor (tampered or mismatched)

Node Details

GET /current/workspace/{workspace_id}/storage/{node_id}/details/
GET /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

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{node_id}stringYesNode 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 CodeHTTP StatusDescription
1609 (Not Found)404Node not found
1680 (Access Denied)403No permission to view details (share only)

Add File from Upload

POST /current/workspace/{workspace_id}/storage/{parent_id}/addfile/
POST /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

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{parent_id}stringYesParent folder OpaqueId or "root"

Request Body (form-encoded)

ParameterTypeRequiredDescription
namestringYesFilename for the new file
fromstringYesJSON-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 CodeHTTP StatusDescription
1605 (Invalid Input)400Upload session not found or not associated with your account
1605 (Invalid Input)400Upload is not complete
1609 (Not Found)404Parent folder not found
1605 (Invalid Input)400Parent node is not a folder
1609 (Not Found)404Parent folder is in trash
1605 (Invalid Input)400Name conflict (only when using FAIL strategy)

Notes:

POST /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

ParameterTypeRequiredDescription
{workspace_id}stringYes19-digit workspace profile ID
{parent_id}stringYesParent folder OpaqueId or "root"

Request Body (form-encoded)

ParameterTypeRequiredDescription
link_target_typestringYesMust be "share"
sharestringYesShare 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 CodeHTTP StatusDescription
1683 (Resource Missing)404Share not found or not accessible
1605 (Invalid Input)400Share does not belong to this workspace
1605 (Invalid Input)400A link to this share already exists (only one per share)

Create Folder

POST /current/workspace/{workspace_id}/storage/{parent_id}/createfolder/
POST /current/share/{share_id}/storage/{parent_id}/createfolder/

Create a new folder.

Auth required. Permission: Guest (workspace), folder creation permission (share).

Path Parameters

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{parent_id}stringYesParent folder OpaqueId or "root"

Request Body (form-encoded)

ParameterTypeRequiredDescription
namestringYesFolder 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 CodeHTTP StatusDescription
1605 (Invalid Input)400Duplicate name in parent folder
1609 (Not Found)404Parent folder not found
1605 (Invalid Input)400Parent node is not a folder
1609 (Not Found)404Parent folder is in trash
1680 (Access Denied)403No folder creation permission (share only)

Create Note (Workspace Only)

POST /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

ParameterTypeRequiredDescription
{workspace_id}stringYes19-digit workspace profile ID
{parent_id}stringYesParent folder OpaqueId or "root"

Request Body (form-encoded)

ParameterTypeRequiredConstraintsDescription
namestringYesMust end in .mdNote name
contentstringYesMax 100 KBMarkdown 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 CodeHTTP StatusDescription
1605 (Invalid Input)400Filename must end with .md
1605 (Invalid Input)400Duplicate name in parent folder
1609 (Not Found)404Parent folder not found

Update Note (Workspace Only)

POST /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

ParameterTypeRequiredDescription
{workspace_id}stringYes19-digit workspace profile ID
{node_id}stringYesNote OpaqueId

Request Body (form-encoded)

ParameterTypeRequiredConstraintsDescription
namestringNoMust end in .mdNew note name
contentstringNoMax 100 KBNew 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 CodeHTTP StatusDescription
1609 (Not Found)404Note not found
1605 (Invalid Input)400Node is not a note
1609 (Not Found)404Note is in trash
1605 (Invalid Input)400No content or name provided
1605 (Invalid Input)400Duplicate name in parent folder

Read Note

GET /current/workspace/{workspace_id}/storage/{node_id}/readnote/
GET /current/share/{share_id}/storage/{node_id}/readnote/

Read a note's content as JSON. Unlike the binary /read/ endpoint, this returns the sanitized markdown content as a string within the JSON response along with the full note resource.

Auth required. Permission: View (workspace), download permission or download token (share).

Path Parameters

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{node_id}stringYesNote OpaqueId

Query Parameters

ParameterTypeRequiredDescription
version_idstringNoSpecific version OpaqueId to read
tokenstringNoDownload token (share only — bypasses JWT auth)

curl Example

# Workspace
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/n5mno-pqrst-uvwxy-z1234-abcde-fghij6/readnote/" \
  -H "Authorization: Bearer {jwt_token}"

# Share
curl -X GET "https://api.fast.io/current/share/12345678901234567890/storage/n5mno-pqrst-uvwxy-z1234-abcde-fghij6/readnote/" \
  -H "Authorization: Bearer {jwt_token}"

# Share with download token (no JWT needed)
curl -X GET "https://api.fast.io/current/share/12345678901234567890/storage/n5mno-pqrst-uvwxy-z1234-abcde-fghij6/readnote/?token={download_token}"

Response

{
  "result": "yes",
  "response": {
    "content": "# Meeting Notes\n\nDiscussed project timeline.",
    "note": {
      "id": "n5mno-pqrst-uvwxy-z1234-abcde-fghij6",
      "type": "note",
      "name": "meeting-notes.md",
      "parent": "root",
      "mimetype": "text/markdown",
      "version": "v1",
      "created": "2025-01-15T10:30:00Z",
      "modified": "2025-01-15T10:30:00Z"
    }
  }
}

Response Fields

FieldTypeDescription
contentstringSanitized markdown content of the note
noteobjectFull note node object (same shape as other node responses)

Error Responses

Error CodeHTTP StatusDescription
1605 (Invalid Input)400Invalid node ID
1609 (Not Found)404Note not found
1605 (Invalid Input)400Node is not a note
1609 (Not Found)404Note is in trash
1609 (Not Found)404Version not found
1605 (Invalid Input)400Version does not belong to this note
1609 (Not Found)404Version data no longer available

Update Node

POST /current/workspace/{workspace_id}/storage/{node_id}/update/
POST /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

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{node_id}stringYesNode OpaqueId

Request Body (form-encoded)

ParameterTypeRequiredConstraintsDescription
namestringNoNew node name
fromstringNoJSON-encodedNew file content source (same format as addfile)
metadata_titlestringNoMax 50 charsCustom title override
metadata_shortstringNoMax 2048 charsCustom 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 CodeHTTP StatusDescription
1609 (Not Found)404Node not found
1605 (Invalid Input)400Cannot update a Note with this endpoint
1609 (Not Found)404Node is in trash

Notes:

Move Node

POST /current/workspace/{workspace_id}/storage/{node_id}/move/
POST /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

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{node_id}stringYesNode OpaqueId to move

Request Body (form-encoded)

ParameterTypeRequiredDescription
parentstringYesDestination 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 CodeHTTP StatusDescription
1609 (Not Found)404Source or destination node not found
1609 (Not Found)404Source or destination is in trash
1605 (Invalid Input)400Cannot move a folder into itself or its subfolders
1680 (Access Denied)403No move permission (share only)

Notes:

Copy Node

POST /current/workspace/{workspace_id}/storage/{node_id}/copy/
POST /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

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{node_id}stringYesNode OpaqueId to copy

Request Body (form-encoded)

ParameterTypeRequiredDescription
parentstringYesDestination 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 CodeHTTP StatusDescription
1609 (Not Found)404Source or destination not found
1605 (Invalid Input)400Destination is not a folder
1609 (Not Found)404Source or destination is in trash

Notes:

Transfer Node

POST /current/workspace/{workspace_id}/storage/{node_id}/transfer/
POST /current/share/{share_id}/storage/{node_id}/transfer/

Copy or move a node to a different storage instance (e.g., from workspace to share, share to workspace, or share to share). By default the original node remains in place (copy). Use mode=move to copy the node and then trash the source.

Auth required. Permission: Guest on source + write access on destination.

Path Parameters

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYesSource profile ID
{node_id}stringYesNode OpaqueId to transfer, or "root" for all

Request Body (form-encoded)

ParameterTypeRequiredDescription
instancestringYes19-digit destination workspace or share profile ID
parentstringYesDestination parent folder OpaqueId or "root"
modestringNocopy (default) or move. When move, the source node is trashed after copying. Cannot use mode=move when {node_id} is "root".

curl Example (copy, default)

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'

curl Example (move)

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' \
  -d 'mode=move'

Response (copy)

{
  "result": "yes",
  "response": {
    "node": {
      "id": "f7stu-vwxyz-12345-abcde-fghij-klmno8",
      "type": "file",
      "name": "document.pdf",
      "parent": "root"
    },
    "job": null
  }
}

Response (move)

{
  "result": "yes",
  "response": {
    "node": {
      "id": "f7stu-vwxyz-12345-abcde-fghij-klmno8",
      "type": "file",
      "name": "document.pdf",
      "parent": "root"
    },
    "source_trashed": true,
    "job": null
  }
}

Error Responses

Error CodeHTTP StatusDescription
1609 (Not Found)404Source node not found or outside scope
1609 (Not Found)404Source or destination instance (workspace/share) not found
1680 (Access Denied)403No write access to destination
1605 (Invalid Input)400mode=move cannot be used with "root" as the source node

Notes:

Delete Node (Move to Trash)

DELETE /current/workspace/{workspace_id}/storage/{node_id}/delete/
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

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{node_id}stringYesNode 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 CodeHTTP StatusDescription
1609 (Not Found)404Node not found
1609 (Not Found)404Node already in trash
1680 (Access Denied)403No delete permission (share only)
1680 (Access Denied)403No permission to empty trash (share, non-admin)

Notes:

Purge Node (Permanent Delete)

DELETE /current/workspace/{workspace_id}/storage/{node_id}/purge/
DELETE /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

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{node_id}stringYesOpaqueId 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 CodeHTTP StatusDescription
1609 (Not Found)404Node not found
1605 (Invalid Input)400Node is not in trash
1680 (Access Denied)403Insufficient permission (share, non-admin)

Restore from Trash

POST /current/workspace/{workspace_id}/storage/{node_id}/restore/
POST /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

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{node_id}stringYesOpaqueId 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 CodeHTTP StatusDescription
1609 (Not Found)404Node not found
1605 (Invalid Input)400Node is not in trash
1680 (Access Denied)403No restore permission (share only)

List Versions

GET /current/workspace/{workspace_id}/storage/{node_id}/versions/
GET /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

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{node_id}stringYesNode 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)

FieldTypeDescription
idstringVersion OpaqueId
version_numberintegerIncrementing version number
createdstringVersion creation timestamp (YYYY-MM-DD HH:MM:SS)
operationstringHow this version was created: "create", "update", "restore"
sizeintegerFile size in bytes for this version
hashstringContent hash for this version

Error Responses

Error CodeHTTP StatusDescription
1609 (Not Found)404Node not found
1605 (Invalid Input)400Unsupported node type
1665 (Object Init Failed)500Node data is corrupted

Restore Version

POST /current/workspace/{workspace_id}/storage/{node_id}/restore-version/
POST /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

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{node_id}stringYesFile OpaqueId

Request Body (form-encoded)

ParameterTypeRequiredDescription
version_idstringYesOpaqueId 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 CodeHTTP StatusDescription
1609 (Not Found)404Node not found
1605 (Invalid Input)400Can only restore file versions (not folders)
1605 (Invalid Input)400Cannot restore version of trashed file
1609 (Not Found)404Version not found
1605 (Invalid Input)400Version does not belong to this file
1609 (Not Found)404Version data no longer available
1680 (Access Denied)403No permission to restore versions (share only)

Notes:

Download File (Read)

GET /current/workspace/{workspace_id}/storage/{node_id}/read/
GET /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

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{node_id}stringYesFile or note OpaqueId

Query Parameters

ParameterTypeRequiredDescription
tokenstringNoDownload token from requestread (bypasses JWT auth)
version_idstringNoSpecific 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.

Error Responses

Error CodeHTTP StatusDescription
1609 (Not Found)404File not found
1605 (Invalid Input)400Can only read file or note (not folder)
1609 (Not Found)404File is in trash
1609 (Not Found)404Version not found
1605 (Invalid Input)400Version does not belong to this file
1609 (Not Found)404Version data no longer available
1680 (Access Denied)403File flagged as virus-infected (share only)

Request Download Token

GET /current/workspace/{workspace_id}/storage/{node_id}/requestread/
GET /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

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{node_id}stringYesFile 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 CodeHTTP StatusDescription
1609 (Not Found)404File not found
1605 (Invalid Input)400Can only read file or note
1609 (Not Found)404File is in trash
1680 (Access Denied)403No download permission (share only)

Download Folder as ZIP

GET /current/workspace/{workspace_id}/storage/{folder_id}/zip/
GET /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

ParameterTypeRequiredDescription
{workspace_id} or {share_id}stringYes19-digit profile ID
{folder_id}stringYesFolder 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:

Recent Files

GET /current/workspace/{workspace_id}/storage/recent/
GET /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

ParameterTypeDefaultDescription
page_sizeint100One of: 100, 250, 500 (snapped to nearest)
cursorstringOpaque cursor string from previous response
typestringFilter 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

FieldTypeDescription
nodes.countintegerNumber of nodes in this page
nodes.itemsarrayArray of node resources
pagination.has_morebooleanWhether more pages exist
pagination.next_cursorstring/nullCursor for the next page
pagination.page_sizeintegerEffective page size used

Error Responses

Error CodeHTTP StatusDescription
1605 (Invalid Input)406Invalid pagination cursor
1680 (Access Denied)401Insufficient permissions to view files (share only)
1609 (Not Found)404Orphaned workspace folder share

Notes:

GET /current/workspace/{workspace_id}/storage/search/
GET /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

ParameterTypeRequiredDescription
searchstringYesSearch 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

FieldTypeDescription
filesobjectMap of node OpaqueIds to file info
files.{id}.namestringFile name
files.{id}.parent_idstringParent folder node ID
files.{id}.typestringNode type

Error Responses

Error CodeHTTP StatusDescription
1609 (Not Found)404Search not available for workspace folder shares (share only)
1680 (Access Denied)403No search permission (share only)

Notes:

QuickShare (Workspace Only)

POST /current/workspace/{workspace_id}/storage/{node_id}/quickshare/
GET /current/workspace/{workspace_id}/storage/{node_id}/quickshare/
DELETE /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

ParameterTypeRequiredDescription
{workspace_id}stringYes19-digit workspace profile ID
{node_id}stringYesFile OpaqueId

POST — Create or Update QuickShare

Request Body (form-encoded)

ParameterTypeRequiredDefaultDescription
expiresstring (digits)No10800 (3 hours)Expiration in seconds from now (max 604800 = 7 days)
expires_atstringNoAbsolute expiration datetime. Accepts ISO 8601 (e.g., 2026-03-12T14:30:00Z) or YYYY-MM-DD HH:MM:SS format. Takes precedence over expires. Must be in the future and within 7 days.

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 CodeHTTP StatusDescription
1680 (Access Denied)403File too large for quickshare
1605 (Invalid Input)400Expiration too far in the future
1685 (Feature Limit)403Per-workspace QuickShare creation rate limit reached (limits scale with plan tier)

GET — Get QuickShare Details

Returns the same format as POST. Returns 1609 (Not Found) (404) if no quickshare exists.

DELETE — Delete QuickShare

Returns {"result": "yes"}. Returns 1609 (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

GET /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

POST /current/workspace/{workspace_id}/storage/{node_id}/lock/
POST /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)

ParameterTypeRequiredConstraintsDescription
durationintegerNo60-3600 secondsLock duration (default varies)
client_infostringNoJSON objectClient 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

FieldTypeDescription
lock_tokenstringToken required for heartbeat and release operations
locked_atstringLock acquisition time, ISO 8601 (YYYY-MM-DDTHH:MM:SS+00:00)
expires_atstringLock expiration time, ISO 8601 (YYYY-MM-DDTHH:MM:SS+00:00)
node_idstringOpaqueId of the locked node

Error Responses

Error CodeHTTP StatusDescription
1609 (Not Found)404Node does not exist
1609 (Not Found)404Cannot lock a deleted node
1660 (Conflict)409Node already locked by another user

Heartbeat (Extend Lock)

POST /current/workspace/{workspace_id}/storage/{node_id}/lock/heartbeat/
POST /current/share/{share_id}/storage/{node_id}/lock/heartbeat/

Extend the lock duration.

Auth required.

Request Body (form-encoded)

ParameterTypeRequiredDescription
lock_tokenstringYesToken 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 CodeHTTP StatusDescription
1609 (Not Found)404No lock exists on this node
1609 (Not Found)404Lock has expired
1680 (Access Denied)403Lock token does not match

Notes:

Release Lock

DELETE /current/workspace/{workspace_id}/storage/{node_id}/lock/
DELETE /current/share/{share_id}/storage/{node_id}/lock/

Release a lock on a file.

Auth required.

Request Body/Query

ParameterTypeRequiredDescription
lock_tokenstringYesToken from acquire response

Response

{
  "result": "yes",
  "response": {
    "released": true
  }
}

Error Responses

Error CodeHTTP StatusDescription
1609 (Not Found)404No lock exists on this node
1680 (Access Denied)403Lock token does not match

Lock Status

GET /current/workspace/{workspace_id}/storage/{node_id}/lock/
GET /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

ValueDescription
thumbnailSmall thumbnail image
imageFull-size image preview
hlsstreamHLS video/audio stream
pdfPDF document preview
spreadsheetSpreadsheet preview

Preview States

Returned in node details responses under previews.{type}.state:

StateDescription
unknownPreview status not yet determined
not possibleFile type cannot be previewed
not generatedPreview not yet generated
errorPreview generation failed
in progressPreview is being generated
readyPreview is available

Preauthorize Preview

GET /current/workspace/{workspace_id}/storage/{node_id}/preview/{preview_type}/preauthorize/
GET /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

ParameterTypeRequiredDescription
{preview_type}stringYesOne 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

FieldTypeDescription
downloadTokenstringJWT token for preview access
pathstringFull API path to read the preview file
primaryFilenamestringName of the primary preview file

Error Responses

Error CodeHTTP StatusDescription
1609 (Not Found)404File not found
1605 (Invalid Input)400Can only preview file or note
1609 (Not Found)404File is in trash
1652 (Resource Not Found)404Preview not available

Read Preview

GET /current/workspace/{workspace_id}/storage/{node_id}/preview/{preview_type}/read/
GET /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.

If the source file is corrupt, truncated, or otherwise unreadable by the render pipeline, returns HTTP 422 Unprocessable Entity. Clients should not retry — the source file itself is the problem.

Auth required.

Token-Based Preview Read

GET /current/workspace/{workspace_id}/storage/{node_id}/preview/{preview_type}/read/{token}/file/{filename}
GET /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

ParameterTypeRequiredDescription
{token}stringYesDownload token from preauthorize
{filename}stringYesPreview filename

Transforms

Image transforms allow on-the-fly resizing, cropping, rotating, and format conversion.

Get Transform Status

GET /current/workspace/{workspace_id}/storage/{node_id}/transform/{transform_name}/
GET /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

StateDescription
renderedTransform is ready
renderingTransform in progress
unrenderedTransform not yet requested
unable to renderTransform failed or unsupported

Request Transform

POST /current/workspace/{workspace_id}/storage/{node_id}/transform/{transform_name}/request/
POST /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 CodeHTTP StatusDescription
1609 (Not Found)404Unknown transformation name
1609 (Not Found)404Unable to transform (failed or unsupported)

Read Transformed File

GET /current/workspace/{workspace_id}/storage/{node_id}/transform/{transform_name}/read/
GET /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:

ParameterTypeValues
output-formatstringpng, jpg
widthintTarget width in pixels
heightintTarget height in pixels
cropwidthintCrop region width
cropheightintCrop region height
cropxintCrop region X offset
cropyintCrop region Y offset
rotateint0, 90, 180, 270
sizestringPredefined: 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)

GET /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:

  1. GET .../storage/{node_id}/requestread/ — returns {"token": "..."}
  2. 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.

In medium security mode, file previews are available for guests but direct downloads are restricted. Owners and admins can still download normally.

Metadata Saved Views

Each user can persist per-template column order, column visibility, and sort preferences. Saved views are private to the user — two users can independently customize the same template. Identity is the tuple (workspace, user, template); there is at most one saved view per user per template per workspace.

GET /current/workspace/{workspace_id}/metadata/view/?template_id={template_id}
POST /current/workspace/{workspace_id}/metadata/view/
DELETE /current/workspace/{workspace_id}/metadata/view/?template_id={template_id}
GET /current/workspace/{workspace_id}/metadata/views/

Retrieve, upsert, delete, or list the caller's saved views.

Auth required. Permission: Member. Metadata billing feature required.

GET — Retrieve Saved View

Returns the caller's saved view for the supplied template. Responds 1609 (Not Found) (404) when the caller has no view saved for that template.

Query Parameters

ParameterTypeRequiredDescription
template_idstringYesTemplate OpaqueId to resolve the view against.

POST — Create or Update Saved View

Upserts the caller's saved view. If a view already exists for this template, the row is replaced in place (its id and created timestamp are preserved; updated is refreshed). Otherwise a new row is created.

Send as application/x-www-form-urlencoded. The config field holds a JSON-encoded string (not a nested JSON body) — sending Content-Type: application/json is rejected with 406 (This field is missing).

Request Body

ParameterTypeRequiredDescription
Content-TypeheaderYesMust be application/x-www-form-urlencoded. application/json bodies are rejected.
template_idstringYesTemplate OpaqueId the view belongs to. Accepted in the body or the query string.
configstring (URL-encoded JSON)YesForm-encoded field whose value is a JSON-serialized string of the view's config object. See Config Schema below for the JSON shape that must be serialized into this field.

Example

curl -X POST "https://api.fast.io/current/workspace/{workspace_id}/metadata/view/" \
  -H "Authorization: Bearer {jwt_token}" \
  --data-urlencode "template_id={template_id}" \
  --data-urlencode 'config={"version":1,"columns":[{"field":"title","visible":true,"width":180}],"sort":{"field":"updated","dir":"desc"},"filters":[]}'

DELETE — Remove Saved View

Deletes only the caller's own view; other users' views are untouched. Responds 1609 (Not Found) (404) when the caller has no view saved for that template.

Query Parameters

ParameterTypeRequiredDescription
template_idstringYesTemplate OpaqueId whose saved view should be removed.

GET Views — List Saved Views

Lists every saved view the caller owns in this workspace (one entry per template the caller has customized). Views belonging to other users are never returned.

Config Schema

{
  "version": 1,
  "columns": [
    { "field": "title",  "visible": true,  "width": 180 },
    { "field": "status", "visible": true,  "width": 120 }
  ],
  "sort": { "field": "updated", "dir": "desc" },
  "filters": [
    { "field": "status",   "operator": "=",  "value_type": "string", "value": "active" },
    { "field": "priority", "operator": ">=", "value_type": "int",    "value": 3 }
  ]
}
FieldTypeRequiredDescription
versionintYesSchema version. Must equal 1.
columnsarrayYesOrdered list of column entries. The array order IS the display order.
columns[].fieldstringYesTemplate field name. Non-empty.
columns[].visibleboolNoWhether the column is visible.
columns[].widthintNoColumn width in pixels. Positive.
sortobjectYesDefault sort for this view.
sort.fieldstringYesTemplate field to sort by.
sort.dirstringYesasc or desc.
filtersarrayYesOrdered list of filter entries (may be empty). AND-chained; order preserved round-trip. See Filters below.
filters[].fieldstringYesTemplate field name. Non-empty. Matches the naming used by columns[].field and sort.field.
filters[].operatorstringYesOne of =, !=, <, <=, >, >=.
filters[].value_typestringYesOne of string, int, float, bool. json is rejected.
filters[].valuemixedYesNon-null scalar matching value_type. Cannot be an array or object.

Unknown top-level keys, unknown columns[] keys, unknown sort keys, or unknown filters[] keys cause the request to be rejected with 1605 (Invalid Input).

Filters

Filter entries in a saved view use {field, operator, value_type, value} — the per-entry field name matches the naming used by columns[].field and sort.field for a uniform identifier across the config.

Value coercion. Values follow standard scalar coercion — strings like "true", "1", "yes", "on" (and their falsy counterparts) are accepted when value_type is bool; numeric-form strings like "42" or "1.5" are accepted when value_type is int or float. Sending the typed value directly (e.g. 3 instead of "3") is preferred and round-trips unchanged.

Stateless filters query parameter shape. The template nodes listing endpoint accepts a stateless filters query parameter whose per-entry identifier is still key (not field); that pre-existing query-layer contract is unchanged. Saved View configs use field for internal consistency with columns[].field and sort.field. When the server auto-applies a saved view on the nodes endpoint, it handles the translation internally. Use field when writing a Saved View; use key only when passing a stateless filters query parameter directly on the nodes endpoint.

Response Shape

{
  "result": "yes",
  "response": {
    "id": "{view_id}",
    "user_id": "{user_id}",
    "template_id": "{template_id}",
    "config": { "version": 1, "columns": [], "sort": { "field": "updated", "dir": "desc" }, "filters": [] },
    "created": "2026-04-23T11:02:00+00:00",
    "updated": "2026-04-23T11:02:00+00:00"
  }
}

The list endpoint wraps rows under response.items[] and adds a response.count field.

Auto-Apply on Template Nodes Listing

GET /current/workspace/{workspace_id}/metadata/templates/{template_id}/nodes inspects the caller's saved view for the given template.

Column order and visibility are not applied server-side — clients use the saved view's columns array to decide which columns to render.

Error Responses

Error CodeHTTP StatusDescription
1605 (Invalid Input)400Missing or malformed parameters, or config failed validation (unknown keys, bad types, bad operator / value_type, or more than 5 filters)
1609 (Not Found)404Caller has no saved view for this template (GET / DELETE only)
1664 (Datastore Error)500Failed to read or persist the view
1680 (Access Denied)403Not a workspace member or metadata feature not enabled

Workspace-Only Features

These endpoints are only available on workspaces, not shares:

Share-Specific Notes

↑ Back to top