tigusigalpa/okx-php

A production-grade PHP/Laravel SDK for the OKX v5 API.

Maintainers

Package info

github.com/tigusigalpa/okx-php

pkg:composer/tigusigalpa/okx-php

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-03-15 02:08 UTC

This package is auto-updated.

Last update: 2026-03-15 02:15:17 UTC


README

OKX PHP client

PHP Version License

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 string to avoid float rounding
  • Laravel Service Provider, Facade, publishable config
  • PSR-3 logging, PSR-12 code style
  • PHP 8.2+ (readonly classes, 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

  1. Fork it
  2. Create a branch (git checkout -b fix/something)
  3. Make your changes, add tests
  4. 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.

Links