Disconnected

Message Log

0 messages

No messages yet

Connect to a WebSocket server to see messages

Public WebSocket API

WebSocket Connection Management

WebSocket endpoint is wss://api.whitebit.com/ws

The API is based on JSON RPC of WebSocket protocol.

⚠️️ Connection Timeout ⚠️️

  • Server closes websocket connection after 60 seconds of inactivity
  • Inactivity is defined as no messages sent by the client

Maintaining Connection

To keep the websocket connection active:

  • Send periodic ping messages every 50 seconds
  • Handle potential connection closures gracefully in your application logic

Example Implementation

// Establish websocket connection
const socket = new WebSocket("wss://api.whitebit.com/ws");
 
// Set up periodic ping
setInterval(() => {
  if (socket.readyState === WebSocket.OPEN) {
    socket.send(JSON.stringify({
            id: 0,
            method: "ping",
            params: [],
        }));
  }
}, 50000); // Every 50 seconds

❗ Rate limit 1000 ws connections per minute and 200 requests per minute in one connection.❗

All endpoints return time in Unix-time format.

⤴️ Request message

JSON Structure of request message:

  • id - Integer. Should be unique to handle response for your request.
  • method - String. Name of request.
  • params - Array. Here you pass params for method.

🚫 WebSocket connection will be closed if invalid JSON was sent.

Types of request messages

  • Query (ping, candles_request, etc)
  • Subscription (candles_subscribe, lastprice_subscribe, etc). Repeated subscription will be cancelled for the same data type.

⤵️ Response message

JSON Structure of response message:

  • id - Integer. Id of request.
  • result - Null for failure, for success - look for responses below
  • error - Null for success, JSON Object for failure:
    • message - Detailed text
    • code - Error code
CodeMessage
1invalid argument
2internal error
3service unavailable
4method not found
5service timeout

Types of response messages

  • Query result
  • Subscription status (success/failed)
  • Update events

Examples

Example messages for request with response:

⤴️ Request

{
  "id": 0,
  "method": "ping",
  "params": []
}

⤵️ Response

{
  "id": 0,
  "result": "pong",
  "error": null
}

Example subscription:

⤴️ Request

{
  "id": 0,
  "method": "candles_subscribe",
  "params": []
}

⤵️ Response

{
  "id": 0,
  "result": {
    "status": "success"
  },
  "error": null
}

🔄 Update events

{
  "id": null,
  "method": "candles_update",
  "params": [] // look below for params
}

API

Service

Ping

⤴️ Request
{
  "id": 0,
  "method": "ping",
  "params": []
}
⤵️ Response
{
  "id": 0,
  "result": "pong",
  "error": null
}

Time

⤴️ Request
{
  "id": 1,
  "method": "time",
  "params": []
}
⤵️ Response
{
  "id": 1,
  "result": 1493285895,
  "error": null
}

Kline

Query

The requested interval must meet the following conditions:

  • If the number is less than 60, then 60 must be divisible by the requested number without a remainder;
  • Less than 3600 (1 hour) - the number must be divisible by 60 without a remainder, and 3600 must be divisible by the requested number without a remainder;
  • Less than 86400 (day) - the number must be whitened by 3600 without a remainder, and 86400 must be divisible by the number without a remainder;
  • Less than 86400 * 7 (week) - the number must be divisible by 86400 without a remainder;
  • Equal to 86400 * 7;
  • Equal to 86400 * 30.
⤴️ Request
{
  "id": 2,
  "method": "candles_request",
  "params": [
    "ETH_BTC", // market
    1659569940, // start time
    1660894800, // end time
    3600 // interval in seconds
  ]
}
⤵️ Response
{
    "id": 2,
    "result": [
        [
            1580860800,       // time
            "0.020543",       // open
            "0.020553",       // close
            "0.020614",       // highest
            "0.02054",        // lowest
            "7342.597",       // volume in stock
            "151.095481849",  // volume in deal
            "ETH_BTC"         // market
        ],
    ],
    "error": null
}

Subscribe

Update interval: 0.5 sec

⤴️ Request
{
  "id": 3,
  "method": "candles_subscribe",
  "params": [
    "BTC_USD", // market
    900 // interval in seconds
  ]
}
⤵️ Response
{
  "id": 3,
  "result": {
    "status": "success"
  },
  "error": null
}
🔄 Update events
{
  "id": null,
  "method": "candles_update",
  "params": [
    [
      1580895000, // time
      "0.020683", // open
      "0.020683", // close
      "0.020683", // high
      "0.020666", // low
      "504.701", // volume in stock
      "10.433600491", // volume in money (deal)
      "ETH_BTC" // market
    ]
  ]
}

Unsubscribe

