AI & Chat RAG-powered chat, semantic search, notes, metadata extraction, and auto-summarization

Base URL: https://api.fast.io/current/ Auth: Bearer {jwt_token}

Overview

Fast.io provides built-in AI capabilities for workspaces and shares:

AI chat is read-only. It can read, analyze, search, and answer questions about files, but it cannot modify files, change settings, manage members, or access events. All write operations must be done through the API directly.

Plan Requirements

AI capabilities are gated by two billing-plan features that work together:

Current plan coverage:

Plancontent_aiai_agentEffect
FreeoffoffAI chat and intelligence unavailable
Agent (free)onoffRead-only AI surfaces; cannot create chats, send messages, or enable intelligence
ProononFull AI (chat, intelligence, RAG)
BusinessononFull AI (chat, intelligence, RAG)

How gated endpoints respond when a plan lacks the feature:

Agent-plan accounts can still ingest, store, search, and share files; transfer org ownership to a human on a paid plan to unlock agentic chat. See the Organizations reference for transfer flow.

Intelligence Setting

The intelligence boolean on a workspace or portal share controls whether uploaded files are automatically indexed for RAG.

Shared folder restriction: Intelligence is only available on portal shares (independent storage). Workspace folder shares (storage_mode=workspace_folder) cannot have intelligence enabled — their files are indexed through the parent workspace instead. The API will return an error if you attempt to enable intelligence on a shared folder share.

Enable at creation:

POST /current/org/{org_id}/create/workspace/

Pass intelligence=true

Update later:

POST /current/workspace/{workspace_id}/update/

Pass intelligence=true

Note: Intelligence can be enabled and disabled within time restrictions. Disabling intelligence destroys indexed embeddings (the vector index is flushed). Re-enabling intelligence incurs re-indexing costs as AI credits are consumed to re-index all files. When a plan loses ai_agent (e.g. on downgrade), the RAG indexing pipeline stops even if the instance flag remains set; previously indexed embeddings remain but will not be updated.

Chat Types

Two chat types are available. Both augment answers with web knowledge.

chat — General AI Conversation

chat_with_files — RAG-Powered Chat

File Scope vs File Attachments

These are two different ways to give the AI context. They cannot be combined in the same request.

Folder/File Scope (files_scope, folders_scope)

Limits the RAG search space. The AI searches indexed files within the specified scope and uses matching content as citations.

files_scope — comma-separated nodeId:versionId pairs (max 100). Both nodeId and versionId are required and must be non-empty in each pair. Get the versionId from the file’s version field in storage list/details responses.

folders_scope — comma-separated nodeId:depth pairs (max 100 subfolder references). Depth controls how many levels of subfolders are enumerated (1–10). Only subfolder references count toward the limit, not individual files. The RAG backend searches all indexed files within the scoped folders automatically.

You do not need to enumerate individual files. Just provide top-level folder IDs with depth.

File Attachments (files_attach)

Files are directly attached to the chat message for analysis. Use this for direct analysis tasks. Only file nodes are accepted—folder nodes are rejected. To include folder contents, use folders_scope instead.

Format: comma-separated nodeId:versionId pairs, e.g., files_attach=nodeId1:versionId1,nodeId2:versionId2

Choosing Between Scope and Attachments

Use CaseMechanismChat Type
Search across many indexed filesfiles_scope / folders_scopechat_with_files
Analyze specific files directlyfiles_attachchat or chat_with_files
Ask general questions about the workspaceOmit scope (defaults to all files)chat_with_files
General conversation, no filesNeitherchat

AI State (File Readiness)

Files in an intelligent workspace progress through AI processing states:

StateMeaning
disabledIntelligence not enabled for this file/workspace
pendingQueued for AI processing
in_progressCurrently being processed by AI
readyFile can be used with AI chat (attached directly or via scope). The file has been processed enough (e.g., preview/summary generated) to be usable in AI conversations.
indexedFile contents have been indexed via RAG. Indexed files are searchable by semantic meaning and their content is used as grounding in scoped AI chats.
failedAI processing failed

Files with ai_state: ready can be used with AI chat. Files with ai_state: indexed have additionally had their contents indexed for RAG-powered semantic search. When intelligence is enabled on a workspace/share, files progress to indexed automatically. Check a file’s AI state in the ai.state field of storage list or file details responses.

Personality Parameter

The personality parameter controls the length and style of AI responses. Pass it when creating a chat or sending a message.

ValueBehavior
conciseShort, brief, direct answers with minimal elaboration
detailedComprehensive answers with context, evidence, and examples (default)

You can also control verbosity directly in your question phrasing:

Notes (Stored Knowledge)

Notes are a storage node type (like files and folders) that store markdown content directly on the server. They appear in storage listings with "type": "note" and "mimetype": "text/markdown". Notes are workspace-only — they cannot be created in shares.

Why Notes Matter

In an intelligent workspace, notes are ingested and indexed just like uploaded files. This makes them a way to bank knowledge over time — store interesting facts, research findings, decisions, or project context. In future AI chats that scope the entire workspace (or include the note’s folder), the note content will be used as grounding when the AI searches for relevant information.

Create a note

POST /current/workspace/{workspace_id}/storage/{parent_id}/createnote/
ParameterTypeRequiredDescription
namestringYesNote name, must end in .md
contentstringYesMarkdown content, max 100 KB

{parent_id} is a folder OpaqueId or "root". Returns the created note as a node resource.

Update a note

POST /current/workspace/{workspace_id}/storage/{node_id}/updatenote/
ParameterTypeRequiredDescription
namestringNoNew name, must end in .md
contentstringNoNew markdown content, max 100 KB

At least one of name or content must be provided. Updating content creates a new version.

Read note content

GET /current/workspace/{workspace_id}/storage/{node_id}/read/

Returns the raw markdown content.

Linking a user to a note

Workspace AI Endpoints

Create a new chat

POST /current/workspace/{workspace_id}/ai/chat/

Creates a chat with an initial message. The AI begins processing asynchronously.

Auth: Bearer token required. Workspace view permission. content_ai and ai_agent plan features required.

ParameterTypeRequiredDefaultDescription
typestringYeschat or chat_with_files
questionstringYesInitial question, 2–12,768 characters
privacystringNopublicprivate or public
namestringNoAuto-generatedChat name. Auto-generated from first 10 words of question if omitted.
personalitystringNodetailedconcise or detailed
files_scopestringNoAll indexed filesComma-separated nodeId:versionId pairs (max 100). Requires chat_with_files type and Intelligence enabled.
folders_scopestringNoAll indexed filesComma-separated nodeId:depth pairs (max 100, depth 1–10). Requires chat_with_files type and Intelligence enabled.
files_attachstringNoComma-separated file nodeId:versionId pairs (max 20, 200 MB total). Only file nodes accepted—folder nodes are rejected. Cannot be combined with files_scope/folders_scope. Files must have AI summaries ready.

Request example:

curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/ai/chat/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d "type=chat_with_files" \
  -d "question=What were the Q3 revenue figures?" \
  -d "privacy=private" \
  -d "personality=detailed"

Response (200 OK):

{
  "result": "yes",
  "response": {
    "chat": {
      "id": "aBcDeFgHiJkLmNoPqR",
      "message": {
        "id": "xYzAbCdEfGhIjKlMnO"
      }
    }
  },
  "current_api_version": "1.0"
}
FieldTypeDescription
response.chat.idstringOpaque ID of the created chat
response.chat.message.idstring/nullOpaque ID of the initial message, or null if no question was provided

Error responses:

Error CodeHTTP StatusCause
1605 (Invalid Input)400Invalid type, privacy, or personality value
1605 (Invalid Input)400File/folder scope used without Intelligence enabled
1605 (Invalid Input)400Both files_attach and files_scope specified
1605 (Invalid Input)400Invalid name or other property
1664 (Datastore Error)500Chat or message creation failed

List chats

GET /current/workspace/{workspace_id}/ai/chat/list/

Returns all chats created by the current user in the workspace. Sorted by most recently modified first.

Auth: Bearer token required. Workspace view permission. content_ai plan feature required.

Variant: Append /deleted to the path to list deleted chats: GET .../ai/chat/list/deleted

Request example:

curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/ai/chat/list/" \
  -H "Authorization: Bearer {jwt_token}"

Response (200 OK):

