Skip to main content
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.dev.predictstreet.sde.adifoundation.ai/ws/market
wss://ws-gateway.dev.predictstreet.sde.adifoundation.ai/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" } — 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

ChannelGatewayIdentifier modelRequired scopePurpose
user_activity/ws/userno ids (scoped to the key’s associated wallet)portfolio:readown orders, trades, account-control
token_trades/ws/marketids = [tokenId, ...]public trade tape per outcome token
token_book/ws/marketids = [tokenId, ...]public orderbook snapshots + deltas
condition_status/ws/marketids = [conditionId, ...]market lifecycle, pause/unpause, oracle, payout
system/ws/marketids = ["platform_status"]platform-wide freeze / maintenance banner
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_trades",     "ids": ["12345..."] },
      { "channel": "token_book",       "ids": ["12345..."] },
      { "channel": "condition_status", "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.