Bybit API Trading: The Complete Guide to Automated Crypto
Master Bybit API trading with step-by-step Python examples, TradingView webhooks, futures automation, copy trading setup, and demo account testing tips.
Master Bybit API trading with step-by-step Python examples, TradingView webhooks, futures automation, copy trading setup, and demo account testing tips.
Bybit has become one of the most developer-friendly exchanges in crypto, and its REST API is a big reason why. Whether you're building a bybit api trading bot, connecting Pine Script alerts from TradingView, or automating futures positions, the V5 API gives you everything you need under one roof. This guide walks through everything from generating your first API key to executing live trades and pulling bybit api trade history — with working Python code you can run today.
Before writing a single line of code, you need API credentials. On Bybit, go to Account Settings and navigate to API Management. You'll create a key pair — a public API key and a private secret — and assign permissions based on what your bot needs to do. Keep the secret somewhere safe; Bybit only shows it once.
Bybit offers three permission levels: Read-Only (for pulling bybit api trade history and account data), Trade (for placing and canceling orders), and Withdraw (never assign this to an automated bot). For most algorithmic trading setups, Read plus Trade is everything you need.
Bybit's testnet (testnet.bybit.com) mirrors the live API exactly. The bybit api paper trading environment uses the same endpoints, same authentication, and same response structure — just a different base URL and separate credentials. Code that works on testnet will work on mainnet with a one-line URL change.
Bybit's V5 API uses HMAC-SHA256 signatures. Every private request requires a millisecond timestamp, your API key, a receive window (how long the signed request stays valid), and a signature computed from those values concatenated with your request body or query string. Here's the authentication layer you'll reuse across all your API calls:
import hashlib
import hmac
import time
import requests
import json
API_KEY = "your_api_key_here"
API_SECRET = "your_api_secret_here"
BASE_URL = "https://api.bybit.com" # Swap to "https://api-testnet.bybit.com" for demo
RECV_WINDOW = "5000"
def generate_signature(payload: str, timestamp: str) -> str:
param_str = timestamp + API_KEY + RECV_WINDOW + payload
return hmac.new(
API_SECRET.encode("utf-8"),
param_str.encode("utf-8"),
hashlib.sha256
).hexdigest()
def get_headers(payload: str) -> dict:
"""Build signed headers. Pass query string for GET, JSON body for POST."""
timestamp = str(int(time.time() * 1000))
return {
"X-BAPI-API-KEY": API_KEY,
"X-BAPI-SIGN": generate_signature(payload, timestamp),
"X-BAPI-TIMESTAMP": timestamp,
"X-BAPI-RECV-WINDOW": RECV_WINDOW,
"Content-Type": "application/json",
}
The receive window (5000ms by default) defines how long the server will accept a signed request after the timestamp. If your system clock drifts from Bybit's servers, you'll start getting timestamp mismatch errors. On Linux, sync with ntpdate or chronyc; on Mac, system time is typically accurate enough. Unlike OKX which requires an additional passphrase header, or Binance which uses a slightly different HMAC format, Bybit's approach is clean and consistent across all V5 endpoints.
The core of any bybit api trading bot is order execution. Bybit's V5 API uses a unified endpoint for spot, futures, and options — you switch markets by changing the category field. This is a genuine advantage over Binance, where spot and futures APIs live under entirely different base paths and require separate implementations.
def place_market_order(
symbol: str,
side: str,
qty: str,
category: str = "spot"
) -> dict:
"""
Place a market order on Bybit.
category options: 'spot', 'linear' (USDT perp), 'inverse' (coin perp)
side: 'Buy' or 'Sell'
"""
payload = {
"category": category,
"symbol": symbol,
"side": side,
"orderType": "Market",
"qty": qty,
}
body = json.dumps(payload)
headers = get_headers(body)
response = requests.post(
f"{BASE_URL}/v5/order/create",
headers=headers,
data=body,
timeout=10
)
result = response.json()
if result["retCode"] == 0:
print(f"Order placed successfully: {result['result']['orderId']}")
else:
print(f"Error {result['retCode']}: {result['retMsg']}")
return result
# Market buy 0.001 BTC on spot
place_market_order("BTCUSDT", "Buy", "0.001", category="spot")
# Open a long position on BTC USDT perpetual futures (qty in contracts)
place_market_order("BTCUSDT", "Buy", "0.01", category="linear")
Now let's pull the bybit api trade history to review executions. The execution list endpoint returns filled trades with price, quantity, fee paid, and timestamp — everything you need for trade journaling, tax reporting, or feeding a performance dashboard.
def get_trade_history(
symbol: str = "BTCUSDT",
category: str = "spot",
limit: int = 50
) -> list:
"""Fetch recent executions. Returns a list of trade dicts."""
query = f"category={category}&symbol={symbol}&limit={limit}"
headers = get_headers(query) # For GET requests, sign the query string
response = requests.get(
f"{BASE_URL}/v5/execution/list?{query}",
headers=headers,
timeout=10
)
data = response.json()
if data["retCode"] != 0:
raise RuntimeError(f"API error {data['retCode']}: {data['retMsg']}")
trades = data["result"]["list"]
for t in trades:
print(
f"{t['execTime']} | {t['side']:4s} "
f"{t['execQty']} @ {t['execPrice']} "
f"| fee: {t['execFee']} {t['feeCurrency']}"
)
return trades
# Fetch last 50 ETH spot trades
get_trade_history("ETHUSDT", category="spot")
Always check retCode before processing the response body. Common error codes to handle in production: 10001 (invalid parameters — usually a typo in symbol or category), 10003 (invalid API key — double-check your credentials), and 110007 (insufficient margin on futures orders). Build your error handler once and reuse it everywhere.
Bybit's bybit api futures trading layer is where the platform really earns its reputation. The linear category covers USDT-margined perpetuals — BTCUSDT, ETHUSDT, SOLUSDT — while inverse covers coin-margined contracts where your collateral is the base asset itself (BTC, ETH). Most bots target linear because USDT accounting is predictable: your PnL is always in dollars.
One important detail for futures bots: you need to set the position mode (one-way or hedge) before placing your first order. In one-way mode, a Buy on BTCUSDT opens a long and a Sell closes it. In hedge mode, Buy and Sell create separate long and short positions simultaneously. Set it once via /v5/position/switch-mode and it persists.
For bybit api copy trading, Bybit exposes dedicated endpoints to follow signal providers and mirror their trades programmatically. You can set per-provider position size multipliers, max drawdown limits, and stop conditions. Access requires enabling copy trading API permissions separately in account settings. Platforms like Binance and OKX have similar social trading APIs, but Bybit's copy trading infrastructure is more mature and better documented for developers building on top of it.
| Category | Market Type | Margin Asset | Best For |
|---|---|---|---|
| linear | USDT Perpetuals | USDT | Most trading bots, trend-following strategies |
| inverse | Coin Perpetuals | BTC / ETH | Hedging, coin-native position management |
| spot | Spot Markets | Quote currency | DCA bots, grid trading, spot arbitrage |
| option | Options | USDC | Volatility strategies, delta-neutral hedging |
The most popular use case for bybit api tradingview integration is webhook-driven order execution. When a Pine Script strategy fires an alert on TradingView, it sends a JSON payload to a URL you control — your server translates that signal into a Bybit order. This is how thousands of retail traders automate strategies without writing their own signal logic from scratch.
Services like VoiceOfChain publish real-time on-chain and market signals that traders route through exactly this kind of webhook bridge — turning curated alerts into automated executions on Bybit, OKX, Binance, or whichever exchange the trader prefers. The architecture is simple: signal source → webhook server → exchange API.
from flask import Flask, request, jsonify
app = Flask(__name__)
WEBHOOK_SECRET = "replace_with_your_own_secret"
@app.route("/webhook", methods=["POST"])
def tradingview_webhook():
data = request.get_json(force=True)
# Validate the incoming alert is from your TradingView alert
if data.get("secret") != WEBHOOK_SECRET:
return jsonify({"error": "Unauthorized"}), 401
symbol = data.get("symbol", "BTCUSDT")
side = data.get("side") # 'Buy' or 'Sell'
qty = data.get("qty", "0.001")
category = data.get("category", "linear")
if side not in ("Buy", "Sell"):
return jsonify({"error": f"Invalid side: {side}"}), 400
result = place_market_order(symbol, side, qty, category)
return jsonify(result)
if __name__ == "__main__":
# Deploy this on a VPS or cloud function with a public URL
app.run(host="0.0.0.0", port=5000)
In TradingView, set your alert message body to JSON like: {"secret": "your_secret", "symbol": "BTCUSDT", "side": "Buy", "qty": "0.01", "category": "linear"}. Point the Webhook URL field at your publicly accessible server. Never expose this endpoint without the secret check — anyone who discovers the URL could trigger trades on your account.
Understanding the bybit api trading fee structure is critical for bot profitability. Spot trading on Bybit starts at 0.10% for both maker and taker at the standard tier, with a 25% discount if you hold BIT tokens. USDT perpetual futures are where the fee structure gets genuinely interesting: taker orders cost 0.06%, but maker limit orders earn a -0.01% rebate. That means providing liquidity with limit orders actually pays you.
| Market | Maker Fee | Taker Fee | Notes |
|---|---|---|---|
| Spot | 0.10% | 0.10% | 25% discount with BIT token holdings |
| USDT Perpetuals (linear) | -0.01% | 0.06% | Negative maker = rebate on limit orders |
| Coin Perpetuals (inverse) | -0.01% | 0.06% | Same structure, coin-margined |
| Options | 0.02% | 0.05% | Calculated on underlying notional value |
For bybit api demo trading and bybit api paper trading, use the testnet base URL https://api-testnet.bybit.com with credentials created at testnet.bybit.com. The testnet is fully functional — you receive simulated USDT, all V5 endpoints behave identically to mainnet, and you can run your bot under real market conditions without touching real funds. Make it a rule: every new strategy runs for at least one week on testnet before going live.
Rate limits on Bybit's API are applied per endpoint group and per UID. Most order-related endpoints allow 10 requests per second. If you're building a high-frequency system, switch to WebSocket streams for real-time price data and order updates — this eliminates polling entirely and keeps your REST API budget for actual order operations. Bybit returns HTTP 429 with a Retry-After header when throttled; implement exponential backoff and respect it.
If your bot runs on USDT perpetuals and primarily places limit orders, the -0.01% maker rebate means trading is net-profitable on fees alone. A strategy doing $500K in monthly notional volume earns $50 in rebates just from fee structure — before counting any actual trade PnL.
Bybit's V5 API is one of the cleanest exchange interfaces in the industry — unified authentication, consistent endpoint structure across spot and futures, a fully functional bybit api paper trading environment, and a fee model that actually rewards limit order placement with rebates. Whether you're wiring up a bybit api tradingview webhook bridge, building a full bybit api trading bot with custom signal logic, or connecting to curated real-time signals from a platform like VoiceOfChain, the foundation is the same: solid HMAC authentication, careful error handling by retCode, and a firm habit of always testing on bybit api demo trading before any real capital goes live. The patterns in this guide will take you from zero to executing live orders in a single afternoon.