Skip to content

WebSocket API

The Atlas WebSocket endpoint mirrors the host used for HTTPS. Production URL:

wss://atlas.mavr.finance/ws?token=<access_token>

Pass the same short-lived JWT access token used for REST (Authentication) as the token query parameter. The server validates it during the HTTP upgrade; invalid or expired tokens typically yield an abnormal close (for example codes such as 1006 / TLS or proxy rejection — reference clients also treat 1000 normal and 1005 no-status as non-abnormal).

Clients send no application frames; all payloads are JSON messages from server to client.

Every broadcast matches the BroadcastMessage shape used in atlas-web (frontends/atlas-web/src/types/ws.ts):

FieldTypeMeaning
kindstringLogical channel / topic (see table below).
message_typestring (optional)"snapshot" — replace local collection for that kind; "delta" — upsert rows and apply removed keys. Defaults to snapshot when omitted (message_type ?? "snapshot" in the reference client).
seqnumber (optional)Monotonic sequence per connection / broadcast stream. Use for gap detection (see Sequence numbers).
tsstring or omitted/nullServer timestamp (RFC 3339 when present). May be missing on malformed payloads.
dataobjectKind-specific payload; may be {}, string-encoded JSON, or null depending on kind.

Example skeleton:

{
"kind": "positions",
"message_type": "delta",
"seq": 1234,
"ts": "2026-05-20T10:00:00.123456Z",
"data": { }
}

The server emits periodic heartbeat messages so idle connections stay warm and clients can refresh “last message” timers. Heartbeats carry kind: "heartbeat" and no meaningful data. They are not listed in the TypeScript WsKind union but are part of the live protocol.

Several kinds use the same pattern:

  • message_type: "snapshot" — replace the entire local cache for that domain with the rows in data (after parsing).
  • message_type: "delta"upsert rows keyed by the domain’s natural id and delete ids listed in removed.

For positions, the reference parser accepts data.positions, data.rows, data.items, nested envelopes, or a bare JSON array / double-encoded string (parsePositionsWsData in frontends/atlas-web/src/lib/positionSnapshotEnvelope.ts). Removed keys are string ids (e.g. position_line_key).

For cash_balance, ocp, and payment_order, the broadcaster prefers explicit arrays (cash_balances, ocp_positions, payment_orders) but still accepts legacy upsert for compatibility.

The application kinds defined as WsKind in frontends/atlas-web/src/types/ws.ts behave as follows (plus heartbeat above). “Reference client” denotes frontends/atlas-web/src/api/ws.ts.

kindSnapshot vs deltaSuggested client action
positionsSnapshot replaces full position map; delta upserts rows and deletes removed keys.Merge into keyed map. Reference client skips an empty snapshot if the store already has rows from REST /positions/snapshot (avoids clobbering enriched rows when the broadcaster returns [] on failure).
tradesSame pattern: data.trades + data.removed (trade ids).Merge / remove by trade_id.
blotterSame pattern: data.entries + data.removed.Merge blotter rows; remove by id list.
ordersSignal-only in reference client (parses then discards row arrays).Invalidate / refetch orders from REST; atlas-web calls invalidateWsQueries(["orders"]).
curvesNo structured merge in reference client.Invalidate / refetch curves REST queries.
dividendsInvalidate / refetch dividends REST queries.
couponsInvalidate / refetch coupons REST queries.
report_generatedEvent payload (not snapshot/delta). Fields include report_id, run_id, entity_id, optional desk_id, business_date, version, optional seal_hash_sha256.Update local report/catalogue state if modeled; invalidate reports, v2, catalogue queries.
report_editEvent payload: run_id, optional report_id, optional desk_id, user_id, section_code, optional edited_at.Patch edit metadata; invalidate section + catalogue (+ report id when present).
report_lockedEvent payload: desk_id, business_date, optional locked_at.Patch lock state for desk/date.
cash_balanceSnapshot replaces balances; delta merges cash_balances (or upsert) and removes composite keys in removed.Merge keyed cash rows (reference: Zustand setSnapshot / applyDelta).
ocpSame for open-currency positions: ocp_positions / upsert, removed.Merge keyed OCP rows.
payment_orderSame for payment orders: payment_orders / upsert, removed (ids).Merge + invalidate payment-orders REST queries.

Row-level schemas for positions, trades, and blotter align with the corresponding REST snapshots where applicable.

Reference client: reconnection and watchdog

Section titled “Reference client: reconnection and watchdog”

The atlas-web client (AtlasWebSocketClient in frontends/atlas-web/src/api/ws.ts) implements:

After a non-clean disconnect (and after ctor failures), it schedules reconnect with delay reconnect, starting at 1000 ms, doubling each attempt (×2), capped at 30_000 ms. Backoff resets to 1000 ms on successful onopen. Tab visibility (visibilitychange → visible) and browser online trigger an immediate reconnect attempt when status is disconnected or error (resetting backoff).

If no message (including heartbeats) arrives for 45 seconds (DEAD_CONNECTION_MS), the client treats the socket as dead, marks status disconnected, and calls connect() again. The check runs on a 10-second interval timer while connected.

When seq is present, the reference client stores lastSeq for diagnostics only; it does not automatically recover from gaps.

Recommended integration behavior: if seq is strictly increasing and you observe seq > expected + 1, assume missed messages: refetch authoritative snapshots over REST (or reconnect and wait for server snapshots) for affected domains rather than continuing from a partially stale cache.