{
  "result": "yes",
  "response": {
    "chats": [
      {
        "chat_id": "aBcDeFgHiJkLmNoPqR",
        "creator": { "type": "user", "id": "12345678901234567890" },
        "type": "chat_with_files",
        "name": "Quarterly report analysis",
        "status": "active",
        "message_count": 5,
        "latest_message": {
          "message_id": "xYzAbCdEfGhIjKlMnO",
          "creator": { "type": "user", "id": "12345678901234567890" },
          "state": "complete",
          "message": { "text": "Summarize the quarterly report" },
          "response": null,
          "created": "2025-06-15T10:30:00Z",
          "updated": "2025-06-15T10:30:05Z"
        },
        "unique_creators": [
          { "type": "user", "id": "12345678901234567890" }
        ],
        "cost": { "credits": { "tokens": 1500 } },
        "efficiency": "good",
        "privacy": {
          "visibility": "private",
          "owner": { "type": "user", "id": "12345678901234567890" }
        },
        "created_at": "2025-06-15T10:00:00Z",
        "updated_at": "2025-06-15T10:30:05Z"
      }
    ]
  },
  "current_api_version": "1.0"
}
FieldTypeDescription
response.chatsarrayArray of chat objects
response.chats[].chat_idstringOpaque ID of the chat
response.chats[].creatorobject{type, id} — the chat creator
response.chats[].typestringchat or chat_with_files
response.chats[].namestringChat display name
response.chats[].statusstringChat status
response.chats[].message_countintegerTotal messages in the chat
response.chats[].latest_messageobjectMost recent message preview
response.chats[].unique_creatorsarrayDistinct participants
response.chats[].cost.credits.tokensintegerTotal token cost
response.chats[].efficiencystringEfficiency rating
response.chats[].privacyobject{visibility, owner}
response.chats[].created_atstringCreation timestamp (YYYY-MM-DD HH:MM:SS)
response.chats[].updated_atstringLast update timestamp (YYYY-MM-DD HH:MM:SS)

Get chat details

GET /current/workspace/{workspace_id}/ai/chat/{chat_id}/details/

Returns chat details with full message history.

Auth: Bearer token required. content_ai plan feature required.

Request example:

curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/ai/chat/aBcDeFgHiJkLmNoPqR/details/" \
  -H "Authorization: Bearer {jwt_token}"

Response (200 OK):

{
  "result": "yes",
  "response": {
    "chat": {
      "chat_id": "aBcDeFgHiJkLmNoPqR",
      "creator": { "type": "user", "id": "12345678901234567890" },
      "type": "chat_with_files",
      "name": "Quarterly report analysis",
      "status": "active",
      "message_count": 3,
      "messages": [
        {
          "chat_id": "aBcDeFgHiJkLmNoPqR",
          "message_id": "xYzAbCdEfGhIjKlMnO",
          "creator": { "type": "user", "id": "12345678901234567890" },
          "personality": "detailed",
          "state": "complete",
          "message": {
            "text": "Summarize the quarterly report",
            "author_name": "John",
            "scope": {},
            "attached": []
          },
          "response": {
            "text": "The quarterly report shows revenue growth of 15%...",
            "error": false,
            "created": "2025-06-15T10:30:05Z",
            "cost": { "tokens": 500, "details": {} },
            "author_name": "Ripley",
            "events": [],
            "table_data": [],
            "analysis_chunks": [],
            "citations": [
              {
                "hash": "a1b2c3d4",
                "nodeId": "f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4",
                "versionId": "v1abc-defgh-ijklm",
                "entries": [
                  { "page": 3, "snippet": "Revenue increased by 15% year over year...", "timestamp": null }
                ]
              }
            ]
          },
          "created": "2025-06-15T10:30:00Z",
          "updated": "2025-06-15T10:30:05Z"
        }
      ],
      "unique_creators": [ { "type": "user", "id": "12345678901234567890" } ],
      "cost": { "credits": { "tokens": 1500 } },
      "efficiency": "good",
      "privacy": { "visibility": "private", "owner": { "type": "user", "id": "12345678901234567890" } },
      "created_at": "2025-06-15T10:00:00Z",
      "updated_at": "2025-06-15T10:30:05Z"
    }
  },
  "current_api_version": "1.0"
}

Error responses:

Error CodeHTTP StatusCause
1609 (Not Found)404Chat ID not found
1654 (Internal Error)500Internal failure loading chat

Update a chat

POST /current/workspace/{workspace_id}/ai/chat/{chat_id}/update/

Update the name of an existing chat.

Auth: Bearer token required. content_ai plan feature required.

ParameterTypeRequiredDescription
namestringYesNew chat name

Request example:

curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/ai/chat/aBcDeFgHiJkLmNoPqR/update/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d "name=Updated Chat Name"

Response (200 OK):

{ "result": "yes", "current_api_version": "1.0" }

Error responses:

Error CodeHTTP StatusCause
1658 (Not Acceptable)406Chat not found or locked
1605 (Invalid Input)400Invalid name value
1664 (Datastore Error)500Update failed

Delete a chat

DELETE /current/workspace/{workspace_id}/ai/chat/{chat_id}/

Auth: Bearer token required. content_ai plan feature required.

Request example:

curl -X DELETE "https://api.fast.io/current/workspace/12345678901234567890/ai/chat/aBcDeFgHiJkLmNoPqR/" \
  -H "Authorization: Bearer {jwt_token}"

Response (200 OK):

{ "result": "yes", "current_api_version": "1.0" }

Error responses:

Error CodeHTTP StatusCause
1658 (Not Acceptable)406Chat not found or locked
1654 (Internal Error)500Chat in non-deletable state or internal error

Deleted chats can be listed via GET .../ai/chat/list/deleted.

Send a follow-up message

POST /current/workspace/{workspace_id}/ai/chat/{chat_id}/message/

Send a new message to an existing chat. The message is processed asynchronously.

Auth: Bearer token required. content_ai and ai_agent plan features required.

ParameterTypeRequiredDefaultDescription
questionstringYesFollow-up question, 2–12,768 characters
personalitystringNodetailedconcise or detailed
files_scopestringNoAll indexed filesComma-separated nodeId:versionId pairs (max 100). Only for chat_with_files type.
folders_scopestringNoAll indexed filesComma-separated nodeId:depth pairs (max 100, depth 1–10). Only for chat_with_files type.
files_attachstringNoComma-separated file nodeId:versionId pairs (max 20, 200 MB total). Only file nodes accepted—folder nodes are rejected. Cannot be combined with scope params.

The chat type is inherited from the chat itself — you do not need to specify type again.

Request example:

curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/ai/chat/aBcDeFgHiJkLmNoPqR/message/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d "question=How does that compare to Q2?"

Response (200 OK):

{
  "result": "yes",
  "response": {
    "message": {
      "id": "mNoPqRsTuVwXyZaBcD"
    }
  },
  "current_api_version": "1.0"
}

Error responses:

Error CodeHTTP StatusCause
1658 (Not Acceptable)406Chat not found or locked
1605 (Invalid Input)400Both files_attach and files_scope specified
1605 (Invalid Input)400Scope used with wrong chat type
1654 (Internal Error)500Message creation failed

List messages in a chat

GET /current/workspace/{workspace_id}/ai/chat/{chat_id}/messages/list/

Returns all messages in chronological order (oldest first).

Auth: Bearer token required. content_ai plan feature required.

Request example:

curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/ai/chat/aBcDeFgHiJkLmNoPqR/messages/list/" \
  -H "Authorization: Bearer {jwt_token}"

Response (200 OK):

{
  "result": "yes",
  "response": {
    "messages": [
      {
        "chat_id": "aBcDeFgHiJkLmNoPqR",
        "message_id": "xYzAbCdEfGhIjKlMnO",
        "creator": { "type": "user", "id": "12345678901234567890" },
        "personality": "detailed",
        "state": "complete",
        "message": {
          "text": "Summarize the quarterly report",
          "author_name": "John",
          "scope": {},
          "attached": []
        },
        "response": {
          "text": "The quarterly report shows...",
          "error": false,
          "created": "2025-06-15T10:30:05Z",
          "cost": { "tokens": 500, "details": {} },
          "author_name": "Ripley",
          "events": [],
          "table_data": [],
          "analysis_chunks": [],
          "citations": []
        },
        "created": "2025-06-15T10:30:00Z",
        "updated": "2025-06-15T10:30:05Z"
      }
    ]
  },
  "current_api_version": "1.0"
}

Get message details

GET /current/workspace/{workspace_id}/ai/chat/{chat_id}/message/{message_id}/details/

Retrieve detailed information about a specific message, including response text, citations, and cost.

Auth: Bearer token required. content_ai plan feature required.

Key response fields:

FieldDescription
stateMessage processing state: ready, in_progress, complete, errored
message.textThe original question text
message.scopeFile/folder scope used for RAG context
message.attachedAttached files as {node_id, version_id} objects
response.textThe AI response (available when state is complete)
response.errorWhether an error occurred during processing
response.cost{tokens, details} — message token cost
response.citationsArray of file citations (see Citation Format below)

Only read the response when state is complete.

Error responses:

Error CodeHTTP StatusCause
1683 (Resource Missing)404Message not found in the chat
1654 (Internal Error)500Internal retrieval failure

Stream message response (SSE)

GET /current/workspace/{workspace_id}/ai/chat/{chat_id}/message/{message_id}/read/

Returns a Server-Sent Events (SSE) stream of the AI response.

Auth: Bearer token required. content_ai plan feature required.

Request example:

curl -N -X GET "https://api.fast.io/current/workspace/12345678901234567890/ai/chat/aBcDeFgHiJkLmNoPqR/message/xYzAbCdEfGhIjKlMnO/read/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Accept: text/event-stream"

SSE stream format:

event: data
data: {"item": "The quarterly report "}

