PredictStreet exposes WebSocket streaming through two separate gateways that share one client protocol. Pick the gateway by what data you want; never mix subscriptions across the two on one socket. Both gateways authenticate withDocumentation Index
Fetch the complete documentation index at: https://docs.adipredictstreet.com/llms.txt
Use this file to discover all available pages before exploring further.
X-Api-Key — the same key you
use on HTTP, same scope rules.
| Gateway | Path | Auth | What lives here |
|---|---|---|---|
| market | /ws/market | X-Api-Key | public trades, orderbooks, market lifecycle, platform status |
| user | /ws/user | X-Api-Key (portfolio:read scope) | own orders / fills / account-control events |
id / cmd / params)
and Polymarket-style identifier lists (channel + ids[]).
Connect
Same handshake contract for both gateways:X-Api-Key: ps_live_<keyId>_<secret>header on the upgrade request?key=<token>query parameter — for browser clients that can’t set custom headers on the WebSocket upgrade
/ws/market the greeting is just { "gateway": "market", "authMethod": "api_key", "protocolVersion": 2 } — no wallet context, since market data isn’t per-user.
Command envelope
Every client-to-server message uses the same shape:id— client-side correlation id; echoed in the server’s responsecmd—subscribe/update_subscription/unsubscribe/list_subscriptions/pingparams— command-specific payload
sid (numeric).
Use sid for subsequent updates / unsubscribes / event routing on
the client side. sids are not stable across reconnects.
Channel catalog
Public, on/ws/market:
| Channel | Identifier model | Required scope | Purpose |
|---|---|---|---|
token_trade_matches | ids = [tokenId, ...] | — | low-latency tape from the matcher (off-chain match) |
token_trade_settlements | ids = [tokenId, ...] | — | chain-confirmed settlements (OrderFilled indexed) |
token_book | ids = [tokenId, ...] | — | public orderbook snapshots + updates |
token_ohlc | ids = [tokenId, ...] | — | rolling 5-second OHLC candles |
condition_lifecycle | ids = [conditionId, ...] | — | market lifecycle, pause/unpause, oracle, payout |
system | ids = ["platform_status"] | — | platform-wide freeze / maintenance banner |
/ws/user:
| Channel | Identifier model | Required scope | Purpose |
|---|---|---|---|
user_orders | no ids (scoped to the key’s wallet) | portfolio:read | own order_placed / order_cancelled |
user_fills | no ids (scoped to the key’s wallet) | portfolio:read | own user_fill (chain-confirmed fills) |
vault_positions | ids = [vaultAddress, ...] | portfolio:read | per-vault balance changes / split / merge / redeem |
Where do tokenId and conditionId come from?
Market data is keyed by on-chain native ids, not by app symbol.
Pull them from REST first:
GET /api/markets/{symbol}→conditionId/questionId/yesTokenId/noTokenId(binary)- For neg-risk multi-outcome markets, each question has its own
conditionIdand yes/no token ids — resolve them through the on-chainNegRiskAdapterbefore subscribing
/ws/market and subscribe by those native ids:
What clients should NOT do
- No symbol-based subscriptions. Use
tokenId/conditionId. - No invented room strings like
vault:0xabc:erc1155. Usechannel + idsonly. - No mixing of
/ws/userand/ws/marketon one socket. The gateway rejects cross-gateway channels withforbidden— open one socket per gateway. - No assumptions about
sidstability across reconnects. After any close, re-subscribe from scratch.
Next
Subscriptions
Per-channel subscribe / update / unsubscribe payloads.
Message shapes
Outbound event envelope and full event catalog by channel.
Reconnect
Heartbeat, sid rebuild, snapshot resync.
API keys
Scope catalog, rotation, revoke.