(market, channel) pair on a connection. You create them
with subscribe, name the market with a MarketStream, and the server hands
back a subscriptionId that keys every frame that follows.
MarketStream
How you reference a market on the wire. It’s a discriminated union on venue —
you build it from venue-native identifiers you already have, or that you get
from the Markets API.
Limitless YES and NO are two views of one shared orderbook — the NO book is the
exact complement of the YES book. One slug covers both sides; you subscribe to
YES and NO as two separate
MarketStream entries, one per token. You can
subscribe to either or both; both stream accurately.Kalshi works differently: one ticker, one book, one subscribable side.
Where Limitless gives you two entries and you pick either or both, a Kalshi
ticker addresses a single YES-priced orderbook and there is no second entry to
subscribe to.
side accepts only "yes"; a subscribe naming "no" is
refused with UNKNOWN_MARKET rather than
returning a NO feed. You read the NO side by deriving it locally — see below.side: "yes" and an omitted side name the same subscription. Sending both
forms on one connection does not create two: the second returns the existing
subscriptionId, under the idempotency rule described in
subscribe.Deriving the NO side of a Kalshi market
The book we publish is YES-priced. The NO side is that same book read from the other end, which you compute locally. Two transforms, and you need both — applying1 - price without swapping the sides produces a plausible book that
is wrong:
- Price becomes
1 - price. - Sides swap. Our
asksare your NO bids; ourbidsare your NO asks. - Size carries across unchanged. One contract is one contract read from
either end: buying NO at
0.47and selling YES at0.53move the same single contract, so only the price coordinate and the bid/ask label flip.sizeis in shares, not notional, so it never scales by price. - Re-sort afterwards. Our
bidsare ordered best first (descendingprice) and ourasksbest first (ascendingprice), and1 - pricereverses both orderings.
snapshot for { "venue": "kalshi", "ticker": "KXNBA-25-LAL" }:
Three checks to assert against your own implementation:
- YES best ask
0.53+ NO best bid0.47=1.00 - YES best bid
0.52+ NO best ask0.48=1.00 - The spread is preserved:
0.01in both views.
delta frames derive the same way, side included:
size: 0 still deletes the level.
Channels
A subscription is one
(market, channel) pair. Subscribing to one market on
both channels counts as two subscriptions against the
per-connection cap.
subscribe
For each market in the batch you get back either a
subscribed ack or
an error (for example, UNKNOWN_MARKET) — one reply per market, so a single
bad entry never sinks the rest of the batch.
subscriptionId to whatever local state you keep for
that market — every subsequent frame for this subscription is keyed by that id,
and it’s also the handle you pass to unsubscribe.
snapshotPending: true tells you a snapshot is on its way (it is always
false on the trade channel — the tape has no snapshot).
Subscribing is idempotent per (connection, market, channel): a repeat returns
the existing subscriptionId rather than creating a second one.
unsubscribe
subscriptionId(s) from prior subscribed acks. One
unsubscribed reply per id, carrying subscriptionId, market, and channel.
list
subscriptions frame: one atomic snapshot of every active
subscription on this connection.