Skip to main content

Realtime API

WebSocket-based real-time data changes, presence tracking, and broadcast messaging.


Connection

Connect to the Realtime WebSocket endpoint with a channel specified as a query parameter:

wss://your-project.edgebase.dev/api/realtime?channel=realtime:shared:posts

Authentication

After establishing the WebSocket connection, send an authentication message as the first message:

{ "type": "auth", "token": "<accessToken>" }

On success, the server responds with:

{ "type": "auth_success", "userId": "user_123" }

If the token is refreshed during the connection lifetime, the server sends:

{ "type": "auth_refreshed", "userId": "user_123" }

On authentication failure:

{ "type": "auth_error", "message": "Invalid or expired token" }

Client to Server Messages

Subscribe

Subscribe to a channel to begin receiving events.

{ "type": "subscribe", "channel": "realtime:shared:posts" }

Unsubscribe

Stop receiving events from a channel.

{ "type": "unsubscribe", "channel": "realtime:shared:posts" }

Subscribe with Filters

Subscribe to a channel with optional server-side filters.

{
"type": "subscribe",
"channel": "realtime:shared:posts",
"filters": [
["status", "==", "published"],
["authorId", "==", "user-123"]
],
"orFilters": [
["category", "==", "news"],
["category", "==", "tech"]
]
}
FieldTypeRequiredDescription
channelstringYesChannel to subscribe to
filtersarrayNoAND conditions — all must match
orFiltersarrayNoOR conditions — any one match is sufficient

Filter tuple format: [field, operator, value]. Max 5 conditions per filter array.

Update Filters

Update filter conditions on an existing subscription without resubscribing.

{
"type": "update_filters",
"channel": "realtime:shared:posts",
"filters": [["status", "==", "draft"]],
"orFilters": null
}

Server responds with:

{
"type": "filters_updated",
"channel": "realtime:shared:posts",
"serverFilter": true
}

Set filters or orFilters to null to clear that filter type.

Track Presence

Start tracking the current user's presence state on the connection's channel.

{ "type": "track", "state": { "name": "Jane", "status": "online" } }

Untrack Presence

Stop tracking presence for the current user.

{ "type": "untrack" }

Broadcast

Send a broadcast event to all subscribers on the channel.

{ "type": "broadcast", "event": "message", "data": { "text": "hi" } }
FieldTypeRequiredDefaultDescription
eventstringYesCustom event name
dataobjectYesPayload to broadcast
excludeSelfbooleanNotrueWhen true, the sender does not receive their own broadcast. Set to false to include the sender in broadcast recipients.

Example with excludeSelf: false:

{
"type": "broadcast",
"event": "cursor-move",
"data": { "x": 100, "y": 200 },
"excludeSelf": false
}

Ping

Send a keepalive ping to the server. Updates the lastSeen timestamp for presence tracking.

{ "type": "ping" }

The server responds with a pong message. If no ping is received within the TTL window (default 60s), the connection's presence is cleaned up. Recommended ping interval: 30 seconds.


Server to Client Messages

pong

Response to a client ping message.

{ "type": "pong" }

auth_success

Authentication succeeded.

{ "type": "auth_success", "userId": "user_123" }

auth_refreshed

Token was refreshed during the connection. When a client's auth token is refreshed on a long-lived WebSocket connection, the server re-evaluates channel access and includes any channels the client lost access to.

{
"type": "auth_refreshed",
"userId": "user_123",
"revokedChannels": ["db:private-table"]
}
FieldTypeDescription
userIdstringThe authenticated user ID
revokedChannelsstring[]List of channels the client lost access to after token refresh. Empty array if no channels were revoked.
  • The client should handle this by removing subscriptions for revoked channels
  • This occurs when user roles/permissions change while connected
  • If the refresh fails, the server responds with an error instead and preserves the existing auth

auth_error

Authentication failed.

{ "type": "auth_error", "message": "Invalid or expired token" }

subscribed

Successfully subscribed to a channel.

{ "type": "subscribed", "channel": "realtime:shared:posts", "serverFilter": false }
FieldTypeDescription
channelstringThe subscribed channel name
serverFilterbooleanWhether server-side filtering is active for this subscription

db_change

A database change event on a subscribed table.

