Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.adipredictstreet.com/llms.txt

Use this file to discover all available pages before exploring further.

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 with X-Api-Key — the same key you use on HTTP, same scope rules.
GatewayPathAuthWhat lives here
market/ws/marketX-Api-Keypublic trades, orderbooks, market lifecycle, platform status
user/ws/userX-Api-Key (portfolio:read scope)own orders / fills / account-control events
The protocol is Kalshi-style (envelope with id / cmd / params) and Polymarket-style identifier lists (channel + ids[]).

Connect

Same handshake contract for both gateways:
wss://ws-gateway.adipredictstreet.com/ws/market
wss://ws-gateway.adipredictstreet.com/ws/user
Pick one of:
  • 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
The server pushes one greeting after the upgrade:
{
  "type": "connected",
  "data": {
    "gateway":       "user",
    "walletAddress": "0x1111111111111111111111111111111111111111",
    "authMethod":    "api_key"
  }
}
On /ws/market the greeting is just { "gateway": "market", "authMethod": "api_key", "protocolVersion": 2 } — no wallet context, since market data isn’t per-user.
Auth is validated at handshake only. Rotating a key does not invalidate an open socket; close and reopen to switch identity. A bad key closes with 4401 <reason> (e.g. 4401 api_key_revoked). Revoking a key closes every live socket bound to that keyId immediately via apikey:invalidate Redis pub/sub.

Command envelope

Every client-to-server message uses the same shape:
{ "id": 1, "cmd": "subscribe", "params": { /* ... */ } }
  • id — client-side correlation id; echoed in the server’s response
  • cmdsubscribe / update_subscription / unsubscribe / list_subscriptions / ping
  • params — command-specific payload
Every accepted subscription gets a connection-local 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:
ChannelIdentifier modelRequired scopePurpose
token_trade_matchesids = [tokenId, ...]low-latency tape from the matcher (off-chain match)
token_trade_settlementsids = [tokenId, ...]chain-confirmed settlements (OrderFilled indexed)
token_bookids = [tokenId, ...]public orderbook snapshots + updates
token_ohlcids = [tokenId, ...]rolling 5-second OHLC candles
condition_lifecycleids = [conditionId, ...]market lifecycle, pause/unpause, oracle, payout
systemids = ["platform_status"]platform-wide freeze / maintenance banner
Private, on /ws/user:
ChannelIdentifier modelRequired scopePurpose
user_ordersno ids (scoped to the key’s wallet)portfolio:readown order_placed / order_cancelled
user_fillsno ids (scoped to the key’s wallet)portfolio:readown user_fill (chain-confirmed fills)
vault_positionsids = [vaultAddress, ...]portfolio:readper-vault balance changes / split / merge / redeem
Detailed payloads + examples in Subscriptions and Messages.

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 conditionId and yes/no token ids — resolve them through the on-chain NegRiskAdapter before subscribing
Then open /ws/market and subscribe by those native ids:
{
  "id": 1,
  "cmd": "subscribe",
  "params": {
    "subscriptions": [
      { "channel": "token_trade_matches",     "ids": ["12345..."] },
      { "channel": "token_trade_settlements", "ids": ["12345..."] },
      { "channel": "token_book",              "ids": ["12345..."] },
      { "channel": "condition_lifecycle",     "ids": ["0xabc..."] }
    ]
  }
}
Don’t subscribe by app symbol — symbols are app metadata, not the canonical on-chain identity.

What clients should NOT do

  • No symbol-based subscriptions. Use tokenId / conditionId.
  • No invented room strings like vault:0xabc:erc1155. Use channel + ids only.
  • No mixing of /ws/user and /ws/market on one socket. The gateway rejects cross-gateway channels with forbidden — open one socket per gateway.
  • No assumptions about sid stability 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.