Все статьи
Справочник APIAPI PolymarketОтладкаCLOB

Ошибки API Polymarket: расшифровка каждого кода

Сообщения об ошибках Polymarket лаконичны, а те, что ломают вашего бота в 3 часа ночи, обычно вообще отсутствуют в документации. Вот полный справочник — задокументированные ошибки, незадокументированные и что на самом деле делать с каждой.

12 мин чтения

Каждая ошибка CLOB API Polymarket возвращается в одном и том же виде — JSON-объект с единственным полем error. Это восхитительно единообразно и совершенно бесполезно, когда вы пытаетесь понять, куда только что исчез ваш ордер.

{
  "error": "<message>"
}

Эта страница их расшифровывает. Здесь — задокументированные ошибки CLOB, коды статуса и их настоящие причины, а также то, чего вы не найдёте в официальной документации: ошибки, с которыми люди реально сталкиваются в продакшене и которые Polymarket так и не описал.

У каждого задокументированного сообщения также есть своя страница с причинами и рекомендацией по повтору — они перечислены в указателе ошибок Polymarket.

Краткий справочник по кодам статуса

СтатусЗначениеЧастые причины
400Bad RequestНеверные параметры, некорректная полезная нагрузка, нарушение бизнес-логики
401UnauthorizedОтсутствующий или недействительный API-ключ, неверная подпись HMAC, просроченная метка времени
404Not FoundРынок не существует, ордер не найден, ID токена не распознан
425Too EarlyМеханизм сопоставления перезапускается — повторите с отступом
429Too Many RequestsПревышен лимит запросов — экспоненциально увеличивайте паузу
500Internal Server ErrorНепредвиденная ошибка сервера — повторите с отступом
503Service UnavailableБиржа на паузе или заблокирована режимом cancel-only / post-only

Подмена кода статуса, которая собьёт вас с толку

CLOB API переписывает коды статуса в зависимости от содержания сообщения. Любое сообщение об ошибке, содержащее "not found", возвращает 404, содержащее "unauthorized" — 401, а содержащее "context canceled" — 400, независимо от исходного кода статуса. Если код статуса противоречит сообщению, причина в этом. Стройте обработку ошибок на тексте сообщения, а не на числе.

401 — ошибки аутентификации

Unauthorized/Invalid api key

Самая часто ищущаяся ошибка Polymarket. Ваш API-ключ отсутствует, истёк или недействителен. На практике это почти никогда не действительно плохой ключ — обычно дело в одном из этих пунктов:

  1. Вы отправляете только часть набора учётных данных. Аутентификации L2 в Polymarket нужны ключ, секрет и passphrase вместе. Частая ошибка — заполнить POLY_API_KEY и POLY_PASSPHRASE, но не задать секрет: клиент отправляет корректно сформированный, но не поддающийся подписи запрос.
  2. Системные часы рассинхронизировались. Подпись включает метку времени, и часы, отстающие больше чем на несколько секунд, дают подпись, которую сервер отклоняет как недействительную. Эту причину находят последней, и она удручающе часто встречается на виртуальных машинах и в контейнерах.
  3. Вы получили ключ для другого кошелька, а не того, с которого торгуете. Ключи привязаны к адресу подписанта, который их создал.
  4. Вы обращаетесь к аутентифицированному эндпоинту с заголовками 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-дневного бесплатного пробного периода.

Читать дальше