# OKX V5 API Reference Documentation ## Authentication ### Signature Generation (HMAC SHA256 + Base64) The signature algorithm: ``` signature = Base64(HMAC_SHA256(secret_key, timestamp + method + request_path + body)) ``` **Java Example:** ```java import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public static String sign(String timestamp, String method, String requestPath, String body, String secretKey) { try { String preHash = timestamp + method + requestPath + body; Mac mac = Mac.getInstance("HmacSHA256"); SecretKeySpec spec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256"); mac.init(spec); return Base64.getEncoder().encodeToString(mac.doFinal(preHash.getBytes())); } catch (Exception e) { throw new RuntimeException("Signature failed", e); } } ``` **Python Example:** ```python import hmac, base64, hashlib def sign(timestamp, method, request_path, body, secret_key): pre_hash = timestamp + method + request_path + body signature = hmac.new( secret_key.encode(), pre_hash.encode(), hashlib.sha256 ).digest() return base64.b64encode(signature).decode() ``` **Go Example:** ```go import ( "crypto/hmac" "crypto/sha256" "encoding/base64" ) func sign(timestamp, method, requestPath, body, secretKey string) string { preHash := timestamp + method + requestPath + body mac := hmac.New(sha256.New, []byte(secretKey)) mac.Write([]byte(preHash)) return base64.StdEncoding.EncodeToString(mac.Sum(nil)) } ``` ### Required Headers All authenticated REST requests MUST include: | Header | Description | |-------------------------|-----------------------------------------------| | OK-ACCESS-KEY | API key | | OK-ACCESS-SIGN | Base64-encoded HMAC SHA256 signature | | OK-ACCESS-TIMESTAMP | ISO 8601 timestamp (e.g., 2023-01-01T00:00:00.000Z) | | OK-ACCESS-PASSPHRASE | API passphrase | | x-simulated-trading | Set to "1" for demo trading (optional) | ## Market Types | Type | Description | |-----------|----------------------| | SPOT | Spot trading | | SWAP | Perpetual swap | | FUTURES | Futures contracts | | OPTION | Options trading | ## WebSocket ### Public Channel ``` wss://ws.okx.com:8443/ws/v5/public ``` Access market data without authentication: tickers, order books, trades, mark prices, funding rates, etc. ### Private Channel ``` wss://ws.okx.com:8443/ws/v5/private ``` Requires authentication (login). Access account data, order updates, position changes, balance updates. ### Business Channel ``` wss://ws.okx.com:8443/ws/v5/business ``` Requires authentication. Access business-specific channels (requires application). ### Ping/Pong - Client must send a ping message if no message has been sent in the last 30 seconds - Server responds with pong - If no pong received, client should reconnect ```json {"op": "ping"} ``` ```json {"op": "pong"} ``` ### Subscription Example ```json { "op": "subscribe", "args": [ { "channel": "tickers", "instId": "BTC-USDT" } ] } ``` ### Login (Private Channel) ```json { "op": "login", "args": [ { "apiKey": "YOUR_API_KEY", "passphrase": "YOUR_PASSPHRASE", "timestamp": "2023-01-01T00:00:00.000Z", "sign": "BASE64_SIGNATURE" } ] } ``` WebSocket login signature: `timestamp + "GET" + "/users/self/verify"` (no body). ## Common REST Endpoints ### Account | Method | Path | Description | |--------|------------------------------------|--------------------------| | GET | /api/v5/account/balance | Get account balance | | GET | /api/v5/account/positions | Get positions | | GET | /api/v5/account/positions-history | Get positions history | | GET | /api/v5/account/bills | Get bills (transaction history) | | GET | /api/v5/account/config | Get account configuration | | GET | /api/v5/account/instruments | Get instruments | | POST | /api/v5/account/set-position-mode | Set position mode | | GET | /api/v5/account/leverage-info | Get leverage | | POST | /api/v5/account/set-leverage | Set leverage | ### Trade | Method | Path | Description | |--------|------------------------------|---------------------| | POST | /api/v5/trade/order | Place order | | POST | /api/v5/trade/amend-order | Amend order | | POST | /api/v5/trade/cancel-order | Cancel order | | POST | /api/v5/trade/batch-orders | Place batch orders | | POST | /api/v5/trade/batch-amend-orders | Amend batch orders | | POST | /api/v5/trade/batch-cancel-orders | Cancel batch orders | | POST | /api/v5/trade/close-position | Close position | | GET | /api/v5/trade/order | Get order details | | GET | /api/v5/trade/orders-pending | Get pending orders | | GET | /api/v5/trade/orders-history | Get order history | | GET | /api/v5/trade/fills | Get transaction details | | GET | /api/v5/trade/fills-history | Get transaction history | ### Market Data | Method | Path | Description | |--------|------------------------------------|--------------------------| | GET | /api/v5/market/tickers | Get all tickers | | GET | /api/v5/market/ticker | Get single ticker | | GET | /api/v5/market/books | Get order book | | GET | /api/v5/market/candles | Get candlestick (K-line) | | GET | /api/v5/market/history-candles | Get historical candles | | GET | /api/v5/market/trades | Get recent trades | | GET | /api/v5/market/history-trades | Get historical trades | | GET | /api/v5/market/mark-price | Get mark price | | GET | /api/v5/market/funding-rate | Get funding rate | ## Order Placement Example ### REST - Place Limit Order ``` POST /api/v5/trade/order ``` **Request Body:** ```json { "instId": "BTC-USDT-SWAP", "tdMode": "cross", "side": "buy", "ordType": "limit", "sz": "1", "px": "20000" } ``` **Response:** ```json { "code": "0", "msg": "", "data": [ { "clOrdId": "", "ordId": "123456", "tag": "", "sCode": "0", "sMsg": "" } ] } ``` ## Rate Limits - REST: 20 requests / 2 seconds per endpoint (varies by endpoint) - WebSocket: 1 subscription request / second - Public WebSocket data: throttled per channel - Always implement exponential backoff on 429 responses ## Error Codes | Code | Meaning | |---------|--------------------------------| | 0 | Success | | 50001 | Request timeout | | 50002 | Service unavailable | | 50004 | Rate limit exceeded | | 50011 | API key does not exist | | 50012 | API key has expired | | 50013 | Invalid sign | | 50014 | Invalid passphrase | | 50015 | Invalid IP | | 50016 | Permission denied | | 50017 | Withdrawal address not whitelisted | | 50100 | Unsupported operation | | 51000 | Parameter error | | 51001 | Instrument ID does not exist | | 51006 | Order does not exist | | 51400 | Order cancellation failed | | 51500 | Insufficient balance | ## Best Practices 1. **Timestamp synchronization**: Ensure server time is synced via NTP; timestamp must be within 30 seconds of OKX server time 2. **Exponential backoff**: On rate limit (429) or 5xx errors, implement exponential backoff starting at 1s 3. **WebSocket reconnection**: Automatically reconnect on disconnect with backoff; resubscribe all channels 4. **Demo first**: Always test on demo trading (x-simulated-trading: 1) before live 5. **Idempotency**: Use `clOrdId` to prevent duplicate orders 6. **Error logging**: Log full error responses including code, msg, and data fields 7. **Connection pooling**: Reuse HTTP connections for REST calls 8. **WebSocket heartbeat**: Maintain 30-second ping/pong cycle