event: data
data: {"item": "shows revenue growth of "}

event: data
data: {"item": "15% year over year."}

event: analysis_data
data: {"type": "analysis_chunk", ...}

event: table_data
data: {"type": "table_data", ...}

event: done

SSE event types:

Event TypeDescription
dataText chunks of the AI response. Payload: {"item": "..."}. Concatenate all data events for the full text.
eventStatus update or event notification
analysis_dataStructured analysis data, citations, and references to source files
table_dataTabular data extracted or generated by the AI
doneStream complete. No more events will be sent.

Behavior:

Error responses:

Error CodeHTTP StatusCause
1683 (Resource Missing)404Message not found
1605 (Invalid Input)400Message not in in_progress or complete state
1683 (Resource Missing)404No SSE chunk data exists for this message
1654 (Internal Error)500Internal streaming failure

Publish a private chat

POST /current/workspace/{workspace_id}/ai/chat/{chat_id}/publish/

Makes a private chat public (visible to other workspace members). One-way operation — published chats cannot be made private again.

Auth: Bearer token required. content_ai plan feature required.

Response (200 OK):

{ "result": "yes", "current_api_version": "1.0" }

Error responses:

Error CodeHTTP StatusCause
1658 (Not Acceptable)406Chat not found or locked
1660 (Conflict)409Chat is already public
1664 (Datastore Error)500Update failed

Generate AI Share

POST /current/workspace/{workspace_id}/ai/share/

Generates markdown with temporary download URLs for selected files. Designed to be pasted into external AI chatbots.

Auth: Bearer token required. Workspace view permission. Does NOT require content_ai plan feature — available on all plans.

ParameterTypeRequiredDescription
filesarray (JSON)YesJSON array of file opaque IDs. Min 1, max 25.

Request example:

curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/ai/share/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{"files": ["aBcDeFgHiJkLmN", "oPqRsTuVwXyZ12"]}'

Response (200 OK):

{
  "result": "yes",
  "response": {
    "markdown": "## Files\n\n### quarterly-report.pdf\n[Download](https://api.fast.io/...)\nSize: 2.5 MB\n\n..."
  },
  "current_api_version": "1.0"
}
FieldTypeDescription
response.markdownstringGenerated markdown with file info and temporary download URLs

Notes:

Error responses:

Error CodeHTTP StatusCause
1605 (Invalid Input)400Empty files array
1605 (Invalid Input)400More than 25 files

List AI transactions

GET /current/workspace/{workspace_id}/ai/transactions/

Returns up to 40 most recent AI token usage transactions for the workspace. Workspace-only — no share equivalent.

Auth: Bearer token required. Workspace view permission. content_ai plan feature required.

Request example:

curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/ai/transactions/" \
  -H "Authorization: Bearer {jwt_token}"

Response (200 OK):

{
  "result": "yes",
  "response": {
    "count": 2,
    "items": [
      {
        "id": "txn_abc123",
        "type": "chat_with_files",
        "status": "complete",
        "tokens": 1500,
        "updated": "2025-06-15 10:30:05 UTC",
        "created": "2025-06-15 10:30:00 UTC"
      }
    ]
  },
  "current_api_version": "1.0"
}
FieldTypeDescription
response.countintegerNumber of transactions returned
response.items[].idstringFormatted transaction ID
response.items[].typestringParent type (e.g., chat, chat_with_files)
response.items[].statusstringTransaction status
response.items[].tokensintegerToken credits consumed
response.items[].updatedstringLast update timestamp (UTC)
response.items[].createdstringCreation timestamp (UTC)

Asking a Question and Getting the Response

Complete workflow

1. Create the chat:

curl -X POST "https://api.fast.io/current/workspace/{workspace_id}/ai/chat/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d "question=What were the Q3 revenue figures?" \
  -d "type=chat_with_files" \
  -d "personality=detailed"

Response includes chat_id and message_id. The AI begins processing asynchronously.

2. Wait for completion using activity polling (do NOT poll the message endpoint in a loop):

curl -X GET "https://api.fast.io/current/activity/poll/{workspace_id}?wait=95&lastactivity={timestamp}" \
  -H "Authorization: Bearer {jwt_token}"

Watch for the ai_chat:{chatId} activity key. This fires when the message state changes. The server holds the connection for up to 95 seconds and returns immediately when something changes.

3. Check message state:

curl -X GET "https://api.fast.io/current/workspace/{workspace_id}/ai/chat/{chat_id}/message/{message_id}/details/" \
  -H "Authorization: Bearer {jwt_token}"

Message states: readyin_progresscomplete (or errored). Only read the response when state is complete.

4. Stream the response:

curl -N -X GET "https://api.fast.io/current/workspace/{workspace_id}/ai/chat/{chat_id}/message/{message_id}/read/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Accept: text/event-stream"

Returns SSE with event types: data (text chunks), analysis_data, table_data, done.

5. Send follow-ups:

curl -X POST "https://api.fast.io/current/workspace/{workspace_id}/ai/chat/{chat_id}/message/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d "question=How does that compare to Q2?"

Same polling flow for the reply.

Linking a user to an AI chat

Construct a workspace URL with a chat query parameter:

https://{org_domain}.fast.io/workspace/{workspace_name}?chat={chat_opaque_id}

The chat_opaque_id is returned in the chat_id field when creating or listing chats.

Share AI Endpoints

Share AI endpoints follow the same pattern as workspace AI. Replace /workspace/{workspace_id} with /share/{share_id}.

Auto-generate OG image

GET /current/share/{share_id}/ai/autoog/

Generates an Open Graph image for the share. Returns binary PNG image data (not JSON).

Auth: Conditional — required for private shares; optional for public shares.

BehaviorDescription
Public shareCustom AI-generated image based on share content
Private shareDefault private image returned

Error responses:

Error CodeHTTP StatusCause
1609 (Not Found)404Share is disabled
1654 (Internal Error)500Default image not available

Auto-generate title and description

POST /current/share/{share_id}/ai/autotitle/

AI-generates a title, description, and display type based on the share’s contents. Values are applied directly to the share.

Auth: Bearer token required.

ParameterTypeRequiredDescription
contextstringNoOptional user-provided context to guide AI generation

Request example:

curl -X POST "https://api.fast.io/current/share/12345678901234567890/ai/autotitle/" \
  -H "Authorization: Bearer {jwt_token}"

Response (200 OK):

{
  "result": "yes",
  "response": {
    "title": "Q4 Financial Reports",
    "description": "Quarterly financial reports and analysis for fiscal year 2025.",
    "display_type": "document"
  }
}
FieldTypeDescription
response.titlestringAI-generated title
response.descriptionstringAI-generated description
response.display_typestringAI-suggested display type

Error responses:

Error CodeHTTP StatusCause
1680 (Access Denied)403Insufficient share permissions
1654 (Internal Error)500Share update or generation failure

Share chat endpoints mirror workspace chat endpoints. All response formats and schemas are identical to the workspace versions documented above. The key differences are:

Create a new chat (Share)

POST /current/share/{share_id}/ai/chat/

Creates a chat with an initial message in a share. The AI begins processing asynchronously.

Auth: Bearer token required. Share view permission and chat permission. content_ai and ai_agent plan features required.

ParameterTypeRequiredDefaultDescription
typestringYeschat or chat_with_files
questionstringYesInitial question, 2–12,768 characters
privacystringNopublicprivate or public
namestringNoAuto-generatedChat name. Auto-generated from first 10 words of question if omitted.
personalitystringNodetailedconcise or detailed
files_scopestringNoAll indexed filesComma-separated nodeId:versionId pairs (max 100). Requires chat_with_files type and Intelligence enabled.
folders_scopestringNoAll indexed filesComma-separated nodeId:depth pairs (max 100, depth 1–10). Requires chat_with_files type and Intelligence enabled.
files_attachstringNoComma-separated file nodeId:versionId pairs (max 20, 200 MB total). Only file nodes accepted—folder nodes are rejected. Cannot be combined with files_scope/folders_scope. Files must have AI summaries ready.

Request example:

curl -X POST "https://api.fast.io/current/share/12345678901234567890/ai/chat/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d "type=chat_with_files" \
  -d "question=What were the Q3 revenue figures?" \
  -d "privacy=private" \
  -d "personality=detailed"

Response (200 OK):

{
  "result": "yes",
  "response": {
    "chat": {
      "id": "aBcDeFgHiJkLmNoPqR",
      "message": {
        "id": "xYzAbCdEfGhIjKlMnO"
      }
    }
  },
  "current_api_version": "1.0"
}
FieldTypeDescription
response.chat.idstringOpaque ID of the created chat
response.chat.message.idstring/nullOpaque ID of the initial message, or null if no question was provided

Error responses:

Error CodeHTTP StatusCause
1605 (Invalid Input)400Invalid type, privacy, or personality value
1605 (Invalid Input)400File/folder scope used without Intelligence enabled
1605 (Invalid Input)400Both files_attach and files_scope specified
1664 (Datastore Error)500Chat or message creation failed

List chats (Share)

GET /current/share/{share_id}/ai/chat/list/

