Language: English | Русский
A PHP library for working with the Bybit V5 API. Supports REST and WebSockets, and works both standalone and with Laravel.
Features • Installation • Quick Start • API Methods • TradFi • WebSocket • Examples
- Full Bybit V5 API coverage (spot, linear, inverse, options)
- TradFi support — gold, silver, forex, stock CFDs, and indices via
BybitTradFi - HMAC-SHA256 and RSA-SHA256 signatures
- WebSocket for real-time data (orderbook, trades, klines, account updates)
- Testnet and demo trading support
- Regional endpoints (NL, TR, KZ, GE, AE)
- Laravel integration (facade, service provider, config publishing)
- Automatic reconnection for WebSocket
composer require tigusigalpa/bybit-phpFor local monorepo setup:
- Add repository to
composer.json:
{
"repositories": [
{
"type": "path",
"url": "public_html/packages/bybit-php"
}
]
}- Install the package:
composer require tigusigalpa/bybit-php:* --prefer-source- Publish configuration:
php artisan vendor:publish --tag=bybit-configLaravel auto-discovery регистрирует service provider и facade автоматически.
Create or update your .env file:
BYBIT_API_KEY=your_api_key_here
BYBIT_API_SECRET=your_api_secret_here
BYBIT_TESTNET=true
BYBIT_DEMO_TRADING=false
BYBIT_REGION=global
BYBIT_RECV_WINDOW=5000
BYBIT_SIGNATURE=hmac
# For RSA signature (optional):
# BYBIT_SIGNATURE=rsa
# BYBIT_RSA_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"| Parameter | Type | Default | Description |
|---|---|---|---|
BYBIT_API_KEY |
string | - | Your Bybit API public key |
BYBIT_API_SECRET |
string | - | Your Bybit API secret key |
BYBIT_TESTNET |
boolean | false |
Enable testnet environment |
BYBIT_DEMO_TRADING |
boolean | false |
Enable demo trading environment |
BYBIT_REGION |
string | global |
Regional endpoint (global, nl, tr, kz, ge, ae) |
BYBIT_RECV_WINDOW |
integer | 5000 |
Request receive window (ms) |
BYBIT_SIGNATURE |
string | hmac |
Signature type (hmac or rsa) |
BYBIT_RSA_PRIVATE_KEY |
string | null |
RSA private key (PEM format) |
<?php
require_once 'vendor/autoload.php';
use Tigusigalpa\ByBit\BybitClient;
// Initialize client
$client = new BybitClient(
apiKey: 'your_api_key',
apiSecret: 'your_api_secret',
testnet: true,
region: 'global',
recvWindow: 5000,
signature: 'hmac'
);
// Get server time
$serverTime = $client->getServerTime();
echo "Server Time: " . json_encode($serverTime) . "\n";
// Get market tickers
$tickers = $client->getTickers([
'category' => 'linear',
'symbol' => 'BTCUSDT'
]);
print_r($tickers);
// Place a limit order
$order = $client->createOrder([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'side' => 'Buy',
'orderType' => 'Limit',
'qty' => '0.01',
'price' => '30000',
'timeInForce' => 'GTC'
]);
print_r($order);
// Get positions
$positions = $client->getPositions([
'category' => 'linear',
'symbol' => 'BTCUSDT'
]);
print_r($positions);Using Facade:
use Tigusigalpa\ByBit\Facades\Bybit;
// Get server time
$time = Bybit::getServerTime();
// Get market data
$tickers = Bybit::getTickers([
'category' => 'linear',
'symbol' => 'BTCUSDT'
]);
// Place order
$order = Bybit::createOrder([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'side' => 'Buy',
'orderType' => 'Limit',
'qty' => '0.01',
'price' => '30000'
]);Using Dependency Injection:
use Tigusigalpa\ByBit\BybitClient;
class TradingController extends Controller
{
public function __construct(
private BybitClient $bybit
) {}
public function placeOrder()
{
$order = $this->bybit->createOrder([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'side' => 'Buy',
'orderType' => 'Market',
'qty' => '0.01'
]);
return response()->json($order);
}
}// Get server time
$time = $client->getServerTime();
// Get market tickers
$tickers = $client->getTickers([
'category' => 'linear',
'symbol' => 'BTCUSDT'
]);
// Get kline/candlestick data
$klines = $client->getKline([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'interval' => '60', // 1m, 3m, 5m, 15m, 30m, 60m, 120m, 240m, 360m, 720m, D, W, M
'limit' => 200
]);
// Get orderbook depth
$orderbook = $client->getOrderbook([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'limit' => 50 // Max depth: 1, 25, 50, 100, 200, 500
]);
// Get RPI (Risk Premium Index) orderbook
$rpiOrderbook = $client->getRPIOrderbook([
'category' => 'option',
'symbol' => 'BTC-30DEC23-80000-C',
'limit' => 25
]);
// Get open interest
$openInterest = $client->getOpenInterest([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'intervalTime' => '5min' // 5min, 15min, 30min, 1h, 4h, 1d
]);
// Get recent public trades
$recentTrades = $client->getRecentTrades([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'limit' => 60
]);
// Get funding rate history
$fundingHistory = $client->getFundingRateHistory([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'limit' => 200
]);
// Get historical volatility (options)
$historicalVolatility = $client->getHistoricalVolatility([
'category' => 'option',
'baseCoin' => 'BTC',
'period' => 7 // 7, 14, 21, 30, 60, 90, 180, 270 days
]);
// Get insurance pool data
$insurance = $client->getInsurancePool([
'coin' => 'USDT'
]);
// Get risk limit
$riskLimit = $client->getRiskLimit([
'category' => 'linear',
'symbol' => 'BTCUSDT'
]);// Create order
$order = $client->createOrder([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'side' => 'Buy',
'orderType' => 'Limit',
'qty' => '0.01',
'price' => '30000',
'timeInForce' => 'GTC'
]);
// Get open orders
$openOrders = $client->getOpenOrders([
'category' => 'linear',
'symbol' => 'BTCUSDT'
]);
// Amend order
$amended = $client->amendOrder([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'orderId' => 'order_id_here',
'qty' => '0.02',
'price' => '31000'
]);
// Cancel order
$cancelled = $client->cancelOrder([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'orderId' => 'order_id_here'
]);
// Cancel all orders
$cancelledAll = $client->cancelAllOrders([
'category' => 'linear',
'symbol' => 'BTCUSDT'
]);
// Get order history
$history = $client->getHistoryOrders([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'limit' => 50
]);// Get positions
$positions = $client->getPositions([
'category' => 'linear',
'symbol' => 'BTCUSDT'
]);
// Set leverage
$client->setLeverage('linear', 'BTCUSDT', 10);
// Switch position mode (One-Way or Hedge)
$client->switchPositionMode([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'mode' => 0 // 0: One-Way, 3: Hedge
]);
// Set trading stop (TP/SL)
$client->setTradingStop([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'positionIdx' => 0,
'takeProfit' => '35000',
'stopLoss' => '28000'
]);
// Set auto add margin
$client->setAutoAddMargin([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'autoAddMargin' => 1, // 0: off, 1: on
'positionIdx' => 0
]);
// Manually add or reduce margin
$client->addOrReduceMargin([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'margin' => '100', // positive to add, negative to reduce
'positionIdx' => 0
]);
// Get closed P&L (last 2 years)
$closedPnl = $client->getClosedPnL([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'limit' => 50
]);
// Get closed options positions (last 6 months)
$closedOptions = $client->getClosedOptionsPositions([
'category' => 'option',
'symbol' => 'BTC-30DEC23-80000-C',
'limit' => 50
]);
// Move position between UIDs
$moveResult = $client->movePosition([
'fromUid' => '100307601',
'toUid' => '592324',
'list' => [
[
'category' => 'linear',
'symbol' => 'BTCUSDT',
'price' => '30000',
'side' => 'Buy',
'qty' => '0.01'
]
]
]);
// Get move position history
$moveHistory = $client->getMovePositionHistory([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'limit' => 50
]);
// Confirm new risk limit
$confirmRisk = $client->confirmNewRiskLimit([
'category' => 'linear',
'symbol' => 'BTCUSDT'
]);// Get wallet balance
$balance = $client->getWalletBalance([
'accountType' => 'UNIFIED',
'coin' => 'USDT'
]);
// Get transferable amount (Unified account)
$transferable = $client->getTransferableAmount([
'accountType' => 'UNIFIED',
'coin' => 'USDT'
]);
// Get transaction log
$transactions = $client->getTransactionLog([
'accountType' => 'UNIFIED',
'category' => 'linear',
'limit' => 50
]);
// Get account info
$accountInfo = $client->getAccountInfo();
// Get account instruments info
$instrumentsInfo = $client->getAccountInstrumentsInfo([
'category' => 'linear',
'symbol' => 'BTCUSDT'
]);
// Calculate trading fee
$fee = $client->computeFee('spot', 1000.0, 'Non-VIP', 'taker');Demo trading — тестирование стратегий без риска. Используется домен api-demo.bybit.com.
// Initialize demo trading client
$demoClient = new BybitClient(
apiKey: 'your_demo_api_key',
apiSecret: 'your_demo_api_secret',
testnet: false,
region: 'global',
recvWindow: 5000,
signature: 'hmac',
rsaPrivateKey: null,
http: null,
fees: null,
demoTrading: true // Enable demo trading mode
);
// Create demo account (use production API key with api.bybit.com)
$productionClient = new BybitClient('prod_key', 'prod_secret');
$demoAccount = $productionClient->createDemoAccount();
// Returns: ['uid' => '123456789', ...]
// Request demo funds (use demo API key with api-demo.bybit.com)
$fundingResult = $demoClient->requestDemoFunds([
'adjustType' => 0, // 0: add, 1: reduce
'utaDemoApplyMoney' => [
['coin' => 'USDT', 'amountStr' => '10000'],
['coin' => 'BTC', 'amountStr' => '1']
]
]);
// All trading methods work the same in demo mode
$order = $demoClient->createOrder([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'side' => 'Buy',
'orderType' => 'Market',
'qty' => '0.01'
]);Laravel Demo Trading:
// In .env file
BYBIT_DEMO_TRADING=true
// Use normally
$balance = Bybit::getWalletBalance(['accountType' => 'UNIFIED']);Pure PHP WebSocket:
use Tigusigalpa\ByBit\BybitWebSocket;
// Create WebSocket instance
$ws = new BybitWebSocket(
apiKey: null,
apiSecret: null,
testnet: false,
region: 'global',
isPrivate: false
);
// Subscribe to orderbook
$ws->subscribeOrderbook('BTCUSDT', 50);
// Subscribe to trades
$ws->subscribeTrade('BTCUSDT');
// Subscribe to ticker
$ws->subscribeTicker('BTCUSDT');
// Subscribe to klines
$ws->subscribeKline('BTCUSDT', '1'); // 1m candles
// Handle messages
$ws->onMessage(function($data) {
if (isset($data['topic'])) {
echo "Topic: {$data['topic']}\n";
print_r($data['data']);
}
});
// Start listening (blocking)
$ws->listen();Authenticated WebSocket for account updates:
use Tigusigalpa\ByBit\BybitWebSocket;
$ws = new BybitWebSocket(
apiKey: 'your_api_key',
apiSecret: 'your_api_secret',
testnet: false,
region: 'global',
isPrivate: true
);
// Subscribe to position updates
$ws->subscribePosition();
// Subscribe to order updates
$ws->subscribeOrder();
// Subscribe to execution updates
$ws->subscribeExecution();
// Subscribe to wallet updates
$ws->subscribeWallet();
$ws->onMessage(function($data) {
match($data['topic'] ?? null) {
'position' => handlePositionUpdate($data),
'order' => handleOrderUpdate($data),
'execution' => handleExecutionUpdate($data),
'wallet' => handleWalletUpdate($data),
default => null
};
});
$ws->listen();Laravel Background Command:
// app/Console/Commands/BybitWebSocketListener.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Tigusigalpa\ByBit\BybitWebSocket;
class BybitWebSocketListener extends Command
{
protected $signature = 'bybit:listen {symbol=BTCUSDT}';
protected $description = 'Listen to Bybit WebSocket streams';
public function handle()
{
$symbol = $this->argument('symbol');
$ws = app(BybitWebSocket::class);
$ws->subscribeOrderbook($symbol, 50);
$ws->subscribeTrade($symbol);
$ws->onMessage(fn($data) =>
$this->info(json_encode($data, JSON_PRETTY_PRINT))
);
$this->info("🚀 WebSocket listener started for {$symbol}...");
$ws->listen();
}
}Run with: php artisan bybit:listen BTCUSDT
The BybitTradFi class provides a dedicated interface for trading traditional financial instruments — gold, silver, forex pairs, stock CFDs, and indices — all available on Bybit as linear perpetuals through the standard V5 API.
Instantiate by passing an existing BybitClient:
use Tigusigalpa\ByBit\BybitClient;
use Tigusigalpa\ByBit\BybitTradFi;
$client = new BybitClient(
apiKey: 'your_api_key',
apiSecret: 'your_api_secret',
testnet: true
);
$tradfi = new BybitTradFi($client);BybitTradFi::METALS; // ['XAUUSD', 'XAGUSD', 'XPTUSD']
BybitTradFi::FOREX_MAJORS; // ['EURUSD', 'GBPUSD', 'USDJPY', 'USDCHF', 'AUDUSD', 'NZDUSD', 'USDCAD']
BybitTradFi::FOREX_MINORS; // ['EURGBP', 'EURJPY', 'GBPJPY', ...]
BybitTradFi::US_STOCKS; // ['AAPLUSDT', 'TSLAUSDT', 'NVDAUSDT', ...]
BybitTradFi::INDICES; // ['US500USD', 'US100USD', 'US30USD', 'DE40USD', 'JP225USD', ...]// Get instruments, optionally filtered by asset class:
// 'metal', 'forex', 'stock', 'index', 'commodity', or '' for all
$instruments = $tradfi->getInstruments('forex');
// Single ticker
$gold = $tradfi->getTicker('XAUUSD');
echo $gold['result']['list'][0]['lastPrice'];
// Shortcut tickers
$metals = $tradfi->getMetalsTickers(); // XAUUSD, XAGUSD, XPTUSD
$forex = $tradfi->getForexTickers(); // major pairs
$stocks = $tradfi->getStockTickers(); // US stock CFDs
$indices = $tradfi->getIndexTickers(); // US500USD, DE40USD, etc.
// Kline / candlestick data
// interval: 1, 3, 5, 15, 30, 60, 120, 240, 360, 720, D, W, M
$klines = $tradfi->getKline('XAUUSD', '60', 50);
// Order book depth (1, 25, 50, 100, 200)
$orderbook = $tradfi->getOrderbook('EURUSD', 25);
// Overnight swap fee info
$swap = $tradfi->getSwapFee('XAUUSD');
// Trading fee rate
$fee = $tradfi->getFeeRate('EURUSD');// Place a limit buy order on gold with TP/SL
$order = $tradfi->placeOrder(
symbol: 'XAUUSD',
side: 'Buy',
orderType: 'Limit',
qty: '0.01',
price: '3200',
extra: [
'timeInForce' => 'GTC',
'takeProfit' => '3350',
'stopLoss' => '3100',
]
);
// Place a market sell on EURUSD
$order = $tradfi->placeOrder('EURUSD', 'Sell', 'Market', '1');
// Close an open long position at market price
$tradfi->closePosition('XAUUSD', 'Buy', '0.01');
// Set leverage
$tradfi->setLeverage('XAUUSD', 10);
// Cancel an order
$tradfi->cancelOrder('XAUUSD', orderId: 'abc123');
// Open orders
$orders = $tradfi->getOpenOrders('XAUUSD');
// Order & trade history
$history = $tradfi->getOrderHistory('EURUSD', limit: 50);
$trades = $tradfi->getTradeHistory('XAUUSD', limit: 50);
// Open positions (pass '' for all TradFi positions)
$positions = $tradfi->getPositions('XAUUSD');BybitTradFi::isTradFiSymbol('XAUUSD'); // true — gold
BybitTradFi::isTradFiSymbol('EURUSD'); // true — forex
BybitTradFi::isTradFiSymbol('US500USD'); // true — index
BybitTradFi::isTradFiSymbol('BTCUSDT'); // false — crypto
BybitTradFi::isTradFiSymbol('ETHUSDT'); // false — crypto
// Filter TradFi positions from a mixed position list
$allPositions = $client->getPositions(['category' => 'linear']);
$tradfiOnly = array_filter(
$allPositions['result']['list'] ?? [],
fn($p) => BybitTradFi::isTradFiSymbol($p['symbol'])
);Note: TradFi instruments follow market hours (unlike 24/7 crypto). Outside trading sessions the API may return empty order books or stale prices. Swap fees apply when holding positions past daily market close — check
getSwapFee()before sizing.
// Spot limit order
$order = $client->placeOrder(
type: 'spot',
symbol: 'BTCUSDT',
execution: 'limit',
price: 30000.0,
side: 'Buy',
leverage: null,
size: 0.01,
slTp: null
);
// Derivatives market order with leverage
$order = $client->placeOrder(
type: 'derivatives',
symbol: 'BTCUSDT',
execution: 'market',
price: null,
side: 'Buy',
leverage: 10,
size: 100, // margin in USDT
slTp: [
'type' => 'percent',
'takeProfit' => 0.02, // 2%
'stopLoss' => 0.01 // 1%
]
);
// Trigger order with absolute TP/SL
$order = $client->placeOrder(
type: 'derivatives',
symbol: 'BTCUSDT',
execution: 'trigger',
price: 29500.0,
side: 'Buy',
leverage: 5,
size: 150,
slTp: [
'type' => 'absolute',
'takeProfit' => 31000.0,
'stopLoss' => 29000.0
],
extra: ['timeInForce' => 'GTC']
);// Spot trading fee
$feeSpot = $client->computeFee('spot', 1000.0, 'Non-VIP', 'taker');
// Result: 1.0 USDT (0.1%)
// Derivatives with leverage
$margin = 100.0;
$leverage = 10.0;
$volume = $margin * $leverage; // 1000
$feeDeriv = $client->computeFee('derivatives', $volume, 'VIP1', 'maker');| Region | Code | Endpoint |
|---|---|---|
| 🌐 Global | global |
https://api.bybit.com |
| 🇳🇱 Netherlands | nl |
https://api.bybit.nl |
| 🇹🇷 Turkey | tr |
https://api.bybit-tr.com |
| 🇰🇿 Kazakhstan | kz |
https://api.bybit.kz |
| 🇬🇪 Georgia | ge |
https://api.bybitgeorgia.ge |
| 🇦🇪 UAE | ae |
https://api.bybit.ae |
| 🧪 Testnet | - | https://api-testnet.bybit.com |
Bybit V5 API uses HMAC-SHA256 or RSA-SHA256 for request signing:
For GET requests:
signature_payload = timestamp + api_key + recv_window + queryString
For POST requests:
signature_payload = timestamp + api_key + recv_window + jsonBody
HMAC-SHA256: Returns lowercase hex RSA-SHA256: Returns base64
X-BAPI-API-KEY: your_api_key
X-BAPI-TIMESTAMP: 1234567890000
X-BAPI-RECV-WINDOW: 5000
X-BAPI-SIGN: generated_signature
X-BAPI-SIGN-TYPE: 2 (for HMAC)
Content-Type: application/json (for POST)
Official docs: https://bybit-exchange.github.io/docs/v5/guide
<?php
require 'vendor/autoload.php';
use Tigusigalpa\ByBit\BybitClient;
$client = new BybitClient(
apiKey: getenv('BYBIT_API_KEY'),
apiSecret: getenv('BYBIT_API_SECRET'),
testnet: true
);
// Check balance
$balance = $client->getWalletBalance([
'accountType' => 'UNIFIED',
'coin' => 'USDT'
]);
echo "Balance: {$balance['result']['list'][0]['totalWalletBalance']} USDT\n";
// Get current price
$ticker = $client->getTickers([
'category' => 'linear',
'symbol' => 'BTCUSDT'
]);
$currentPrice = $ticker['result']['list'][0]['lastPrice'];
echo "BTC Price: \${$currentPrice}\n";
// Place order
$order = $client->createOrder([
'category' => 'linear',
'symbol' => 'BTCUSDT',
'side' => 'Buy',
'orderType' => 'Limit',
'qty' => '0.01',
'price' => (string)($currentPrice * 0.99), // 1% below market
'timeInForce' => 'GTC'
]);
echo "Order placed: {$order['result']['orderId']}\n";Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
MIT License
Copyright (c) 2026 Igor Sazonov
- Author: Igor Sazonov (
tigusigalpa) - Email: sovletig@gmail.com
- GitHub: https://github.com/tigusigalpa/bybit-php
