Skip to content

WebSocket API

Igor Sazonov edited this page Mar 15, 2026 · 1 revision

A guide to working with the OKX WebSocket API for real-time data streaming.

Overview

The SDK supports all 53 OKX WebSocket channels:

  • Public channels β€” Market data (no authentication required)
  • Private channels β€” Account data (authentication required)
  • Business channels β€” Deposits, withdrawals, and related events

Creating a Client

use Tigusigalpa\OKX\WebsocketClient;

$ws = new WebsocketClient(
    apiKey: 'your-api-key',
    secretKey: 'your-secret-key',
    passphrase: 'your-passphrase',
    isDemo: false
);

Public Channels

Connect

$ws->connectPublic();

Tickers

$ws->subscribe('tickers', ['instId' => 'BTC-USDT'], function ($data) {
    $ticker = $data['data'][0];
    echo "BTC-USDT: {$ticker['last']}\n";
    echo "24h Volume: {$ticker['vol24h']}\n";
    echo "24h Change: {$ticker['sodUtc0']}\n";
});

Order Book

// Full order book
$ws->subscribe('books', ['instId' => 'BTC-USDT'], function ($data) {
    $book = $data['data'][0];
    echo "Asks: " . count($book['asks']) . "\n";
    echo "Bids: " . count($book['bids']) . "\n";
});

// Top 5 levels
$ws->subscribe('books5', ['instId' => 'BTC-USDT'], function ($data) {
    $book = $data['data'][0];
    $bestAsk = $book['asks'][0];
    $bestBid = $book['bids'][0];
    echo "Best Ask: {$bestAsk[0]} @ {$bestAsk[1]}\n";
    echo "Best Bid: {$bestBid[0]} @ {$bestBid[1]}\n";
});

Trades

$ws->subscribe('trades', ['instId' => 'BTC-USDT'], function ($data) {
    foreach ($data['data'] as $trade) {
        echo "Trade: {$trade['side']} {$trade['sz']} @ {$trade['px']}\n";
    }
});

Candlesticks

// Available intervals: 1m, 3m, 5m, 15m, 30m, 1H, 2H, 4H, 6H, 12H, 1D, 1W, 1M
$ws->subscribe('candle1H', ['instId' => 'BTC-USDT'], function ($data) {
    foreach ($data['data'] as $candle) {
        [$ts, $open, $high, $low, $close, $vol, $volCcy] = $candle;
        echo "Candle: O:{$open} H:{$high} L:{$low} C:{$close}\n";
    }
});

Index Tickers

$ws->subscribe('index-tickers', ['instId' => 'BTC-USDT'], function ($data) {
    $index = $data['data'][0];
    echo "Index Price: {$index['idxPx']}\n";
});

Funding Rate

$ws->subscribe('funding-rate', ['instId' => 'BTC-USDT-SWAP'], function ($data) {
    $funding = $data['data'][0];
    echo "Funding Rate: {$funding['fundingRate']}\n";
    echo "Next Funding Time: {$funding['nextFundingTime']}\n";
});

Mark Price

$ws->subscribe('mark-price', ['instId' => 'BTC-USDT-SWAP'], function ($data) {
    $mark = $data['data'][0];
    echo "Mark Price: {$mark['markPx']}\n";
});

Open Interest

$ws->subscribe('open-interest', ['instId' => 'BTC-USDT-SWAP'], function ($data) {
    $oi = $data['data'][0];
    echo "Open Interest: {$oi['oi']}\n";
});

Private Channels

Connect

$ws->connectPrivate();

Account

$ws->subscribe('account', ['ccy' => 'BTC'], function ($data) {
    foreach ($data['data'] as $account) {
        echo "Currency: {$account['ccy']}\n";
        echo "Balance: {$account['bal']}\n";
        echo "Available: {$account['availBal']}\n";
        echo "Frozen: {$account['frozenBal']}\n";
    }
});

Positions

$ws->subscribe('positions', [
    'instType' => 'SWAP',
    'instId' => 'BTC-USDT-SWAP'
], function ($data) {
    foreach ($data['data'] as $position) {
        echo "Position: {$position['instId']}\n";
        echo "Size: {$position['pos']}\n";
        echo "PnL: {$position['upl']}\n";
        echo "Margin: {$position['margin']}\n";
    }
});

Orders

$ws->subscribe('orders', ['instType' => 'SPOT'], function ($data) {
    foreach ($data['data'] as $order) {
        echo "Order {$order['ordId']}: {$order['state']}\n";
        echo "Instrument: {$order['instId']}\n";
        echo "Side: {$order['side']}\n";
        echo "Price: {$order['px']}\n";
        echo "Size: {$order['sz']}\n";
        echo "Filled: {$order['accFillSz']}\n";
    }
});

Algo Orders

$ws->subscribe('orders-algo', ['instType' => 'SPOT'], function ($data) {
    foreach ($data['data'] as $algoOrder) {
        echo "Algo Order {$algoOrder['algoId']}: {$algoOrder['state']}\n";
        echo "Type: {$algoOrder['ordType']}\n";
        echo "Trigger Price: {$algoOrder['triggerPx']}\n";
    }
});

Fills

$ws->subscribe('fills', ['instType' => 'SPOT'], function ($data) {
    foreach ($data['data'] as $fill) {
        echo "Fill: {$fill['side']} {$fill['fillSz']} @ {$fill['fillPx']}\n";
        echo "Fee: {$fill['fee']} {$fill['feeCcy']}\n";
    }
});

Balance and Positions