Returns all chats created by the current user in the share. Sorted by most recently modified first.

Auth: Bearer token required. Share view permission and chat permission. content_ai plan feature required.

Variant: Append /deleted to the path to list deleted chats: GET .../ai/chat/list/deleted

Request example:

curl -X GET "https://api.fast.io/current/share/12345678901234567890/ai/chat/list/" \
  -H "Authorization: Bearer {jwt_token}"

Response: Same format as workspace chat list. See List chats above.

Get chat details (Share)

GET /current/share/{share_id}/ai/chat/{chat_id}/details/

Returns chat details with full message history.

Auth: Bearer token required. Share view permission and chat permission. content_ai plan feature required.

Request example:

curl -X GET "https://api.fast.io/current/share/12345678901234567890/ai/chat/aBcDeFgHiJkLmNoPqR/details/" \
  -H "Authorization: Bearer {jwt_token}"

Response: Same format as workspace chat details. See Get chat details above.

Error responses:

Error CodeHTTP StatusCause
1609 (Not Found)404Chat ID not found
1654 (Internal Error)500Internal failure loading chat

Update a chat (Share)

POST /current/share/{share_id}/ai/chat/{chat_id}/update/

Update the name of an existing chat in a share.

Auth: Bearer token required. Share view permission and chat permission. content_ai plan feature required.

ParameterTypeRequiredDescription
namestringYesNew chat name

Request example:

curl -X POST "https://api.fast.io/current/share/12345678901234567890/ai/chat/aBcDeFgHiJkLmNoPqR/update/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d "name=Updated Chat Name"

Response (200 OK):

{ "result": "yes", "current_api_version": "1.0" }

Error responses:

Error CodeHTTP StatusCause
1658 (Not Acceptable)406Chat not found or locked
1605 (Invalid Input)400Invalid name value
1664 (Datastore Error)500Update failed

Delete a chat (Share)

DELETE /current/share/{share_id}/ai/chat/{chat_id}/

Auth: Bearer token required. Share view permission and chat permission. content_ai plan feature required.

Request example:

curl -X DELETE "https://api.fast.io/current/share/12345678901234567890/ai/chat/aBcDeFgHiJkLmNoPqR/" \
  -H "Authorization: Bearer {jwt_token}"

Response (200 OK):

{ "result": "yes", "current_api_version": "1.0" }

Error responses:

Error CodeHTTP StatusCause
1658 (Not Acceptable)406Chat not found or locked
1654 (Internal Error)500Chat in non-deletable state or internal error

Deleted chats can be listed via GET .../ai/chat/list/deleted.

Send a follow-up message (Share)

POST /current/share/{share_id}/ai/chat/{chat_id}/message/

Send a new message to an existing chat in a share. The message is processed asynchronously.

Auth: Bearer token required. Share view permission and chat permission. content_ai and ai_agent plan features required.

ParameterTypeRequiredDefaultDescription
questionstringYesFollow-up question, 2–12,768 characters
personalitystringNodetailedconcise or detailed
files_scopestringNoAll indexed filesComma-separated nodeId:versionId pairs (max 100). Only for chat_with_files type.
folders_scopestringNoAll indexed filesComma-separated nodeId:depth pairs (max 100, depth 1–10). Only for chat_with_files type.
files_attachstringNoComma-separated file nodeId:versionId pairs (max 20, 200 MB total). Only file nodes accepted—folder nodes are rejected. Cannot be combined with scope params.

The chat type is inherited from the chat itself — you do not need to specify type again.

Request example:

curl -X POST "https://api.fast.io/current/share/12345678901234567890/ai/chat/aBcDeFgHiJkLmNoPqR/message/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d "question=How does that compare to Q2?"

Response (200 OK):

{
  "result": "yes",
  "response": {
    "message": {
      "id": "mNoPqRsTuVwXyZaBcD"
    }
  },
  "current_api_version": "1.0"
}

Error responses:

Error CodeHTTP StatusCause
1658 (Not Acceptable)406Chat not found or locked
1605 (Invalid Input)400Both files_attach and files_scope specified
1605 (Invalid Input)400Scope used with wrong chat type
1654 (Internal Error)500Message creation failed

List messages in a chat (Share)

GET /current/share/{share_id}/ai/chat/{chat_id}/messages/list/

Returns all messages in chronological order (oldest first).

Auth: Bearer token required. Share view permission and chat permission. content_ai plan feature required.

Request example:

curl -X GET "https://api.fast.io/current/share/12345678901234567890/ai/chat/aBcDeFgHiJkLmNoPqR/messages/list/" \
  -H "Authorization: Bearer {jwt_token}"

Response: Same format as workspace message list. See List messages in a chat above.

Get message details (Share)

GET /current/share/{share_id}/ai/chat/{chat_id}/message/{message_id}/details/

Retrieve detailed information about a specific message, including response text, citations, and cost.

Auth: Bearer token required. Share view permission and chat permission. content_ai plan feature required.

Request example:

curl -X GET "https://api.fast.io/current/share/12345678901234567890/ai/chat/aBcDeFgHiJkLmNoPqR/message/xYzAbCdEfGhIjKlMnO/details/" \
  -H "Authorization: Bearer {jwt_token}"

Response: Same format as workspace message details. See Get message details above.

Error responses:

Error CodeHTTP StatusCause
1683 (Resource Missing)404Message not found in the chat
1654 (Internal Error)500Internal retrieval failure

Stream message response (SSE) (Share)

GET /current/share/{share_id}/ai/chat/{chat_id}/message/{message_id}/read/

Returns a Server-Sent Events (SSE) stream of the AI response.

Auth: Bearer token required. Share view permission and chat permission. content_ai plan feature required.

Request example:

curl -N -X GET "https://api.fast.io/current/share/12345678901234567890/ai/chat/aBcDeFgHiJkLmNoPqR/message/xYzAbCdEfGhIjKlMnO/read/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Accept: text/event-stream"

SSE stream format and behavior: Identical to the workspace version. See Stream message response (SSE) above.

Error responses:

Error CodeHTTP StatusCause
1683 (Resource Missing)404Message not found
1605 (Invalid Input)400Message not in in_progress or complete state
1683 (Resource Missing)404No SSE chunk data exists for this message
1654 (Internal Error)500Internal streaming failure

Publish a private chat (Share)

POST /current/share/{share_id}/ai/chat/{chat_id}/publish/

Makes a private chat public (visible to other share members). One-way operation — published chats cannot be made private again.

Auth: Bearer token required. Share view permission and chat permission. content_ai plan feature required.

Request example:

curl -X POST "https://api.fast.io/current/share/12345678901234567890/ai/chat/aBcDeFgHiJkLmNoPqR/publish/" \
  -H "Authorization: Bearer {jwt_token}"

Response (200 OK):

{ "result": "yes", "current_api_version": "1.0" }

Error responses:

Error CodeHTTP StatusCause
1658 (Not Acceptable)406Chat not found or locked
1660 (Conflict)409Chat is already public
1664 (Datastore Error)500Update failed

Generate AI Share (Share)

POST /current/share/{share_id}/ai/share/

Generates markdown with temporary download URLs for selected files. Designed to be pasted into external AI chatbots.

Auth: Bearer token required. Share view permission and download permission. Does NOT require content_ai plan feature — available on all plans.

ParameterTypeRequiredDescription
filesarray (JSON)YesJSON array of file opaque IDs. Min 1, max 25.

Request example:

curl -X POST "https://api.fast.io/current/share/12345678901234567890/ai/share/" \
  -H "Authorization: Bearer {jwt_token}" \
  -H "Content-Type: application/json" \
  -d '{"files": ["aBcDeFgHiJkLmN", "oPqRsTuVwXyZ12"]}'

Response (200 OK):

{
  "result": "yes",
  "response": {
    "markdown": "## Files\n\n### quarterly-report.pdf\n[Download](https://api.fast.io/...)\nSize: 2.5 MB\n\n..."
  },
  "current_api_version": "1.0"
}
FieldTypeDescription
response.markdownstringGenerated markdown with file info and temporary download URLs

Notes:

Error responses:

Error CodeHTTP StatusCause
1605 (Invalid Input)400Empty files array
1605 (Invalid Input)400More than 25 files
1680 (Access Denied)403Insufficient download permissions

Workspace AI vs. Share AI differences

FeatureWorkspace AIShare AI
AI Transactions endpointYesNo
Auto OG image endpointNoYes
Auto title endpointNoYes
content_ai feature requiredYes (except AI Share)Yes (except AI Share)
ai_agent feature requiredYes, for create-chat and send-message (except AI Share)Yes, for create-chat and send-message (except AI Share)
File scope contextWorkspace filesShare files

AI Share File Download

GET /current/ai/share/{token}?file={index}

Download a file from an AI Share using a temporary token. No authentication required — access is controlled by the token.

ParameterTypeRequiredDescription
{token}string (path)YesAlphanumeric AI share token (generated by the AI Share creation endpoint)
fileinteger (query)YesZero-based file index within the AI Share

Request example:

