Events & Activity Event search, activity polling, WebSocket realtime, and webhooks.

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

Events capture every action in the system — file operations, membership changes, comments, AI activity, billing, workflow, and more. Use the event search endpoints to query the log, activity polling for efficient change detection, and WebSocket for real-time delivery.

Search and filter the event log. Events capture every action in the system — file operations, membership changes, comments, AI activity, billing, workflow, and more.

Search Events

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 channel events_search).

Query Parameters

ParameterTypeRequiredDefaultDescription
user_id string Conditional 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 Filter by organization profile ID
workspace_id string Conditional Filter by workspace profile ID
share_id string Conditional Filter by share profile ID
parent_event_id string Conditional Filter by parent event ID for serial/batch events. Cannot combine with filters other than acknowledged, limit, offset.
event string No Filter by specific event name (e.g., workspace_storage_file_added). Max 100 characters.
category string No Filter by event category. See Event Categories.
subcategory string No Filter by event subcategory. See Event Subcategories.
calling_user_id string No Filter by the user who triggered the event (20-digit numeric ID)
object_id string No Filter by related object ID (file, folder, etc.)
acknowledged string No Filter by acknowledgment status: "true" or "false"
visibility string No All non-internal "external_audit_log" or "external"
created-min string No Lower bound for event creation time (ISO 8601, e.g., 2025-12-01T06:00:00Z)
created-max string No Upper bound for event creation time (ISO 8601; must be > created-min)
limit integer No 100 Maximum number of results (1–250)
offset integer No 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.

Example Request

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)

{
  "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

FieldTypeDescription
resultstring"yes" on success
response.eventsarrayArray of event objects
response.events[].event_idstringUnique event identifier (alphanumeric OpaqueId)
response.events[].createdstringEvent timestamp in Y-m-d H:i:s format
response.events[].acknowledgedbooleanWhether the current user has acknowledged this event
response.events[].eventstringEvent name identifier (e.g., workspace_storage_file_added)
response.events[].categorystringEvent category name
response.events[].subcategorystringEvent subcategory name
response.events[].object_idstringRelated object OpaqueId (if applicable)
response.events[].calling_user_idstring20-digit numeric ID of the triggering user
response.events[].calling_user_namestringDisplay name of the triggering user
response.events[].org_idstringOrganization ID context (if applicable)
response.events[].workspace_idstringWorkspace ID context (if applicable)
response.events[].share_idstringShare ID context (if applicable)
response.events[].user_idstringTarget 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 CodeHTTP StatusDescription
APP_ERROR_INPUT_INVALID400No profile filter or parent_event_id provided
APP_ERROR_INPUT_INVALID400created-min is greater than created-max
APP_ERROR_INPUT_INVALID400parent_event_id combined with disallowed filters
APP_DENIED403Token scope does not include the requested profile
APP_ERROR_QUERY_ERROR500Internal database error during event search
APP_AUTH_INVALID401Missing or invalid JWT token
APP_REQUEST_TYPE400Wrong HTTP method (only GET accepted)

Notes: Results are cached for 10 seconds with automatic invalidation when new events are committed. OAuth scoped tokens enforce entity-level access: events are filtered to only entities within the token's scope. Post-query permission filtering silently excludes events the user cannot access.


Summarize Events (AI)

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). Shares the events_search rate limit channel.

Additional Query Parameters

ParameterTypeRequiredDefaultDescription
user_context string No "" Focus guidance for the AI summary (e.g., "Focus on uploads"). Max 64 chars; letters, numbers, spaces, . , ! ? ' - only.

All other parameters are identical to Search Events.

Example Request

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)

