Connecting
?pairs= is optional; omit it to receive every asset. No authentication, though the handshake is
capped — see Limits. Browser clients are subject to an origin allowlist; a rejected upgrade is
closed with a bare 403.
Server messages
One snapshot on connect, carrying theseq baseline for every asset:
data is byte-identical to a row from GET /v1/prices — seq sits on the frame, not inside it,
so the tick payload stays the same shape as REST.
Client messages
ack carrying pairCount (the number of assets you now
receive; null is all of them, 0 is none), or an error carrying a code of malformed,
unknown_type, invalid_pairs, no_filter or rate_limited.
subscribe on an unfiltered connection is a no-op acked with
"pairCount": null — to narrow, reconnect with ?pairs=. unsubscribe needs a filtered
connection and is rejected with no_filter otherwise. Unsubscribing your last asset leaves you
receiving nothing ("pairCount": 0), which subscribe recovers without reconnecting.
Detecting loss
Delivery is best effort, but loss is detectable. If more than 1 MB is buffered for a slow client, ticks are dropped rather than queued — and you are told:seq is a per-asset counter, so a jump between consecutive tick frames for one asset means you
missed that many. Baseline each asset from the snapshot, then compare.
Two limits on what seq can tell you. It is per connection — process-wide, not global, so it
does not survive a reconnect and is not comparable across replicas. And there is no replay: the
stream tells you that you fell behind, not what you missed, so recover by re-reading
GET /v1/prices.
Assets with no trading schedule are omitted entirely, from the snapshot and from ticks. A missing
asset is not a signal that its market is closed.
Limits
Per pod, so the effective ceiling scales with replica count. Read the headers on a rejected upgrade rather than hard-coding these.
Rejected upgrades carry
Retry-After.
Heartbeat
The server pings every 30 seconds and terminates a connection that has not ponged since the previous ping. Browsers pong automatically; other clients need a library that does. On shutdown the server closes with1001 going away after draining.