Skip to main content
All client commands use the command envelope:
{ "id": <client_correlation_id>, "cmd": "<verb>", "params": { ... } }

Subscribe

{
  "id": 1,
  "cmd": "subscribe",
  "params": {
    "subscriptions": [
      { "channel": "user_activity" },
      { "channel": "token_trades",     "ids": ["12345...", "67890..."] },
      { "channel": "token_book",       "ids": ["12345..."] },
      { "channel": "condition_status", "ids": ["0xabc..."] },
      { "channel": "system",           "ids": ["platform_status"] }
    ]
  }
}
Server echoes back accepted (with assigned sid) and rejected items:
{
  "id": 1,
  "type": "subscribed",
  "accepted": [
    { "sid": 10, "channel": "user_activity" },
    { "sid": 12, "channel": "token_trades",     "ids": ["12345...", "67890..."] },
    { "sid": 13, "channel": "token_book",       "ids": ["12345..."] },
    { "sid": 14, "channel": "condition_status", "ids": ["0xabc..."] },
    { "sid": 15, "channel": "system",           "ids": ["platform_status"] }
  ],
  "rejected": []
}
Remember: user_activity lives on /ws/user; the four public channels live on /ws/market. A subscribe with a mix like the one above runs on TWO separate WebSocket connections, not one.

Normalization rules

  • All addresses lowercased.
  • tokenId is decimal-string form (no leading zeroes).
  • conditionId is lowercased 32-byte hex.
  • Duplicate ids removed.

Rejection codes

A subscription that fails validation comes back under rejected[]:
{ "channel": "user_activity", "code": "api_key_scope_missing", "message": "api_key_scope_missing: channel user_activity needs portfolio:read" }
CodeWhen
unknown_channelchannel name not in the catalog
forbiddenwrong gateway (public channel on /ws/user or user_activity on /ws/market)
api_key_scope_missingkey is missing a scope required by the channel (e.g. user_activity needs portfolio:read)
invalidmalformed id (bad hex, bad address, missing required ids)

Per-channel reference

user_activity — own orders / trades / account-control

  • Gateway: /ws/user
  • ids: not allowed (always scoped to the key’s associated wallet)
  • Required scope: portfolio:read
{ "channel": "user_activity" }
Use for own order lifecycle, own trade lifecycle, own pause/unpause.

token_trades — public trade tape

  • Gateway: /ws/market
  • ids: one or more outcome tokenIds (decimal-string)
{ "channel": "token_trades", "ids": ["12345..."] }
For neg-risk markets, each outcome has its own token; subscribe to exactly the outcomes you display.

token_book — public orderbook snapshots + deltas

  • Gateway: /ws/market
  • ids: one or more outcome tokenIds
{ "channel": "token_book", "ids": ["12345..."] }
Server pushes book_snapshot immediately after subscribe, then book_delta events with monotonically increasing seq. See Reconnect for resync rules.

condition_status — market-level lifecycle

  • Gateway: /ws/market
  • ids: one or more conditionIds (lowercased bytes32 hex)
{ "channel": "condition_status", "ids": ["0xabc..."] }
Use for pause/unpause, oracle outcome announcement, resolution / payout state — anything market-wide that’s keyed to the condition rather than to one outcome token.

system — platform-wide status

  • Gateway: /ws/market
  • ids: must be ["platform_status"]
{ "channel": "system", "ids": ["platform_status"] }
Use for the platform freeze / maintenance / degraded-mode banner.

Update existing subscription

For id-based channels (token_trades, token_book, condition_status, system) you can change ids on an existing sid instead of opening a new subscription.

Add ids

{
  "id": 2,
  "cmd": "update_subscription",
  "params": { "sid": 12, "action": "add_ids", "ids": ["789"] }
}

Remove ids

{
  "id": 3,
  "cmd": "update_subscription",
  "params": { "sid": 12, "action": "remove_ids", "ids": ["123"] }
}
Response (server returns the resulting full id set):
{
  "id": 2,
  "type": "ok",
  "sid": 12,
  "channel": "token_trades",
  "ids": ["456", "789"]
}
update_subscription is rejected with invalid_params for channels that don’t take ids (e.g. user_activity).

Unsubscribe

{
  "id": 4,
  "cmd": "unsubscribe",
  "params": { "sids": [12, 13] }
}
{ "id": 4, "type": "unsubscribed", "sids": [12, 13] }

List subscriptions

{ "id": 5, "cmd": "list_subscriptions" }
{
  "id": 5,
  "type": "subscriptions",
  "items": [
    { "sid": 10, "channel": "user_activity" }
  ]
}
Useful after a reconnect to confirm what the server thinks you’re subscribed to before rebuilding state.

Ping

{ "id": 6, "cmd": "ping" }
{ "id": 6, "type": "pong", "ts": 1776949200000 }
ts is the server clock in milliseconds — clients can use it as a clock-skew probe.