Connect Your Bot to Bybit V5: Authentication, WebSocket, Rate Limiting

A trading bot losing connection to the exchange, orders failing due to limits, and positions diverging from reality—all consequences of shallow API integration. We connect your bot to Bybit V5 turnkey: configuring authentication, WebSocket, and rate limiting so your strategy runs reliably. Our team handles the entire cycle, from audit to support, delivering a dependable solution that scales with your business.

Blockchain Development Services

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1335
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1293
  • B2B Advance company logo design
    B2B Advance company logo design
    738
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1031
  • AIDER company logo development
    AIDER company logo development
    978
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1087

Your crypto bot loses connection to the exchange, orders fail due to rate limits, position sync drifts from reality — the result of a shallow API integration. Especially if you use async trading. We are a team of blockchain engineers with 5+ years of experience in trading bot development. We integrate your bot with Bybit API V5 end-to-end: from authentication setup to fault-tolerant WebSocket.

Recently, a client lost $50k due to incorrect WebSocket reconnect handling — we fixed it in two days. Bybit V5 API offers 40% lower latency compared to V3 thanks to unified endpoints and improved limits. We connect any strategy: from simple DCA to complex arbitrage grids. After deploying our solution, another client cut operational costs by $12k per month through automation. We guarantee stable bot operation 24/7 with minimal latency.

Why Bybit V5 Authentication Differs from V3

Bybit API uses HMAC-SHA256 signing. In V5, the signature string format changed: now you must include timestamp, api_key, recv_window, and request parameters. The field order is critical. An ordering mistake — and the request is rejected with code 10001. We automate signature generation, eliminating manual edits. According to Bybit V5 documentation, this approach is mandatory for all trading requests.

import hmac
import hashlib
import time
import httpx

class BybitClient:
    BASE_URL = "https://api.bybit.com"

    def __init__(self, api_key: str, api_secret: str, testnet: bool = False):
        self.api_key = api_key
        self.api_secret = api_secret
        if testnet:
            self.BASE_URL = "https://api-testnet.bybit.com"

    def _sign(self, params: str, timestamp: int) -> str:
        sign_str = f"{timestamp}{self.api_key}5000{params}"
        return hmac.new(
            self.api_secret.encode('utf-8'),
            sign_str.encode('utf-8'),
            hashlib.sha256
        ).hexdigest()

    async def get_wallet_balance(self, account_type: str = "UNIFIED") -> dict:
        timestamp = int(time.time() * 1000)
        params = f"accountType={account_type}"
        signature = self._sign(params, timestamp)
        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"{self.BASE_URL}/v5/account/wallet-balance",
                params={"accountType": account_type},
                headers={
                    "X-BAPI-API-KEY": self.api_key,
                    "X-BAPI-TIMESTAMP": str(timestamp),
                    "X-BAPI-RECV-WINDOW": "5000",
                    "X-BAPI-SIGN": signature
                }
            )
            return response.json()

Placing Orders

async def place_order(
        self, category: str, symbol: str, side: str, order_type: str, qty: str, price: str = None, time_in_force: str = "GTC"
) -> dict:
    payload = {
        "category": category,
        "symbol": symbol,
        "side": side,
        "orderType": order_type,
        "qty": qty,
        "timeInForce": time_in_force
    }
    if price:
        payload["price"] = price
    timestamp = int(time.time() * 1000)
    body = json.dumps(payload)
    signature = self._sign(body, timestamp)
    async with httpx.AsyncClient() as client:
        response = await client.post(
            f"{self.BASE_URL}/v5/order/create",
            content=body,
            headers={
                "X-BAPI-API-KEY": self.api_key,
                "X-BAPI-TIMESTAMP": str(timestamp),
                "X-BAPI-RECV-WINDOW": "5000",
                "X-BAPI-SIGN": signature,
                "Content-Type": "application/json"
            }
        )
    return response.json()

How to Set Up WebSocket for Real-Time Data?

For real-time market data, we use WebSocket. The connection involves three steps:

  1. Connect to wss://stream.bybit.com/v5/public/linear.
  2. Send a JSON with operation subscribe and channel arguments (e.g., orderbook.50.BTCUSDT).
  3. Process incoming messages asynchronously.

For private channels (orders, positions), use wss://stream.bybit.com/v5/private with HMAC-signed authentication. Bybit recommends refreshing subscriptions every 24 hours — we implement automatic reconnection with exponential backoff and heartbeat pings every 20 seconds.

Example WebSocket Implementation
import asyncio
import websockets
import json