curl -X GET "https://api.fast.io/current/ai/share/aBcDeFgHiJkLmNoPqRsTuVwXyZ?file=0" \
  -o downloaded_file.pdf

Success response: Binary file data with appropriate Content-Type, Content-Disposition, Content-Length, and Accept-Ranges headers. Supports HTTP range requests.

Error responses:

Error CodeHTTP StatusCause
1609 (Not Found)404Token missing, invalid, expired, or use limit reached
1609 (Not Found)404File index out of range
1654 (Internal Error)500Unable to retrieve or read file

All invalid/expired token errors return 404 to prevent token enumeration.

Deprecated: The /ai/search/ endpoint is deprecated. Use GET /current/workspace/{id}/storage/search/ (or /share/{id}/storage/search/) instead. The unified storage search endpoint automatically performs semantic search when workspace intelligence is enabled. Pass the search parameter for your query, and optionally files_scope and folders_scope to narrow results. Semantic results include relevance_score, content_snippet, match_source, media_segment, mimetype, and search_metadata fields.

The legacy endpoints below continue to work but will be removed in a future release.

GET /current/workspace/{workspace_id}/ai/search/

Auth: Bearer token required. Workspace view permission. content_ai plan feature required.

GET /current/share/{share_id}/ai/search/

Identical to workspace semantic search but scoped to a share.

ParameterTypeRequiredDefaultDescription
query_textstringYesSearch query, 2–1,000 characters
files_scopestringNoAll indexed filesComma-separated nodeId:versionId pairs (max 100)
folders_scopestringNoAll indexed filesComma-separated nodeId:depth pairs (max 100, depth 1–10)
limitintegerNo100Results per page, 1–500
offsetintegerNo0Pagination offset
detailsstringNofalseWhen "true", each result includes a node field with the full node resource (previews, AI state, versions, metadata, size). Default limit drops to 10 (enrichment is expensive). An explicit limit overrides this default.

Preferred approach — use /storage/search instead:

# Basic search
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/search/?search=quarterly%20revenue&limit=10" \
  -H "Authorization: Bearer {jwt_token}"

# Search with full node details
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/search/?search=quarterly%20revenue&details=true" \
  -H "Authorization: Bearer {jwt_token}"

Response (200 OK):

{
  "result": true,
  "response_code": 200,
  "results": [
    {
      "content": "The quarterly revenue showed a 15% increase...",
      "score": 0.95,
      "node": {
        "id": "f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4",
        "type": "file",
        "name": "quarterly-report.pdf",
        "parent": "root",
        "size": 1048576,
        "mimetype": "application/pdf",
        "ai": { "state": "indexed", "attach": true, "summary": true }
      }
    }
  ],
  "pagination": {
    "total": 25,
    "limit": 10,
    "offset": 0,
    "has_more": true
  }
}
FieldTypeDescription
results[].contentstringMatched text snippet from the indexed document
results[].scorefloatRelevance score (0.0–1.0, higher is more relevant)
results[].nodeobject/nullFull node resource, or null if the file was deleted
results[].file_detailsobjectRaw metadata when node is null (node_id, version_id, name, mimetype)
pagination.totalintegerTotal number of results
pagination.has_morebooleanWhether more results are available

Hybrid response fields (intelligence enabled):

When workspace intelligence is enabled, each file entry in the /storage/search response includes additional semantic fields:

FieldTypeDescription
relevance_scorefloatSemantic relevance score (0.0–1.0)
content_snippetstring/nullThe actual matching text from semantic search. NULL for keyword-only matches.
match_sourcestringSource of the match: keyword, semantic, or both
mimetypestringFile MIME type (e.g., application/pdf, audio/mpeg). Present for semantic matches.
media_segmentobjectOnly for audio/video matches when intelligence is on. Contains start_seconds and end_seconds for deep-linking to the exact timestamp range.
search_metadataobjectAdditional search metadata

Response with details=true (via /storage/search):

When using the preferred /storage/search endpoint with ?details=true, each file entry includes a node field with the full node resource:

{
  "result": "yes",
  "response": {
    "files": {
      "f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4": {
        "name": "report.pdf",
        "parent_id": "...",
        "type": "file",
        "relevance_score": 0.92,
        "content_snippet": "Revenue increased 15%...",
        "match_source": "both",
        "mimetype": "application/pdf",
        "node": {
          "id": "f3jm5-zqzfx-pxdr2-dx8z5-bvnb3-rpjfm4",
          "name": "report.pdf",
          "type": "file",
          "size": 123456,
          "previews": { "...": "..." },
          "ai": { "state": "indexed" }
        }
      }
    }
  }
}

Error responses:

Error CodeHTTP StatusCause
1605 (Invalid Input)400Intelligence not enabled
1605 (Invalid Input)400Malformed files_scope or folders_scope

How to Phrase Questions

With folder/file scope (RAG)

Write questions that will match content in indexed files. The AI searches for relevant passages and cites them. Be specific.

With file attachments

You can be more direct since the AI has the full file content.

Chat Session Object Schema

The chat resource is returned by details and list endpoints.

FieldTypeDescription
chat_idstringOpaque ID of the chat
creatorobject{type: string, id: string} — the chat creator
typestringchat or chat_with_files
namestringDisplay name of the chat
statusstringCurrent chat status
message_countintegerTotal number of messages
messagesarrayFull message list (details endpoint) or omitted
latest_messageobjectMost recent message (list endpoint) or omitted
unique_creatorsarrayDistinct participants as {type, id} objects
costobject{credits: {tokens: int}} — total token cost
efficiencystringEfficiency rating
privacyobject{visibility: "private"|"public", owner: {type, id}|null}
created_atstringCreation timestamp (YYYY-MM-DD HH:MM:SS)
updated_atstringLast update timestamp (YYYY-MM-DD HH:MM:SS)

Message Object Schema

FieldTypeDescription
chat_idstringParent chat opaque ID
message_idstringOpaque ID of the message
creatorobject{type: string, id: string} — message author
personalitystringAI personality mode used (concise or detailed)
statestringProcessing state: ready, in_progress, complete, errored
messageobjectUser’s query (see sub-fields below)
message.textstringThe question text
message.author_namestringUser’s given name
message.scopeobjectFile/folder scope used for RAG context
message.attachedarrayAttached files as {node_id, version_id} objects
responseobject/nullAI response (null if not yet available)
response.textstringAI response text
response.errorbooleanWhether an error occurred during processing
response.createdstringResponse timestamp (YYYY-MM-DD HH:MM:SS)
response.costobject{tokens: int, details: object} — message token cost
response.author_namestringAI persona name (e.g., Ripley)
response.eventsarrayStatus events generated during processing
response.table_dataarrayStructured table data in the response
response.analysis_chunksarrayAnalysis progress chunks
response.citationsarrayFile citations (see below)

Citation Format

Citations reference specific locations in files that informed the AI response.

FieldTypeDescription
hashstringFile content hash (used for grouping)
nodeIdstringStorage node opaque ID
versionIdstringFile version opaque ID
entriesarrayCitation locations within the file
entries[].pageintegerPage number in the document
entries[].snippetstring/nullRelevant text excerpt
entries[].timestampfloat/nullTimestamp for audio/video files (seconds)

Activity Polling for AI Chat Completion

Do NOT poll the message details endpoint in a loop. Use activity long-polling instead.

GET /current/activity/poll/{workspace_id}?wait=95&lastactivity={timestamp}

The server holds the connection for up to 95 seconds and returns immediately when something changes. Watch for the ai_chat:{chatId} activity key — this fires when the message state changes.

Activity Key PatternWhat Changed
ai_chat:{chatId}AI chat message state updated
storage:{fileId}File added, updated, or removed
preview:{fileId}File preview/thumbnail is ready

Pass the returned lastactivity timestamp into your next poll to receive only newer changes.

Anti-pattern: Do not GET .../ai/chat/{id}/message/{id}/details/ in a loop. Poll once on the workspace activity endpoint and wait for the ai_chat key.

Metadata Templates

Structured metadata for workspace files. Templates define schemas (fields, types, constraints) and have many-to-many relationships with files — a template can be applied to multiple files, and files can have metadata from multiple templates. Templates are managed at the workspace level.

The metadata feature is available on all plan tiers, with three distinct caps that scale by plan:

PlanMax Templates (views)Max Files per TemplateMax Fields (Columns) per Template
Free11010
Agent11010
Pro21010
Business10100050

Listing, details, and preview endpoints return plan_node_limit, is_truncated, and an unfiltered count alongside the visible (capped) count, so consumers can render upsell messaging. Manual /nodes/add rejects requests that would exceed the per-template file cap. Auto-match silently truncates its candidate set to the remaining slots and incurs no LLM cost when the template is already at its cap. On downgrade, overflow rows are preserved but hidden; under truncation, the visible window is ordered by mapping creation order (oldest-mapped first), so the same files remain visible across plan changes and re-upgrade restores full visibility.

The field cap bounds the number of fields (columns) declared in a template's schema. It is enforced at every commit point that mutates the field set: create, update, and copy. Exceeding the cap returns 1605 (Invalid Input) with a message describing the attempted field count and the cap. The /details and /list endpoints surface the current declared field count as field_count and the per-plan ceiling as plan_field_limit (-1 when unlimited or unresolved).

