AI & Chat RAG-powered chat, semantic search, notes, metadata extraction, and auto-summarization
Overview
Fast.io provides built-in AI capabilities for workspaces and shares:
- RAG-powered chat — Ask questions about indexed files with citations to specific pages and snippets
- General chat — AI conversation with optional file attachments for one-off analysis
- Auto-summarization — AI-generated titles and descriptions for shares
- Metadata extraction — AI-powered structured metadata extraction from documents, spreadsheets, images, and code
- Semantic search — Find files by meaning, not just keywords
- Notes — Markdown storage nodes that are indexed for RAG, letting you bank knowledge over time
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.
Intelligence Setting
The intelligence boolean on a workspace or portal share controls whether uploaded files are automatically indexed for RAG.
intelligence=true(default for agent accounts) — Files are auto-indexed for semantic search, summarization, and citation. Required forchat_with_filestype chats with file/folder scope.intelligence=false— Files are stored/shared without RAG indexing. You can still usechattype withfiles_attachfor direct file analysis.
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:
/current/org/{org_id}/create/workspace/
Pass intelligence=true
Update later:
/current/workspace/{workspace_id}/update/
Pass intelligence=true
Warning: Intelligence cannot be re-enabled once disabled. Disabling is permanent.
Chat Types
Two chat types are available. Both augment answers with web knowledge.
chat — General AI Conversation
- Does not use RAG or workspace file indexing
- Works regardless of the workspace
intelligencesetting - You can attach files directly via
files_attachfor one-off analysis (e.g., “Describe this image”, “Summarize this PDF”) - Any file with a ready preview or AI summary can be attached
chat_with_files — RAG-Powered Chat
- Searches indexed files in the workspace/share (or a scoped folder/file set)
- Returns answers with citations to specific files, pages, and text snippets
- Requires the workspace/share
intelligencesetting to be enabled when using file/folder scope - Default scope is the entire workspace/share — omit scope parameters to search all indexed files
- Only files with
ai_state: readyare included in searches
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.
- Default scope is the entire workspace/share — omit both
files_scopeandfolders_scopeto search all indexed files - Only files with
ai_state: readyare included - Only used with
chat_with_filestype
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.
- Files must have AI summaries ready (be in a “ready” state or eligible for summarization)
- Max 20 files, 200 MB total (effective size after preview optimization)
- Works with both
chatandchat_with_filestypes - Good for: “Describe this image”, “Extract action items from this transcript”, “Compare these two contracts”
Format: comma-separated nodeId:versionId pairs, e.g., files_attach=nodeId1:versionId1,nodeId2:versionId2
Choosing Between Scope and Attachments
| Use Case | Mechanism | Chat Type |
|---|---|---|
| Search across many indexed files | files_scope / folders_scope | chat_with_files |
| Analyze specific files directly | files_attach | chat or chat_with_files |
| Ask general questions about the workspace | Omit scope (defaults to all files) | chat_with_files |
| General conversation, no files | Neither | chat |
AI State (File Readiness)
Files in an intelligent workspace progress through AI processing states:
| State | Meaning |
|---|---|
disabled | Intelligence not enabled for this file/workspace |
pending | Queued for AI processing |
inprogress | Currently being indexed |
ready | Indexed and available for RAG searches |
failed | Indexing failed |
Only files with ai_state: ready are included in RAG folder/file scope searches. 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.
| Value | Behavior |
|---|---|
concise | Short, brief, direct answers with minimal elaboration |
detailed | Comprehensive answers with context, evidence, and examples (default) |
You can also control verbosity directly in your question phrasing:
- “In one sentence, what is the main conclusion?”
- “List only the file names that mention GDPR, no explanations”
- “Give me a brief summary — 2–3 bullet points max”
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
/current/workspace/{workspace_id}/storage/{parent_id}/createnote/
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Note name, must end in .md |
| content | string | Yes | Markdown content, max 100 KB |
{parent_id} is a folder OpaqueId or "root". Returns the created note as a node resource.
Update a note
/current/workspace/{workspace_id}/storage/{node_id}/updatenote/
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | No | New name, must end in .md |
| content | string | No | New markdown content, max 100 KB |
At least one of name or content must be provided. Updating content creates a new version.
Read note content
/current/workspace/{workspace_id}/storage/{node_id}/read/
Returns the raw markdown content.
Linking a user to a note
- In workspace context:
https://{org_domain}.fast.io/workspace/{workspace_name}?note={note_opaque_id} - Direct preview: use the preview URL for the note node
Workspace AI Endpoints
Create a new chat
/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 plan feature required.
Rate limits: 1/1s, 5/10s, 10/60s, 50/hr, 200/day (per workspace + user).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| type | string | Yes | — | chat or chat_with_files |
| question | string | Yes | — | Initial question, 2–12,768 characters |
| privacy | string | No | public | private or public |
| name | string | No | Auto-generated | Chat name. Auto-generated from first 10 words of question if omitted. |
| personality | string | No | detailed | concise or detailed |
| files_scope | string | No | All indexed files | Comma-separated nodeId:versionId pairs (max 100). Requires chat_with_files type and Intelligence enabled. |
| folders_scope | string | No | All indexed files | Comma-separated nodeId:depth pairs (max 100, depth 1–10). Requires chat_with_files type and Intelligence enabled. |
| files_attach | string | No | — | Comma-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"
}
| Field | Type | Description |
|---|---|---|
response.chat.id | string | Opaque ID of the created chat |
response.chat.message.id | string/null | Opaque ID of the initial message, or null if no question was provided |
Error responses:
| Error Code | HTTP Status | Cause |
|---|---|---|
APP_ERROR_INPUT_INVALID | 400 | Invalid type, privacy, or personality value |
APP_ERROR_INPUT_INVALID | 400 | File/folder scope used without Intelligence enabled |
APP_ERROR_INPUT_INVALID | 400 | Both files_attach and files_scope specified |
APP_ERROR_INPUT_INVALID | 400 | Invalid name or other property |
APP_ERROR_DATASTORE | 500 | Chat or message creation failed |
List chats
/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.
Rate limits: 3/1s, 10/10s, 20/60s, 50/hr, 200/day.
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"
}
| Field | Type | Description |
|---|---|---|
response.chats | array | Array of chat objects |
response.chats[].chat_id | string | Opaque ID of the chat |
response.chats[].creator | object | {type, id} — the chat creator |
response.chats[].type | string | chat or chat_with_files |
response.chats[].name | string | Chat display name |
response.chats[].status | string | Chat status |
response.chats[].message_count | integer | Total messages in the chat |
response.chats[].latest_message | object | Most recent message preview |
response.chats[].unique_creators | array | Distinct participants |
response.chats[].cost.credits.tokens | integer | Total token cost |
response.chats[].efficiency | string | Efficiency rating |
response.chats[].privacy | object | {visibility, owner} |
response.chats[].created_at | string | ISO 8601 creation timestamp |
response.chats[].updated_at | string | ISO 8601 last update timestamp |
Get chat details
/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.
Rate limits: 100/10s, 350/60s, 2000/hr.
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 Code | HTTP Status | Cause |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Chat ID not found |
APP_INTERNAL_ERROR | 500 | Internal failure loading chat |
Update a chat
/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.
Rate limits: 1/1s, 5/10s, 10/60s, 50/hr, 200/day.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | New 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 Code | HTTP Status | Cause |
|---|---|---|
APP_NOT_ACCEPTED | 406 | Chat not found or locked |
APP_ERROR_INPUT_INVALID | 400 | Invalid name value |
APP_ERROR_DATASTORE | 500 | Update failed |
Delete a chat
/current/workspace/{workspace_id}/ai/chat/{chat_id}/
Auth: Bearer token required. content_ai plan feature required.
Rate limits: 3/1s, 20/10s, 50/60s, 250/hr, 500/day.
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 Code | HTTP Status | Cause |
|---|---|---|
APP_NOT_ACCEPTED | 406 | Chat not found or locked |
APP_INTERNAL_ERROR | 500 | Chat in non-deletable state or internal error |
Deleted chats can be listed via GET .../ai/chat/list/deleted.
Send a follow-up message
/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 plan feature required.
Rate limits: 10/10s, 20/60s, 500/hr.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| question | string | Yes | — | Follow-up question, 2–12,768 characters |
| personality | string | No | detailed | concise or detailed |
| files_scope | string | No | All indexed files | Comma-separated nodeId:versionId pairs (max 100). Only for chat_with_files type. |
| folders_scope | string | No | All indexed files | Comma-separated nodeId:depth pairs (max 100, depth 1–10). Only for chat_with_files type. |
| files_attach | string | No | — | Comma-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 Code | HTTP Status | Cause |
|---|---|---|
APP_NOT_ACCEPTED | 406 | Chat not found or locked |
APP_ERROR_INPUT_INVALID | 400 | Both files_attach and files_scope specified |
APP_ERROR_INPUT_INVALID | 400 | Scope used with wrong chat type |
APP_INTERNAL_ERROR | 500 | Message creation failed |
List messages in a chat
/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
/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.
Rate limits: 200/60s, 2000/hr.
Key response fields:
| Field | Description |
|---|---|
state | Message processing state: ready, in_progress, complete, errored |
message.text | The original question text |
message.scope | File/folder scope used for RAG context |
message.attached | Attached files as {node_id, version_id} objects |
response.text | The AI response (available when state is complete) |
response.error | Whether an error occurred during processing |
response.cost | {tokens, details} — message token cost |
response.citations | Array of file citations (see Citation Format below) |
Only read the response when state is complete.
Error responses:
| Error Code | HTTP Status | Cause |
|---|---|---|
APP_MISSING | 404 | Message not found in the chat |
APP_INTERNAL_ERROR | 500 | Internal retrieval failure |
Stream message response (SSE)
/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.
Rate limits: 5/3s, 20/10s, 100/60s, 700/hr.
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 Type | Description |
|---|---|
data | Text chunks of the AI response. Payload: {"item": "..."}. Concatenate all data events for the full text. |
event | Status update or event notification |
analysis_data | Structured analysis data, citations, and references to source files |
table_data | Tabular data extracted or generated by the AI |
done | Stream complete. No more events will be sent. |
Behavior:
- The message must be in
in_progressorcompletestate - For completed messages, all existing chunks are sent immediately followed by
done - For in-progress messages, the connection stays open and polls for new chunks at intervals (~5 seconds)
- The connection auto-terminates after a maximum wait time
- Headers include
Cache-Control: no-cache, no-store, must-revalidate - This endpoint returns an SSE stream, NOT the standard JSON response envelope
Error responses:
| Error Code | HTTP Status | Cause |
|---|---|---|
APP_MISSING | 404 | Message not found |
APP_ERROR_INPUT_INVALID | 400 | Message not in in_progress or complete state |
APP_MISSING | 404 | No SSE chunk data exists for this message |
APP_INTERNAL_ERROR | 500 | Internal streaming failure |
Publish a private chat
/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.
Rate limits: 1/1s, 5/10s, 10/60s, 50/hr, 200/day.
Response (200 OK):
{ "result": "yes", "current_api_version": "1.0" }
Error responses:
| Error Code | HTTP Status | Cause |
|---|---|---|
APP_NOT_ACCEPTED | 406 | Chat not found or locked |
APP_CONFLICT | 409 | Chat is already public |
APP_ERROR_DATASTORE | 500 | Update failed |
Generate AI Share
/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.
Rate limits: 5/min, 100/hr (per user).
| Parameter | Type | Required | Description |
|---|---|---|---|
| files | array (JSON) | Yes | JSON 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"
}
| Field | Type | Description |
|---|---|---|
response.markdown | string | Generated markdown with file info and temporary download URLs |
Notes:
- Download URLs expire after 5 minutes (300 seconds)
- Each token can be used a maximum of 3 times
- Individual files limited to 50 MB; total size limited to 100 MB
- When more than 5 files: titles only. 5 or fewer: includes full descriptions.
- The
filesinput is a JSON array (not comma-separated strings)
Error responses:
| Error Code | HTTP Status | Cause |
|---|---|---|
APP_ERROR_INPUT_INVALID | 400 | Empty files array |
APP_ERROR_INPUT_INVALID | 400 | More than 25 files |
List AI transactions
/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"
}
| Field | Type | Description |
|---|---|---|
response.count | integer | Number of transactions returned |
response.items[].id | string | Formatted transaction ID |
response.items[].type | string | Parent type (e.g., chat, chat_with_files) |
response.items[].status | string | Transaction status |
response.items[].tokens | integer | Token credits consumed |
response.items[].updated | string | Last update timestamp (UTC) |
response.items[].created | string | Creation 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: ready → in_progress → complete (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
/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.
Rate limits (private shares only): 1,000/10min, 20,000/day.
| Behavior | Description |
|---|---|
| Public share | Custom AI-generated image based on share content |
| Private share | Default private image returned |
Error responses:
| Error Code | HTTP Status | Cause |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Share is disabled |
APP_INTERNAL_ERROR | 500 | Default image not available |
Auto-generate title and description
/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.
Rate limits: 1,000/10min, 5,000/day.
| Parameter | Type | Required | Description |
|---|---|---|---|
| context | string | No | Optional 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"
}
}
| Field | Type | Description |
|---|---|---|
response.title | string | AI-generated title |
response.description | string | AI-generated description |
response.display_type | string | AI-suggested display type |
Error responses:
| Error Code | HTTP Status | Cause |
|---|---|---|
APP_DENIED | 403 | Insufficient share permissions |
APP_INTERNAL_ERROR | 500 | Share 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:
- Auth uses share permissions instead of workspace permissions
- File scope references share files instead of workspace files
- No AI Transactions endpoint (workspace-only)
Create a new chat (Share)
/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 plan feature required.
Rate limits: 1/1s, 5/10s, 10/60s, 50/hr, 200/day (per share + user).
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| type | string | Yes | — | chat or chat_with_files |
| question | string | Yes | — | Initial question, 2–12,768 characters |
| privacy | string | No | public | private or public |
| name | string | No | Auto-generated | Chat name. Auto-generated from first 10 words of question if omitted. |
| personality | string | No | detailed | concise or detailed |
| files_scope | string | No | All indexed files | Comma-separated nodeId:versionId pairs (max 100). Requires chat_with_files type and Intelligence enabled. |
| folders_scope | string | No | All indexed files | Comma-separated nodeId:depth pairs (max 100, depth 1–10). Requires chat_with_files type and Intelligence enabled. |
| files_attach | string | No | — | Comma-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"
}
| Field | Type | Description |
|---|---|---|
response.chat.id | string | Opaque ID of the created chat |
response.chat.message.id | string/null | Opaque ID of the initial message, or null if no question was provided |
Error responses:
| Error Code | HTTP Status | Cause |
|---|---|---|
APP_ERROR_INPUT_INVALID | 400 | Invalid type, privacy, or personality value |
APP_ERROR_INPUT_INVALID | 400 | File/folder scope used without Intelligence enabled |
APP_ERROR_INPUT_INVALID | 400 | Both files_attach and files_scope specified |
APP_ERROR_DATASTORE | 500 | Chat or message creation failed |
List chats (Share)
/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.
Rate limits: 3/1s, 10/10s, 20/60s, 50/hr, 200/day.
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)
/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.
Rate limits: 10/1s, 60/10s, 150/60s, 1000/hr.
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 Code | HTTP Status | Cause |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Chat ID not found |
APP_INTERNAL_ERROR | 500 | Internal failure loading chat |
Update a chat (Share)
/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.
Rate limits: 1/1s, 5/10s, 10/60s, 50/hr, 200/day.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | New 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 Code | HTTP Status | Cause |
|---|---|---|
APP_NOT_ACCEPTED | 406 | Chat not found or locked |
APP_ERROR_INPUT_INVALID | 400 | Invalid name value |
APP_ERROR_DATASTORE | 500 | Update failed |
Delete a chat (Share)
/current/share/{share_id}/ai/chat/{chat_id}/
Auth: Bearer token required. Share view permission and chat permission. content_ai plan feature required.
Rate limits: 3/1s, 20/10s, 50/60s, 250/hr, 500/day.
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 Code | HTTP Status | Cause |
|---|---|---|
APP_NOT_ACCEPTED | 406 | Chat not found or locked |
APP_INTERNAL_ERROR | 500 | Chat in non-deletable state or internal error |
Deleted chats can be listed via GET .../ai/chat/list/deleted.
Send a follow-up message (Share)
/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 plan feature required.
Rate limits: 10/10s, 20/60s, 500/hr.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| question | string | Yes | — | Follow-up question, 2–12,768 characters |
| personality | string | No | detailed | concise or detailed |
| files_scope | string | No | All indexed files | Comma-separated nodeId:versionId pairs (max 100). Only for chat_with_files type. |
| folders_scope | string | No | All indexed files | Comma-separated nodeId:depth pairs (max 100, depth 1–10). Only for chat_with_files type. |
| files_attach | string | No | — | Comma-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 Code | HTTP Status | Cause |
|---|---|---|
APP_NOT_ACCEPTED | 406 | Chat not found or locked |
APP_ERROR_INPUT_INVALID | 400 | Both files_attach and files_scope specified |
APP_ERROR_INPUT_INVALID | 400 | Scope used with wrong chat type |
APP_INTERNAL_ERROR | 500 | Message creation failed |
List messages in a chat (Share)
/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)
/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.
Rate limits: 200/60s, 2000/hr.
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 Code | HTTP Status | Cause |
|---|---|---|
APP_MISSING | 404 | Message not found in the chat |
APP_INTERNAL_ERROR | 500 | Internal retrieval failure |
Stream message response (SSE) (Share)
/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.
Rate limits: 5/3s, 20/10s, 100/60s, 700/hr.
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 Code | HTTP Status | Cause |
|---|---|---|
APP_MISSING | 404 | Message not found |
APP_ERROR_INPUT_INVALID | 400 | Message not in in_progress or complete state |
APP_MISSING | 404 | No SSE chunk data exists for this message |
APP_INTERNAL_ERROR | 500 | Internal streaming failure |
Publish a private chat (Share)
/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.
Rate limits: 1/1s, 5/10s, 10/60s, 50/hr, 200/day.
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 Code | HTTP Status | Cause |
|---|---|---|
APP_NOT_ACCEPTED | 406 | Chat not found or locked |
APP_CONFLICT | 409 | Chat is already public |
APP_ERROR_DATASTORE | 500 | Update failed |
Generate AI Share (Share)
/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.
Rate limits: 5/min, 100/hr (per user).
| Parameter | Type | Required | Description |
|---|---|---|---|
| files | array (JSON) | Yes | JSON 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"
}
| Field | Type | Description |
|---|---|---|
response.markdown | string | Generated markdown with file info and temporary download URLs |
Notes:
- Download URLs expire after 5 minutes (300 seconds)
- Each token can be used a maximum of 3 times
- Individual files limited to 50 MB; total size limited to 100 MB
- When more than 5 files: titles only. 5 or fewer: includes full descriptions.
- The
filesinput is a JSON array (not comma-separated strings)
Error responses:
| Error Code | HTTP Status | Cause |
|---|---|---|
APP_ERROR_INPUT_INVALID | 400 | Empty files array |
APP_ERROR_INPUT_INVALID | 400 | More than 25 files |
APP_DENIED | 403 | Insufficient download permissions |
Workspace AI vs. Share AI differences
| Feature | Workspace AI | Share AI |
|---|---|---|
| AI Transactions endpoint | Yes | No |
| Auto OG image endpoint | No | Yes |
| Auto title endpoint | No | Yes |
content_ai feature required | Yes (except AI Share) | Yes (except AI Share) |
| File scope context | Workspace files | Share files |
AI Share File Download
/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.
Rate limits: 60/min, 300/hr (per IP).
| Parameter | Type | Required | Description |
|---|---|---|---|
| {token} | string (path) | Yes | Alphanumeric AI share token (generated by the AI Share creation endpoint) |
| file | integer (query) | Yes | Zero-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 Code | HTTP Status | Cause |
|---|---|---|
APP_ERROR_NOT_FOUND | 404 | Token missing, invalid, expired, or use limit reached |
APP_ERROR_NOT_FOUND | 404 | File index out of range |
APP_INTERNAL_ERROR | 500 | Unable to retrieve or read file |
All invalid/expired token errors return 404 to prevent token enumeration.
Semantic Search
/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.
Workspace Semantic Search (Deprecated)
/current/workspace/{workspace_id}/ai/search/
Auth: Bearer token required. Workspace view permission. content_ai plan feature required.
Rate limits: 2/1s, 10/10s, 30/60s, 200/hr, 1000/day.
Share Semantic Search (Deprecated)
/current/share/{share_id}/ai/search/
Identical to workspace semantic search but scoped to a share.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| query_text | string | Yes | — | Search query, 2–1,000 characters |
| files_scope | string | No | All indexed files | Comma-separated nodeId:versionId pairs (max 100) |
| folders_scope | string | No | All indexed files | Comma-separated nodeId:depth pairs (max 100, depth 1–10) |
| limit | integer | No | 100 | Results per page, 1–500 |
| offset | integer | No | 0 | Pagination offset |
| details | string | No | false | When "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": "ready", "attach": true, "summary": true }
}
}
],
"pagination": {
"total": 25,
"limit": 10,
"offset": 0,
"has_more": true
}
}
| Field | Type | Description |
|---|---|---|
results[].content | string | Matched text snippet from the indexed document |
results[].score | float | Relevance score (0.0–1.0, higher is more relevant) |
results[].node | object/null | Full node resource, or null if the file was deleted |
results[].file_details | object | Raw metadata when node is null (node_id, version_id, name, mimetype) |
pagination.total | integer | Total number of results |
pagination.has_more | boolean | Whether 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:
| Field | Type | Description |
|---|---|---|
relevance_score | float | Semantic relevance score (0.0–1.0) |
content_snippet | string/null | The actual matching text from semantic search. NULL for keyword-only matches. |
match_source | string | Source of the match: keyword, semantic, or both |
mimetype | string | File MIME type (e.g., application/pdf, audio/mpeg). Present for semantic matches. |
media_segment | object | Only for audio/video matches when intelligence is on. Contains start_seconds and end_seconds for deep-linking to the exact timestamp range. |
search_metadata | object | Additional 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": "ready" }
}
}
}
}
}
Error responses:
| Error Code | HTTP Status | Cause |
|---|---|---|
APP_ERROR_INPUT_INVALID | 400 | Intelligence not enabled |
APP_ERROR_INPUT_INVALID | 400 | Malformed 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.
- Good: “What were the revenue figures for Q3 2025 compared to Q2?”
- Good: “Summarize the key findings from the compliance audit reports”
- Bad: “Tell me about these files” — too vague, no searchable content to match
With file attachments
You can be more direct since the AI has the full file content.
- Good: “Describe this image in detail” (with an image attached)
- Good: “Extract all action items from this meeting transcript”
- Good: “Compare these two contracts and list the differences”
Chat Session Object Schema
The chat resource is returned by details and list endpoints.
| Field | Type | Description |
|---|---|---|
chat_id | string | Opaque ID of the chat |
creator | object | {type: string, id: string} — the chat creator |
type | string | chat or chat_with_files |
name | string | Display name of the chat |
status | string | Current chat status |
message_count | integer | Total number of messages |
messages | array | Full message list (details endpoint) or omitted |
latest_message | object | Most recent message (list endpoint) or omitted |
unique_creators | array | Distinct participants as {type, id} objects |
cost | object | {credits: {tokens: int}} — total token cost |
efficiency | string | Efficiency rating |
privacy | object | {visibility: "private"|"public", owner: {type, id}|null} |
created_at | string | ISO 8601 creation timestamp |
updated_at | string | ISO 8601 last update timestamp |
Message Object Schema
| Field | Type | Description |
|---|---|---|
chat_id | string | Parent chat opaque ID |
message_id | string | Opaque ID of the message |
creator | object | {type: string, id: string} — message author |
personality | string | AI personality mode used (concise or detailed) |
state | string | Processing state: ready, in_progress, complete, errored |
message | object | User’s query (see sub-fields below) |
message.text | string | The question text |
message.author_name | string | User’s given name |
message.scope | object | File/folder scope used for RAG context |
message.attached | array | Attached files as {node_id, version_id} objects |
response | object/null | AI response (null if not yet available) |
response.text | string | AI response text |
response.error | boolean | Whether an error occurred during processing |
response.created | string | ISO 8601 response timestamp |
response.cost | object | {tokens: int, details: object} — message token cost |
response.author_name | string | AI persona name (e.g., Ripley) |
response.events | array | Status events generated during processing |
response.table_data | array | Structured table data in the response |
response.analysis_chunks | array | Analysis progress chunks |
response.citations | array | File citations (see below) |
Citation Format
Citations reference specific locations in files that informed the AI response.
| Field | Type | Description |
|---|---|---|
hash | string | File content hash (used for grouping) |
nodeId | string | Storage node opaque ID |
versionId | string | File version opaque ID |
entries | array | Citation locations within the file |
entries[].page | integer | Page number in the document |
entries[].snippet | string/null | Relevant text excerpt |
entries[].timestamp | float/null | Timestamp 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.
/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 Pattern | What 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 with plan-based limits (Free: 1, Pro: 1, Business: 10).
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.
Create a template
/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.
Rate limits: 10/min, 100/hr, 300/day.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Template name (1–255 characters) |
| description | string | Yes | Template description |
| category | string | Yes | Category (1–50 chars). Must be a valid category from the categories endpoint. |
| fields | string (JSON) | Yes | JSON-encoded array of field definitions |
Field definition structure:
| Property | Type | Description |
|---|---|---|
name | string | Field identifier (alphanumeric + underscore) |
description | string | Human-readable description |
type | string | string, int, float, bool, json, url, or datetime |
min | number | Minimum value/length constraint |
max | number | Maximum value/length constraint |
default | mixed | Default value |
fixed_list | array | Allowed values for dropdown-style fields |
can_be_null | boolean | Whether 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
/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.
Rate limits: 10/min, 100/hr, 300/day.
Error responses:
| Error Code | HTTP Status | Cause |
|---|---|---|
APP_MISSING | 404 | Template not found |
APP_DENIED | 403 | Cannot delete a system template |
APP_ERROR_DATASTORE | 500 | Deletion failed |
List templates
/current/workspace/{workspace_id}/metadata/templates/list/
Auth: Bearer token required. Workspace member. Metadata billing feature required.
Rate limits: 3/1s, 10/10s, 20/60s, 50/hr, 200/day.
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
/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.
Rate limits: 3/1s, 10/10s, 20/60s, 50/hr, 200/day.
Update template settings
/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.
Rate limits: 20/min, 100/hr, 500/day.
| Parameter | Type | Required | Description |
|---|---|---|---|
| enabled | string | Yes | "true" or "false" |
| priority | string | Yes | Priority level "1" through "5" |
Error responses:
| Error Code | HTTP Status | Cause |
|---|---|---|
APP_MISSING | 404 | Template not found |
APP_ERROR_NOT_FOUND | 404 | Template is deleted |
APP_DENIED | 403 | Template is locked |
APP_ERROR_DATASTORE | 500 | Update failed |
Update template definition
/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.
Rate limits: 10/min, 100/hr, 300/day.
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | No | Updated template name (1–255 characters) |
| description | string | No | Updated description (up to 1000 characters) |
| category | string | No | Updated category (1–50 characters) |
| fields | string (JSON) | No | Updated JSON-encoded array of field definitions |
Append /create/ to the path to copy the template instead of updating in place.
Template-Node Mapping
Templates have many-to-many relationships with files. Use these endpoints to manage which files are mapped to which templates.
Eligible files
/current/workspace/{workspace_id}/metadata/eligible/
Paginated list of files eligible for metadata extraction (files that have both an AI summary and a preview ready).
Auth: Bearer token required. Workspace member. Metadata billing feature required.
Rate limits: 10/min, 100/hr, 500/day.
| Parameter | Type | Required | Description |
|---|---|---|---|
| limit | integer | No | Number of items to return (1–500, default: 100) |
| offset | integer | No | Number of items to skip (default: 0) |
Add files to template
/current/workspace/{workspace_id}/metadata/templates/{template_id}/nodes/add/
Manually add files to a template. Creates the many-to-many mapping between the template and the specified files.
Auth: Bearer token required. Workspace member. Metadata billing feature required.
Rate limits: 10/min, 100/hr, 300/day.
| Parameter | Type | Required | Description |
|---|---|---|---|
| node_ids | string (JSON) | Yes | JSON-encoded array of node IDs to add to the template |
Remove files from template
/current/workspace/{workspace_id}/metadata/templates/{template_id}/nodes/remove/
Remove files from a template. Removes the many-to-many mapping between the template and the specified files.
Auth: Bearer token required. Workspace member. Metadata billing feature required.
Rate limits: 10/min, 100/hr, 300/day.
| Parameter | Type | Required | Description |
|---|---|---|---|
| node_ids | string (JSON) | Yes | JSON-encoded array of node IDs to remove from the template |
List files in template
/current/workspace/{workspace_id}/metadata/templates/{template_id}/nodes/
List all files currently mapped to a template.
Auth: Bearer token required. Workspace member. Metadata billing feature required.
Rate limits: 10/min, 100/hr, 500/day.
| Parameter | Type | Required | Description |
|---|---|---|---|
| limit | integer | No | Number of items to return (1–500, default: 100) |
| offset | integer | No | Number of items to skip (default: 0) |
Auto-match files to template
/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.
Auth: Bearer token required. Workspace member. Metadata billing feature required.
Rate limits: 2/min, 10/hr.
Batch extract metadata (template-level)
/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.
Rate limits: 2/min, 10/hr.
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
/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.
Rate limits: 5000/hr, 25000/day.
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": "12345678901234567890",
"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"
}
| Field | Type | Description |
|---|---|---|
response.template_id | string/null | Associated template ID, or null |
response.node_id | object | Storage node resource with file details |
response.metadata[].key | string | Metadata field key |
response.metadata[].type | string | Value type (string, int, float, bool, json, url, datetime) |
response.metadata[].value | mixed | The metadata value |
response.metadata[].is_auto | boolean | Whether the value was auto-generated by AI extraction |
response.metadata[].updated | string | Last update timestamp |
Update file metadata
/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.
Rate limits: 250/hr, 1000/day.
| Parameter | Type | Required | Description |
|---|---|---|---|
| key_values | string (JSON) | Yes | JSON-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
/current/workspace/{workspace_id}/storage/{node_id}/metadata/
Delete metadata keys from a file.
Auth: Bearer token required. Workspace member. Metadata billing feature required.
Rate limits: 20/min, 100/hr, 500/day.
| Parameter | Type | Required | Description |
|---|---|---|---|
| keys | string (JSON) | No | JSON-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)
/current/workspace/{workspace_id}/storage/{node_id}/metadata/extract/
AI-extracts metadata from a file using a specified template.
Auth: Bearer token required. Workspace member. Metadata billing feature required.
Rate limits: 10/min, 100/hr, 300/day.
| Parameter | Type | Required | Description |
|---|---|---|---|
| template_id | string | Yes | The template ID to extract metadata against |
Supports documents, spreadsheets, images (PNG, JPEG, WebP), and code files. Extraction is synchronous. Extracted values are stored with is_auto: true.
Error responses:
| Error Code | HTTP Status | Cause |
|---|---|---|
APP_ERROR_INPUT_INVALID | 400 | Node is root (use template-level extract-all for batch extraction) |
APP_ERROR_NOT_FOUND | 404 | Template not found |
APP_ERROR_NOT_FOUND | 404 | Node not found |
APP_ERROR_DATASTORE | 500 | Extraction failed |
List metadata by template
/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.
Rate limits: 100/min, 1000/hr, 3000/day.
| Parameter | Type | Required | Description |
|---|---|---|---|
| filters | string (JSON) | No | JSON-encoded filter criteria |
| order_by | string | No | Field key name to sort by |
| order_desc | string | No | "true" or "false" for descending sort |
List templates in use
/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.
Rate limits: 100/min, 400/hr, 1500/day.
Metadata versions
/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 views
Save, list, and delete custom views for metadata display.
Create/update a view
/current/workspace/{workspace_id}/storage/{node_id}/metadata/view/
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | View name (1–30 characters) |
| template_id | string | Yes | Template ID to associate |
| filters | string (JSON) | No | Filter criteria |
| order_by | string | No | Sort field |
| order_desc | string | No | "true" or "false" for descending |
Rate limits: 10/min, 200/hr, 500/day.
List views
/current/workspace/{workspace_id}/storage/{node_id}/metadata/views/
Rate limits: 50/min, 500/hr, 2000/day.
Delete a view
/current/workspace/{workspace_id}/storage/{node_id}/metadata/view/{view_id}/
Rate limits: 10/min, 200/hr, 500/day.
Template Resource Schema
| Field | Type | Description |
|---|---|---|
id | string | Opaque template identifier |
instanceId | string | Workspace ID |
orgId | string/null | Organization ID |
category | string | Template category |
name | string | Template name |
description | string | Template description |
locked | boolean | Whether the template is locked from editing |
priority | integer/null | Priority level 1–5, or null |
enabled | boolean | Whether enabled for the workspace |
deleted | string/null | Soft-delete timestamp, or null |
updated | string | Last updated timestamp |
created | string | Creation timestamp |
fields | array | Array of field definition objects |
Supported Field Types
| Type | Description |
|---|---|
string | Text values (max 10,000 characters) |
int | Integer numbers |
float | Decimal numbers |
bool | Boolean true/false |
json | Complex JSON structures |
url | Validated URLs |
datetime | Date 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
POST /current/workspace/{id}/storage/{node}/metadata/extract/
template_id={template_id}
List eligible files for metadata
GET /current/workspace/{id}/metadata/eligible/
Add files to a template
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.