> Part of the Fast.io API Reference. Overview: https://api.fast.io/current/llms/ # Events, Activity & Realtime Base URL: `https://api.fast.io/current/` Auth: All endpoints require `Authorization: Bearer {jwt_token}` unless noted. Response format: JSON (standard envelope with `result`, `status`, and data fields). --- ## Events Search Search and filter the event log. Events capture every action in the system -- file operations, membership changes, comments, AI activity, billing, workflow, and more. --- ### `GET /current/events/search/` Search and filter events with comprehensive filtering options. Uses offset-based pagination. **Auth:** Required (JWT). Rate limited: 5 per 3s, 15 per 30s, 120 per 10min (shared rate limit). **Query Parameters:** | Parameter | Type | Required | Default | Constraints | Description | |-----------|------|----------|---------|-------------|-------------| | `user_id` | string | Conditional | - | 20-digit numeric ID | Filter by user profile ID. One of `user_id`, `org_id`, `workspace_id`, `share_id`, or `parent_event_id` is required. | | `org_id` | string | Conditional | - | 20-digit numeric ID | Filter by organization profile ID | | `workspace_id` | string | Conditional | - | 20-digit numeric ID | Filter by workspace profile ID | | `share_id` | string | Conditional | - | 20-digit numeric ID | Filter by share profile ID | | `parent_event_id` | string | Conditional | - | Alphanumeric OpaqueId | Filter by parent event ID for serial/batch events. Cannot combine with filters other than `acknowledged`, `limit`, `offset`. | | `event` | string | No | - | Max 100 characters | Filter by specific event name (e.g., `workspace_storage_file_added`) | | `category` | string | No | - | See Event Categories | Filter by event category | | `subcategory` | string | No | - | See Event Subcategories | Filter by event subcategory | | `calling_user_id` | string | No | - | 20-digit numeric ID | Filter by the user who triggered the event | | `object_id` | string | No | - | Alphanumeric OpaqueId | Filter by related object ID (file, folder, etc.) | | `acknowledged` | string | No | - | `"true"` or `"false"` | Filter by acknowledgment status | | `visibility` | string | No | All non-internal | `"external_audit_log"` or `"external"` | Filter by event visibility level | | `created-min` | string | No | - | ISO 8601 datetime (e.g., `2025-12-01T06:00:00Z`, `2025-12-01 06:00:00.000000 UTC`) | Lower bound for event creation time | | `created-max` | string | No | - | ISO 8601 datetime; must be > `created-min` | Upper bound for event creation time | | `limit` | integer | No | `100` | 1-250 | Maximum number of results | | `offset` | integer | No | `0` | 0+ | Number of results to skip for pagination | **Profile filter priority:** If multiple profile filters are supplied, priority is: `user_id` > `org_id` > `workspace_id` > `share_id`. Only the highest-priority filter is applied. **curl Example:** ```bash curl -X GET "https://api.fast.io/current/events/search/?workspace_id=12345678901234567890&category=workspace&subcategory=storage&limit=50" \ -H "Authorization: Bearer {jwt_token}" ``` **Response (200 OK):** ```json { "result": "yes", "response": { "events": [ { "event_id": "evt_abc123xyz789", "created": "2025-01-20 10:30:45", "acknowledged": false, "event": "workspace_storage_file_added", "category": "workspace", "subcategory": "storage", "object_id": "node_def456ghi789", "calling_user_id": "98765432109876543210", "calling_user_name": "Jane Smith", "org_id": "11111111111111111111", "workspace_id": "12345678901234567890", "filename": "quarterly_report.pdf", "file_size": 2485760 } ] } } ``` **Response Fields:** | Field | Type | Description | |-------|------|-------------| | `result` | string | `"yes"` on success | | `response.events` | array | Array of event objects | | `response.events[].event_id` | string | Unique event identifier (alphanumeric OpaqueId) | | `response.events[].created` | string | Event timestamp in `Y-m-d H:i:s` format | | `response.events[].acknowledged` | boolean | Whether the current user has acknowledged this event | | `response.events[].event` | string | Event name identifier (e.g., `workspace_storage_file_added`) | | `response.events[].category` | string | Event category name | | `response.events[].subcategory` | string | Event subcategory name | | `response.events[].object_id` | string | Related object OpaqueId (if applicable) | | `response.events[].calling_user_id` | string | 20-digit numeric ID of the triggering user | | `response.events[].calling_user_name` | string | Display name of the triggering user | | `response.events[].org_id` | string | Organization ID context (if applicable) | | `response.events[].workspace_id` | string | Workspace ID context (if applicable) | | `response.events[].share_id` | string | Share ID context (if applicable) | | `response.events[].user_id` | string | Target user ID for user-specific events (if applicable) | Additional event-specific fields (e.g., `filename`, `file_size`, `member_name`) vary by event type. **Error Responses:** | Error Code | HTTP Status | Description | |------------|-------------|-------------| | `APP_ERROR_INPUT_INVALID` | 406 | No profile filter or `parent_event_id` provided ("Event profile was missing.") | | `APP_ERROR_INPUT_INVALID` | 406 | `created-min` is greater than `created-max` | | `APP_ERROR_INPUT_INVALID` | 406 | `parent_event_id` combined with disallowed filters | | `APP_ERROR_INPUT_INVALID` | 406 | Invalid datetime format for `created-min` or `created-max` | | `APP_DENIED` | 403 | Token scope does not include the requested profile | | `APP_ERROR_QUERY_ERROR` | 500 | Internal error during event search | | `APP_AUTH_INVALID` | 401 | Missing or invalid JWT token | | `APP_REQUEST_TYPE` | 400 | Wrong HTTP method (only GET accepted) | **Notes:** - Results may be slightly delayed due to caching. - OAuth scoped tokens enforce entity-level access: events are filtered to only entities within the token's scope. - Events the user cannot access are automatically excluded. --- ### `GET /current/events/search/summarize/` Search events and generate an AI-powered natural language summary. Accepts all parameters from `/events/search/` plus `user_context`. **Auth:** Required (JWT). Rate limited: shares the search rate limit. **Additional Query Parameters:** | Parameter | Type | Required | Default | Constraints | Description | |-----------|------|----------|---------|-------------|-------------| | `user_context` | string | No | `""` | Max 64 chars; letters, numbers, spaces, `. , ! ? ' -` only | Focus guidance for the AI summary (e.g., `"Focus on uploads"`) | All other parameters are identical to `GET /current/events/search/`. **curl Example:** ```bash curl -X GET "https://api.fast.io/current/events/search/summarize/?workspace_id=12345678901234567890&user_context=Focus%20on%20file%20uploads&limit=100" \ -H "Authorization: Bearer {jwt_token}" ``` **Response (200 OK):** ```json { "result": "yes", "response": { "summary": { "text": "@[user:98765432109876543210:Jane Smith] uploaded 12 files to the project folder, including quarterly reports and design assets. @[user:55555555555555555555:John Doe] added 3 new members to the workspace.", "metrics": { "total_events": 50, "unique_actors": 5, "date_range": { "start": "2025-01-01T00:00:00+00:00", "end": "2025-01-20T10:30:45+00:00" }, "categories": { "storage": 30, "members": 20 } } }, "events": [ ... ] } } ``` **Response Fields (additional to events search):** | Field | Type | Description | |-------|------|-------------| | `response.summary` | object or null | AI-generated summary, or `null` if no events or generation failed | | `response.summary.text` | string | Natural language summary with `@[type:ID:name]` mention pills | | `response.summary.metrics.total_events` | integer | Total events summarized | | `response.summary.metrics.unique_actors` | integer | Distinct users who triggered events | | `response.summary.metrics.date_range.start` | string | ISO 8601 timestamp of earliest event | | `response.summary.metrics.date_range.end` | string | ISO 8601 timestamp of most recent event | | `response.summary.metrics.categories` | object | Map of category names to event counts | **Summary Mention Pill Formats:** | Entity | Format | Example | |--------|--------|---------| | User | `@[user:USER_ID:Display Name]` | `@[user:98765432109876543210:Jane Smith]` | | File | `@[file:FILE_ID:filename.ext]` | `@[file:node_abc123:report.pdf]` | | Folder | `@[folder:FOLDER_ID:foldername]` | `@[folder:node_def456:Projects]` | | Workspace | `@[workspace:WS_ID:name]` | `@[workspace:12345678901234567890:Engineering]` | | Share | `@[share:SHARE_ID:name]` | `@[share:55555555555555555555:Client Files]` | **Error Responses:** All errors from `/events/search/` apply. Summary generation failures are non-fatal: `summary` is `null` but events are still returned. **Notes:** - Requires a billable organization for AI token billing (resolved from profile context). - AI token consumption is billed to the associated organization. --- ### `GET /current/event/{event_id}/details/` Get full details for a single event. **Auth:** Required (JWT). Default rate limiting. **Path Parameters:** | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `{event_id}` | string | Yes | Alphanumeric OpaqueId of the event | **curl Example:** ```bash curl -X GET "https://api.fast.io/current/event/evt_abc123xyz789/details/" \ -H "Authorization: Bearer {jwt_token}" ``` **Response (200 OK):** ```json { "result": "yes", "response": { "event": { "event_id": "evt_abc123xyz789", "created": "2025-01-20 10:30:45", "acknowledged": false, "event": "workspace_storage_file_added", "category": "workspace", "subcategory": "storage", "object_id": "node_def456ghi789", "calling_user_id": "98765432109876543210", "calling_user_name": "Jane Smith", "org_id": "11111111111111111111", "workspace_id": "12345678901234567890", "filename": "quarterly_report.pdf", "file_size": 2485760 } } } ``` **Response Fields:** | Field | Type | Description | |-------|------|-------------| | `result` | string | `"yes"` on success | | `response.event` | object | Full event object (same fields as event search results) | **Access Rules:** | Condition | Access | |-----------|--------| | User is the `calling_user` | Granted | | User is the `event_user` (target) | Granted | | Event has `targeted` permission and user is neither target nor caller | Denied | | Event is `internal` visibility | Always denied | | User has appropriate profile-level permissions | Granted based on permission level | **Error Responses:** | Error Code | HTTP Status | Description | |------------|-------------|-------------| | `APP_ERROR_INPUT_INVALID` | 400 | Event ID missing, empty, or not a valid OpaqueId | | `APP_ERROR_NOT_FOUND` | 404 | No event exists with the provided ID | | `APP_ERROR_INPUT_INVALID` | 400 | Event has `internal` visibility | | `APP_ERROR_INPUT_INVALID` | 400 | User lacks permission (targeted event) | | `APP_AUTH_INVALID` | 401 | Missing or invalid JWT token | | `APP_REQUEST_TYPE` | 400 | Wrong HTTP method (only GET accepted) | --- ### `GET /current/event/{event_id}/ack/` Acknowledge (mark as read) an event for the current user. Idempotent: acknowledging an already-acknowledged event succeeds silently. **Auth:** Required (JWT). Default rate limiting. **Path Parameters:** | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `{event_id}` | string | Yes | Alphanumeric OpaqueId of the event to acknowledge | **curl Example:** ```bash curl -X GET "https://api.fast.io/current/event/evt_abc123xyz789/ack/" \ -H "Authorization: Bearer {jwt_token}" ``` **Response (200 OK):** ```json { "result": "yes" } ``` **Error Responses:** | Error Code | HTTP Status | Description | |------------|-------------|-------------| | `APP_ERROR_INPUT_INVALID` | 400 | Event ID missing or invalid | | `APP_ERROR_NOT_FOUND` | 404 | Event not found | | `APP_ERROR_INPUT_INVALID` | 400 | Event has `internal` visibility | | `APP_ERROR_INPUT_INVALID` | 400 | User lacks permission (targeted event) | | `APP_ERROR_DATASTORE` | 500 | Failed to persist the acknowledgment | | `APP_AUTH_INVALID` | 401 | Missing or invalid JWT token | **Notes:** - Acknowledgment is per-user. Acknowledging for one user does not affect others. - Same access rules as event details apply. --- ## Event Categories | Category | API Value | Description | |----------|-----------|-------------| | Upload | `upload` | File upload operations | | User | `user` | User account events | | Organization | `org` | Organization events | | Workspace | `workspace` | Workspace operations | | Share | `share` | Share operations | | AI | `ai` | AI/ML operations | | Invitation | `invitation` | Invitation events | | Email | `email` | Email-related events | | Billing | `billing` | Billing and subscription events | | Metadata | `metadata` | Metadata operations | | Domain | `domain` | Custom domain events | | Apps | `apps` | Application/integration events | | Workflow | `workflow` | Workflow events (task lists, tasks, worklogs, approvals, todos) | --- ## Event Subcategories | Subcategory | API Value | Description | |-------------|-----------|-------------| | Storage | `storage` | File and folder operations | | Comments | `comments` | Comment activity | | Members | `members` | Membership changes | | Lifecycle | `lifecycle` | Create, update, delete, archive events | | Settings | `settings` | Configuration changes | | Security | `security` | Security-related events | | Authentication | `authentication` | Login and auth events | | AI | `ai` | AI processing events | | Invitations | `invitations` | Invitation management | | Billing | `billing` | Subscription and payment | | Assets | `assets` | Asset (avatar, branding) updates | | Upload | `upload` | Upload events | | Transfer | `transfer` | Ownership transfer events | | Import/Export | `import_export` | Import/export operations | | Quick Share | `quickshare` | Quick share events | | Metadata | `metadata` | Metadata operations | | Workflow | `workflow` | Workflow events | --- ## Event Visibility Levels | Visibility | API Value | Description | |------------|-----------|-------------| | Internal | `internal` | System events. Never accessible via API. | | Audit Log | `external_audit_log` | Audit/compliance events. Targeted permission checks bypassed for admins. | | External | `external` | Standard user-facing events. | Default (no `visibility` parameter): returns both `external_audit_log` and `external` events, excludes `internal`. --- ## Event Permission Levels | Permission | Description | |------------|-------------| | `member` | Any member of the profile can view | | `admin` | Only admins of the profile can view | | `targeted` | Only the target user or the calling user can view | When querying with `visibility=external_audit_log`, targeted permission checks are bypassed. --- ## Event Names Reference ### Workspace Storage - `workspace_storage_file_added` -- File uploaded - `workspace_storage_file_deleted` -- File trashed - `workspace_storage_file_moved` -- File moved - `workspace_storage_file_copied` -- File copied - `workspace_storage_file_updated` -- File metadata updated - `workspace_storage_file_restored` -- File restored from trash - `workspace_storage_file_version_restored` -- File version restored - `workspace_storage_folder_created` -- Folder created - `workspace_storage_folder_deleted` -- Folder trashed - `workspace_storage_folder_moved` -- Folder moved - `workspace_storage_download_token_created` -- Download token issued - `workspace_storage_zip_downloaded` -- ZIP download completed - `workspace_storage_link_added` -- Link added ### Share Storage - `share_storage_file_added` -- File uploaded - `share_storage_file_deleted` -- File trashed - `share_storage_file_moved` -- File moved - `share_storage_file_copied` -- File copied - `share_storage_file_updated` -- File metadata updated - `share_storage_file_restored` -- File restored - `share_storage_folder_created` -- Folder created - `share_storage_folder_deleted` -- Folder trashed - `share_storage_folder_moved` -- Folder moved - `share_storage_download_token_created` -- Download token issued - `share_storage_zip_downloaded` -- ZIP download completed ### Comments - `comment_created` -- Comment created - `comment_updated` -- Comment updated - `comment_deleted` -- Comment deleted - `comment_mentioned` -- User mentioned in comment (targeted permission) - `comment_replied` -- Reply to a comment - `comment_reaction` -- Reaction added ### Membership - `added_member_to_org` / `removed_member_from_org` -- Org membership - `added_member_to_workspace` / `removed_member_from_workspace` -- Workspace membership - `added_member_to_share` / `removed_member_from_share` -- Share membership - `membership_updated` -- Permission changes ### Workspace Lifecycle - `workspace_created` / `workspace_updated` / `workspace_deleted` - `workspace_archived` / `workspace_unarchived` ### Share Lifecycle - `share_created` / `share_updated` / `share_deleted` - `share_archived` / `share_unarchived` - `share_imported_to_workspace` -- Share imported into workspace ### AI - `ai_chat_created` / `ai_chat_updated` / `ai_chat_deleted` -- Chat lifecycle - `ai_chat_new_message` -- New AI chat message - `ai_chat_published` -- Chat published - `node_ai_summary_created` -- AI summary generated for a file - `workspace_ai_share_created` -- AI share created in workspace ### Metadata - `metadata_kv_update` / `metadata_kv_delete` / `metadata_kv_extract` - `metadata_template_update` / `metadata_template_delete` / `metadata_template_select` - `metadata_view_update` / `metadata_view_delete` ### Quick Shares - `workspace_quickshare_created` / `workspace_quickshare_updated` / `workspace_quickshare_deleted` - `workspace_quickshare_file_downloaded` / `workspace_quickshare_file_previewed` ### Invitations - `invitation_email_sent` / `invitation_accepted` / `invitation_declined` ### User - `user_created` / `user_updated` / `user_deleted` - `user_email_reset` / `user_asset_updated` ### Organization - `org_created` / `org_updated` / `org_closed` - `org_transfer_token_created` / `org_transfer_completed` ### Billing - `subscription_created` / `subscription_cancelled` - `billing_free_trial_ended` ### Workflow - `task_list_created` / `task_list_updated` / `task_list_deleted` - `task_created` / `task_updated` / `task_deleted` - `task_status_changed` / `task_assigned` / `task_completed` - `worklog_entry_created` - `worklog_interjection_created` / `worklog_interjection_acknowledged` - `approval_requested` / `approval_approved` / `approval_rejected` - `todo_created` / `todo_toggled` / `todo_deleted` / `todo_updated` --- ## Event Search Examples **Recent comments in a workspace:** ``` GET /current/events/search/?workspace_id={id}&subcategory=comments ``` **File uploads to a share in a date range:** ``` GET /current/events/search/?share_id={id}&event=share_storage_file_added&created-min=2025-12-01T06:00:00Z ``` **Membership changes in an org:** ``` GET /current/events/search/?org_id={id}&subcategory=members ``` **AI activity in a workspace:** ``` GET /current/events/search/?workspace_id={id}&category=ai ``` **Unacknowledged events for a user:** ``` GET /current/events/search/?user_id={id}&acknowledged=false ``` **Audit log events only:** ``` GET /current/events/search/?workspace_id={id}&visibility=external_audit_log&limit=100 ``` **Child events of a batch operation:** ``` GET /current/events/search/?parent_event_id=evt_abc123xyz789&limit=100 ``` **Workflow activity in a workspace:** ``` GET /current/events/search/?workspace_id={id}&category=workflow ``` --- ## Activity Polling Long-poll endpoints for efficient change detection. The server holds the connection open and returns immediately when something changes, avoiding expensive resource polling. --- ### `GET /current/activity/poll/` Poll for activity updates on the current user's profile. **Auth:** Required (JWT). Rate limited: 200 per 60s, 1000 per hour. **Query Parameters:** | Parameter | Type | Required | Default | Constraints | Description | |-----------|------|----------|---------|-------------|-------------| | `wait` | integer | No | `0` | 0-95 | Long-poll timeout in seconds. Server holds connection open until update or timeout. | | `lastactivity` | string | No | Current time | Micro-precision datetime (e.g., `2025-01-20 10:30:45.123456`) | Only return activity newer than this timestamp | | `updated` | any | No | - | Any value = enabled | If present, only return activity fields updated since `lastactivity` | | `fields` | string | No | All fields | Comma-delimited; max 30 fields | Activity field names to check. Supports ID qualifier via colon (e.g., `storage:12345`). | **curl Example:** ```bash curl -X GET "https://api.fast.io/current/activity/poll/?wait=30&lastactivity=2025-01-20%2010:30:45.123456" \ -H "Authorization: Bearer {jwt_token}" ``` **Response (200 OK -- activity found):** ```json { "result": "yes", "response": { "results": 3, "activity": { "storage": "2025-01-20 10:30:45.123456 UTC", "members": "2025-01-20 09:15:22.654321 UTC", "settings": "2025-01-19 14:00:00.000000 UTC" }, "lastactivity": "2025-01-20 10:30:45.123456 UTC" } } ``` **Response (200 OK -- no activity):** ```json { "result": "yes", "response": { "results": 0, "activity": [] } } ``` **Response Fields:** | Field | Type | Description | |-------|------|-------------| | `result` | string | `"yes"` on success | | `response.results` | integer | Number of activity fields returned | | `response.activity` | object | Map of activity field names to micro-precision UTC timestamps | | `response.lastactivity` | string | Most recent timestamp; pass as `lastactivity` in next poll | **Error Responses:** | Error Code | HTTP Status | Description | |------------|-------------|-------------| | `APP_ERROR_INPUT_INVALID` | 400 | Invalid profile ID format | | `APP_ERROR_INPUT_INVALID` | 400 | User lacks permissions for the specified profile | | `APP_ERROR_INPUT_INVALID` | 400 | Invalid field names or more than 30 fields | | `APP_ERROR_OBJECT_INIT` | 500 | Internal error | | `APP_AUTH_INVALID` | 401 | Missing or invalid JWT token | --- ### `GET /current/activity/poll/{profile_id}/` Poll for activity updates on a specific workspace, share, or org. **Auth:** Required (JWT). Same rate limits and parameters as `GET /current/activity/poll/`. **Path Parameters:** | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `{profile_id}` | string | Yes | 20-digit numeric profile ID (org, workspace, or share). For upload progress, use your user ID. | **Access Requirements:** | Profile Type | Permission Required | |--------------|-------------------| | User (self) | Authenticated | | Organization | `PERM_VIEW` on the org | | Workspace | `PERM_VIEW` on the workspace | | Share | Share view permissions + multiplayer enabled | **curl Example:** ```bash curl -X GET "https://api.fast.io/current/activity/poll/12345678901234567890/?wait=30&fields=storage,members&updated=1&lastactivity=2025-01-20%2010:30:45.123456" \ -H "Authorization: Bearer {jwt_token}" ``` Response format is identical to `GET /current/activity/poll/`. --- ### Polling Workflow 1. Make initial poll request (no `lastactivity` parameter) 2. Receive response with `activity` fields and `lastactivity` timestamp 3. Process changes by fetching updated resources based on activity field names 4. Make next poll with `lastactivity` from previous response 5. Repeat -- server returns immediately on change, or after `wait` seconds timeout ### Activity Key Patterns | Key Pattern | What Changed | |-------------|-------------| | `storage:{fileId}` | File added, updated, or removed | | `preview:{fileId}` | File preview/thumbnail is ready | | `ai_chat:{chatId}` | AI chat message updated | | `comments:{nodeId}` | Comment added or updated | | `member:{userId}` | Membership changed | ### Anti-Patterns - **Do NOT** loop on resource detail endpoints to wait for previews or processing. - **Instead**, poll on the workspace/share and watch for the relevant activity key. - **For uploads**, use your user ID as the `profile_id` since upload progress is tied to the user, not a workspace. --- ## WebSocket (Real-Time) Optional real-time delivery (~300ms latency vs ~1s for polling). Provides the same data as activity polling but pushed immediately via WebSocket. --- ### `GET /current/websocket/auth/{profile_id}` Generate a WebSocket authentication JWT for a specific profile. Tokens are valid for 24 hours. **Auth:** Required (JWT). No credit consumption. **Path Parameters:** | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `{profile_id}` | string | Yes | 20-digit numeric ID of the user, org, workspace, or share to subscribe to | **curl Example:** ```bash curl -X GET "https://api.fast.io/current/websocket/auth/12345678901234567890" \ -H "Authorization: Bearer {jwt_token}" ``` **Response (200 OK):** ```json { "result": "yes", "response": { "expires_in": 86400, "auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }, "current_api_version": "1.0" } ``` **Response Fields:** | Field | Type | Description | |-------|------|-------------| | `result` | string | `"yes"` on success | | `response.expires_in` | integer | Token lifetime in seconds (86400 = 24 hours) | | `response.auth_token` | string | Signed JWT with `websocket` scope, bound to the requested profile | **Access Requirements:** | Profile Type | Permission Required | |--------------|-------------------| | User (self) | None beyond authentication | | Organization | `PERM_VIEW` on the org | | Workspace | `PERM_VIEW` on the workspace | | Share | `canViewShareDetails` | **Error Responses:** | Error Code | HTTP Status | Description | |------------|-------------|-------------| | `APP_ERROR_INPUT_INVALID` | 400 | No profile ID provided or invalid format | | `APP_ERROR_INPUT_INVALID` | 400 | Profile type unsupported, not found, or user lacks permissions | | `APP_AUTH_INVALID` | 401 | Missing or invalid JWT, or internal JWT generation failure | --- ### WebSocket Connection Connect to: `wss://{host}/api/websocket/?token={auth_token}` Where `{auth_token}` is the JWT returned from the auth endpoint above. ### WebSocket Message Format The server pushes JSON messages when resources change: ```json { "response": "activity", "activity": ["storage:2abc...", "preview:2abc..."] } ``` The `activity` array contains the same activity key patterns as the polling endpoint. Fetch only the resources that have changed. ### WebSocket Fallback If the WebSocket connection drops, fall back to long-polling (`GET /current/activity/poll/{profile_id}/`). The data is identical, with slightly higher latency (~1s vs ~300ms). --- ## Realtime Auth (Collaborative Rooms) Separate from WebSocket activity channels, these endpoints provide authentication for collaborative editing rooms. --- ### `GET /current/realtime/auth/{room_id}` Generate a realtime JWT for a workspace or share collaborative room. Tokens are valid for 24 hours. **Auth:** Required (JWT). Not rate limited. No credit consumption. **Path Parameters:** | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `{room_id}` | string | Yes | 20-digit numeric ID of the workspace or share to join | **curl Example:** ```bash curl -X GET "https://api.fast.io/current/realtime/auth/12345678901234567890" \ -H "Authorization: Bearer {jwt_token}" ``` **Response (200 OK):** ```json { "result": "yes", "response": { "expires_in": 86400, "auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }, "current_api_version": "1.0" } ``` **Response Fields:** | Field | Type | Description | |-------|------|-------------| | `result` | string | `"yes"` on success | | `response.expires_in` | integer | Token lifetime in seconds (86400 = 24 hours) | | `response.auth_token` | string | Signed JWT with `realtime` scope, bound to the requested room | **Access Requirements:** | Profile Type | Permission Required | |--------------|-------------------| | Workspace | At least `PERM_VIEW` | | Share | `canViewShareDetails` + multiplayer enabled | **Error Responses:** | Error Code | HTTP Status | Description | |------------|-------------|-------------| | `APP_ERROR_INPUT_INVALID` | 400 | Missing room ID | | `APP_ERROR_INPUT_INVALID` | 400 | Room ID is not numeric | | `APP_ERROR_INPUT_INVALID` | 400 | Room ID does not correspond to a workspace or share | | `APP_DENIED` | 403 | User lacks permissions on the room | | `APP_AUTH_INVALID` | 401 | Missing or invalid JWT, or internal JWT generation failure | **Notes:** - Only workspace and share profile types are accepted as room IDs. --- ### `GET /current/realtime/auth/validate/` Validate a realtime JWT and extract the room ID. Intended for backend services to verify tokens. **Auth:** Bearer token in Authorization header (the realtime JWT to validate, not a user JWT). **curl Example:** ```bash curl -X GET "https://api.fast.io/current/realtime/auth/validate/" \ -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ``` **Response (200 OK):** ```json { "result": "yes", "response": { "room_id": "12345678901234567890" }, "current_api_version": "1.0" } ``` **Response Fields:** | Field | Type | Description | |-------|------|-------------| | `result` | string | `"yes"` on success | | `response.room_id` | string | The workspace or share profile ID the token is bound to | **Error Responses:** | Error Code | HTTP Status | Description | |------------|-------------|-------------| | `APP_AUTH_INVALID` | 401 | Missing Authorization header | | `APP_ERROR_INPUT_INVALID` | 400 | Malformed Authorization header | | `APP_ERROR_INPUT_INVALID` | 400 | Authorization header does not use Bearer scheme | | `APP_ERROR_INPUT_INVALID` | 400 | Bearer keyword present but no token follows | | `APP_ERROR_INPUT_INVALID` | 400 | Token is not valid JWT format | | `APP_DENIED` | 403 | Token signature verification or expiration check failed | | `APP_ERROR_GENERAL` | 500 | Token payload is malformed or missing required fields | | `APP_ERROR_INPUT_INVALID` | 400 | Token scope is not `realtime` | **Notes:** - Only validates tokens with `realtime` scope. WebSocket-scoped tokens are rejected. - Validation is performed using the JWT alone.