{
  "result": "yes",
  "response": {
    "summary": {
      "text": "@[user:98765432109876543210:Jane Smith] uploaded 12 files...",
      "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)

FieldTypeDescription
response.summaryobject|nullAI-generated summary, or null if no events or generation failed
response.summary.textstringNatural language summary with @[type:ID:name] mention pills
response.summary.metrics.total_eventsintegerTotal events summarized
response.summary.metrics.unique_actorsintegerDistinct users who triggered events
response.summary.metrics.date_range.startstringISO 8601 timestamp of earliest event
response.summary.metrics.date_range.endstringISO 8601 timestamp of most recent event
response.summary.metrics.categoriesobjectMap of category names to event counts

Summary Mention Pill Formats

EntityFormatExample
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]

Notes: Summary generation failures are non-fatal: summary is null but events are still returned. Requires a billable organization for AI token billing (resolved from profile context).


Event Details

GET /current/event/{event_id}/details/

Get full details for a single event.

Auth: Required (JWT). Default rate limiting. Credit limit checks are skipped.

Path Parameters

ParameterTypeRequiredDescription
{event_id} string Yes Alphanumeric OpaqueId of the event

Example Request

curl -X GET "https://api.fast.io/current/event/evt_abc123xyz789/details/" \
  -H "Authorization: Bearer {jwt_token}"

Response (200 OK)

{
  "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
    }
  }
}

Access Rules

ConditionAccess
User is the calling_userGranted
User is the event_user (target)Granted
Event has targeted permission and user is neither target nor callerDenied
Event is internal visibilityAlways denied
User has appropriate profile-level permissionsGranted based on permission level

Error Responses

Error CodeHTTP StatusDescription
APP_ERROR_INPUT_INVALID400Event ID missing, empty, or not a valid OpaqueId
APP_ERROR_NOT_FOUND404No event exists with the provided ID
APP_ERROR_INPUT_INVALID400Event has internal visibility
APP_ERROR_INPUT_INVALID400User lacks permission (targeted event)
APP_AUTH_INVALID401Missing or invalid JWT token
APP_REQUEST_TYPE400Wrong HTTP method (only GET accepted)

Acknowledge Event

GET /current/event/{event_id}/ack/

Acknowledge (mark as read) an event for the current user. Idempotent.

Auth: Required (JWT). Default rate limiting.

Path Parameters

ParameterTypeRequiredDescription
{event_id} string Yes Alphanumeric OpaqueId of the event to acknowledge

Example Request

curl -X GET "https://api.fast.io/current/event/evt_abc123xyz789/ack/" \
  -H "Authorization: Bearer {jwt_token}"

Response (200 OK)

{
  "result": "yes"
}

Error Responses

Error CodeHTTP StatusDescription
APP_ERROR_INPUT_INVALID400Event ID missing or invalid
APP_ERROR_NOT_FOUND404Event not found
APP_ERROR_INPUT_INVALID400Event has internal visibility
APP_ERROR_INPUT_INVALID400User lacks permission (targeted event)
APP_ERROR_DATASTORE500Failed to persist the acknowledgment
APP_AUTH_INVALID401Missing or invalid JWT token

Note: Acknowledgment is per-user. Acknowledging for one user does not affect others. Same access rules as event details apply.

Event Categories

CategoryAPI ValueDescription
UploaduploadFile upload operations
UseruserUser account events
OrganizationorgOrganization events
WorkspaceworkspaceWorkspace operations
ShareshareShare operations
AIaiAI/ML operations
InvitationinvitationInvitation events
EmailemailEmail-related events
BillingbillingBilling and subscription events
MetadatametadataMetadata operations
DomaindomainCustom domain events
AppsappsApplication/integration events
WorkflowworkflowWorkflow events (task lists, tasks, worklogs, approvals, todos)

Event Subcategories

SubcategoryAPI ValueDescription
StoragestorageFile and folder operations
CommentscommentsComment activity
MembersmembersMembership changes
LifecyclelifecycleCreate, update, delete, archive events
SettingssettingsConfiguration changes
SecuritysecuritySecurity-related events
AuthenticationauthenticationLogin and auth events
AIaiAI processing events
InvitationsinvitationsInvitation management
BillingbillingSubscription and payment
AssetsassetsAsset (avatar, branding) updates
UploaduploadUpload events
TransfertransferOwnership transfer events
Import/Exportimport_exportImport/export operations
Quick SharequickshareQuick share events
MetadatametadataMetadata operations
WorkflowworkflowWorkflow events

