Інтеграція API OKX у мобільні крипто-додатки
OKX — одна з небагатьох бирж, де REST та WebSocket живуть у різних URL-просторах й з різною логікою аутентифікації. REST іде на https://www.okx.com/api/v5/, WebSocket — на wss://ws.okx.com:8443/ws/v5/public і /private. Якщо команда раніше працювала з Binance й переносить архітектуру «як є» — будуть сюрпризи.
Підпис: три поля в заголовках, не в параметрах
OKX аутентифікує запити через HTTP-заголовки, а не через query string або body:
-
OK-ACCESS-KEY— API key -
OK-ACCESS-SIGN— Base64(HMAC-SHA256(timestamp + method + requestPath + body)) -
OK-ACCESS-TIMESTAMP— ISO 8601 (наприклад2024-01-15T10:30:00.123Z) -
OK-ACCESS-PASSPHRASE— третій секрет, встановлюється при створенні ключа
requestPath включає query string: для GET /api/v5/account/balance?ccy=BTC підписуємо /api/v5/account/balance?ccy=BTC. Тіло для GET-запитів — пустий рядок "". Помилка {"code":"50113","msg":"Invalid Sign"} майже завжди означає проблему з requestPath — або забули query string, або додали зайвий слеш.
Часова мітка в форматі ISO 8601 з мілісекундами — рідкість для бирж. На Android Instant.now().toString() дає потрібний формат починаючи з API 26. Для більш старих версій — SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US) з UTC timezone.
WebSocket Private: аутентифікація сесії
{
"op": "login",
"args": [{
"apiKey": "...",
"passphrase": "...",
"timestamp": "1705312200",
"sign": "..."
}]
}
Signature для WebSocket відрізняється від REST: HMAC-SHA256(timestamp + "GET" + "/users/self/verify"), де timestamp — Unix seconds (не мілісекунди, не ISO). Ця різниця — частий джерел помилок при рефакторингу спільного auth-модуля.
OKX відключає WebSocket-сесію через 30 секунд без activity. Ping/pong — нестандартний: відправляємо рядок "ping", отримуємо "pong". Не JSON-об'єкт, саме raw string. Бібліотеки, які працюють лише з text-frame JSON, ломаються на цьому місці.
Нюанси продуктової логіки
OKX підтримує instType (instrument type): SPOT, MARGIN, SWAP, FUTURES, OPTION. Один і той же тикер, наприклад BTC-USDT, існує в кількох instType з різними правилами торгівлі. При реалізації ордерної форми потрібно явно передавати instType — інакше біржа повертає {"code":"51001","msg":"Instrument ID does not exist"} для інструментів, які існують у іншому типі.
Ще одна особливість — tdMode (trade mode): cash для Spot, cross або isolated для маржи. Мобільні UI часто скривають цей вибір «для простоти», що призводить до випадкового відкриття маржинальних позицій. Рекомендуємо явний UI-вибір з попередженням.
Робота з історичними даними
OKX обмежує свічі: GET /api/v5/market/candles повертає максимум 300 записів. Для підгрузки історії при скролі графіка назад потрібна пагінаціонна запит з параметром before (ID свічи). Стандартна помилка — використовувати after замість before й отримувати дані в зворотньому порядку, потім інвертувати масив в UI з візуальним артефактом.
Стек та підхід
Для React Native: axios з request interceptor для підпису + reconnecting-websocket з кастомним pingInterval. Стан ринку — в Redux Toolkit з RTK Query для REST і кастомним middleware для WebSocket подій.
Для Flutter: dio + web_socket_channel, BLoC для управління станом торговельних екранів. Розділяємо PublicStreamBloc та PrivateStreamBloc — різні життєві цикли (публічні стрімиа живуть весь час, приватні — лише при авторизованій сесії).
Тестування: OKX Demo Trading (www.okx.com/demo-trading) — повноцінне середовище з реальними стаканами й можливістю виставляти ордери без реальних коштів. Суттєво краще, ніж у деяких конкурентів.
Період: базова інтеграція (маркет-дані + spot trading) — 2–4 тижні. Деривативи + margin — додайте ще 3–4 тижні на бізнес-логіку та тестування edge cases.