⤴️ Request
{
  "id": 4,
  "method": "candles_unsubscribe",
  "params": []
}
⤵️ Response
{
  "id": 4,
  "result": {
    "status": "success"
  },
  "error": null
}

Last price

Query

⤴️ Request
{
  "id": 5,
  "method": "lastprice_request",
  "params": [
    "ETH_BTC" // market
  ]
}
⤵️ Response
{
  "id": 5,
  "result": "0.020553",
  "error": null
}

Subscribe

Update interval: 1 sec

⤴️ Request
{
    "id": 6,
    "method": "lastprice_subscribe",
    "params": [
        "ETH_BTC", // markets
        "BTC_USDT",
    ]
}
⤵️ Response
{
  "id": 6,
  "result": {
    "status": "success"
  },
  "error": null
}
🔄 Update events
{
  "id": null,
  "method": "lastprice_update",
  "params": [
    "ETH_BTC", // market
    "0.020683" // price
  ]
}

Unsubscribe

⤴️ Request
{
  "id": 7,
  "method": "lastprice_unsubscribe",
  "params": []
}
⤵️ Response
{
  "id": 7,
  "result": {
    "status": "success"
  },
  "error": null
}

Market statistics

Query

⤴️ Request
{
  "id": 5,
  "method": "market_request",
  "params": [
    "ETH_BTC", // market
    86400 // period in seconds
  ]
}
⤵️ Response
{
  "id": 5,
  "result": {
    "period": 86400, // period in seconds
    "last": "0.020981", // last price
    "open": "0.02035", // open price that was at 'now - period' time
    "close": "0.020981", // price that closes this period
    "high": "0.020988", // highest price
    "low": "0.020281", // lowest price
    "volume": "135220.218", // volume in stock
    "deal": "2776.587022649" // volume in money
  },
  "error": null
}

Subscribe

You can subscribe only for 86400s (24h from now).

Update interval: 1 sec

⤴️ Request
{
    "id": 6,
    "method": "market_subscribe",
    "params": [
        "ETH_BTC", // markets
        "BTC_USDT",
    ]
}
⤵️ Response
{
  "id": 6,
  "result": {
    "status": "success"
  },
  "error": null
}
🔄 Update events
{
  "id": null,
  "method": "market_update",
  "params": [
    "ETH_BTC", // market
    {
      // response same as 'market_request'
      "period": 86400, // period in seconds
      "last": "0.020964", // last price
      "open": "0.020349", // open price that was at 'now - period' time
      "close": "0.020964", // price that closes this period
      "high": "0.020997", // highest price
      "low": "0.020281", // lowest price
      "volume": "135574.476", // volume in stock
      "deal": "2784.413999488" // volume in money
    }
  ]
}

Unsubscribe

⤴️ Request
{
  "id": 7,
  "method": "market_unsubscribe",
  "params": []
}
⤵️ Response
{
  "id": 7,
  "result": {
    "status": "success"
  },
  "error": null
}

Market statistics for current day UTC

Query

⤴️ Request
{
  "id": 14,
  "method": "marketToday_query",
  "params": [
    "ETH_BTC" // only one market per request
  ]
}
⤵️ Response
{
  "id": 14,
  "result": {
    "last": "0.020981", // last price
    "open": "0.02035", // open price that was at 'now - period' time
    "high": "0.020988", // highest price
    "low": "0.020281", // lowest price
    "volume": "135220.218", // volume in stock
    "deal": "2776.587022649" // volume in money
  },
  "error": null
}

Subscribe

Update interval: 1 sec

⤴️ Request
{
    "id": 15,
    "method": "marketToday_subscribe",
    "params": [
        "ETH_BTC", // markets
        "BTC_USDT",
    ]
}
⤵️ Response
{
  "id": 15,
  "result": {
    "status": "success"
  },
  "error": null
}
🔄 Update events
{
  "id": null,
  "method": "marketToday_update",
  "params": [
    "ETH_BTC", // market
    {
      // response same as 'market_request'
      "last": "0.020964", // last price
      "open": "0.020349", // open price that was at 'now - period' time
      "high": "0.020997", // highest price
      "low": "0.020281", // lowest price
      "volume": "135574.476", // volume in stock
      "deal": "2784.413999488" // volume in money
    }
  ]
}

Unsubscribe

⤴️ Request
{
  "id": 16,
  "method": "marketToday_unsubscribe",
  "params": []
}
⤵️ Response
{
  "id": 16,
  "result": {
    "status": "success"
  },
  "error": null
}

Market trades

Query

⤴️ Request
{
  "id": 8,
  "method": "trades_request",
  "params": [
    "ETH_BTC", // market
    100, // limit
    41358445 // largest id from which you want to request trades
  ]
}
⤵️ Response
{
    "id": 8,
    "result": [
        {
            "id": 41358530,           // trade id
            "time": 1580905394.70332, // time in milliseconds
            "price": "0.020857",      // trade price
            "amount": "5.511",        // trade amount
            "type": "sell"            // type of trade (buy/sell)
        },
    ],
    "error": null
}
 

