Skip to main content

Realtime overview

Switera Realtime lets your SaaS frontend subscribe to live app, tenant, user, and role channels while your backend publishes messages through a trusted API key. The browser never receives runtime secrets. It receives short-lived Switera-issued tokens derived from the signed-in Connect user.

Use Realtime for live notifications, workspace updates, activity feeds, background-job progress, collaboration indicators, and customer-facing dashboards that should update without refresh.

Launch surface

AreaUse it forLaunch state
Connection tokensLet a signed-in Connect user open a websocket connection.Available through /api/v1/connect/realtime/token.
Subscription tokensAuthorize one private app, tenant, user, or role channel.Available through /api/v1/connect/realtime/subscriptions.
Publish APISend trusted backend events to one channel.Available through /api/v1/apps/{appId}/realtime/publish.
Runtime statusVerify token signing, public websocket URL, and runtime health.Available in the app console and API.
Channel scopesKeep live messages scoped to the intended audience.Available for app, tenant, user, and role namespaces.

Channel scopes

Channels are part of your application contract. Keep topic names stable once application code subscribes to them.

ScopePatternTypical audience
Appapp:{appId}:{topic}All connected users for one app.
Tenanttenant:{appId}:{tenantId}:{topic}Users who belong to one customer organization.
Useruser:{appId}:{userId}:{topic}One app user.
Rolerole:{appId}:{tenantId}:{role}:{topic}Members of one organization with a specific role.

Good launch examples:

app:app_123:broadcast
tenant:app_123:tenant_456:updates
user:app_123:user_789:notifications
role:app_123:tenant_456:admin:updates

Runtime readiness

Open Services > Realtime or call the runtime endpoint before wiring frontend code.

GET /api/v1/apps/{appId}/realtime/runtime
Authorization: Bearer sf_secret_...
{
"status": "ready",
"summary": "Realtime runtime checks are passing.",
"websocket_url": "wss://switera.com/realtime/connection/websocket",
"namespaces": [
{
"name": "tenant",
"pattern": "tenant:{appId}:{tenantId}:{topic}",
"presence": true,
"history": "120s"
}
],
"checks": [
{
"key": "token_secret",
"status": "ready",
"summary": "Realtime token signing is configured."
}
]
}

Treat any setup_required or needs_attention status as a launch blocker for realtime features.

Issue a connection token

Your SaaS frontend calls the Connect route after the user is signed in. The request uses the existing browser session or Connect bearer token.

POST /api/v1/connect/realtime/token
Content-Type: application/json
{
"tenant_id": "tenant_456"
}
{
"token_type": "Bearer",
"expires_in": 900,
"app_id": "app_123",
"user_id": "user_789",
"tenant_id": "tenant_456",
"role": "admin",
"websocket_url": "wss://switera.com/realtime/connection/websocket",
"channels": [
"app:app_123:broadcast",
"user:app_123:user_789:notifications",
"tenant:app_123:tenant_456:updates",
"role:app_123:tenant_456:admin:updates"
]
}

Switera derives app_id, user_id, tenant_id, email, and role from trusted Auth and organization records. Do not send those values from browser code except the tenant the user is trying to enter.

Authorize a private channel

For private subscriptions, ask Switera for one subscription token per channel.

POST /api/v1/connect/realtime/subscriptions
Content-Type: application/json
{
"channel": "tenant:app_123:tenant_456:updates"
}

Switera checks that:

  • app channels belong to the signed-in app,
  • tenant channels belong to an organization where the user is an active member,
  • user channels match the resolved app user,
  • role channels match the user's active organization role.

Publish from a trusted backend

Publish from your backend, job runner, or automation using an app secret key.

POST /api/v1/apps/{appId}/realtime/publish
Authorization: Bearer sf_secret_...
Content-Type: application/json
{
"channel": "tenant:app_123:tenant_456:updates",
"data": {
"type": "invoice.paid",
"invoice_id": "inv_123"
},
"idempotency_key": "invoice-paid-inv_123"
}
{
"channel": "tenant:app_123:tenant_456:updates",
"published": true
}

Browser token example

const tokenResponse = await auth.issueRealtimeConnectionToken({
tenant_id: 'tenant_456'
});

const channel = 'tenant:app_123:tenant_456:updates';
const subscriptionToken = await auth.issueRealtimeSubscriptionToken({
channel
});

console.log(tokenResponse.websocket_url);
console.log(tokenResponse.token);
console.log(subscriptionToken.token);

Use the returned websocket_url and tokens with the realtime client layer in your application. First-party Switera connection wrappers are tracked in the SDK roadmap.

What not to do

  • Do not put app secret keys in browser code.
  • Do not publish directly to the internal realtime runtime.
  • Do not use app-wide broadcast channels for tenant-specific data.
  • Do not treat channel names as user input. Build them from trusted app, tenant, user, and role IDs.