Ошибки API Polymarket: расшифровка каждого кода
Сообщения об ошибках Polymarket лаконичны, а те, что ломают вашего бота в 3 часа ночи, обычно вообще отсутствуют в документации. Вот полный справочник — задокументированные ошибки, незадокументированные и что на самом деле делать с каждой.
Каждая ошибка CLOB API Polymarket возвращается в одном и том же виде — JSON-объект с единственным полем error. Это восхитительно единообразно и совершенно бесполезно, когда вы пытаетесь понять, куда только что исчез ваш ордер.
{
"error": "<message>"
}Эта страница их расшифровывает. Здесь — задокументированные ошибки CLOB, коды статуса и их настоящие причины, а также то, чего вы не найдёте в официальной документации: ошибки, с которыми люди реально сталкиваются в продакшене и которые Polymarket так и не описал.
У каждого задокументированного сообщения также есть своя страница с причинами и рекомендацией по повтору — они перечислены в указателе ошибок Polymarket.
Краткий справочник по кодам статуса
| Статус | Значение | Частые причины |
|---|---|---|
400 | Bad Request | Неверные параметры, некорректная полезная нагрузка, нарушение бизнес-логики |
401 | Unauthorized | Отсутствующий или недействительный API-ключ, неверная подпись HMAC, просроченная метка времени |
404 | Not Found | Рынок не существует, ордер не найден, ID токена не распознан |
425 | Too Early | Механизм сопоставления перезапускается — повторите с отступом |
429 | Too Many Requests | Превышен лимит запросов — экспоненциально увеличивайте паузу |
500 | Internal Server Error | Непредвиденная ошибка сервера — повторите с отступом |
503 | Service Unavailable | Биржа на паузе или заблокирована режимом cancel-only / post-only |
Подмена кода статуса, которая собьёт вас с толку
CLOB API переписывает коды статуса в зависимости от содержания сообщения. Любое сообщение об ошибке, содержащее "not found", возвращает 404, содержащее "unauthorized" — 401, а содержащее "context canceled" — 400, независимо от исходного кода статуса. Если код статуса противоречит сообщению, причина в этом. Стройте обработку ошибок на тексте сообщения, а не на числе.
401 — ошибки аутентификации
Unauthorized/Invalid api key
Самая часто ищущаяся ошибка Polymarket. Ваш API-ключ отсутствует, истёк или недействителен. На практике это почти никогда не действительно плохой ключ — обычно дело в одном из этих пунктов:
- Вы отправляете только часть набора учётных данных. Аутентификации L2 в Polymarket нужны ключ, секрет и passphrase вместе. Частая ошибка — заполнить
POLY_API_KEYиPOLY_PASSPHRASE, но не задать секрет: клиент отправляет корректно сформированный, но не поддающийся подписи запрос. - Системные часы рассинхронизировались. Подпись включает метку времени, и часы, отстающие больше чем на несколько секунд, дают подпись, которую сервер отклоняет как недействительную. Эту причину находят последней, и она удручающе часто встречается на виртуальных машинах и в контейнерах.
- Вы получили ключ для другого кошелька, а не того, с которого торгуете. Ключи привязаны к адресу подписанта, который их создал.
- Вы обращаетесь к аутентифицированному эндпоинту с заголовками L1 там, где ожидается L2, или наоборот.
Invalid L1 Request headers
Ваши заголовки аутентификации L1 — набор подписи EIP-712 — сформированы неверно, или подпись не соответствует адресу, который вы указываете. Проверьте, что подписываете тем же приватным ключом, что и адрес в заголовке, и что разделитель домена соответствует вашей сети (Polygon, chain ID 137). Подпись, действительная для неверного chain ID, остаётся действительной подписью — просто не для этого сервера.
Could not create api key / Could not derive api key!
Именно эти ошибки стоят за поисковым запросом «polymarket unable to generate api credentials». Обе возвращаются эндпоинтами аутентификации, когда создание или получение ключа не удаётся. Could not derive api key! на GET /auth/derive-api-key обычно означает, что для этого подписанта ключа ещё нет: derive возвращает существующий ключ, а не создаёт новый. Сначала создайте ключ через POST /auth/api-key, а при последующих запусках получайте его через derive.
Шаблон «сначала derive, потом create»
Вместо хранения ключей большинство продакшен-ботов сначала пробуют derive и переходят к create, если это не удалось. Это идемпотентно при перезапусках и не плодит брошенные ключи — у эндпоинтов аутентификации лимит 100 запросов / 10 с, так что создавать ключ при каждом запуске всё равно не стоит.
400 — ошибки отклонения ордеров
Они возвращаются, когда ордер проходит транспортную проверку, но нарушает бизнес-правила. Они появляются в теле ответа POST /order и POST /orders.
| Сообщение об ошибке | Что это значит |
|---|---|
the order signer address has to be the address of the API KEY | Ключ, подписывающий ордер, — не тот ключ, который указан в ордере как подписавший. Вы смешиваете учётные данные — обычно это устаревший ключ от предыдущего кошелька. |
the order owner has to be the owner of the API KEY | Адрес maker в ордере не совпадает с адресом, которому принадлежит API-ключ. |
order {id} is invalid. Price ({price}) breaks minimum tick size rule: {tick} | Ваша цена не лежит на сетке тиков рынка. Вызовите GET /tick-size и округлите до неё — не предполагайте 0.01. |
order {id} is invalid. Size ({size}) lower than the minimum: {min} | Размер ордера меньше минимального для рынка. |
not enough balance / allowance | Недостаточный баланс pUSD, или вы не выдали контракту биржи разрешение на списание. Нужно и то и другое. |
invalid post-only order: order crosses book | Ваш post-only ордер немедленно забрал бы ликвидность. Измените цену, чтобы он встал в стакан. |
order couldn't be fully filled. FOK orders are fully filled or killed. | Fill-or-Kill не нашёл достаточной ликвидности. Весь ордер отклонён. |
no orders found to match with FAK order. | Fill-and-Kill вообще не нашёл совпадений. Требуется хотя бы одно. |
invalid expiration | Метка времени истечения в прошлом или сформирована неверно. |
order {id} is invalid. Duplicated. | Один и тот же ордер был отправлен дважды. |
order canceled in the CTF exchange contract | Ордер был отменён ончейн. |
'{address}' address banned | Адресу запрещено торговать. |
'{address}' address in closed only mode | Адрес может только закрывать существующие позиции. |
Размер тика у каждого рынка свой, и он меняется
Самое частое молчаливое отклонение ордера — нарушение размера тика. Размер тика различается между рынками и может уменьшаться по мере взросления рынка: цена, которая была допустимой на прошлой неделе, сегодня может уже не подойти. Запрашивайте GET /tick-size для каждого рынка и округляйте до него, а не зашивайте сетку в код.
Пакетные ордера ломаются иначе
В POST /orders ошибки по отдельным ордерам возвращаются внутри массива ответа 200 в виде отдельных полей errorMsg, а не как ошибка верхнего уровня. 200 не означает, что каждый ордер в пакете принят. Проходите по массиву и проверяйте каждую запись.
425 — Too Early
Необычный код статуса, который сбивает с толку, потому что в остальном вебе его почти не используют. В Polymarket он означает, что механизм сопоставления перезапускается. Ваш запрос пришёл в тот момент, когда биржа снова поднимается.
Эта ошибка действительно временная, и её действительно безопасно повторять — пожалуй, это самая подходящая для повтора ошибка на платформе. Подождите и попробуйте снова; не считайте это сбоем и не поднимайте тревогу из-за единичного случая.
503 — биржа в ограниченном режиме
Polymarket может переводить биржу в ограниченные режимы. Это не сбои на вашей стороне, и сколько ни повторяй тот же запрос, это не поможет, пока режим не снимут.
| Сообщение | Что ещё можно делать |
|---|---|
Trading is currently disabled. Check polymarket.com for updates | Ничего. Ордера не принимаются, включая отмены. |
Trading is currently cancel-only. New orders are not accepted, but cancels are allowed. | Отменять существующие ордера. Открывать новые нельзя. |
post-only mode: only post-only orders and cancels are allowed | Отменять или выставлять ордера с postOnly: true. Ордера, забирающие ликвидность, отклоняются. |
Режим post-only стоит обработать как следует, потому что он точно говорит, когда возвращаться. Ответ содержит code: "post_only_mode" и retry_after_seconds, а та же задержка передаётся в заголовке Retry-After.
{
"error": "post-only mode: only post-only orders and cancels are allowed",
"code": "post_only_mode",
"retry_after_seconds": 79
}Режим cancel-only может поймать в ловушку бота-маркетмейкера
Если при завершении работы ваш бот перевыставляет котировки до отмены, режим cancel-only отклонит перевыставление, и бот может зациклиться вместо того, чтобы закрыть позиции. Обрабатывайте 503 так: сначала отмена, и только потом решение, входить ли снова.
Ошибки, которых нет в документации
Именно на них уходит большая часть реального времени отладки. Следующих ошибок нет в справочнике кодов ошибок Polymarket, потому что они вообще не исходят от приложения CLOB — они приходят с edge, из сети или из вашей клиентской библиотеки. Знание того, какой слой породил ошибку, подсказывает, где искать.
"The server was unable to process your request"
Самая часто ищущаяся ошибка Polymarket, которой нет в документации. Это сообщение слоя edge, а не ошибка CLOB API: вы получаете его, когда запрос так и не дошёл до приложения или не вернулся из него без проблем. На практике обычные причины такие:
- Некорректный запрос, который edge отклоняет до маршрутизации — слишком большая полезная нагрузка, плохой заголовок или недопустимый HTTP-метод для маршрута.
- Временный сбой вышестоящего сервиса во время повторного развёртывания или под нагрузкой.
- Длительное превышение лимита запросов. Поскольку Cloudflare ограничивает скорость, ставя запросы в очередь, а не отклоняя их, клиент, сильно превышающий лимит, может получать таймауты на edge вместо чистого
429.
Считайте её повторяемой с отступом, но если она постоянная, а не эпизодическая, сначала проверьте частоту запросов — см. справочник по лимитам запросов, — а затем размер полезной нагрузки.
403 Forbidden
403 от Polymarket обычно не связан с аутентификацией, и именно это сбивает с толку. Как правило, это edge блокирует запрос. Частые причины — географические ограничения на торговых эндпоинтах, проверки для IP-диапазонов дата-центров и VPN, а также отсутствующие или не похожие на браузерные заголовки в запросах, которые edge ожидает от клиента.
Если 403 появляется только с вашей облачной виртуальной машины, но не с ноутбука, это проблема репутации IP, а не кода. Если он появляется на торговых эндпоинтах, но не на эндпоинтах рыночных данных, причина географическая.
Ошибки SSL, TLS и сертификатов
«polymarket ssl error», «polymarket certificate error» и «polymarket https error» почти всегда возникают на стороне клиента. С сертификатами Polymarket всё в порядке; не в порядке что-то между вами и ними. Проверьте по порядку: устаревший набор корневых сертификатов (очень часто встречается в старых Docker-образах и замороженных окружениях Python), корпоративный прокси с инспекцией TLS, подставляющий собственный сертификат, и системные часы, отстающие настолько, что сертификаты кажутся ещё не действительными или истёкшими.
# 1. Does TLS work at all, outside your app's HTTP client?
curl -sS -o /dev/null -w "%{http_code} %{ssl_verify_result}\n" \
https://clob.polymarket.com/ok
# 2. Is your CA bundle current? (Python)
python3 -c "import certifi, os; print(certifi.where()); print(os.path.getmtime(certifi.where()))"
# 3. Is your clock right? Certificate validation depends on it.
date -u"Service not ready"
Сообщение о стадии запуска: сервис уже достаточно поднялся, чтобы ответить, но ещё не готов обслуживать. По сути обрабатывайте его как 425 — подождите и повторите. Оно должно пройти за секунды, и исправить его на стороне клиента нельзя.
"Order manager not ready"
Сообщение о стадии запуска от механизма сопоставления, близкий родственник 425 Too Early. Сервис доступен, но слой управления ордерами ещё не до конца поднялся, поэтому он примет ваше соединение и откажет вашему ордеру. Ошибка временная, её безопасно повторять с отступом, — но воспринимайте её как сигнал прекратить отправку на несколько секунд, а не долбить сервер, потому что перезапуск обычно означает, что стакан вот-вот изменится у вас под ногами.
Если вы видите её постоянно, а не всплесками, проверьте статус Polymarket, прежде чем отлаживать собственный код, — на стороне клиента исправлять нечего.
"Couldn't get a quote"
Обычно означает, что на стороне, для которой вы запросили цену, нет ликвидности в стакане, а не что что-то сломалось. На тонких рынках Up/Down перед экспирацией одна сторона регулярно пустеет — никто не продаёт Up ни по какой цене, когда Up уже предрешён, — поэтому запрос котировки ничего не возвращает. Наши собственные данные показывают, что это обычное дело: в выборке 5-минутных рынков BTC у 1,454 из 8,510 за 60 секунд до экспирации на одной из сторон был пустой стакан аск.
Обрабатывайте это как «нет рынка», а не как ошибку: пропустите сделку и не повторяйте в плотном цикле. Если нужно знать, как часто это случается в серии, которой вы торгуете, страницы рыночных данных показывают ликвидность по таймфреймам.
Исключения клиентской библиотеки
Ошибки вроде PolyApiException[status_code=None, error_message=request exception!] приходят из Python-клиента, а не с сервера. Подсказка — status_code=None: HTTP-ответ так и не был получен, значит, это сбой на уровне соединения — DNS, TLS, таймаут или оборванный сокет, — который всплывает как исключение библиотеки. Отлаживайте это как сетевую проблему, а не как проблему API. То же рассуждение относится к BuilderApiKeyCreds invalid authorization 401 в клиенте relayer: это значит, что переданные клиенту учётные данные builder не были приняты; получите их заново, а не используйте закешированный набор.
Политика повторов, которая справляется со всем этим
Практический вывод: ошибки Polymarket делятся на три группы, и их смешение делает ботов хрупкими: повторять вслепую, повторять после конкретной задержки и никогда не повторять.
| Категория | Коды / сообщения | Действие |
|---|---|---|
| Временные | 425, 500, Service not ready, ошибки соединения | Повтор с экспоненциальным отступом + случайным разбросом |
| Лимит запросов | 429 | Повтор после Retry-After; если его нет — отступ со случайным разбросом |
| Ограниченный режим | 503 post-only | Подождать retry_after_seconds, затем повторить |
| Ограниченный режим | 503 cancel-only / торговля отключена | Перестать открывать позиции; отменять, если разрешено; медленно опрашивать |
| Окончательные | 400 (валидация), 401, 404 | Не повторять — исправить запрос или учётные данные |
type Decision =
| { retry: true; delayMs: number }
| { retry: false; reason: string };
function classify(status: number, body: { error?: string; code?: string; retry_after_seconds?: number }, attempt: number): Decision {
const msg = (body.error ?? "").toLowerCase();
const backoff = Math.min(2 ** attempt * 250, 8000);
const jittered = Math.random() * backoff;
// Never retry — the request itself is wrong.
if (status === 401) return { retry: false, reason: "auth: check key, secret, passphrase and clock drift" };
if (status === 404) return { retry: false, reason: "not found" };
if (status === 400) return { retry: false, reason: `validation: ${body.error}` };
// Mode-restricted — the server tells you when to come back.
if (status === 503 && body.code === "post_only_mode") {
return { retry: true, delayMs: (body.retry_after_seconds ?? 60) * 1000 };
}
if (status === 503) return { retry: false, reason: "exchange paused or cancel-only" };
// Transient — safe to retry.
if (status === 425 || status === 429 || status >= 500) return { retry: true, delayMs: jittered };
if (msg.includes("service not ready")) return { retry: true, delayMs: jittered };
return { retry: false, reason: `unhandled status ${status}` };
}Логируйте сообщение, оповещайте по категории
Оповещения по сырым строкам ошибок дают шум, потому что сообщения Polymarket содержат ID ордеров и цены. Оповещайте по категории: всплеск окончательных 400 означает, что вы выкатили ошибку; всплеск 429 — что нужно сбавить темп; всплеск 425 — что Polymarket перезапускается и делать ничего не нужно.
Ошибки, из которых не выбраться отладкой
Некоторые вещи, похожие на ошибки, просто не поддерживаются. У Polymarket нет эндпоинта исторического стакана, так что неправильно вызывать нечего. Стакан разрешившегося рынка возвращает 404, потому что Polymarket перестаёт его отдавать после расчёта по рынку, даже если ваш ID токена в порядке.
Если вы упираетесь в эти стены, вы не отлаживаете интеграцию — вам не хватает источника данных. PolyTest записывает снимки крипторынков Polymarket Up/Down на конкретный момент времени, пока они работают, с полной глубиной стакана, так что история остаётся и после разрешения. Наш собственный справочник по ошибкам описывает форматы ошибок API PolyTest, которые на этом фоне намеренно скучны.
Часто задаваемые вопросы
- Что означает «Unauthorized/Invalid api key» в Polymarket?
- Это значит, что ваш API-ключ отсутствует, истёк или недействителен, но на практике причина обычно одна из четырёх: вы отправляете неполный набор учётных данных (нужны ключ, секрет и passphrase), системные часы рассинхронизировались настолько, что подпись запроса стала недействительной, вы получили ключ для другого кошелька, а не того, с которого торгуете, или вы отправляете заголовки L1 там, где ожидаются заголовки L2.
- Что такое ошибка 425 в Polymarket?
- HTTP 425 Too Early означает, что механизм сопоставления Polymarket перезапускается и ваш запрос пришёл в это окно. Ошибка временная, её безопасно повторять с экспоненциальным отступом. Из-за одиночной 425 не стоит поднимать тревогу.
- Почему Polymarket пишет «The server was unable to process your request»?
- Это сообщение слоя edge, а не задокументированная ошибка CLOB API: запрос не дошёл до приложения или не вернулся из него без проблем. Обычные причины — некорректный запрос, отклонённый до маршрутизации, временный сбой вышестоящего сервиса или длительное превышение лимита запросов: поскольку Polymarket ограничивает скорость очередью, а не отказами, клиент, сильно превышающий лимит, может видеть таймауты на edge вместо чистых 429.
- Почему я получаю 403 от API Polymarket?
- 403 от Polymarket обычно означает, что запрос блокирует edge, а не что аутентификация не прошла. Частые причины — географические ограничения на торговых эндпоинтах, проверки для IP-диапазонов дата-центров и VPN и отсутствие заголовков, похожих на браузерные. Если это происходит с облачной виртуальной машины, но не с вашего ноутбука, дело в репутации IP; если на торговых эндпоинтах, но не на эндпоинтах рыночных данных, — в географии.
- Как исправить «the order signer address has to be the address of the API KEY»?
- Ключ, подписывающий ваш ордер, не совпадает с ключом, который указан в ордере. Значит, вы смешиваете учётные данные — обычно это устаревший API-ключ, закешированный от предыдущего кошелька. Получите учётные данные API заново для кошелька, с которого реально торгуете, и убедитесь, что адрес maker в ордере совпадает с адресом владельца ключа.
- Что означает «order manager not ready» в Polymarket?
- Это сообщение о стадии запуска от механизма сопоставления: сервис доступен, но слой управления ордерами ещё не до конца поднялся, поэтому он принимает соединение и отказывает ордеру. Ошибка временная и тесно связана с HTTP 425 Too Early. Повторяйте с отступом, но приостановите отправку на несколько секунд, а не долбите сервер, потому что перезапуск обычно означает, что стакан вот-вот сдвинется. Постоянное появление — проблема на стороне Polymarket, а не ошибка клиента.
- Почему Polymarket сообщает, что не удалось получить котировку?
- Почти всегда потому, что на стороне, для которой вы запросили цену, нет ликвидности в стакане, а не потому, что что-то сломалось. На тонких рынках Up/Down перед экспирацией одна сторона регулярно пустеет — никто не предлагает Up, когда Up уже предрешён. В выборке 5-минутных рынков BTC у 1,454 из 8,510 за 60 секунд до экспирации на одной из сторон был пустой стакан аск. Считайте это «нет рынка» и пропускайте сделку, а не повторяйте в цикле.
- Нужно ли автоматически повторять запросы при ошибках API Polymarket?
- Только при некоторых. Повторяйте 425, 429, ошибки серии 500 и ошибки соединения с экспоненциальным отступом и случайным разбросом. Режим 503 post-only повторяйте после значения retry_after_seconds из ответа. Никогда не повторяйте ошибки валидации 400, ошибки аутентификации 401 и 404 — для них нужно исправить запрос или учётные данные, а повторы лишь сжигают бюджет лимита запросов.
Получите исторические данные, которые Polymarket не хранит
PolyTest записывает крипторынки Polymarket Up/Down в процессе их работы — 240M+ снимков с 8 уровнями глубины стакана, метками времени с точностью до долей секунды и сохранёнными разрешившимися рынками. Начните с 3-дневного бесплатного пробного периода.
Читать дальше
Лимиты запросов API Polymarket: полный справочник
Polymarket публикует свои лимиты запросов на нескольких страницах, в двух совершенно разных системах и с 10-секундным окном, которого почти никто не ожидает. Здесь всё это собрано в одном наборе таблиц — плюс что на самом деле происходит, когда вы превышаете лимит.
Как создать торгового бота для Polymarket
Большинство руководств по ботам для Polymarket построены на SDK, которых больше не существует. Здесь — актуальный путь от начала до конца: что устанавливать в 2026 году, как на самом деле работает аутентификация, где пробелы в данных и какие сбои убивают ботов в первую неделю.
Python SDK для Polymarket в 2026 году (и уход с py-clob-client)
Если ваш код всё ещё импортирует ClobClient из py_clob_client, он построен на устаревшем пакете — как и большая часть кода для Polymarket, который напишет вам ИИ-ассистент. Вот актуальный SDK и как на него перейти.