Subscribe

Update interval: real-time

❗ For each websocket connection, you can subscribe to either one or several specific markets, or all markets. Every following subscription will replace the existing one.

Note: To subscribe to all markets, send the request with an empty params array.

⤴️ Request

Subscribe to specific markets:

{
    "id": 9,
    "method": "trades_subscribe",
    "params": [
        "ETH_BTC", // markets
        "BTC_USDT",
    ]
}

Subscribe to all markets:

{
    "id": 9,
    "method": "trades_subscribe",
    "params": []
}
⤵️ Response
{
  "id": 9,
  "result": {
    "status": "success"
  },
  "error": null
}
🔄 Update events
{
    "id": null,
    "method": "trades_update",
    "params": [
        "ETH_BTC",                         // market
         [                                 // response same as 'market_request'
             {
                 "id": 41358530,           // trade id
                 "time": 1580905394.70332, // time in milliseconds
                 "price": "0.020857",      // trade price
                 "amount": "5.511",        // trade amount
                 "type": "sell",           // type of trade (buy/sell)
                 "rpi": true               // Indicates whether the trade involved a Retail Price Improvement (RPI) order
             }
         ]
    ]
}

Unsubscribe

⤴️ Request
{
  "id": 10,
  "method": "trades_unsubscribe",
  "params": []
}
⤵️ Response
{
  "id": 10,
  "result": {
    "status": "success"
  },
  "error": null
}

Market depth

Query

This endpoint allows clients to request the current market depth for a specific cryptocurrency pair.

⤴️ Request
{
  "id": 11,
  "method": "depth_request",
  "params": [
    "ETH_BTC", // market
    100, // limit, max value is 100
    "0" // price interval units. "0" - no interval, available values - "0.00000001", "0.0000001", "0.000001", "0.00001", "0.0001", "0.001", "0.01", "0.1"
  ]
}
⤵️ Response
{
    "id": 11,
    "result": {
        "timestamp": 1689600180.5164471, // timestamp of the update from matchengine
        "asks": [                   // sorted ascending
            ["0.020846", "29.369"], // [price, amount]
        ],
        "bids": [                   // sorted descending
            ["0.02083", "9.598"],   // [price, amount]
        ]
    },
    "error": null
}
 

Subscribe

This endpoint allows clients to subscribe to market depth data updates. After successful subscription, the server immediately sends a full snapshot of the current order book as the first depth_update message. Subsequent messages are incremental updates containing only changes. The server pushes updates every 100ms to subscribed clients when there are actual changes to the order book.

⤴️ Request
{
  "id": 12,
  "method": "depth_subscribe",
  "params": [
    "ETH_BTC",  // market
    100,        // limit. available values - 1, 5, 10, 20, 30, 50, 100
    "0",        // price interval units. "0" - no interval, available values - "0.00000001", "0.0000001", "0.000001", "0.00001", "0.0001", "0.001", "0.01", "0.1"
    true        // multiple subscription flag. true - add, false - unsubscribe from all
  ]
}

The fourth parameter - Multiple subscription flag - allows you to subscribe to market depths as many markets as you want. The only restriction is one subscription with specific parameters per market.

INFO: If 10 seconds have elapsed without a change in the depth subscription, a snapshot message will be pushed again

⤵️ Response
{
  "id": 12,
  "result": {
    "status": "success"
  },
  "error": null
}
🔄 Update events

Update events provide real-time updates to the subscribed market depth. The first message after subscription is a full snapshot of the order book, while subsequent messages are incremental updates.

First message (full snapshot):

{
    "id": null,
    "method": "depth_update",
    "params": [
        true,
        {
            "timestamp": 1689600180.5164471, // timestamp of the update from matchengine
            "update_id": 214403,
            "asks": [                   // sorted ascending - full order book snapshot
                ["0.020846", "29.369"],
                ["0.020850", "15.123"],
                ["0.020855", "8.456"],
            ],
            "bids": [                   // sorted descending - full order book snapshot
                ["0.020844", "5.949"],
                ["0.020840", "12.345"],
                ["0.020835", "20.678"],
            ],
            "event_time": 1749026542.817343
        },
        "ETH_BTC"                       // market pair
    ]
}

Subsequent messages (incremental updates):