{
"type": "db_change",
"table": "posts",
"changeType": "added",
"docId": "01J...",
"data": {
"id": "01J...",
"title": "New Post",
"createdAt": "2026-01-01T00:00:00.000Z"
},
"timestamp": "2026-01-01T00:00:00.000Z"
}
FieldTypeDescription
tablestringTable name where the change occurred
changeTypestringOne of added, modified, or removed
docIdstringThe document ID that changed
dataobject | nullThe full document data (for added/modified) or null (for removed)
timestampstringISO 8601 timestamp of the change

batch_changes

Multiple changes delivered as a batch.

{
"type": "batch_changes",
"channel": "realtime:shared:posts",
"changes": [
{ "table": "posts", "changeType": "added", "docId": "01J...", "data": { "..." : "..." }, "timestamp": "..." },
{ "table": "posts", "changeType": "modified", "docId": "01K...", "data": { "..." : "..." }, "timestamp": "..." }
],
"total": 2
}
FieldTypeDescription
channelstringThe channel for these changes
changesarrayArray of db_change objects
totalnumberTotal number of changes in the batch

presence_sync

Presence state synchronization for a presence channel.

{
"type": "presence_sync",
"channel": "presence:room",
"users": [
{ "userId": "user_1", "state": { "name": "Jane", "status": "online" } },
{ "userId": "user_2", "state": { "name": "John", "status": "away" } }
]
}

presence_join

A user joined the presence channel.

{
"type": "presence_join",
"userId": "user-123",
"connectionId": "conn-abc",
"state": { "status": "online", "cursor": { "x": 0, "y": 0 } }
}
FieldTypeDescription
userIdstringAuthenticated user ID
connectionIdstringUnique WebSocket connection identifier
stateobjectUser-defined presence state (max 1 KB)

presence_update

A user updated their presence state.

{
"type": "presence_update",
"userId": "user-123",
"connectionId": "conn-abc",
"state": { "status": "away" }
}

presence_leave

A user left the presence channel (disconnected or timed out).

{
"type": "presence_leave",
"userId": "user-123",
"connectionId": "conn-abc",
"reason": "timeout"
}
FieldTypeDescription
userIdstringAuthenticated user ID
connectionIdstringUnique WebSocket connection identifier
reasonstringLeave reason — "disconnect" (clean close) or "timeout" (TTL expired)

broadcast_event

A broadcast event received from another client or the server.

{
"type": "broadcast_event",
"channel": "broadcast:chat",
"event": "message",
"data": { "text": "hello", "from": "user_1" }
}

error

An error occurred.

{ "type": "error", "code": "AUTH_FAILED", "message": "Invalid or expired token" }
FieldTypeDescription
codestringMachine-readable error code
messagestringHuman-readable error description

Channel Patterns

PatternDescription
realtime:{namespace}:{tableName}Subscribe to all changes on a table (e.g. realtime:shared:posts)
realtime:{namespace}:{tableName}:{docId}Subscribe to changes on a single document in a static namespace
presence:{channel}Presence tracking channel
broadcast:{channel}Broadcast messaging channel
realtime:{namespace}:{instanceId}:{tableName}Subscribe to a dynamic DB block table

Examples

realtime:shared:posts                   # All changes on the "posts" table in shared namespace
realtime:shared:posts:01J... # Single document in the shared namespace
presence:lobby # Presence tracking for "lobby"
broadcast:chat-room # Broadcast messages in "chat-room"
realtime:workspace:ws-123:documents # Dynamic DB block table subscription

Broadcast REST Endpoint

POST /api/realtime/broadcast

Send a broadcast message from the server to all subscribers on a channel. This is a REST endpoint, not a WebSocket message.

Auth: Service Key required (X-EdgeBase-Service-Key header)

Request BodyTypeRequiredDescription
channelstringYesTarget channel (must include broadcast: prefix)
eventstringYesEvent name
payloadobjectYesData to broadcast
{
"channel": "broadcast:chat-room",
"event": "new-message",
"payload": { "text": "hello", "from": "server" }
}

Response 200

{ "ok": true }
ErrorStatusDescription
Missing Service Key401X-EdgeBase-Service-Key header not provided
Invalid Service Key403Service Key does not match