Each template field also carries an autoextract boolean (defaults to true). Fields with autoextract=false are excluded from the default auto-extraction scope, which is useful for purely manual fields. Every template must have at least one field with autoextract=true; templates that opt every field out are rejected at create/update/copy. A full-row extract request that would yield an empty effective scope short-circuits with success and does not enqueue a job; an explicit fields array on the extract endpoint overrides the flag and is always honored.

Per-node autoextract eligibility is surfaced as an autoextractable boolean on both the metadata details endpoint (GET /workspace/{id}/storage/{node_id}/metadata/details/) and the template nodes listing (GET /workspace/{id}/metadata/templates/{tid}/nodes). It is true when the node is a non-trashed file with a completed AI summary — the same signal the extraction pipeline uses — and clients can use it to gate "extract now" affordances without making an extra probe.

Files are linked to templates either manually (add/remove endpoints) or automatically via AI-based matching. When intelligence is enabled, metadata is automatically extracted during file ingestion for documents, spreadsheets, images (PNG, JPEG, WebP), and code files.

Compact Responses (output=)

Every metadata endpoint that returns object-metadata, template, saved-view, or eligible-node records accepts an optional output query parameter that selects the shape of each record 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.

Object metadata (GET /workspace/{id}/storage/{node}/metadata/details/):

LevelFields returned on each metadata record (cumulative)
terseobject_id, template_id, node_id (narrowed to {id, name, type}), metadata (the full key/value payload)
standardterse + instance_id, node_id widened to {id, name, type, parent, mimetype}, autoextractable
fulleverything

The key/value payload is the point of a metadata response, so terse keeps it. The savings come from trimming the nested node pointer — terse carries only the minimum identity fields needed to address the node in a follow-up call, standard adds parent and mimetype for list rendering, and full keeps the entire node resource.

Templates (GET /workspace/{id}/metadata/templates/list/, GET /workspace/{id}/metadata/templates/{tid}/details/):

LevelFields returned (cumulative)
terseid, name, description, enabled, priority
standardterse + instanceId, orgId, locked, deleted, updated, created, fields, node_count, field_count, node_count_capped, plan_node_limit, is_truncated, plan_field_limit
fulleverything

deleted is included in standard so trash/restore workflows can surface the soft-delete timestamp without promoting to full.

Saved views (GET /workspace/{id}/metadata/template/{tid}/resolve/views/):

LevelFields returned (cumulative)
tersename
standardterse + node_id, filters, order_by, order_desc, created, updated
fulleverything

Eligible nodes (GET /workspace/{id}/metadata/eligible/):

LevelFields returned (cumulative)
tersenode_id, name, mimetype
standardterse + size, summary_title, summary_short, updated, templates
fulleverything

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.

Create a template

POST /current/workspace/{workspace_id}/metadata/templates/

Create a new metadata template defining fields, types, and constraints.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

ParameterTypeRequiredDescription
namestringYesTemplate name (1–255 characters)
descriptionstringYesTemplate description
categorystringYesCategory (1–50 chars). Must be a valid category from the categories endpoint.
fieldsstring (JSON)YesJSON-encoded array of field definitions

Field definition structure:

PropertyTypeDescription
namestringField identifier (alphanumeric + underscore)
descriptionstringHuman-readable description
typestringstring, int, float, bool, json, url, or datetime
minnumberMinimum value/length constraint
maxnumberMaximum value/length constraint
defaultmixedDefault value
fixed_listarrayAllowed values for dropdown-style fields
can_be_nullbooleanWhether the field allows null values

Request example:

curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/metadata/templates/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d 'name=Invoice+Template' \
  -d 'description=Metadata+schema+for+invoices' \
  -d 'category=financial' \
  -d 'fields=[{"name":"invoice_number","description":"Invoice number","type":"string","min":1,"max":50,"can_be_null":false},{"name":"amount","description":"Total amount","type":"float","min":0,"can_be_null":false}]'

Response (200 OK):

{
  "result": "yes",
  "response": {
    "template": {
      "id": "mt_aBcDeFgHiJkLmN",
      "instanceId": "12345678901234567890",
      "orgId": "98765432109876543210",
      "category": "financial",
      "name": "Invoice Template",
      "description": "Metadata schema for invoices",
      "locked": false,
      "priority": null,
      "enabled": false,
      "deleted": null,
      "updated": "2025-01-20 10:30:00",
      "created": "2025-01-20 10:30:00",
      "fields": [
        {
          "name": "invoice_number",
          "description": "Invoice number",
          "type": "string",
          "min": 1,
          "max": 50,
          "fixed_list": [],
          "can_be_null": false
        }
      ]
    }
  },
  "current_api_version": "1.0"
}

Newly created templates start with enabled: false. Use the settings endpoint to enable them.

Delete a template

DELETE /current/workspace/{workspace_id}/metadata/templates/{template_id}/

Soft-delete a metadata template. System templates cannot be deleted.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

Error responses:

Error CodeHTTP StatusCause
1683 (Resource Missing)404Template not found
1680 (Access Denied)403Cannot delete a system template
1664 (Datastore Error)500Deletion failed

List templates

GET /current/workspace/{workspace_id}/metadata/templates/list/

Auth: Bearer token required. Workspace member. Metadata billing feature required.

Optional path filter (append to URL): all (default, both system and custom), custom (non-system only), system (system only), enabled, or disabled.

Request example:

# List all templates
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/metadata/templates/list/" \
  -H "Authorization: Bearer {jwt_token}"

# List only enabled templates
curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/metadata/templates/list/enabled/" \
  -H "Authorization: Bearer {jwt_token}"

Response (200 OK):

{
  "result": "yes",
  "response": {
    "count": 2,
    "items": [
      {
        "id": "mt_aBcDeFgHiJkLmN",
        "instanceId": "12345678901234567890",
        "orgId": "98765432109876543210",
        "category": "legal",
        "name": "Contract Template",
        "description": "Standard contract metadata fields",
        "locked": true,
        "priority": 3,
        "enabled": true,
        "deleted": null,
        "updated": "2025-01-15 08:00:00",
        "created": "2025-01-01 00:00:00",
        "fields": [
          {
            "name": "contract_type",
            "description": "Type of contract",
            "type": "string",
            "fixed_list": ["NDA", "MSA", "SOW"],
            "can_be_null": false
          }
        ]
      }
    ]
  },
  "current_api_version": "1.0"
}

Get template details

GET /current/workspace/{workspace_id}/metadata/templates/{template_id}/details/

Returns the full template with fields and workspace-level instance settings.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

Update template settings

POST /current/workspace/{workspace_id}/metadata/templates/{template_id}/settings/

Update per-workspace instance settings (enable/disable, priority).

Auth: Bearer token required. Workspace member. Metadata billing feature required.

ParameterTypeRequiredDescription
enabledstringYes"true" or "false"
prioritystringYesPriority level "1" through "5"

Error responses:

Error CodeHTTP StatusCause
1683 (Resource Missing)404Template not found
1609 (Not Found)404Template is deleted
1680 (Access Denied)403Template is locked
1664 (Datastore Error)500Update failed

Update template definition

POST /current/workspace/{workspace_id}/metadata/templates/{template_id}/update/

Update a template’s field definitions. All body fields are optional — only provided fields are updated.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

ParameterTypeRequiredDescription
namestringNoUpdated template name (1–255 characters)
descriptionstringNoUpdated description (up to 1000 characters)
categorystringNoUpdated category (1–50 characters)
fieldsstring (JSON)NoUpdated JSON-encoded array of field definitions

Append /create/ to the path to copy the template instead of updating in place.

Response: Returns the updated template object. When the fields array changes in a way that invalidates stored values, the response additionally includes a schema_update object. Auto-triggered partial re-extraction runs only for: (a) new field names, and (b) type changes on existing names. Soft edits (description, min/max, nullable, fixed_list, regex) bump the schema hash but do not auto-trigger extraction — call the extract-all endpoint manually if you want those applied.

{
  "result": "yes",
  "response": {
    "template": { "...": "..." },
    "schema_update": {
      "previous_hash": 1234567890,
      "current_hash": 2345678901,
      "extraction_auto_enqueued": true,
      "added_fields": ["currency"],
      "type_changed_fields": ["total_amount"]
    }
  }
}

The schema_update object is absent when only name or description change.

Template-Node Mapping

Templates have many-to-many relationships with files. Use these endpoints to manage which files are mapped to which templates.

Eligible nodes

GET /current/workspace/{workspace_id}/metadata/eligible/

Paginated list of files and notes eligible for metadata extraction (nodes that have both an AI summary and a preview ready). Folders and links are excluded.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

ParameterTypeRequiredDescription
limitintegerNoNumber of items to return (1–500, default: 100)
offsetintegerNoNumber of items to skip (default: 0)

Add nodes to template

POST /current/workspace/{workspace_id}/metadata/templates/{template_id}/nodes/add/