{
    "id": null,
    "method": "depth_update",
    "params": [
        false,
        {
            "timestamp": 1689600180.5164471, // timestamp of the update from matchengine
            "update_id": 214404,
            "past_update_id": 214403, // present in incremental updates
            "asks": [
                ["0.020861", "0"],      // finished orders will be [price, "0"]
                ["0.020900", "2.5"],
            ],
            "bids": [
                ["0.020844", "5.949"],
                ["0.020800", "0"],
            ],
            "event_time": 1749026542.817343
        },
        "ETH_BTC"                       // market pair
    ]
}
💻 Code examples
type IDepth = [string, string];
 
interface OrderBook {
    asks: IDepth[];
    bids: IDepth[];
}
 
const ws = new WebSocket("wss://api.whitebit.com/ws");
const orderBook: OrderBook = { asks: [], bids: [] };
const LIMIT = 100;
 
ws.addEventListener("open", () => {
    ws.send(
        JSON.stringify({
            id: 1,
            method: "depth_subscribe",
            params: ["ETH_BTC", LIMIT, "0", true]
        }),
    );
});
 
ws.addEventListener("message", (event: MessageEvent) => {
    const message = JSON.parse(event.data.toString());
 
    if (message.method === "depth_update") {
        const updateData = message.params[0] as Partial<OrderBook & { past_update_id?: number }>;
        const isFirstMessage = !updateData.past_update_id;
 
        if (isFirstMessage) {
            // First message or keepalive snapshot is a full snapshot - replace order book
            orderBook.asks = updateData.asks ?? [];
            orderBook.bids = updateData.bids ?? [];
        } else {
            // Subsequent messages are incremental updates
            applyUpdates(orderBook.asks, updateData.asks, "ask");
            applyUpdates(orderBook.bids, updateData.bids, "bid");
            truncateOrderBook(orderBook.asks);
            truncateOrderBook(orderBook.bids);
        }
    }
});
 
function applyUpdates(orderBookSide: IDepth[], updates: IDepth[] | undefined, side: "ask" | "bid") {
    if (updates === undefined) return;
    for (const [price, amount] of updates) {
        // Find the index of an entry in orderBookSide that matches the given price.
        const priceIndex = orderBookSide.findIndex((level) => level[0] === price);
 
        // If the amount is '0', it means this price level should be removed from the orderBookSide.
        if (amount === "0") {
            if (priceIndex !== -1) {
                // Remove the existing price level since the amount is '0'.
                orderBookSide.splice(priceIndex, 1);
            }
        } else {
            // If the amount is not '0', either update the existing price level or add a new one.
            if (priceIndex === -1) {
                // Find the position where the new price level should be inserted.
               const insertIndex = orderBookSide.findIndex((level) =>
                    side === "ask" ? level[0] > price : level[0] < price
                );
 
                if (insertIndex === -1) {
                    // Add to the end if there's no higher price level.
                    orderBookSide.push([price, amount]);
                } else {
                    // Insert at the correct sorted position.
                    orderBookSide.splice(insertIndex, 0, [price, amount]);
                }
            } else {
                // Update the amount for the existing price level.
                orderBookSide[priceIndex][1] = amount;
            }
        }
    }
}
 
function truncateOrderBook(orderBookSide: IDepth[]) {
    if (orderBookSide.length > LIMIT) {
        // Only truncate if the length exceeds the LIMIT
        orderBookSide.splice(LIMIT);
    }
}

Unsubscribe

This endpoint allows clients to unsubscribe from real-time updates of market depth data.

⤴️ Request
{
  "id": 13,
  "method": "depth_unsubscribe",
  "params": []
}
⤵️ Response
{
  "id": 13,
  "result": {
    "status": "success"
  },
  "error": null
}

Book Ticker

The Book Ticker stream provides instant snapshot updates to the best bid and ask prices and quantities for a market.

Subscribe

Update interval: instant snapshot of the current best bid and ask (BBO), followed by incremental updates.

⤴️ Request
{
    "method": "bookTicker_subscribe",
    "params": [
        "SHIB_PERP" // Optional: market name. If empty, subscribes to all markets
    ],
    "id": 1
}
⤵️ Response
{
  "id": 1,
  "result": {
    "status": "success"
  },
  "error": null
}
🔄 Update events
{
    "method": "bookTicker_update",
    "params": [
        [
            1751958383.5933869, // transaction_time - timestamp of the update from matchengine
            1751958383.5935569, // message_time - timestamp of the message from websocket
            "SHIB_PERP",        // market
            80670102,           // update_id
            "0.000011751",      // best_bid_price
            "12547000",         // best_bid_amount
            "0.000011776",      // best_ask_price
            "17424000"          // best_ask_amount
        ]
    ],
    "id": null
}

Unsubscribe

⤴️ Request
{
    "method": "bookTicker_unsubscribe",
    "params": [],
    "id": 2
}
⤵️ Response
{
  "id": 2,
  "result": {
    "status": "success"
  },
  "error": null
}

Try out WebSocket API directly in the documentation