$ws->subscribe('balance_and_position', [], function ($data) {
    $balData = $data['data'][0]['balData'] ?? [];
    $posData = $data['data'][0]['posData'] ?? [];
    
    echo "Balances:\n";
    foreach ($balData as $bal) {
        echo "  {$bal['ccy']}: {$bal['cashBal']}\n";
    }
    
    echo "Positions:\n";
    foreach ($posData as $pos) {
        echo "  {$pos['instId']}: {$pos['pos']}\n";
    }
});

Liquidation Warnings

$ws->subscribe('liquidation-warning', ['instType' => 'SWAP'], function ($data) {
    foreach ($data['data'] as $warning) {
        echo "⚠️ Liquidation Warning!\n";
        echo "Position: {$warning['instId']}\n";
        echo "Margin Ratio: {$warning['mgnRatio']}\n";
    }
});

Business Channels

Connect

$ws->connectBusiness();

Deposits

$ws->subscribe('deposit-info', [], function ($data) {
    foreach ($data['data'] as $deposit) {
        echo "Deposit: {$deposit['ccy']} {$deposit['amt']}\n";
        echo "Status: {$deposit['state']}\n";
        echo "TxId: {$deposit['txId']}\n";
    }
});

Withdrawals

$ws->subscribe('withdrawal-info', [], function ($data) {
    foreach ($data['data'] as $withdrawal) {
        echo "Withdrawal: {$withdrawal['ccy']} {$withdrawal['amt']}\n";
        echo "Status: {$withdrawal['state']}\n";
        echo "TxId: {$withdrawal['txId']}\n";
    }
});

Managing Subscriptions

Unsubscribe from a channel

$ws->unsubscribe('tickers', ['instId' => 'BTC-USDT']);

Subscribe to multiple instruments

$instruments = ['BTC-USDT', 'ETH-USDT', 'SOL-USDT'];

foreach ($instruments as $instId) {
    $ws->subscribe('tickers', ['instId' => $instId], function ($data) use ($instId) {
        $ticker = $data['data'][0];
        echo "{$instId}: {$ticker['last']}\n";
    });
}

Running the Client

// Start listening (blocking call)
$ws->run();

// Stop the client
$ws->stop();

Automatic Reconnection

The client automatically reconnects if the connection drops:

$ws->connectPublic();

$ws->subscribe('tickers', ['instId' => 'BTC-USDT'], function ($data) {
    // Subscriptions are automatically restored after reconnection
    echo "Price: {$data['data'][0]['last']}\n";
});

$ws->run(); // Reconnects automatically on errors

Heartbeat (Ping/Pong)

The client sends a ping every 25 seconds automatically β€” no manual configuration needed.

Full Example

use Tigusigalpa\OKX\WebsocketClient;

$ws = new WebsocketClient(
    apiKey: 'your-api-key',
    secretKey: 'your-secret-key',
    passphrase: 'your-passphrase'
);

// Public data
$ws->connectPublic();

// Monitor price
$ws->subscribe('tickers', ['instId' => 'BTC-USDT'], function ($data) {
    $ticker = $data['data'][0];
    $price = (float) $ticker['last'];
    
    // Alert when price crosses a threshold
    if ($price > 60000) {
        echo "πŸš€ BTC above $60,000!\n";
    }
});

// Monitor trades
$ws->subscribe('trades', ['instId' => 'BTC-USDT'], function ($data) {
    foreach ($data['data'] as $trade) {
        $size = (float) $trade['sz'];
        
        // Alert on large trades
        if ($size > 10) {
            echo "πŸ‹ Large trade: {$trade['side']} {$size} BTC\n";
        }
    }
});

// Start
$ws->run();

Channel Reference

Public Channels (31)

  • tickers β€” Ticker data
  • books β€” Full order book
  • books5 β€” Top 5 levels
  • books-l2-tbt β€” L2 order book (tick-by-tick)
  • bbo-tbt β€” Best bid/offer (tick-by-tick)
  • trades β€” Trade stream
  • candle1m, candle3m, candle5m, candle15m, candle30m β€” Minute candles
  • candle1H, candle2H, candle4H, candle6H, candle12H β€” Hourly candles
  • candle1D, candle1W, candle1M β€” Daily / weekly / monthly candles
  • index-tickers β€” Index tickers
  • index-candle1D β€” Index candles
  • mark-price β€” Mark price
  • mark-price-candle1D β€” Mark price candles
  • price-limit β€” Price limits
  • funding-rate β€” Funding rate
  • open-interest β€” Open interest
  • estimated-price β€” Estimated delivery price
  • opt-summary β€” Options summary
  • liquidation-orders β€” Liquidation orders
  • public-block-trades β€” Public block trades
  • block-tickers β€” Block tickers

Private Channels (18)

  • account β€” Account updates
  • positions β€” Position updates
  • balance_and_position β€” Combined balance and position updates
  • orders β€” Order updates
  • orders-algo β€” Algo order updates
  • fills β€” Fill notifications
  • liquidation-warning β€” Liquidation warnings
  • account-greeks β€” Greeks (options)
  • rfqs β€” RFQ updates
  • quotes β€” Quote updates
  • grid-orders-spot β€” Grid orders (spot)
  • grid-orders-contract β€” Grid orders (contracts)
  • grid-positions β€” Grid positions
  • grid-sub-orders β€” Grid sub-orders
  • algo-advance β€” Advanced algo orders
  • algo-recurring-buy β€” Recurring buy
  • copytrading-lead-notification β€” Copy trading notifications
  • adl-warning β€” ADL warnings

Business Channels (4)

  • deposit-info β€” Deposit events
  • withdrawal-info β€” Withdrawal events
  • sprd-orders β€” Spread orders
  • sprd-trades β€” Spread trades

Back: ← REST API | Next: Laravel Integration β†’