Skip to main content

Documentation Index

Fetch the complete documentation index at: https://limitless-docs-ws-settlement-events.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

WebSocketClient Setup

The WebSocketClient connects to the Limitless Exchange WebSocket server for real-time market data, position updates, order lifecycle events, and transaction notifications.
import { WebSocketClient } from '@limitless-exchange/sdk';

const ws = new WebSocketClient({
  url: 'wss://ws.limitless.exchange',
  autoReconnect: true,
});

ws.connect();

Constructor Options

OptionTypeDefaultDescription
urlstringWebSocket server URL
autoReconnectbooleantrueAutomatically reconnect on disconnection
apiKeystringRequired for authenticated subscriptions (positions, transactions)
Public subscriptions (market prices) do not require an API key. Authenticated subscriptions (positions, order events, transactions) require the apiKey option to be set.

Public Subscriptions

Market Prices

Subscribe to real-time price updates for one or more markets. No authentication required.
const ws = new WebSocketClient({
  url: 'wss://ws.limitless.exchange',
});

ws.connect();

ws.subscribe('subscribe_market_prices', {
  marketSlugs: ['btc-100k-weekly', 'eth-5k-daily'],
  marketAddresses: ['0x1234...'], // For AMM markets
});
Subscriptions replace previous ones. To listen to both CLOB (by slug) and AMM (by address) markets, include both marketSlugs and marketAddresses in a single subscribe_market_prices call.

Authenticated Subscriptions

These subscriptions require an API key passed to the constructor.
const ws = new WebSocketClient({
  url: 'wss://ws.limitless.exchange',
  apiKey: process.env.LIMITLESS_API_KEY,
});

ws.connect();

Positions

Subscribe to real-time updates when your positions change:
ws.subscribe('subscribe_positions');

ws.on('positions', (data) => {
  console.log('Position update:', data);
});

Order Events

Subscribe to CLOB order lifecycle and settlement events for your account:
ws.subscribe('subscribe_order_events');

ws.on('orderEvent', (event: OrderEvent) => {
  if (event.source === 'OME') {
    console.log('Order state:', event.type, event.orderId, event.clientOrderId);
  } else {
    console.log('Settlement:', event.type, event.orderId, event.clientOrderId, event.txHash);
  }
});
orderEvent uses source as a discriminator:
  • source: 'OME' — off-chain order state changes: placement, update, cancellation.
  • source: 'SETTLEMENT' — on-chain settlement results for the taker order and each matched maker order.
For settlement events, clientOrderId is the id of the recipient’s own orderId. If only one side of a trade supplied a clientOrderId, only that side’s event includes it. Counterparty order ids inside takerOrderId or makerMatches[] are not resolved to client ids.

Transactions

Subscribe to transaction confirmations:
ws.subscribe('subscribe_transactions');

ws.on('tx', (data) => {
  console.log('Transaction:', data.hash, data.status);
});

Events

orderbookUpdate (CLOB markets)

Fired when a CLOB market orderbook changes. Contains the full updated orderbook.
ws.on('orderbookUpdate', (data: OrderbookUpdate) => {
  console.log('Market:', data.marketSlug);
  console.log('Bids:', data.orderbook.bids.length);
  console.log('Asks:', data.orderbook.asks.length);

  if (data.orderbook.bids.length > 0 && data.orderbook.asks.length > 0) {
    const spread = data.orderbook.asks[0].price - data.orderbook.bids[0].price;
    console.log('Spread:', spread.toFixed(4));
  }
});

newPriceData (AMM markets)

Fired when AMM market prices update.
ws.on('newPriceData', (data: NewPriceData) => {
  console.log('Market:', data.marketAddress);
  console.log('YES:', data.updatedPrices.yes);
  console.log('NO:', data.updatedPrices.no);
});

positions

Fired when any of your positions change (fill, cancel, resolution).
ws.on('positions', (data: PositionEvent) => {
  console.log('Updated positions:', data);
});

tx

Fired on transaction events related to your account.
ws.on('tx', (data: TransactionEvent) => {
  console.log('Tx hash:', data.hash);
  console.log('Status:', data.status);
});

Type Definitions

interface OrderbookUpdate {
  marketSlug: string;
  orderbook: {
    bids: { price: number; size: number }[];
    asks: { price: number; size: number }[];
  };
}

