Ошибки и лимиты
Ошибки возвращают статус вне 2xx и JSON-тело с сообщением. Обрабатывайте их аккуратно — особенно 401 (подпись) и 429 (лимит).
Формат ошибки#
{
"error": "Market not active"
}Ошибки валидации (Zod) включают массив details с описанием проблемных полей.
Коды статусов#
| Код | Значение | Частая причина |
|---|---|---|
400 | Неверный запрос | Неверные параметры, рынок неактивен, цена не кратна шагу. |
401 | Не авторизован | Нет/неверная подпись или устаревший таймстамп (±30с). |
403 | Запрещено | Адрес не совпадает с API-ключом. |
404 | Не найдено | Неизвестный рынок / токен / ордер. |
429 | Слишком много запросов | Превышен лимит — сделайте паузу и повторите. |
5xx | Ошибка сервера | Временная — повтор с экспоненциальной задержкой. |
Лимиты запросов#
| Часть | Лимит | Примечание |
|---|---|---|
REST API | ~30 req/s | На IP. Списочные эндпоинты кратко кэшируются. |
CLOB | ~60 req/s | На IP. У части маршрутов более строгие лимиты. |
WebSocket | 1 соединение, много подписок | Для живых данных предпочитайте WS, а не опрос. |
Хорошая практика
Кэшируйте списки рынков, подписывайтесь по WebSocket вместо опроса и добавляйте экспоненциальную задержку с джиттером на 429/5xx. Так интеграция останется быстрой и в рамках лимитов.Пример повтора#
async function withRetry<T>(fn: () => Promise<T>, tries = 4): Promise<T> {
let lastErr: unknown;
for (let i = 0; i < tries; i++) {
try {
return await fn();
} catch (err) {
lastErr = err;
const delay = Math.min(1000 * 2 ** i, 8000) + Math.random() * 250;
await new Promise((r) => setTimeout(r, delay));
}
}
throw lastErr;
}