OKX · API на практиці
Поширені помилки OKX API та чек-лист діагностики: виправляй за цією таблицею
Хто пише квант-скрипти, у вісьмох випадках із десяти застрягає не на стратегії, а на одному червоному рядку помилки: скрипт запускається, у термінал вилазить незрозумілий code з англійським текстом — і людина впадає в ступор. Хороша новина: помилок OKX API лише кілька частих різновидів, і коли розумієш, як кожна виглядає й якій причині відповідає, діагностика стає набагато швидшою.
У цій статті ми (команда MeowQuant) звели в чек-лист помилки, на які наступали самі й які раз по раз бачили у спільнотах. Ядро — таблиця кодів помилок: щось зламалося — спершу знайди в таблиці за кодом чи ключовим словом, а потім дивись відповідну покрокову діагностику нижче. Прочитавши, ти зможеш розв'язувати більшість помилок самотужки за лічені хвилини, а не тупити в червоний текст.
Спершу навчись читати помилку: code + msg
Перший крок діагностики — зрозуміти саму помилку. Коли інтерфейс OKX повертає помилку, у ній три речі:
- HTTP-статус: найгрубший шар, наприклад 401 (проблема автентифікації), 429 (забагато запитів), 400 (проблема в самому запиті).
- code: власний числовий код помилки OKX, найточніше вказує на тип проблеми. Це твоя головна опора в діагностиці.
- msg: текстовий опис, допомагає підтвердити напрямок, інколи прямо вказує, яке поле хибне.
Якщо ти на ccxt, він загортає ці сирі помилки в зручніші типи винятків: проблему автентифікації кидає як AuthenticationError, ліміт частоти — RateLimitExceeded, брак коштів — InsufficientFunds. У тексті винятку зазвичай є й оригінальні code та msg від OKX. Гарна звичка — обгорнути все у try/except і чітко вивести:
import ccxt
okx = ccxt.okx({
'apiKey': 'твій_apiKey',
'secret': 'твій_secret',
'password': 'твій_Passphrase',
'enableRateLimit': True,
})
try:
balance = okx.fetch_balance()
print('USDT доступно:', balance['USDT']['free'])
except ccxt.InvalidNonce as e:
print('Часова мітка прострочена (50102), виправ час і повтори запит:', e)
except ccxt.AuthenticationError as e:
print('Автентифікація не вдалася, спершу подивись код у помилці, а тоді вирішуй, що перевіряти:', e)
except ccxt.RateLimitExceeded as e:
print('Спрацював ліміт частоти, сповільни запити:', e)
except ccxt.BaseError as e:
print('Інша помилка, дивись оригінальні code/msg:', e)
Запиши той рядок code й msg із винятку дослівно, звір із таблицею нижче — і майже завжди локалізуєш, до якого класу проблем це належить.
Таблиця частих помилок
Ця таблиця охоплює кілька помилок, на які новачки наштовхуються найчастіше. Значення кодів помилок звірено у 2026-09 за розділом Error Code документації OKX API v5 (OKX інколи коригує значення кодів; якщо щось не збігається — орієнтуйся на текст msg і офіційну документацію), а суть — поєднати «причину → як виправити». Особливо в автентифікаційному класі треба йти саме за кодом: обидві помилки виглядають як «не можу підключитися», але 50113 і 50105 відсилають перевіряти зовсім різні речі.
| Помилка (code / ключове слово) | Найімовірніша причина | Як виправити |
|---|---|---|
| 50011 Too Many Requests / ліміт частоти |
Надто щільні запити спрацювали на захист від перевищення частоти | Увімкни enableRateLimit; усе одно впираєшся — додай повтор з експоненційним відкатом, не використовуй цикл while без затримки |
| 50113 Invalid signature |
Сам підпис не пройшов перевірку — проблема саме на кроці підписування, а не обов'язково в неправильно вписаних даних | Звір, як складається рядок для підпису (метод запиту, шлях запиту, тіло запиту), чи справді ключем для HMAC є secret, чи зроблено HMAC-SHA256 і потім Base64; у ccxt підпис робить бібліотека, тож підозрюй насамперед неправильно скопійований secret |
| 50111 Invalid OK-ACCESS-KEY |
apiKey скопійовано неправильно, його видалено або використано не те середовище (реальний key як демо) | Скопіюй apiKey з кабінету заново; переконайся, що ключ ще існує й не видалений; звір перемикач sandbox із середовищем |
| 50105 OK-ACCESS-PASSPHRASE incorrect (50104 = це поле порожнє) |
Пароль не збігається: у поле password у ccxt уписано пароль для входу, а не Passphrase, заданий при створенні ключа |
Заміни password на Passphrase, який ти задав при створенні того ключа; не пам'ятаєш — лишається видалити ключ і створити заново |
| Недостатньо коштів Insufficient balance |
Сума ордера перевищує доступний баланс, або кошти на іншому рахунку (наприклад, фінансовий vs торговий) | Зменш обсяг ордера; переконайся, що кошти на торговому рахунку; на демо можна скинути віртуальні кошти |
| 50102 Timestamp request expired 50112 Invalid OK-ACCESS-TIMESTAMP |
Часова мітка в запиті не збігається з часом сервера: за офіційною документацією, розходження понад 30 секунд — і запит одразу відхиляють (50112 — це некоректний формат самого поля) | Увімкни автокорекцію часу через NTP, синхронізуй системний час; хмарні сервери зазвичай уже мають це ввімкнене |
| 50120 у цього API-ключа немає прав на цю функцію |
Цей ключ не має потрібного права (типово: поставлено лише читання, без торгівлі); повертається з HTTP 200, а не з 401, як інші помилки автентифікації, — побачити її можна лише прочитавши код у тілі відповіді | Зайди в керування API й додай цьому ключу право «Торгівля», перестворювати не треба |
| 50110 Your IP is not included in your API key's IP whitelist |
Ключу налаштовано білий список IP, але поточна вихідна адреса не в списку (змінилася мережа/увімкнено проксі/змінився IP) | Спершу зʼясуй, яка в тебе зараз вихідна IP-адреса, і додай її в білий список цього ключа (до 20 IP на ключ, підмережі підтримуються); що робити з нестабільною вихідною адресою — нижче, і не роби «зняти білий список» рутинним рішенням |
| Торгова пара не існує instrument does not exist |
Помилка у форматі symbol або ф'ючерсний формат для спотового ордера | Спот пиши як BTC/USDT (великими зі слешем); спершу load_markets() подивись доступні пари |
| Невідповідність кількості/точності size too small |
Обсяг менший за мінімальний для пари, або неправильна кількість знаків точності | Через load_markets() подивись limits і precision для цієї пари й округли за вимогою |
Покрокова діагностика й виправлення
Таблиця дає напрямок, цей розділ — деталі. Обери ту помилку, на яку наштовхнувся, і дивись далі.
Автентифікаційні (50102 / 50105 / 50110 / 50111 / 50112 / 50113) і дозвільна (50120)
На рівні HTTP помилки автентифікації — це завжди 401, а в ccxt майже всі вони кидають AuthenticationError (PermissionDenied, який кидає 50110, — теж його підклас). Виняток — 50102, прострочена часова мітка: за вихідним кодом головної гілки ccxt станом на 2026-09 він зіставлений з InvalidNonce, а той належить до гілки NetworkError, тож голий except AuthenticationError його не зловить — потрібна окрема гілка. Тож не перебирай «найчастіші причини» по черзі: спершу витягни код, а тоді йди по відповідному рядку. 50120 «бракує прав» треба винести окремо: вона не з тієї купи 401. За офіційною таблицею кодів помилок вона повертається з HTTP 200 і розпізнається за кодом у тілі відповіді, тобто на рівні протоколу запит «успішний» — лише за статус-кодом ти взагалі не побачиш, що щось пішло не так.
- 50113 Invalid signature: дивись на крок підписування. Як складається рядок для підпису (метод запиту, шлях запиту, тіло запиту), чи є ключем для HMAC саме secret, чи зроблено HMAC-SHA256 і потім Base64. Якщо працюєш через ccxt, підпис робить бібліотека — тоді підозрюй передусім неправильно скопійований secret.
- 50105 не той Passphrase (50104 — його взагалі не передано): дивись лише на пароль. У поле
passwordу ccxt має бути вписано саме той Passphrase, який ти задав при створенні ключа — не пароль для входу й не secret; не пам'ятаєш його — лишається видалити ключ і створити заново. - 50102 / 50112 проблема з часовою міткою: дивись лише на час. За офіційною документацією, якщо мітка запиту розходиться з часом сервера більш ніж на 30 секунд, запит відхиляють. Увімкни автокорекцію через NTP, а на машинах, що працюють довго, періодично перевіряй, що синхронізація справді йде. У ccxt 50102 кидає
InvalidNonce: у цій гілці виправ час і повтори запит, а наприкінці залиш загальний перехоплювачBaseError. - 50111 Invalid OK-ACCESS-KEY: дивись на сам apiKey — зайвий пробіл на початку чи в кінці після вставки, загублений символ, видалений ключ або реальний ключ, узятий для демо (і навпаки).
- 50110 IP не в білому списку: дивись на мережевий вихід, а не на облікові дані. Див. розділ «Білий список IP» нижче.
- 50120 бракує прав (HTTP 200): з обліковими даними все гаразд, просто в цього ключа не поставлено потрібну галочку. Вона ніколи не приходить у вигляді 401 — побачити її можна лише прочитавши код у тілі відповіді, тож не пиши обробку як просто
if status == 401. Див. «Недостатньо прав» нижче.
До речі: текст msg від OKX іноді прямо називає, у якому саме заголовку проблема — записуй його дослівно поряд із кодом, це значно швидше, ніж гадати за враженнями.
Недостатньо прав
Типовий симптом — «можу перевірити баланс, не можу виставити ордер». Баланс іде через право читання, ордер — через право торгівлі, вони надаються окремо. Зайди в керування API в кабінеті OKX, знайди цей ключ і додай «Торгівлю» — перестворювати не треба. Якщо мимохідь ставив виведення — прибери: квант-ключ ніколи не повинен мати права виведення. І не розумій «право торгівлі» надто вузько: за визначенням із документації OKX воно охоплює не лише виставлення й скасування ордерів, а й переказ коштів та частину налаштувань рахунку, тож заради переказів між власними рахунками ставити виведення не потрібно.
Білий список IP (50110)
Ця помилка каже: «твоя нинішня вихідна IP-адреса не в списку цього ключа», тож розбір починається з мережевого виходу, а не з облікових даних:
- Спершу дізнайся свою поточну вихідну IP-адресу і звір її зі списком, який ти вписав цьому ключу в кабінеті. Увага, йдеться саме про вихідну адресу: з увімкненим проксі, через корпоративний шлюз або після перепідключення домашнього інтернету вихід може бути зовсім не тим, на який ти думаєш.
- Якщо вихідна адреса нестабільна, напрям рішення — зафіксувати вихід, а не зняти замок: перенеси стратегію на машину зі сталим IP або оновлюй білий список за чітким графіком, коли вихід справді змінюється. На кожен ключ OKX дозволяє прив'язати до 20 IP, підтримуються IPv4/IPv6 і підмережі, тож запас лишити неважко.
- На етапі відлагодження бери ключ лише для читання або демо-ключ, а не проби раз за разом основним ключем із правом торгівлі.
- Не роби «зняти білий список» рутинною дією при розборі помилок. Офіційно прив'язку IP наполегливо рекомендують, але не вимагають; проте є правило, яке варто запам'ятати: ключ без прив'язаного IP, який має право trade чи withdraw, спливає після 14 днів без активності — тобто такий ключ не лише ризикованіший, він ще й одного дня може просто перестати працювати. На демо-ключі це правило спливання не діє — це ще одна причина відлагоджувати саме ним.
Недостатньо коштів
Окрім буквального браку грошей, є й прихована причина: у OKX різні рахунки (фінансовий, торговий тощо), і твої кошти можуть бути не на тому, з якого виставляється ордер. Переконайся, що кошти переведено на торговий рахунок. На демо — якщо віртуальні кошти скінчилися, скинь їх в інтерфейсі демо. Це теж перевага того, щоб спершу практикуватися на демо — проби й помилки не коштують справжніх грошей.
symbol / точність
Спотові пари в ccxt — це ВЕЛИКІ/ВЕЛИКІ з прямим слешем, наприклад BTC/USDT. Напишеш BTCUSDT, маленькими чи у ф'ючерсному форматі — буде помилка. Кількість надто мала або точність невірна — через load_markets() подивись мінімальний обсяг і точність для пари й роби за вимогою. Повний приклад виставлення ордера є в нашій статті Квант на OKX API.
Ліміт частоти й повтор із відкатом
Ліміт частоти (50011 / Too Many Requests) — те, на що скриптери впираються найчастіше і що варто запобігати наперед. Це не означає, що ти щось зробив не так, — просто надто щільні запити спрацювали на захист біржі. Обробляється у два шари:
Шар перший: увімкни вбудоване обмеження швидкості ccxt. При ініціалізації додай 'enableRateLimit': True, ccxt сам уставлятиме розумні паузи між запитами, і в більшості випадків цього кроку достатньо:
okx = ccxt.okx({
'apiKey': 'твій_apiKey',
'secret': 'твій_secret',
'password': 'твій_Passphrase',
'enableRateLimit': True, # автообмеження швидкості, вмикай одразу
})
Шар другий: додай повтор з експоненційним відкатом. Якщо твоя стратегія в певні моменти справді шле дуже щільно (наприклад, одночасно опитує багато пар), самого автообмеження може бракувати, і ти інколи впиратимешся. Тоді обгорни ключові запити шаром повтору: уперся раз — чекай 1 с і повтори, ще раз — 2 с, 4 с, поступово збільшуючи, а після кількох спроб — здавайся з помилкою.
import ccxt, time
def with_retry(fn, max_tries=5):
delay = 1
for i in range(max_tries):
try:
return fn()
except ccxt.RateLimitExceeded:
print(f'Ліміт частоти, спроба {i+1}, чекаю {delay}с і повторюю')
time.sleep(delay)
delay *= 2 # експоненційний відкат: 1 → 2 → 4 → 8 ...
raise RuntimeError('Кілька повторів — усе ще ліміт частоти, здаюся')
# Вжиток: кидай сюди виклик, який упирається в ліміт
ticker = with_retry(lambda: okx.fetch_ticker('BTC/USDT'))
print(ticker['last'])
Негативний приклад: не пиши while True:, де одразу б'ється по інтерфейсу без жодної затримки. Такий цикл за секунду випустить десятки-сотні запитів, миттєво впреться в ліміт, а у важких випадках весь ключ ненадовго обмежать. У будь-якому частому циклі лишай паузи.
Поширена пастка з лімітом частоти
fetch_ticker для десятка з гаком пар без жодної затримки, ще й забути ввімкнути enableRateLimit. Написане так, воно раз за разом тригерить захист ендпойнта від частих запитів: термінал починає сипати RateLimitExceeded (тобто 50011), і велика частина наступних запитів провалюється. Виправлення у два кроки: спершу додають при ініціалізації 'enableRateLimit': True, потім обгортають запит кожної пари у ту функцію відкату with_retry вище. Після цього між запитами з'являються паузи, а той запит, що все ж упреться в ліміт, піде на відкат і повтор, замість того щоб просто пропасти. Висновок прямий: б'єш по інтерфейсу в циклі — обмеження швидкості й відкат це стандарт, а не опція.
Поширені запитання
Як читати помилку OKX API?
Коли інтерфейс OKX повертає помилку, у відповіді є code (числовий код помилки), msg (текстовий опис) і HTTP-статус. Дивись спершу code — він найточніше вказує на тип проблеми; msg допомагає підтвердити напрямок. У ccxt помилка зазвичай загорнута у відповідний тип винятку (наприклад, AuthenticationError, RateLimitExceeded, InsufficientFunds), і в тексті винятку зазвичай є оригінальні code та msg від OKX. Просто пошукай цей рядок дослівно — і майже завжди локалізуєш проблему.
Чому постійно вилазить помилка автентифікації / Invalid sign?
Не сприймай помилки автентифікації як одну помилку. На рівні HTTP це все 401, у ccxt майже всі вони кидають AuthenticationError — виняток 50102 (прострочена часова мітка): він кидає InvalidNonce з гілки NetworkError, і для нього потрібна окрема гілка; але код, який повертає OKX, указує на різні речі: 50113 — не пройшов підпис, перевіряй, як складається рядок для підпису, і сам secret; 50105 — не той Passphrase, у поле password в ccxt має бути вписано пароль, заданий при створенні ключа; 50102 і 50112 — проблема з часовою міткою: якщо час запиту розходиться з часом сервера більш ніж на 30 секунд, його відхиляють, тож вмикай NTP; 50111 — недійсний сам apiKey або взято не те середовище; 50110 — поточна вихідна IP-адреса не в білому списку. А 50120 «бракує прав» треба винести окремо: вона не з тієї купи 401 — за офіційною таблицею кодів помилок повертається з HTTP 200 і розпізнається за кодом у тілі відповіді; з обліковими даними все гаразд, просто в цього ключа не поставлено потрібну галочку. Спершу витягни код, а вже потім вирішуй, що перевіряти: це швидше, ніж перебирати причини за досвідом.
Що робити при ліміті частоти (50011 / Too Many Requests)?
Ліміт частоти — це захист, який спрацьовує від надто щільних запитів. Найпростіше рішення — увімкнути enableRateLimit при ініціалізації ccxt, він сам уставлятиме паузи між запитами. Якщо все одно впираєшся — додай у код повтор з експоненційним відкатом: уперся раз — чекай 1 с, ще раз — 2 с, 4 с, поступово збільшуючи. Не бий по інтерфейсу циклом while True без затримки.
Можу перевірити баланс, але ордер видає недостатньо прав — чому?
Перевірка балансу — це право читання, виставлення ордера — право торгівлі, при створенні ключа вони надаються окремо. Можеш дивитися, але не можеш виставляти — практично завжди це означає, що поставлено лише «Читання» без «Торгівлі». Зайди в керування API в кабінеті OKX і додай цьому ключу право торгівлі — перестворювати не треба.
Що означає застаріла часова мітка (timestamp expired)?
OKX має допуск на часову мітку в запиті; якщо системний час твого комп'ютера чи сервера неточний і відхилення перевищує допуск, підпис буде відхилено через застарілу мітку. Рішення — синхронізувати системний час із точним мережевим, увімкнути автокорекцію через NTP. Хмарні сервери зазвичай мають це за замовчуванням, локальні машини інколи «пливуть».
Чому видає «торгова пара не існує»?
Спершу подивись код і msg у помилці: цей клас помилок указує на поле symbol. У ccxt спотові пари — великими літерами з прямим слешем, наприклад BTC/USDT; напишеш BTCUSDT, btc/usdt чи візьмеш ф'ючерсний формат для спотового ордера — отримаєш «торгова пара не існує». Часом msg прямо називає, яке поле некоректне, і перевіряти саме назване поле найшвидше; не впевнений — спершу print(okx.load_markets().keys()) і подивись, які пари взагалі доступні.
Коли пройдеш цей етап діагностики, твій скрипт перестане застрягати на дрібницях. Далі варто витратити час на те, щоб вписати ризик-менеджмент у код — страшніше за помилку те, коли скрипт без помилок безперервно виставляє хибні ордери. І не забувай: новий код спершу кидай у демо, діагностика не коштуватиме справжніх грошей.