Ключевые выводыПозиции кошельков живут только на data-api.polymarket.com; Gamma отдаёт метаданные рынков, а CLOB — стаканы, цены и ваш собственный аутентифицированный журнал.
- Позиции кошельков живут только на
data-api.polymarket.com; Gamma отдаёт метаданные рынков, а CLOB — стаканы, цены и ваш собственный аутентифицированный журнал. - Запрашивать нужно User Profile Address аккаунта, а какой это адрес — зависит от типа: EOA,
POLY_PROXY,GNOSIS_SAFEилиPOLY_1271; для простого EOA фандером служит сам EOA. При неверном адресе вернётся пустой массив, а не ошибка. - У
/positionsпо умолчаниюsizeThreshold=1.0иlimit=100(максимум 500,offsetдо 10 000): ставьте порог в 0, листайте черезoffsetи читайтеoutcomeIndexвместе сsize. /activityпринимает двенадцать типов, а не шесть: к торговым добавлены DEPOSIT, WITHDRAWAL, YIELD, MAKER_REBATE, TAKER_REBATE и REFERRAL_REWARD; для депозитов и выводов нуженexcludeDepositsWithdrawals=false,start/endзадаются в секундах эпохи, аoffsetза пределом 5 000 отклоняется с кодом 400.- Лимиты считаются по IP:
/positionsи/closed-positions— 150 запросов за 10 секунд,/trades— 200, Data API в целом — 1 000. Документация описывает очередь, но наш тест августа 2026 года показал немедленные 429 без плавного замедления. - Чтение полностью публично; аутентификация L1/L2 — с типом подписи и адресом фандера, подобранными под тип аккаунта, — нужна только для торговли и для собственного журнала.
Краткое содержание подготовлено с помощью ИИ.
Где живёт Data API
Базовый адрес — https://data-api.polymarket.com, отдельно от Gamma (рынки и события) и от CLOB (стаканы и торговля). Модель, которая экономит больше всего времени: Gamma говорит, что существует, CLOB — сколько это стоит, а Data API — кто это держит.
Эндпоинт позиций Data API — обычный GET, которому не нужны ни ключ, ни подпись, ни аккаунт: документация описывает маршруты Data API как публичные.
GET https://data-api.polymarket.com/positions?user=0x...&sizeThreshold=50&limit=500
Эндпоинту позиций пользователя обязателен только параметр user, а сверху навешиваются полезные фильтры. market принимает один или несколько condition ID списком через запятую, eventId делает то же самое для событий и взаимоисключающ с market. sizeThreshold задаёт минимальный размер позиции для включения в ответ и по умолчанию равен 1.0 — то есть пыль тихо отсекается; поставьте 0, если нужно всё. redeemable и mergeable сужают ответ до позиций в этих состояниях, а пагинация работает через limit (по умолчанию 100, максимум 500) и offset (максимум 10 000). Сортировка доступна через sortBy — CURRENT, INITIAL, TOKENS, CASHPNL, PERCENTPNL, TITLE, RESOLVING, PRICE или AVGPRICE, по умолчанию TOKENS — с sortDirection в значениях ASC или DESC.
Пример ответа эндпоинта позиций содержит объекты с полями proxyWallet, conditionId, asset, size, avgPrice, initialValue, currentValue, cashPnl, percentPnl, realizedPnl, curPrice, redeemable, mergeable, negativeRisk плюс рыночный контекст — title, slug, outcome, outcomeIndex, oppositeOutcome, endDate.
Два поля заслуживают внимания до того, как вы начнёте на них опираться. Параметр user документирован как User Profile Address, и какой это адрес — зависит от типа аккаунта: Polymarket поддерживает аккаунты на обычном EOA наряду с типами подписи POLY_PROXY, GNOSIS_SAFE и POLY_1271, причём для простого EOA фандером выступает сам EOA. Так что правило «всегда запрашивайте прокси» неверно; верное — запрашивать адрес, который держит позицию при этом типе аккаунта, и именно его ответ возвращает в поле proxyWallet. Запрос подписывающего ключа, который не является профильным адресом, вернёт пустой массив, а не ошибку, — поэтому логируйте, какой адрес вы спрашивали. А outcomeIndex важен не меньше size: у одного рынка есть сторона Yes и сторона No, поэтому позиция осмысленна только вместе с исходом, к которому относится.
import requests
DATA = "https://data-api.polymarket.com"
PAGE = 500 # документированный максимум
def positions(profile_address, min_size=0):
out, offset = [], 0
while offset <= 10000: # документированный потолок offset
r = requests.get(f"{DATA}/positions",
params={"user": profile_address, "sizeThreshold": min_size,
"limit": PAGE, "offset": offset,
"sortBy": "CURRENT", "sortDirection": "DESC"},
timeout=10)
r.raise_for_status()
page = r.json()
out.extend(page)
if len(page) < PAGE: # неполная страница — значит, последняя
break
offset += PAGE
return out
for p in positions("0x0000000000000000000000000000000000000000")[:5]:
print(f"{p['title'][:45]:<45} {p['outcome']:<4} "
f"size={p['size']:>10.2f} value=${p['currentValue']:>10.2f} pnl=${p['cashPnl']:>9.2f}")
На что смотреть: sizeThreshold=0 перекрывает значение по умолчанию 1.0, поэтому пыль не отсекается молча, а цикл идёт по offset, а не останавливается на первых 500 — иначе кошелёк с широким портфелем оказался бы обрезан без всякой ошибки. Цикл завершается на неполной странице и не пытается уйти за документированный потолок offset в 10 000, который и есть реальный предел глубины этого эндпоинта. Для кошелька без открытых позиций вызов вернёт пустой список — ровно ту же форму, что и при запросе адреса, не являющегося профильным для аккаунта.
Откуда взять список кошельков
Позиции бесполезны, пока неизвестно, чьи именно читать, — для этого и нужен лидерборд. Data API отдаёт рейтинг топ-трейдеров по прибыли или объёму за выбранное окно, а рядом существует лидерборд билдеров — приложений, которые направляют поток ордеров через билдер-программу Polymarket. Документация лидерборда тоньше остальной поверхности, а форма ответа менялась не раз, поэтому сверяйте текущий ответ со своим парсером, а не доверяйте списку полей из чужой статьи — включая эту.
Операционный паттерн тот же, что и на любой площадке с такой связкой: рейтинги двигаются медленно, позиции — постоянно. Забирайте лидерборд по медленному расписанию, кешируйте список кошельков и тратьте бюджет запросов на вызовы позиций, которые действительно меняются. Если нужен итог по портфелю, а не разбивка по позициям, /value вернёт совокупную стоимость кошелька одним вызовом — заметно дешевле, чем тянуть все позиции и суммировать самому.
Как читать сделки и активность
Позиции говорят, где кошелёк находится сейчас; эндпоинт активности — как он туда пришёл. GET /activity?user=0x... возвращает ончейн-активность, упорядоченную по времени от свежего к старому, а фильтр type принимает двенадцать значений: TRADE, SPLIT, MERGE, REDEEM, REWARD, CONVERSION, DEPOSIT, WITHDRAWAL, YIELD, MAKER_REBATE, TAKER_REBATE и REFERRAL_REWARD. Этот список стоит прочитать дважды, потому что сделкой из них является только первое: сплиты и мерджи перекладывают средства между дополняющими токенами исходов, редемпшены закрывают разрешившиеся рынки, ребейты и доходность — это поступления, а не активность, и если считать всё это сделками, любая метрика объёма окажется завышенной.
Три параметра ловят людей регулярно. start и end задаются в секундах, а не в миллисекундах — конвенция, обратная большинству биржевых API. Депозиты и выводы по умолчанию исключены: excludeDepositsWithdrawals имеет значение true по умолчанию, и это значение побеждает, даже если вы указали DEPOSIT или WITHDRAWAL в type, — чтобы их увидеть, нужно явно передать false. А история по умолчанию ограничена окном: без start или при start=0 вернутся примерно последние три года, тогда как положительная отметка вроде 1 открывает полную историю. side фильтрует BUY или SELL, но применяется только к сделкам, поэтому в сочетании с фильтром REDEEM вернёт пустоту.
Пагинация здесь ведёт себя иначе, чем у /positions, и разница важна. Потолок offset равен 5 000, причём запросы за его пределами отклоняются с кодом 400, а не обрезаются молча; чтобы уйти глубже, нужно листать внутри окон start/end, у каждого из которых свой бюджет offset. Порядок стабилен в обе стороны, поэтому страницы стыкуются без пропусков и повторов. Сортировка идёт через sortBy со значениями TIMESTAMP, TOKENS или CASH.
Отдельно по исполнениям: /trades возвращает сделки по адресу кошелька с необязательными фильтрами и несёт собственный, более жёсткий бюджет — 200 запросов за 10 секунд. Со стороны рынка, а не кошелька, работает эндпоинт держателей: GET /holders?market=... возвращает крупнейших держателей токенов исхода конкретного рынка — прямой способ находить новые кошельки, достойные наблюдения, вообще не обходя лидерборд.
Позиции в двух других API
Регулярный поисковый запрос — эндпоинт позиций в CLOB или эндпоинт позиций в Gamma, и честный ответ таков: на август 2026 года позиции кошельков не живут ни там, ни там. Это не пробел в вашем чтении, а способ разделения поверхностей.
CLOB на https://clob.polymarket.com — поверхность торговли и рыночных данных: стаканы через /book и /books, цены через /price, /midpoint и /prices-history, а собственный журнал — через /data/orders и /data/trades. Последние два ограничены аккаунтом и требуют аутентификации, то есть показывают, что делали вы, а не что держит произвольный кошелёк. Gamma на https://gamma-api.polymarket.com — поверхность метаданных: события, рынки, теги, поиск. Она отвечает на вопрос «что это за рынок и какие у него condition ID», а это ровно то, что нужно, чтобы превратить conditionId из ответа по позициям в человекочитаемый рынок.
Поэтому практическая форма трекера — три хоста с тремя задачами: Data API для состояния кошельков, Gamma для рыночного контекста, CLOB для живых цен. У каждого свой бюджет лимитов, и это скорее плюс, чем неудобство: обогащение позиций метаданными рынка тратит квоту Gamma, а не ту, которую расходует ваш опрос позиций.
Аутентификация для аккаунтных эндпоинтов
Всё вышеописанное публично. Аутентификация появляется только там, где вы выставляете ордера или читаете собственный журнал, и устроена она в два уровня. L1 — подпись вашим приватным ключом, которая создаёт или выводит API-ключ; L2 — сам этот ключ, используемый как HMAC-заголовки в последующих запросах. Спотыкаются же на паре «подписант — фандер», потому что это не всегда один и тот же адрес: Polymarket поддерживает несколько типов аккаунтов — обычный EOA наряду с типами подписи POLY_PROXY, GNOSIS_SAFE и POLY_1271, — и клиенту нужно сообщить и применимый тип подписи, и адрес, который фактически держит средства. Для аккаунта на EOA фандером выступает сам EOA; для прокси- и Safe-типов — нет. Ошибитесь в этой паре — и ордера не пройдут валидацию, хотя сам ключ верен.
Отсюда два следствия. Первое: конвейеру наблюдения за кошельками учётные данные не нужны вовсе — если вы только читаете позиции, активность и сделки по адресу, неаутентифицированный клиент и есть правильная конструкция. Второе: когда торговля всё же добавляется, эндпоинты API-ключей несут собственный лимит в 100 запросов за 10 секунд, а ордера и отмены в CLOB дополнительно управляются токен-бакетными лимитами на подписанта, которые лежат за пределами IP-ориентированных чисел ниже.
Лимиты и что они значат для масштаба
Лимиты Polymarket считаются по IP и применяются через Cloudflare на скользящих, а не фиксированных окнах. Документация утверждает, что лишние запросы задерживаются и ставятся в очередь, но наш тест августа 2026 года показал немедленные 429 без плавного замедления. Следите и за задержкой, и за кодами статуса, а также ведите собственные счётчики запросов по эндпоинтам вместо расчёта на один неизменный сигнал.
Документированные бюджеты Data API:
| Эндпоинт | Лимит |
|---|---|
| Общий | 1 000 запросов / 10 с |
/positions |
150 запросов / 10 с |
/closed-positions |
150 запросов / 10 с |
/trades |
200 запросов / 10 с |
Для сравнения: общая квота Gamma — 4 000 за 10 секунд, у CLOB — 9 000, а глобальный потолок по всему сразу — 15 000.
Один вызов позиций на кошелёк превращает 150 за 10 секунд в арифметику. Если планировать примерно на 70% от лимита, чтобы держаться в стороне от троттлинга, один адрес обслуживает около 105 чтений кошельков за десятисекундный цикл:
| Кошельков под наблюдением | Обновление раз в 10 с | раз в 30 с | раз в 60 с |
|---|---|---|---|
| 100 | 1 | 1 | 1 |
| 500 | 5 | 2 | 1 |
| 1 000 | 10 | 4 | 2 |
| 5 000 | 48 | 16 | 8 |
Это расчёты по опубликованным лимитам, а не замеры: считайте их отправной точкой планирования и проверяйте на собственном трафике.
Прежде чем добавлять мощность, потратьте программные рычаги — большинство трекеров расточительны одинаково, в трёх местах. Группируйте по рынку, а не по кошельку, где это возможно: /holders отвечает на вопрос «кто держит этот рынок» одним вызовом, заменяя десятки чтений по кошелькам. Используйте /value, когда нужен итог по портфелю, а не каждая строка. И разносите опрос по уровням: кошелькам с крупной живой экспозицией нужен короткий интервал, спящим — длинный, а равномерный таймер тратит большую часть бюджета на подтверждение того, что ничего не изменилось.
За этими рычагами ограничением остаётся то, что бюджет принадлежит IP-адресу, а не аккаунту, — поэтому широкий трекер либо замедляется, либо распределяется по адресам. Эту часть и закрывают наши персональные прокси: выделенные IPv4-адреса, статичные на весь срок плана, к каждому применяется собственная документированная поадресная квота — но реальное масштабирование стоит проверять на своей нагрузке, а не считать линейным по умолчанию. Изоляция воркеров заодно не даёт ответам лимитера или очереди одной задачи тормозить другую.