Skip to main content
All numeric values are returned as decimal strings to preserve precision. Timestamps are unix-ms unless noted. Slot is Solana slot number. Pubkeys are base58 strings.

Orderbook

Snapshot (sent on subscribe and on resync)
Bids are sorted descending by price; asks ascending. Each level is [price, size] (size in base tokens). Delta (sent when the aggregated book changes):
Each delta entry is [price, new_size]. A new_size of "0" means the level is gone, apply it as a delete. Levels not present in the delta are unchanged. sequenceId is monotonic per market. If your client sees a gap (current sequenceId > last + 1), call resync to recover.

Trades

Snapshot (most recent 50 trades, newest first):
The snapshot array is ordered most-recent-first data[0] is the newest trade). Up to 50 trades are returned DEFAULT_TRADES_LIMIT). Live trade (one per fill) — note type is "update", **not** "trade":
Full data field reference (one trade). Every value is a decimal string unless noted:
Fees. Two distinct fees ride on a trade:
  • fee — the taker (protocol) fee, in quote-token units. It’s derived from
the market’s taker_fee_ppm fee = quote_notional × ppm / 1_000_000), using the multiplied sync fee on hybrid markets. The same value appears on both the snapshot and the live update for a trade.
  • integratorFeeAtoms — a separate integrator/referral fee, in atoms, paid
to integratorFeeWallet. Independent of the protocol fee.

Ticker

Pushed on subscribe and at the ticker engine’s update cadence (~1 second by default, ticker.update_interval_ms). Unlike orderbook and trades, the ticker has **no distinct snapshot frame** — the on-subscribe push is an ordinary type: "update" frame identical to the periodic ones. Treat the first one you receive as your snapshot.
volume24h is quote-denominated; baseVolume24h is base-denominated.

Kline / mid_kline

Snapshot (current open bar):
Update (sent whenever the current bar changes, and when it closes):
time is the unix-seconds (not ms) of the bar’s open. The same shape is used for mid_kline with "ch": "mid_kline". Bar close is signaled by a new bar opening — there’s no explicit “bar closed” message.

user_orders / limit_orders (LO lifecycle)

Both channels emit the same payload shape — user_orders is filtered to the subscribed wallet and carries a top-level user; limit_orders is unfiltered for the market and carries a top-level maker instead. type is one of "placed", "resized", "canceled".
data field reference (LoEventPayload) For "type": "resized", data includes both prevSize and newSize. For "type": "canceled", data includes prevSize, and data.size echoes the size that was on chain pre-cancel newSize is absent). For "type": "placed", neither prevSize nor newSize is present. limit_orders is identical but replaces "user" with "maker":
sequenceNumber is the maker book’s last_updated_sequence_number after the mutation — it’s the join key for matching fills to a specific placement (see user_fills below).

user_fills

One message per MakerFillEvent where the maker is the subscribed wallet.
makerFee is signed — a leading - indicates a rebate. sequenceNumber matches the placement event’s sequenceNumber for the level that was hit: a fill at seq S belongs to the latest placed / resized for the same (side, price) with sequenceNumber <= S.

mini_tickers

Pushed periodically (~1.5s) as a single map of every market’s compact ticker:

market_updates

Three frame types, all on the market_updates channel. Note the type values are "listed" / "status_changed" / "delisted" (not prefixed with market_):
status values match the REST API: "active", "paused", "closed"
A market close emits two frames. When a market transitions to "closed", the server sends both a status_changed (with status: "closed") and a delisted frame. Watch delisted if you just want the terminal “market is gone” signal; watch status_changed for the full active ↔ paused ↔ closed lifecycle. delisted fires only on the close transition — not for active or paused.