bybit-client 0.1.0

A Rust client library for the Bybit V5 API with REST and WebSocket support
Documentation

bybit-client

A Rust client library for the Bybit V5 API.

  • Full REST API V5 coverage for market data, trading, positions, and account management
  • WebSocket support for real-time public and private streams
  • WebSocket Trade API for low-latency order management
  • Local orderbook management with delta updates
  • HMAC-SHA256 authentication
  • Async/await support with Tokio
  • Strongly typed request/response structures
  • Automatic retry with exponential backoff
  • Testnet and demo trading support

Installation

[dependencies]
bybit-client = "0.1"

REST API

use bybit_client::{BybitClient, Category};
use bybit_client::api::market::GetTickersParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a public-only client (no authentication needed for public endpoints)
    let client = BybitClient::public_only()?;

    // Get ticker data
    let params = GetTickersParams::new(Category::Linear).symbol("BTCUSDT");
    let tickers = client.market().get_tickers(&params).await?;

    for ticker in &tickers.list {
        println!("{}: ${}", ticker.symbol, ticker.last_price);
    }

    Ok(())
}

Authenticated client

use bybit_client::{BybitClient, ClientConfig, Category, Side};
use bybit_client::types::trade::OrderParams;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create an authenticated client
    let client = BybitClient::new("your_api_key", "your_api_secret")?;

    // Or use testnet for testing
    let client = BybitClient::with_config(
        ClientConfig::new("api_key", "api_secret").testnet()
    )?;

    // Place a market order
    let params = OrderParams::market(Category::Linear, "BTCUSDT", Side::Buy, "0.001");
    let result = client.trade().submit_order(&params).await?;
    println!("Order ID: {}", result.order_id);

    Ok(())
}

WebSocket streams

use bybit_client::ws::{WsClient, WsChannel, WsMessage};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Connect to public stream
    let (client, mut receiver) = WsClient::connect_public(WsChannel::PublicLinear).await?;

    // Subscribe to orderbook and trades
    client.subscribe(&["orderbook.50.BTCUSDT", "publicTrade.BTCUSDT"]).await?;

    // Process incoming messages
    while let Some(msg) = receiver.recv().await {
        match msg {
            WsMessage::Orderbook(ob) => {
                println!("Orderbook: {} bids, {} asks",
                    ob.data.bids.len(), ob.data.asks.len());
            }
            WsMessage::Trade(trades) => {
                for trade in &trades.data {
                    println!("Trade: {} {} @ {}",
                        trade.symbol, trade.size, trade.price);
                }
            }
            _ => {}
        }
    }

    Ok(())
}

Local orderbook

use bybit_client::ws::{WsClient, WsChannel, WsMessage, LocalOrderbook};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let (client, mut receiver) = WsClient::connect_public(WsChannel::PublicLinear).await?;
    client.subscribe(&["orderbook.50.BTCUSDT"]).await?;

    let mut orderbook = LocalOrderbook::new("BTCUSDT");

    while let Some(msg) = receiver.recv().await {
        if let WsMessage::Orderbook(update) = msg {
            orderbook.apply_update(&update)?;

            if let (Some(bid), Some(ask)) = (orderbook.best_bid(), orderbook.best_ask()) {
                println!("Best bid: {} @ {}, Best ask: {} @ {}",
                    bid.size, bid.price, ask.size, ask.price);
                println!("Spread: {:.4}", orderbook.spread().unwrap_or(0.0));
            }
        }
    }

    Ok(())
}

Private WebSocket streams

use bybit_client::ws::{WsClient, WsMessage};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Connect with authentication
    let (client, mut receiver) = WsClient::connect_private(
        "your_api_key",
        "your_api_secret",
    ).await?;

    // Subscribe to private topics
    client.subscribe(&["position", "order", "execution"]).await?;

    while let Some(msg) = receiver.recv().await {
        match msg {
            WsMessage::Position(pos) => println!("Position update: {:?}", pos),
            WsMessage::Order(order) => println!("Order update: {:?}", order),
            WsMessage::Execution(exec) => println!("Execution: {:?}", exec),
            _ => {}
        }
    }

    Ok(())
}

API coverage

REST API services

Service Description Authentication
market() Market data (tickers, orderbook, klines, trades) Public
trade() Order placement and management Required
position() Position information and management Required
account() Wallet balance and account info Required

WebSocket topics

Public topics

  • orderbook.{depth}.{symbol} - Orderbook (depth: 1, 50, 200, 500)
  • publicTrade.{symbol} - Public trades
  • tickers.{symbol} - Ticker updates
  • kline.{interval}.{symbol} - Kline/candlestick data
  • liquidation.{symbol} - Liquidation events

Private topics

  • position - Position updates
  • execution - Execution updates
  • order - Order updates
  • wallet - Wallet balance updates

Configuration

use bybit_client::{ClientConfig, Environment, ApiRegion};

let config = ClientConfig::new("api_key", "api_secret")
    .testnet()                    // Use testnet environment
    .recv_window(10000)           // Set recv_window to 10 seconds
    .debug(true)                  // Enable debug logging
    .timeout_ms(30000);           // Set request timeout to 30 seconds

Environment variables

For convenience, you can set credentials via environment variables:

export BYBIT_API_KEY="your_api_key"
export BYBIT_API_SECRET="your_api_secret"