ws
library, but the protocol is plain JSON over a standard WebSocket, so you can
use any WebSocket client.
Prerequisites
- Your ParlayX API key, the same signed Ed25519 key you use for REST. See Authentication.
- One or more
MarketStreamvalues for the markets you want. See identifying markets.
1. Connect and authenticate
Sign the handshake with your private key and put the credentials on the query string of:401
before the connection opens. A 503 means the gateway is at capacity:
reconnect, and you’ll land on fresh capacity. A 429 means your account is at
its connection limit, so close a
connection you no longer need instead of retrying.
2. Receive WELCOME
Immediately after the upgrade succeeds, the server sends a WELCOME frame:
connectionId, and quote it in any support request so we can find
your session in our logs. The limits tell you how many subscriptions this
connection accepts and how long it will live before the server closes it for a
scheduled reconnect.
3. Subscribe
Send aSUBSCRIBE frame listing the markets you want. The only required
fields are type and markets; channels defaults to ["BOOK"].
SUBSCRIBED ack or an ERROR
(for example, UNKNOWN_MARKET), so a market the server cannot resolve never
sinks the rest of the batch. SUBSCRIBED is sent before the upstream venue feed
has confirmed the market. If the feed then refuses it or does not confirm it in
time, or a book’s first snapshot never arrives, a later ERROR carrying the
subscriptionId ends the subscription, so one market can get a SUBSCRIBED
followed by an ERROR. See ERROR. A frame that
fails validation is different: the whole frame is rejected before any market is
read, so a malformed entry takes its batch with it.
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.
4. Apply the stream
A book subscription delivers aSNAPSHOT first, then DELTA frames:
SNAPSHOT replaces your book; DELTA
mutates it. Because of the sequencing contract,
your apply loop needs no gap-handling logic of its own. If we ever could not
send a contiguous delta, we send a fresh SNAPSHOT instead.
Optional: the trade tape
To also receive each fill on a market as it executes, subscribe with theTRADE channel (each (market, channel) pair is its own subscription, with
its own subscriptionId):
snapshotPending: false on the ack), and frames flow from the moment you
subscribe, and earlier fills are not replayed. See the
TRADE frame reference for the full semantics.
The trade channel is available on Polymarket, Kalshi and ProphetX; Limitless
publishes no public trade feed, so a trade subscribe there is rejected with
UNSUPPORTED_CHANNEL.
5. Keep the connection healthy
- The server sends WebSocket pings every 30 seconds; your client library
answers them automatically. You can also send an application-level
PINGand get aPONGback. - Watch for
GOODBYEframes and socket closes, and reconnect. Connections are closed at theconnectionTtlSecondslifetime fromWELCOME, so schedule a proactive reconnect before then. - On a
STATUSframe withstate: "RESYNCING", drop that subscription’s local book and trust the nextSNAPSHOT. See reconnect & resync handling.