Manually add nodes to a template. Both files and notes can be added; folders and links are rejected. Creates the many-to-many mapping between the template and the specified nodes.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

ParameterTypeRequiredDescription
node_idsstring (JSON)YesJSON-encoded array of node IDs to add to the template

The number of files mapped to a single template is capped per plan tier. When the request would push the template above its cap, the endpoint returns 1605 (Invalid Input) with a message describing the cap, the attempted count, and the remaining slots. Concurrent calls cannot collectively exceed the cap.

Remove nodes from template

POST /current/workspace/{workspace_id}/metadata/templates/{template_id}/nodes/remove/

Remove nodes (files or notes) from a template. Removes the many-to-many mapping between the template and the specified nodes.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

ParameterTypeRequiredDescription
node_idsstring (JSON)YesJSON-encoded array of node IDs to remove from the template

List nodes in template

GET /current/workspace/{workspace_id}/metadata/templates/{template_id}/nodes/

List nodes (files and notes) currently mapped to a template. The visible window is clamped to the workspace plan's per-template cap. When the template is truncated under the cap, rows are ordered by mapping creation order (oldest first) so the visible set is stable across plan changes. The default ordering when no sort_field is supplied is subject to change in upcoming releases; callers that depend on a specific ordering should pass sort_field explicitly.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

ParameterTypeRequiredDescription
limitintegerNoNumber of items to return (1–500, default: 100)
offsetintegerNoNumber of items to skip (default: 0)
sort_fieldstringNoOptional template field name to sort by
sort_dirstringNoasc or desc (only with sort_field)

Response (additional fields):

FieldTypeDescription
total_countintegerVisible row count under the per-plan cap
total_count_unfilteredintegerTrue row count in storage (ignores cap)
plan_node_limitintegerPer-template node cap for the workspace's plan; -1 indicates unlimited / unresolved
is_truncatedbooleantrue when overflow rows exist beyond the cap

Pagination is clamped to the visible window: oversized limit values are silently shortened, and offsets past the visible window return an empty page. Existing pagination fields (items, count, next_cursor, has_more) are unchanged.

Preview template match

POST /current/workspace/{workspace_id}/metadata/templates/preview-match/

Synchronously preview which files would match a proposed metadata template before creating it. Accepts a template name and description, scans a sample of eligible files using AI classification, and returns the matched files with details. No template is created — this is a read-only preview operation.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

ParameterTypeRequiredDescription
namestringYesProposed template name (1–255 characters)
descriptionstringYesProposed template description (1–2000 characters)

Response (200 OK):

{
  "result": "yes",
  "response": {
    "matched_files": [
      {
        "node_id": "aBcDeFgHiJkLmN",
        "name": "invoice_2025.pdf",
        "mimetype": "application/pdf",
        "summary_title": "Invoice from Acme Corp",
        "summary_short": "Invoice INV-2025-001 for $1,500.00"
      }
    ],
    "total_eligible": 45,
    "total_scanned": 45,
    "total_matched": 1,
    "plan_node_limit": 10,
    "would_truncate_at": 1
  }
}
FieldTypeDescription
matched_filesarrayFiles that matched the proposed template
matched_files[].node_idstringFile node opaque ID
matched_files[].namestringFile name
matched_files[].mimetypestringMIME type
matched_files[].summary_titlestringAI-generated summary title
matched_files[].summary_shortstringAI-generated short summary
total_eligibleintegerSize of the eligible-file sample considered by this preview. When the workspace has more eligible files than fit in the sample window, this value is the sample ceiling (plus one, to signal "more available") rather than the true workspace-wide count
total_scannedintegerFiles actually scanned in this preview. May be smaller than total_eligible when the sample is bounded
total_matchedintegerFiles that matched
plan_node_limitintegerPer-template node cap for the workspace's plan; -1 indicates unlimited / unresolved
would_truncate_atintegerNumber of matches that would be persisted by a subsequent auto-match, given the current plan cap and the sampled matches. Equal to min(total_matched, plan_node_limit) when the cap applies, otherwise equal to total_matched. Because the preview only scans a sample, this is an estimate — a subsequent auto-match that scans the full workspace may match a different count. Frontends can show "X of Y matched — upgrade for more" when this value is less than total_matched.

Requires available AI credits. Only files with completed AI summaries and previews are eligible.

Suggest template fields

POST /current/workspace/{workspace_id}/metadata/templates/suggest-fields/

Synchronously suggest a set of custom metadata fields for a proposed view, using AI. Accepts a small sample of eligible file node IDs (typically drawn from a prior preview-match call), a view description, and optional user intent text. Returns 1–10 suggested field definitions shaped to be used directly as the fields parameter of the create-template endpoint. No template is created — this is a read-only suggestion operation. Sits between preview-match and create-template in a view-creation flow.

Auth: Bearer token required. Workspace member. Metadata billing feature required. Rate limited; concurrent calls per user+workspace return 409 Conflict.

ParameterTypeRequiredDescription
node_idsstring (JSON)YesJSON-encoded array of file node IDs to sample (1–25 items)
descriptionstringYesView description (1–2000 characters)
user_contextstringNoOptional user intent string (max 64 characters, letters/numbers/spaces only)

Response (200 OK):

{
  "result": "yes",
  "response": {
    "suggested_fields": [
      {
        "name": "Location",
        "type": "string",
        "description": "Geographic location where the content was created",
        "max": 384,
        "can_be_null": true,
        "example_value": "New York, NY"
      },
      {
        "name": "Year",
        "type": "int",
        "description": "Year the document was created or published",
        "can_be_null": true,
        "example_value": 2024
      },
      {
        "name": "Priority",
        "type": "string",
        "description": "Priority level of the task",
        "max": 384,
        "can_be_null": false,
        "fixed_list": ["low", "medium", "high"],
        "example_value": "medium"
      }
    ],
    "file_sample_count": 25
  }
}
FieldTypeDescription
suggested_fieldsarray1–10 suggested field definitions, directly compatible with create-template fields
suggested_fields[].namestringField display name
suggested_fields[].typestringOne of string, int, float, bool, datetime, url
suggested_fields[].descriptionstringHuman-readable field description
suggested_fields[].maxnumberMaximum length/value constraint (when applicable)
suggested_fields[].can_be_nullboolWhether the field may be null
suggested_fields[].fixed_listarrayAllowed values for bounded categorical fields (status, priority, category). Present only when the field is enumerable.
suggested_fields[].example_valuemixedDisplay-only hint showing what the extraction AI would likely return for this field, grounded in one of the sampled files. Type matches the field's type: string for string/url (HTML-stripped, max 256 chars), integer for int, number for float, boolean for bool, ISO 8601 string for datetime. May be omitted when no clean example is available.
file_sample_countintegerNumber of files actually used to generate suggestions

Requires available AI credits. The json field type is not returned by this endpoint. example_value is a preview hint only and is not part of the create-template field schema; clients should strip it before posting to create-template (passing it through is harmless as unknown keys are ignored).

Auto-match files to template

POST /current/workspace/{workspace_id}/metadata/templates/{template_id}/auto-match/

Use AI to automatically match eligible files in the workspace to the template based on file content and template field definitions. Progress is tracked via the jobs status endpoint under the template_match key.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

The matched set is silently capped at the workspace's per-template node cap. Eligible files are truncated pre-batch (so no LLM credit is spent on candidates that cannot be persisted) and re-checked immediately before persistence to handle interleaved manual adds. When the template is already at its cap, the job completes successfully with no LLM usage.

Batch extract metadata (template-level)

POST /current/workspace/{workspace_id}/metadata/templates/{template_id}/extract-all/

Batch-extract metadata for all files mapped to a template. Async — returns a job_id for tracking.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

Response (200 OK):

{
  "result": "yes",
  "response": {
    "job_id": "aj_aBcDeFgHiJkLmN",
    "template_id": "mt_oPqRsTuVwXyZ12"
  }
}

Maximum 1,000 files processed per job.

Node Metadata

Metadata stored on individual files. Split into template metadata (conforming to mapped templates) and custom metadata (user-defined fields).

Get file metadata

GET /current/workspace/{workspace_id}/storage/{node_id}/metadata/details/

Returns all metadata for a file. Response contains template_metadata and custom_metadata separately.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

Request example:

curl -X GET "https://api.fast.io/current/workspace/12345678901234567890/storage/aBcDeFgHiJkLmN/metadata/details/" \
  -H "Authorization: Bearer {jwt_token}"

Response (200 OK):

{
  "result": "yes",
  "response": {
    "instance_id": "1234567890123456789",
    "object_id": "aBcDeFgHiJkLmN",
    "template_id": "mt_oPqRsTuVwXyZ12",
    "node_id": {
      "id": "aBcDeFgHiJkLmN",
      "name": "invoice_2025.pdf",
      "type": "file",
      "size": 245760
    },
    "metadata": [
      {
        "key": "invoice_number",
        "description": "Invoice number",
        "type": "string",
        "value": "INV-2025-001",
        "is_auto": false,
        "updated": "2025-01-20 10:30:00"
      },
      {
        "key": "amount",
        "description": "Invoice amount",
        "type": "float",
        "value": 1500.00,
        "is_auto": true,
        "updated": "2025-01-20 10:30:00"
      }
    ]
  },
  "current_api_version": "1.0"
}
FieldTypeDescription
response.template_idstring/nullAssociated template ID, or null
response.node_idobjectStorage node resource with file details
response.metadata[].keystringMetadata field key
response.metadata[].typestringValue type (string, int, float, bool, json, url, datetime)
response.metadata[].valuemixedThe metadata value
response.metadata[].is_autobooleanWhether the value was auto-generated by AI extraction
response.metadata[].updatedstringLast update timestamp