Event Visibility Levels

VisibilityAPI ValueDescription
InternalinternalSystem events. Never accessible via API.
Audit Logexternal_audit_logAudit/compliance events. Targeted permission checks bypassed for admins.
ExternalexternalStandard user-facing events.

Default (no visibility parameter): returns both external_audit_log and external events, excludes internal.

Event Permission Levels

PermissionDescription
memberAny member of the profile can view
adminOnly admins of the profile can view
targetedOnly 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

Share Storage

Comments

Membership

Workspace Lifecycle

Share Lifecycle

AI

Metadata

Quick Shares

Invitations

User

Organization

Billing

Workflow

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.

Poll User Activity

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. Credit limit checks skipped.

Query Parameters

ParameterTypeRequiredDefaultDescription
wait integer No 0 Long-poll timeout in seconds (0–95). Server holds connection open until update or timeout.
lastactivity string No Current time Only return activity newer than this timestamp. Micro-precision datetime (e.g., 2025-01-20 10:30:45.123456).
updated any No If present, only return activity fields updated since lastactivity
fields string No All fields Comma-delimited activity field names to check. Max 30 fields. Supports ID qualifier via colon (e.g., storage:12345).

Example Request

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)

{
  "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)

{
  "result": "yes",
  "response": {
    "results": 0,
    "activity": []
  }
}

Response Fields

FieldTypeDescription
resultstring"yes" on success
response.resultsintegerNumber of activity fields returned
response.activityobjectMap of activity field names to micro-precision UTC timestamps
response.lastactivitystringMost recent timestamp; pass as lastactivity in next poll

Error Responses

Error CodeHTTP StatusDescription
APP_ERROR_INPUT_INVALID400Invalid profile ID format
APP_ERROR_INPUT_INVALID400User lacks permissions for the specified profile
APP_ERROR_INPUT_INVALID400Invalid field names or more than 30 fields
APP_ERROR_OBJECT_INIT500Failed to initialize internal status object
APP_AUTH_INVALID401Missing or invalid JWT token

Poll Profile Activity

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 Poll User Activity.

Path Parameters

ParameterTypeRequiredDescription
{profile_id} string Yes 20-digit numeric profile ID (org, workspace, or share). For upload progress, use your user ID.

Access Requirements

Profile TypePermission Required
User (self)Authenticated
OrganizationPERM_VIEW on the org
WorkspacePERM_VIEW on the workspace
ShareShare view permissions + multiplayer enabled

Example Request

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 Poll User Activity.


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 PatternWhat 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

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.

WebSocket Auth

GET /current/websocket/auth/{profile_id}

Generate a WebSocket authentication JWT for a specific profile. Tokens are valid for 24 hours.

Auth: Required (JWT). Credit limit checks skipped.

Path Parameters

ParameterTypeRequiredDescription
{profile_id} string Yes 20-digit numeric ID of the user, org, workspace, or share to subscribe to

Example Request

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

Response (200 OK)

{
  "result": "yes",
  "response": {
    "expires_in": 86400,
    "auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
resultstring"yes" on success
response.expires_inintegerToken lifetime in seconds (86400 = 24 hours)
response.auth_tokenstringSigned JWT with websocket scope, bound to the requested profile

Access Requirements

Profile TypePermission Required
User (self)None beyond authentication
OrganizationPERM_VIEW on the org
WorkspacePERM_VIEW on the workspace
SharecanViewShareDetails

Error Responses

Error CodeHTTP StatusDescription
APP_ERROR_INPUT_INVALID400No profile ID provided or invalid format
APP_ERROR_INPUT_INVALID400Profile type unsupported, not found, or user lacks permissions
APP_AUTH_INVALID401Missing 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.

Message Format

The server pushes JSON messages when resources change:

{
  "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.

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 YJS-based collaborative editing rooms.

Generate Realtime Token

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. Credit limit checks skipped.

Path Parameters

ParameterTypeRequiredDescription
{room_id} string Yes 20-digit numeric ID of the workspace or share to join

Example Request

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

Response (200 OK)

{
  "result": "yes",
  "response": {
    "expires_in": 86400,
    "auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  },
  "current_api_version": "1.0"
}

Access Requirements

Profile TypePermission Required
WorkspaceAt least PERM_VIEW
SharecanViewShareDetails + multiplayer enabled

Error Responses

Error CodeHTTP StatusDescription
APP_ERROR_INPUT_INVALID400Missing room ID
APP_ERROR_INPUT_INVALID400Room ID is not numeric
APP_ERROR_INPUT_INVALID400Room ID does not correspond to a workspace or share
APP_DENIED403User lacks permissions on the room
APP_AUTH_INVALID401Missing or invalid JWT, or internal JWT generation failure

Note: Only workspace and share profile types are accepted as room IDs.


Validate Realtime Token

GET /current/realtime/auth/validate/

Validate a realtime JWT and extract the room ID. Intended for server-side components to verify tokens.

Auth: Bearer token in Authorization header (the realtime JWT to validate, not a user JWT).

Example Request

curl -X GET "https://api.fast.io/current/realtime/auth/validate/" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Response (200 OK)

{
  "result": "yes",
  "response": {
    "room_id": "12345678901234567890"
  },
  "current_api_version": "1.0"
}

Response Fields

FieldTypeDescription
resultstring"yes" on success
response.room_idstringThe workspace or share profile ID the token is bound to

Error Responses

Error CodeHTTP StatusDescription
APP_AUTH_INVALID401Missing Authorization header
APP_ERROR_INPUT_INVALID400Malformed Authorization header
APP_ERROR_INPUT_INVALID400Authorization header does not use Bearer scheme
APP_ERROR_INPUT_INVALID400Bearer keyword present but no token follows
APP_ERROR_INPUT_INVALID400Token is not valid JWT format
APP_DENIED403Token signature verification or expiration check failed
APP_ERROR_GENERAL500Token payload is malformed or missing required fields
APP_ERROR_INPUT_INVALID400Token scope is not realtime

Notes: Only validates tokens with realtime scope. WebSocket-scoped tokens are rejected. No user session or database lookup is performed beyond JWT verification.

Webhooks

Inbound webhook endpoints that receive event notifications from third-party services. These endpoints are not called by API consumers.

Stripe Billing Webhook

POST /current/webhooks/billing/stripe/

Receive and queue a Stripe billing webhook event. Called by Stripe, not by API consumers.

Auth: Stripe HMAC-SHA256 signature verification via Stripe-Signature header (not Bearer token).

Request Headers

HeaderRequiredDescription
Stripe-SignatureYesStripe signature: t={timestamp},v1={signature}
Content-TypeYesapplication/json

Request Body: Raw JSON event object from Stripe.

Example Request

curl -X POST "https://api.fast.io/current/webhooks/billing/stripe/" \
  -H "Content-Type: application/json" \
  -H "Stripe-Signature: t=1492774577,v1=5257a869..." \
  -d '{"id":"evt_test","object":"event","type":"invoice.paid","data":{"object":{}}}'

Response (202 Accepted)

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

Error Responses

Error CodeHTTP StatusDescription
APP_REQUEST_TYPE400Request method is not POST
APP_ERROR_INPUT_INVALID400Stripe-Signature header missing, malformed, or cannot be parsed
APP_ERROR_INPUT_INVALID400HMAC verification failed (timestamp out of range or hash mismatch)
APP_ERROR_INPUT_INVALID400Request body is not valid JSON
APP_ENQUEUE_FAILED500Event valid but could not be placed on processing queue

Notes: Only POST requests are accepted. Signature verification enforces a 5-minute tolerance window for timestamp drift. Events are queued for asynchronous processing; the response confirms receipt, not processing. Stripe retries failed deliveries (non-2xx responses).

↑ Back to top