class BybitWebSocket:
    WS_URL = "wss://stream.bybit.com/v5/public/linear"

    async def subscribe_orderbook(self, symbol: str, depth: int = 50):
        async with websockets.connect(self.WS_URL) as ws:
            await ws.send(json.dumps({
                "op": "subscribe",
                "args": [f"orderbook.{depth}.{symbol}"]
            }))
            async for message in ws:
                data = json.loads(message)
                if data.get("topic", "").startswith("orderbook"):
                    await self.process_orderbook(data)

    async def subscribe_private(self, api_key: str, api_secret: str):
        ws_url = "wss://stream.bybit.com/v5/private"
        async with websockets.connect(ws_url) as ws:
            expires = int((time.time() + 10) * 1000)
            sign = hmac.new(
                api_secret.encode(),
                f"GET/realtime{expires}".encode(),
                hashlib.sha256
            ).hexdigest()
            await ws.send(json.dumps({
                "op": "auth",
                "args": [api_key, expires, sign]
            }))
            await ws.send(json.dumps({
                "op": "subscribe",
                "args": ["order", "execution", "position"]
            }))
            async for message in ws:
                data = json.loads(message)
                await self.handle_private_event(data)

Rate Limits

Bybit V5 enforces stricter limits than V3. REST endpoints in V5 allow 120 requests per second per IP, while V3 allowed up to 150. However, WebSocket subscriptions became more efficient: a single connection can serve up to 480 channels instead of 200.

Method Limit Comment
REST (global) 120 req/s per IP Across all endpoints
REST (per endpoint) 10-600 req/s Depends on type
WebSocket 480 subscriptions per connection Per connection
import asyncio
from collections import deque

class RateLimiter:
    def __init__(self, max_requests: int, window_seconds: float):
        self.max_requests = max_requests
        self.window = window_seconds
        self.requests = deque()

    async def acquire(self):
        now = time.monotonic()
        while self.requests and self.requests[0] < now - self.window:
            self.requests.popleft()
        if len(self.requests) >= self.max_requests:
            sleep_time = self.requests[0] + self.window - now
            await asyncio.sleep(sleep_time)
        self.requests.append(time.monotonic())

For security, store API keys in environment variables (.env), not in code. Use python-dotenv for loading. This is standard practice in production.

What Is a Rate Limiter and How Does It Prevent Blocking?

A rate limiter controls the number of requests to an API per unit time. Without it, your bot may exceed Bybit's limits and get temporarily blocked. Our adaptive rate limiter uses a request queue with exponential backoff on overage. It automatically adjusts to current load, distributing requests evenly. For high-frequency strategies, we use multiple API keys to increase throughput without risking a block.

Error Handling

Bybit returns retCode: 0 on success, non-zero on error.

def check_response(self, response: dict, operation: str):
    ret_code = response.get("retCode", -1)
    if ret_code != 0:
        error_msg = response.get("retMsg", "Unknown error")
        raise BybitAPIError(f"{operation} failed [{ret_code}]: {error_msg}")
    return response.get("result", {})

Common error codes:

Code Meaning Action
10001 Invalid API key Check key and permissions
10006 Rate limit exceeded Wait or reduce frequency
110007 Insufficient balance Adjust order size
130021 Order not found Verify orderId

How to Test the Integration: Step-by-Step Guide

  1. Set up a testnet account on Bybit and obtain test API keys.
  2. Run unit tests for your client: check signing, balance retrieval, order placement.
  3. Connect to WebSocket testnet and verify data arrives within 5 seconds.
  4. Test the rate limiter: send 150 requests per second — the bot should not get code 10006.
  5. Run a stress test: simulate connection loss and check automatic reconnection.
  6. Test error handling: send an invalid API key — the bot should handle the exception correctly.

Common Integration Mistakes

  • Missing recvWindow parameter not signed — must include X-BAPI-RECV-WINDOW in headers.
  • side parameter sent in lowercase (buy/sell) — Bybit expects Buy/Sell.
  • For limit orders, price is mandatory even if timeInForce: "IOC" is set.
  • WebSocket subscription to orderbook.200.100ms requires depth up to 200, but not all symbols support it.

What's Included in the Work

  • Source code of the Bybit V5 client (Python, async).
  • Configuration files for mainnet and testnet.
  • Documentation for deployment and monitoring.
  • Access to a repository with a sample trading strategy.
  • Team training (2 hours online).
  • One month of technical support post-launch.

All source code is covered by tests, documentation is in Russian. Deployment to your server or cloud — we set it up within an hour.

Process

Analysis → Architecture design → API module implementation → Integration of your strategy → Testnet testing → Mainnet deployment → Monitoring and optimization. At each stage — transparent reporting. You always know the status and can influence priorities.

Timelines

From 2 to 4 weeks depending on strategy complexity and trading volumes. The cost is calculated individually. Contact us for a consultation — we will evaluate your project and offer the optimal solution. Order the integration today and get a reliable bot with minimal latency.