Update file metadata

POST /current/workspace/{workspace_id}/storage/{node_id}/metadata/update/{template_id}/

Set or update metadata key-value pairs on a file.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

ParameterTypeRequiredDescription
key_valuesstring (JSON)YesJSON-encoded object of key-value pairs. Keys must match template field names.

Request example:

curl -X POST "https://api.fast.io/current/workspace/12345678901234567890/storage/aBcDeFgHiJkLmN/metadata/update/mt_oPqRsTuVwXyZ12/" \
  -H "Authorization: Bearer {jwt_token}" \
  -d 'key_values={"invoice_number":"INV-2025-001","amount":1500.00}'

Existing metadata for the same keys is overwritten. Keys not included in the request are left unchanged.

Delete file metadata

DELETE /current/workspace/{workspace_id}/storage/{node_id}/metadata/

Delete metadata keys from a file.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

ParameterTypeRequiredDescription
keysstring (JSON)NoJSON-encoded array of key names to delete. If omitted, all keys may be removed.

Only files and notes support metadata — folders return an error.

Extract metadata (single file)

POST /current/workspace/{workspace_id}/storage/{node_id}/metadata/extract/

Enqueues an AI extraction job for a single file against a template. Asynchronous — returns HTTP 202 Accepted with a job descriptor. Poll GET /current/workspace/{workspace_id}/jobs/status/ to track progress, then read the values from GET /current/workspace/{workspace_id}/storage/{node_id}/metadata/details/ once the job reports completed. Supports documents, spreadsheets, images (PNG, JPEG, WebP), and code files. Extracted values are stored with is_auto: true.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

ParameterTypeRequiredDescription
template_idstringNoThe template ID to extract against. Defaults to the first template mapped to the file.
fieldsstring (JSON)NoJSON-encoded array of field names to restrict extraction scope. Each name must exist on the template. Omit to extract the full schema.

Response (HTTP 202 Accepted):

{
  "result": "yes",
  "response": {
    "job_id": "{job_id}",
    "template_id": "{template_id}",
    "node_id": "{node_id}",
    "fields": ["amount", "due_date"],
    "status": "queued",
    "status_uri": "/workspace/{workspace_id}/jobs/status"
  }
}

status is queued for a fresh job, or in_progress when the request is collapsed into an already-running job (see idempotent retries below).

Idempotent retries: submitting the same (node, template, fields) combination while a job is already in flight returns the existing job_id instead of enqueueing a duplicate. Retries within a 30-minute window are safe.

Polling flow:

POST /current/workspace/{id}/storage/{node}/metadata/extract/
  template_id={template_id}
  -> HTTP 202
     { "job_id": "{job_id}", "status": "queued",
       "status_uri": "/workspace/{id}/jobs/status" }

GET  /current/workspace/{id}/jobs/status/
  -> jobs.metadata_extract[] includes
     { "kind": "single",
       "active": true,
       "node_id": "{node_id}",
       "template_id": "{template_id}",
       "job_id": "{job_id}",
       "status": "in_progress",
       "progress_percent": 0 }

GET  /current/workspace/{id}/jobs/status/     (later)
  -> entry now { "status": "completed",
                 "progress_percent": 100,
                 "completed_at": ... }

GET  /current/workspace/{id}/storage/{node}/metadata/details/
  -> extracted values under `template_metadata`

Error responses:

Error CodeHTTP StatusCause
1605 (Invalid Input)400Node is root, fields references an unknown field, or payload is malformed
1609 (Not Found)404Template not found
1609 (Not Found)404Node not found
1664 (Datastore Error)500Failed to enqueue extraction job
1696 (Credits Exhausted)402No AI credits remaining

List metadata by template

GET /current/workspace/{workspace_id}/storage/{node_id}/metadata/list/{template_id}/

List all files with metadata for a specific template. Supports filtering and sorting.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

ParameterTypeRequiredDescription
filtersstring (JSON)NoJSON-encoded filter criteria
order_bystringNoField key name to sort by
order_descstringNo"true" or "false" for descending sort

List templates in use

GET /current/workspace/{workspace_id}/storage/{node_id}/metadata/templates/

List templates that have metadata set on files, with object counts.

Auth: Bearer token required. Workspace member. Metadata billing feature required.

Metadata versions

GET /current/workspace/{workspace_id}/storage/{node_id}/metadata/versions/

List metadata version snapshots for a file. Useful for tracking changes to extracted metadata over time.

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. Full endpoint reference is in the Storage Operations docs.

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/

Auth required. Workspace member. Metadata billing feature required.

POST body: application/x-www-form-urlencoded with template_id (string) and config (JSON-encoded string containing the view config). Do NOT send as application/json — the endpoint only accepts form-encoded bodies and returns 406 (This field is missing) for JSON bodies. The config schema (the JSON serialized into the form field) is { version: 1, columns: [{field, visible?, width?}], sort: {field, dir}, filters: [{field, operator, value_type, value}] }; column array order IS the display order; dir is asc or desc; filters are AND-chained, max 5 per view, with operator in = != < <= > >= and value_type in string | int | float | bool (json rejected). Each saved-view filter entry uses field for its template-field identifier (matching columns[].field and sort.field); the nodes endpoint's stateless filters query parameter keeps its pre-existing key form, and the server handles the translation when auto-applying a saved view. Unknown keys are rejected with 1605 (Invalid Input). See the Storage Operations docs for the full filter contract.

The template nodes listing endpoint (GET /workspace/{workspace_id}/metadata/templates/{template_id}/nodes) auto-applies config.sort and config.filters from the caller's saved view when the corresponding sort_field / filters query parameters are not passed explicitly. An explicit query parameter (even empty) always wins; no server-side merge.

Template Resource Schema

FieldTypeDescription
idstringOpaque template identifier
instanceIdstringWorkspace ID
orgIdstring/nullOrganization ID
categorystringTemplate category
namestringTemplate name
descriptionstringTemplate description
lockedbooleanWhether the template is locked from editing
priorityinteger/nullPriority level 1–5, or null
enabledbooleanWhether enabled for the workspace
deletedstring/nullSoft-delete timestamp, or null
updatedstringLast updated timestamp
createdstringCreation timestamp
fieldsarrayArray of field definition objects

Supported Field Types

TypeDescription
stringText values (max 10,000 characters)
intInteger numbers
floatDecimal numbers
boolBoolean true/false
jsonComplex JSON structures
urlValidated URLs
datetimeDate and time values

Quick Reference

Create a RAG chat and get the answer

POST /current/workspace/{id}/ai/chat/
  question=...&type=chat_with_files&personality=detailed
  -> chat_id, message_id

GET  /current/activity/poll/{id}?wait=95&lastactivity=...
  -> wait for ai_chat:{chatId}

GET  /current/workspace/{id}/ai/chat/{chat_id}/message/{msg_id}/details/
  -> check state == complete

GET  /current/workspace/{id}/ai/chat/{chat_id}/message/{msg_id}/read/
  -> SSE stream: data, analysis_data, table_data, done

Create a note (bank knowledge for RAG)

POST /current/workspace/{id}/storage/{parent}/createnote/
  name=research-notes.md&content=...

Extract metadata from a file (async)

POST /current/workspace/{id}/storage/{node}/metadata/extract/
  template_id={template_id}
  -> HTTP 202 { job_id, status: "queued" | "in_progress" }

GET  /current/workspace/{id}/jobs/status/
  -> jobs.metadata_extract[] (kind: "single") reaches status: "completed"

GET  /current/workspace/{id}/storage/{node}/metadata/details/
  -> extracted values

List eligible nodes for metadata (files and notes)

GET /current/workspace/{id}/metadata/eligible/

Add nodes to a template (files and notes)

POST /current/workspace/{id}/metadata/templates/{template_id}/nodes/add/
  node_ids=["nodeId1","nodeId2"]

AI auto-match files to a template

POST /current/workspace/{id}/metadata/templates/{template_id}/auto-match/

Batch extract metadata for all files in a template

POST /current/workspace/{id}/metadata/templates/{template_id}/extract-all/
  -> returns job_id (rate limited: 2/min, 10/hr)

Semantic search (use /storage/search instead — /ai/search is deprecated)

GET /current/workspace/{id}/storage/search/?search=quarterly+revenue&limit=10
GET /current/workspace/{id}/storage/search/?search=quarterly+revenue&details=true

Optional details=true includes full node resource (previews, AI state, metadata, size) per result. Default limit drops to 10 when details enabled.

↑ Back to top