tigusigalpa / okx-php
A production-grade PHP/Laravel SDK for the OKX v5 API.
Requires
- php: ^8.2
- guzzlehttp/guzzle: ^7.0
- psr/log: ^3.0
- textalk/websocket: ^1.6
Requires (Dev)
- laravel/framework: ^11.0|^12.0
- phpunit/phpunit: ^11.0
README
PHP client for the OKX v5 API. Covers the entire REST API (335 endpoints, 16 categories) and WebSocket API (53 channels). Works standalone or plugs into Laravel 11/12 via a Service Provider.
Go version: tigusigalpa/okx-go | Wiki
What's inside
- 335 REST endpoints grouped into service classes (
account(),trade(),market(), etc.) - WebSocket client with auto-reconnect and ping/pong heartbeat
- HMAC-SHA256 request signing
- Demo trading mode (just flip a flag)
- Typed DTOs for requests and responses; all prices/amounts stay as
stringto avoid float rounding - Laravel Service Provider, Facade, publishable config
- PSR-3 logging, PSR-12 code style
- PHP 8.2+ (
readonlyclasses, named arguments)
Requirements
- PHP 8.2+
- Composer
- Laravel 11 or 12 (optional)
Installation
composer require tigusigalpa/okx-php
Laravel setup
Publish the config:
php artisan vendor:publish --tag=okx-config
Add credentials to .env:
OKX_API_KEY=your-api-key OKX_SECRET_KEY=your-secret-key OKX_PASSPHRASE=your-passphrase OKX_DEMO=false
Then use the facade:
use Tigusigalpa\OKX\Facades\OKX; $balance = OKX::account()->getBalance(); $order = OKX::trade()->placeOrder( instId: 'BTC-USDT', tdMode: 'cash', side: 'buy', ordType: 'limit', sz: '0.01', px: '50000' ); $ticker = OKX::market()->getTicker('BTC-USDT');
Standalone usage
use Tigusigalpa\OKX\Client; $client = new Client( apiKey: 'your-api-key', secretKey: 'your-secret-key', passphrase: 'your-passphrase', ); $balance = $client->account()->getBalance(); $order = $client->trade()->placeOrder( instId: 'BTC-USDT', tdMode: 'cash', side: 'buy', ordType: 'market', sz: '100', tgtCcy: 'quote_ccy' ); $trades = $client->market()->getTrades('BTC-USDT', limit: 100);
Configuration
| Option | Env variable | Default | |
|---|---|---|---|
api_key |
OKX_API_KEY |
'' |
API key |
secret_key |
OKX_SECRET_KEY |
'' |
Secret key |
passphrase |
OKX_PASSPHRASE |
'' |
Passphrase |
demo |
OKX_DEMO |
false |
Use demo trading environment |
base_url |
OKX_BASE_URL |
https://www.okx.com |
Base URL |
REST API coverage
335 endpoints across 16 categories:
| Category | # | Docs |
|---|---|---|
| Account | 53 | Trading Account |
| Trade | 32 | Order Book Trading |
| Market | 24 | Market Data |
| Public Data | 24 | Public Data |
| Asset | 26 | Funding Account |
| Finance | 33 | Financial Products |
| Copy Trading | 26 | Copy Trading |
| Trading Bot | 44 | Trading Bot |
| RFQ | 20 | Block Trading |
| Spread Trading | 13 | Spread Trading |
| Rubik | 15 | Trading Statistics |
| Fiat | 13 | Fiat |
| Users | 8 | Sub-account |
| Support | 2 | Announcements |
| System Status | 1 | Status |
| Affiliate | 1 | Affiliate |
WebSocket
Public channel:
use Tigusigalpa\OKX\WebsocketClient; $ws = new WebsocketClient( apiKey: 'your-api-key', secretKey: 'your-secret-key', passphrase: 'your-passphrase' ); $ws->connectPublic(); $ws->subscribe('tickers', ['instId' => 'BTC-USDT'], function ($data) { echo "BTC-USDT: " . $data['data'][0]['last'] . PHP_EOL; }); $ws->run();
Private channel (authenticated automatically on connect):
$ws->connectPrivate(); $ws->subscribe('account', ['ccy' => 'BTC'], function ($data) { foreach ($data['data'] as $account) { echo "Balance: {$account['bal']} {$account['ccy']}" . PHP_EOL; } }); $ws->run();
Public channels include tickers, books, books5, trades, candle*, index-tickers, mark-price,
funding-rate, open-interest, liquidation-orders, and others.
Private channels include account, positions, orders, orders-algo, fills, balance_and_position,
liquidation-warning, deposit-info, withdrawal-info, and others.
Demo trading
Set OKX_DEMO=true in .env, or pass isDemo: true to the constructor. Same API, sandbox environment, no real money
involved.
$client = new Client( apiKey: 'your-api-key', secretKey: 'your-secret-key', passphrase: 'your-passphrase', isDemo: true );
Examples
Order with TP/SL:
$order = $client->trade()->placeOrder( instId: 'BTC-USDT', tdMode: 'cross', side: 'buy', ordType: 'limit', sz: '0.1', px: '50000', tpTriggerPx: '55000', tpOrdPx: '-1', slTriggerPx: '48000', slOrdPx: '-1' );
Batch orders:
$orders = $client->trade()->batchOrders([ [ 'instId' => 'BTC-USDT', 'tdMode' => 'cash', 'side' => 'buy', 'ordType' => 'limit', 'sz' => '0.01', 'px' => '50000' ], [ 'instId' => 'ETH-USDT', 'tdMode' => 'cash', 'side' => 'buy', 'ordType' => 'limit', 'sz' => '0.1', 'px' => '3000' ] ]);
Set leverage:
$client->account()->setLeverage( lever: '10', mgnMode: 'cross', instId: 'BTC-USDT-SWAP' );
Historical candles:
$candles = $client->market()->getHistoryCandles( instId: 'BTC-USDT', bar: '1H', limit: 100 );
Withdrawal:
$withdrawal = $client->asset()->withdrawal( ccy: 'USDT', amt: '100', dest: '4', toAddr: 'your-wallet-address', fee: '1', chain: 'USDT-TRC20' );
Error handling
Each error type has its own exception class. They all extend OKXException, which carries the raw OKX error code in
$e->okxCode.
use Tigusigalpa\OKX\Exceptions\AuthenticationException; use Tigusigalpa\OKX\Exceptions\RateLimitException; use Tigusigalpa\OKX\Exceptions\InvalidParameterException; use Tigusigalpa\OKX\Exceptions\InsufficientFundsException; use Tigusigalpa\OKX\Exceptions\OKXException; try { $balance = $client->account()->getBalance(); } catch (AuthenticationException $e) { // bad credentials or signature } catch (RateLimitException $e) { // slow down } catch (InvalidParameterException $e) { // check your request params } catch (InsufficientFundsException $e) { // not enough balance } catch (OKXException $e) { // everything else from OKX echo "OKX error [{$e->okxCode}]: " . $e->getMessage(); }
Logging
Pass any PSR-3 logger to the constructor:
use Monolog\Logger; use Monolog\Handler\StreamHandler; $logger = new Logger('okx'); $logger->pushHandler(new StreamHandler('okx.log', Logger::DEBUG)); $client = new Client( apiKey: 'your-api-key', secretKey: 'your-secret-key', passphrase: 'your-passphrase', logger: $logger );
Credentials are never written to logs.
Testing
Unit tests:
vendor/bin/phpunit
Integration tests (needs demo credentials):
export OKX_API_KEY=your-demo-api-key export OKX_SECRET_KEY=your-demo-secret-key export OKX_PASSPHRASE=your-demo-passphrase vendor/bin/phpunit -c phpunit.integration.xml
Contributing
- Fork it
- Create a branch (
git checkout -b fix/something) - Make your changes, add tests
- Push and open a PR
Code must follow PSR-12. Tests must pass.
Security
Found a vulnerability? Email sovletig@gmail.com directly. Don't open a public issue.
License
MIT. See LICENSE.