interface NewPriceData {
  marketAddress: string;
  updatedPrices: {
    yes: string;
    no: string;
  };
}

interface PositionEvent {
  clob: Array<{
    market: { slug: string };
    positions: {
      yes: { size: number; collateral: number };
      no: { size: number; collateral: number };
    };
  }>;
}

type OrderEvent = OmeOrderEvent | SettlementOrderEvent;

interface OmeOrderEvent {
  source: 'OME';
  type: 'PLACEMENT' | 'UPDATE' | 'CANCELLATION';
  eventId: number;
  orderId: string;
  clientOrderId?: string;
  userId: number;
  marketId: string;
  token: string;
  side: 'BUY' | 'SELL';
  price: string;
  remainingSize: string;
  timestamp: string;
}

interface SettlementOrderEvent {
  source: 'SETTLEMENT';
  type: 'MINED' | 'FAILED';
  eventId: string;
  tradeEventId: string;
  orderId?: string;
  clientOrderId?: string;
  takerOrderId?: string;
  takerAccount?: string;
  makerMatches?: Array<{
    account: string;
    orderId: string;
    matchedSize: string;
    price: string;
  }>;
  marketSlug?: string;
  tokenId?: string;
  side?: 'BUY' | 'SELL';
  price?: string;
  amountContracts?: string;
  amountCollateral?: string;
  configuredFeeRateBps?: number;
  effectiveFeeBps?: number;
  feeAmountContracts?: string;
  txHash?: string;
  timestamp: string;
}

interface TransactionEvent {
  hash: string;
  status: 'pending' | 'confirmed' | 'failed';
  type: string;
}

Connection Management

Disconnect handling

Listen for disconnections and clean up resources:
ws.on('disconnect', (reason: string) => {
  console.log('Disconnected:', reason);
});

ws.on('reconnect', () => {
  console.log('Reconnected — resubscribing...');

  ws.subscribe('subscribe_market_prices', {
    marketSlugs: ['btc-100k-weekly'],
  });
});
When autoReconnect is enabled, the client automatically attempts to reconnect. However, you must re-send your subscriptions after reconnection. Listen for the reconnect event to resubscribe.

Graceful shutdown

Clean up the WebSocket connection on process exit:
process.on('SIGINT', () => {
  console.log('Shutting down...');
  ws.disconnect();
  process.exit(0);
});

Debugging

Log all raw events to inspect the data the server sends:
ws.onAny((eventName: string, ...args: unknown[]) => {
  console.log(`[WS] ${eventName}:`, JSON.stringify(args, null, 2));
});
Use raw event logging during development to discover event shapes and debug subscription issues. Remove it before deploying to production.

Full Example

A complete script that subscribes to market prices and positions:
import { WebSocketClient } from '@limitless-exchange/sdk';

const ws = new WebSocketClient({
  url: 'wss://ws.limitless.exchange',
  apiKey: process.env.LIMITLESS_API_KEY,
  autoReconnect: true,
});

ws.connect();

ws.subscribe('subscribe_market_prices', {
  marketSlugs: ['btc-100k-weekly'],
});

ws.subscribe('subscribe_positions');
ws.subscribe('subscribe_order_events');
ws.subscribe('subscribe_transactions');

ws.on('orderbookUpdate', (data) => {
  const best_bid = data.orderbook.bids[0];
  const best_ask = data.orderbook.asks[0];
  console.log(`[${data.marketSlug}] Bid: ${best_bid?.price ?? '-'} | Ask: ${best_ask?.price ?? '-'}`);
});

ws.on('positions', (data) => {
  console.log('[Positions]', JSON.stringify(data));
});

ws.on('orderEvent', (event) => {
  console.log('[OrderEvent]', event.source, event.type, event.orderId, event.clientOrderId ?? '(no client id)');
});

ws.on('tx', (data) => {
  console.log(`[Tx] ${data.hash}${data.status}`);
});

ws.on('disconnect', (reason) => {
  console.log('[Disconnected]', reason);
});

ws.on('reconnect', () => {
  ws.subscribe('subscribe_market_prices', {
    marketSlugs: ['btc-100k-weekly'],
  });
  ws.subscribe('subscribe_positions');
  ws.subscribe('subscribe_order_events');
  ws.subscribe('subscribe_transactions');
});

process.on('SIGINT', () => {
  ws.disconnect();
  process.exit(0);
});

console.log('Listening for events... (Ctrl+C to stop)');