Skip to main content
Control messages are JSON frames distinguished from event envelopes by the presence of a top-level type field without a schema field. Event envelopes always carry "schema": "ws.firm.v1".

Server → client

connected

Sent exactly once, immediately after the upgrade succeeds.

scope.confirmed

Sent in response to every accepted scope.set.

pong

Reply to client ping.

error

Advisory error for the client. Does not close the socket on its own — the server may follow with a close frame (4001 for auth, 4002 for backpressure).

Client → server

scope.set

See Subscription scopes for the full schema. A second scope.set replaces the previous subscription.

ping

Application-level keepalive. Send every 20–30 seconds. The server also sends standard WebSocket control ping frames at ~30s intervals — most client libraries auto-respond to those.

Ordering guarantees

  • The server processes client frames in order. scope.set takes effect before any subsequent event is delivered.
  • Event envelopes are delivered in JetStream seq order per subject. Across subjects, ordering is best-effort; rely on seq per stream and on ts for cross-subject reasoning.