X-Api-Key — the
same key you use for HTTP, same scope rules. A missing or invalid
key closes the socket with 4401 <reason> before any subscribe
command is accepted.
| Gateway | Endpoint | Auth | What’s there |
|---|---|---|---|
| Market | WSS /ws/market | X-Api-Key (partners) OR Bearer JWT (retail, SIWE) | Public trades, orderbook snapshots, market lifecycle, platform status |
| User | WSS /ws/user | X-Api-Key (partners) OR Bearer JWT (retail, SIWE) | Own orders / fills / vault state, deposits, withdrawals, ERC-1155 changes |
Both gateways accept the same two schemes as HTTP —
X-Api-Key for
partners, Bearer JWT for the first-party frontend. Private channels
user_activity and vault_activity require the portfolio:read
scope on API keys; JWT callers bypass the scope check as the wallet
owner. vault_activity is reachable only from JWT-authenticated
sockets (partner rows don’t carry a vault claim — by design). See
/ws/user for the full handshake
matrix and close codes.subscribe, update_subscription,
unsubscribe, list_subscriptions, ping), same per-subscription
sid model on both.
WSS /ws/market
Market data gateway — subscribe by
tokenId / conditionId.WSS /ws/user
Private gateway —
X-Api-Key (partners) or Bearer JWT (retail).Commands
All five client → server commands with payloads + responses.
Server events
Per-channel event catalog (push payloads).
Conventions
- Numeric fields are decimal strings (
"price": "0.52") — don’t parse intoNumber. - Addresses lowercased;
tokenIddecimal-string with no leading zeroes;conditionIdlowercased 32-byte hex. sidis connection-local, not stable across reconnects.- Auth is validated at handshake only — rotating a key does not
invalidate an open socket. Close + reopen to switch identity.
Revoking a key on the admin panel closes every live socket bound
to that
keyIdimmediately via Redis pub/sub. - Heartbeat: send
{ "id": N, "cmd": "ping" }every 20–30 s; the server replies{ "id": N, "type": "pong", "ts": <ms> }.
Implementation status (testnet)
| Channel | Status |
|---|---|
token_trades (/ws/market) | ✅ live — per-fill events flow as soon as a match prints |
user_activity (/ws/user) | ✅ live — order placement, cancel, fill, account-control events |
system (/ws/market) | ✅ live |
condition_status (/ws/market) | ⚠️ subscribe accepted, but events not yet emitted by upstream |
token_book (/ws/market) | ⚠️ subscribe accepted, but book_snapshot / book_delta not yet pushed — under repair |
token_book ships, poll GET /api/markets/{symbol}/orderbook on
demand if you need a snapshot. The protocol contract stays stable —
new events will land on the existing channels without subscription
changes.