Thassa.

API reference

WebSocket

One connection, JSON frames, channel subscriptions. The socket powers the app’s live order books; API keys get the same feed.

Connect

WS/v1/wsX-Thassa-Key or ?key=

Authenticate on connect with the X-Thassa-Key header, or ?key= where headers are unavailable (browsers). Either scope (read or trade) may subscribe to market-data channels.

Node (ws) — header auth
import WebSocket from "ws";

const ws = new WebSocket("ws://localhost:8080/v1/ws", {
  headers: { "X-Thassa-Key": process.env.THASSA_KEY! },
});

ws.on("open", () => {
  ws.send(JSON.stringify({ type: "subscribe", channel: "book:42" }));
});

ws.on("message", (raw) => {
  const { type, channel, payload } = JSON.parse(raw.toString());
  if (type === "book.delta") applyDelta(payload);
  if (type === "book.trade") recordTrade(payload);
});

Frame shape

Every frame — both directions — is:

frame
{ "type": "…", "channel": "…", "payload": { … } }

Subscribing

API keys subscribe to order-book channels: book:{marketId} — order-book deltas plus trades for one market. Subscribe to as many markets as you need on a single connection.

subscribe / unsubscribe
// client → server
{ "type": "subscribe",   "channel": "book:42" }
{ "type": "unsubscribe", "channel": "book:42" }

Channel authorization

Subscriptions are authorized server-side per channel. App-session connections additionally use dm:{conversationId} and user:{me} channels; API keys are for book:* market data.

Events

Book deltas

book.delta
// server → client: a price level changed (shares = new total at the level;
// "0" removes the level)
{
  "type": "book.delta",
  "channel": "book:42",
  "payload": {
    "market_id": "42",
    "side": "yes",
    "price_cents": 62,
    "shares": "1150"
  }
}

Trades

book.trade
// server → client: a fill occurred
{
  "type": "book.trade",
  "channel": "book:42",
  "payload": {
    "market_id": "42",
    "side": "yes",
    "price_cents": 62,
    "shares": "300",
    "fee": "1649200",
    "tx_hash": "0x8c31…e9d0",
    "created_at": "2026-07-15T21:09:44Z"
  }
}

The recommended pattern: fetch the snapshot from GET /trade-api/v1/markets/{id}/book after subscribing, then apply deltas — replacing each level’s total with payload.shares. Deltas are totals, not increments, so a missed frame self-heals on the next delta for that level.

Connection lifecycle

  • The server pings periodically; unresponsive connections are dropped. Reply with standard pongs (every client library does this automatically).
  • On reconnect, re-subscribe and re-fetch snapshots — subscriptions don’t survive the connection.
  • Delivery is best-effort; the REST book endpoint is always the recoverable source of truth.