Ключевые выводыДокументированная первосторонняя поверхность Polymarket — Gamma, CLOB и Data API — это HTTP плюс вебсокет-каналы CLOB; GraphQL-эндпоинт на август 2026 года не документирован ни для одного из трёх хостов.
- Документированная первосторонняя поверхность Polymarket — Gamma, CLOB и Data API — это HTTP плюс вебсокет-каналы CLOB; GraphQL-эндпоинт на август 2026 года не документирован ни для одного из трёх хостов.
- Доступ через GraphQL даёт открытый сабграф Polymarket, который, по документации, может разместить кто угодно, а авторитетный справочник по полям — файл
schema.graphqlв публичном репозитории. - Работа разнесена по сабграфам — позиции, стакан, активность, открытый интерес и P&L, — доступным на публичных эндпоинтах Goldsky, где URL фиксирует конкретную версию, либо через шлюз The Graph с API-ключом; документированный Free Plan на 100 000 запросов в месяц принадлежит именно The Graph, а не Goldsky.
- Перед историческим бэкфиллом проверьте, какие контракты биржи индексирует развёртывание: публичный манифест по-прежнему перечисляет исходный CTF Exchange, тогда как торговля переехала на более новый, — старое развёртывание может быть неполным.
- Перечисленные сабграфы не заменяют ни Gamma для каноничного текста рынка, ни CLOB для живого стакана, — поэтому продукты на сабграфах присоединяют Gamma по condition ID.
- Код 200 не означает, что запрос удался: проверяйте ещё и поле
errors, а листайте курсором (id_gt), а не глубокимskip, приfirstне больше 1 000. - Сторонние GraphQL-индексаторы вроде Bitquery — самостоятельные поставщики со своими схемами, хранением и ценами, а не GraphQL-версии собственных API Polymarket.
Краткое содержание подготовлено с помощью ИИ.
У REST API нет GraphQL-эндпоинта
На август 2026 года три REST API Polymarket — Gamma, CLOB и Data API — описаны как HTTP-интерфейсы в стиле REST: пути, параметры запроса, JSON-ответы, схема OpenAPI на каждый эндпоинт. Ни для одного из трёх хостов GraphQL-эндпоинт не документирован, и маршрута /graphql на gamma-api.polymarket.com или clob.polymarket.com вы не найдёте. Обратите внимание на точность формулировки: CLOB не сводится к схеме «запрос-ответ» — у него есть официальные вебсокет-каналы рынка и пользователя; отсутствует везде именно документированная GraphQL-поверхность.
Сказать это прямо стоит потому, что поисковый спрос предполагает обратное. Люди ищут GraphQL-эндпоинт для рынков в Gamma или GraphQL-схему рынков, которую можно проинтроспектировать, и уходят с ощущением, что документация неполна. Она полна: HTTP- и вебсокет-поверхности и есть всё, что предлагает первая сторона. Вместо GraphQL там существует отдельный, действительно GraphQL-образный слой, построенный на индексации блокчейна, и в документации разработчика Polymarket у него свой раздел.
Различие важнее, чем кажется, потому что слои хранят разные данные. Первосторонние API отдают то, что знают системы самой Polymarket: вопросы рынков, слаги, теги, изображения, стаканы, текущие цены, позиции кошельков с посчитанным P&L. Слой сабграфов отдаёт то, что записал блокчейн: условия, переводы токенов, сделки, сплиты, мерджи, редемпшены, позиции, выведенные из ончейн-событий. Кое-что есть в обоих. А вот то, чего от GraphQL хотят чаще всего, — заголовок рынка и его живая цена — не то, для хранения чего построены перечисленные сабграфы.
Что индексируют сабграфы
Официальная позиция коротка: Polymarket написала и открыла исходники сабграфа, который через GraphQL-интерфейс отдаёт агрегатные расчёты и индексацию событий по объёму, пользовательским позициям, рынкам и ликвидности, обновляется в реальном времени и — вот деталь, определяющая всё дальнейшее — может быть размещён кем угодно. Схема лежит в файле schema.graphql в публичном репозитории, и именно она авторитетна по составу полей.
На практике работа разнесена по нескольким сабграфам, а не по одному. Собственная документация Polymarket для агентов перечисляет набор, размещённый на Goldsky:
| Сабграф | Что индексирует |
|---|---|
positions-subgraph |
Балансы токенов пользователей |
orderbook-subgraph |
События стакана и сделок |
activity-subgraph |
Сплиты, мерджи, редемпшены |
oi-subgraph |
Открытый интерес по рынкам и глобально |
pnl-subgraph |
Прибыль и убыток по позициям |
Эндпоинты следуют фиксированному шаблону — https://api.goldsky.com/api/public/project_.../subgraphs/<имя>/<версия>/gn, — причём версия зафиксирована для каждого сабграфа, поэтому URL, скопированный из годовалого туториала, может указывать на версию, которая уже не соответствует текущей схеме. Проверяйте версию, прежде чем доверять найденному в сети запросу.
Альтернативный хост — децентрализованная сеть: сабграф в The Graph запрашивается через шлюз https://gateway.thegraph.com/api/{api-key}/subgraphs/id/{id}, для которого нужен API-ключ из Graph Explorer. Обратите внимание, чья это бесплатная квота: Goldsky отдаёт публичные эндпоинты сабграфов Polymarket, которым ключ не нужен, а 100 000 запросов в месяц — это документированный Free Plan именно у The Graph, за которым идёт платный тариф с оплатой по использованию. Отсюда и практическая причина предпочесть шлюз для всего, что вы намерены держать в проде: публичный эндпоинт, которым вы не управляете, может измениться или исчезнуть, а у запроса с ключом есть квота, о которой можно рассуждать, и платный уровень, в который можно вырасти.
Поскольку сабграф открыт и размещаем кем угодно, есть и третий вариант — поднять его самостоятельно. Превышение бесплатной квоты причиной для этого не является: для этого существует платный тариф. Self-hosting оправдывает себя, когда нужна изменённая схема, полный контроль над индексацией, гарантированные свойства данных или отсутствие сторонней зависимости в пути данных.
Одна оговорка перед любым историческим бэкфиллом. Публичный манифест сабграфа Polymarket по-прежнему перечисляет исходный контракт CTF Exchange среди индексируемых, тогда как текущая торговая система работает на более новом развёртывании биржи. Сабграф видит только те контракты, которые названы в его манифесте, поэтому старое развёртывание — включая зафиксированную версию Goldsky, скопированную из туториала, — может не содержать полной свежей истории сделок. Развёртывания, знающие о V2, существуют. Прежде чем доверять бэкфиллу, проверьте, какие контракты биржи индексирует конкретное развёртывание, и сверьте его свежие данные с REST-источником, которому вы уже доверяете.
Сторонние GraphQL-сервисы — отдельная категория. Провайдеры вроде Bitquery тоже индексируют активность Polymarket и отдают её через GraphQL, иногда с метаданными рынков и агрегациями, которых в официальных сабграфах нет. Это независимые продукты со своими схемами, глубиной хранения, аутентификацией и ценами — не GraphQL-версии Gamma, CLOB или Data API и не поддерживаются Polymarket. Полезно, но оценивать их следует как поставщиков, а не как официальную поверхность.
Как написать запрос к рынкам и ценам
Вот рабочий GraphQL-запрос к рынкам — точнее, честная версия этой задачи. К публичному эндпоинту Goldsky, ключ не нужен:
curl -X POST \
https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/orderbook-subgraph/0.0.1/gn \
-H "Content-Type: application/json" \
-d '{"query": "query { orderbooks(first: 5) { id tradesQuantity scaledCollateralVolume } }"}'
Запустите — и форма ответа объяснит название раздела. Вы получите id (идентификатор токена или условия), число сделок и объём. Вы не получите «Произойдёт ли X до декабря?», потому что этой строки в блокчейне никогда не было. То же с ценами: сабграф знает исполненные сделки, а не текущие лучшие бид и аск, стоящие в стакане CLOB.
Поэтому реалистичный конвейер использует оба слоя, соединяя их по condition ID:
import requests
GOLDSKY = ("https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw"
"/subgraphs/positions-subgraph/0.0.7/gn")
GAMMA = "https://gamma-api.polymarket.com"
# Поля ниже соответствуют сущности UserPosition в публичном schema.graphql.
# Развёртывания различаются — сначала прогоните интроспекцию внизу.
QUERY = """
query Positions($first: Int!, $lastId: String!) {
userPositions(first: $first, where: { id_gt: $lastId }, orderBy: id) {
id
user
tokenId
amount
avgPrice
realizedPnl
totalBought
}
}
"""
def gql(url, query, variables=None):
r = requests.post(url, json={"query": query, "variables": variables or {}}, timeout=30)
r.raise_for_status() # уровень HTTP
payload = r.json()
if payload.get("errors"): # уровень GraphQL — 200 не значит успех
raise RuntimeError(payload["errors"])
return payload["data"]
def all_positions(page=500): # курсорная пагинация, без глубокого skip
last_id, out = "", []
while True:
rows = gql(GOLDSKY, QUERY, {"first": page, "lastId": last_id})["userPositions"]
if not rows:
return out
out.extend(rows)
last_id = rows[-1]["id"]
def market_title(condition_id): # каноничный текст — Gamma, а не сабграф
r = requests.get(f"{GAMMA}/markets", params={"condition_ids": condition_id}, timeout=15)
r.raise_for_status()
rows = r.json()
return rows[0]["question"] if rows else None
# Проверить схему того развёртывания, которое вы реально вызываете:
INTROSPECT = '{ __type(name: "UserPosition") { fields { name type { name kind } } } }'
print(gql(GOLDSKY, INTROSPECT))
На что смотреть. Успешный HTTP-статус не гарантирует успешной GraphQL-операции: ответ может прийти с кодом 200 и массивом errors в теле, поэтому проверяйте оба уровня — raise_for_status() для одного и поле errors для другого. Пагинация здесь курсорная, а не через skip: first ограничен индексатором тысячей, а большие значения skip работают медленно, тогда как проход по id_gt от последней увиденной строки остаётся быстрым на любой глубине. И самое важное — сначала выполните интроспекцию. Имена полей различаются между развёртываниями и версиями сабграфов (опубликованные гайды показывают разные схемы для одного и того же эндпоинта), поэтому единственный авторитет — схема того развёртывания, которое вы вызываете.
Чего пример не делает: нет политики ретраев, нет кеширования обращений к Gamma (заголовки не меняются, им место в локальном хранилище) и нет обработки лимитов ни для одного из слоёв.
Сабграф или REST: как выбирать
Выбор здесь на самом деле не между GraphQL и REST API как стилями — вопрос в том, в каком слое лежит ваш ответ.
| Что нужно | Слой |
|---|---|
| Вопрос рынка, слаг, теги, изображения, даты | REST (Gamma) |
| Живой стакан, текущая цена, midpoint | REST (CLOB) |
| Текущие позиции кошелька с посчитанным P&L | REST (Data API) — самый простой путь |
| Историю сделок и агрегаты объёма | Сабграф |
| Сплиты, мерджи, редемпшены как события | Сабграф |
| Открытый интерес во времени | Сабграф |
| Произвольную агрегацию по ончейн-истории | Сабграф |
Для текущих позиций кошелька самый простой REST-путь — эндпоинт Data API /positions. Два правила покрывают большинство случаев. Если данные — это текущее значение, которое считает сама Polymarket, REST и проще, и свежее. Если данные историчны, событийны по форме или требуют агрегации, которой ни один REST-эндпоинт не предлагает, инструмент — сабграф: ровно для этого индексатор и нужен.
Насчёт «GraphQL или SDK»: это тоже не альтернативы. Клиенты Polymarket оборачивают REST-поверхности, а сообщество добавляет поверх тех же эндпоинтов клиентов к сабграфам — это избавляет от написания HTTP-обвязки, но не меняет содержимого слоёв. SDK, предлагающий «GraphQL-клиент» рядом с клиентами CLOB, Gamma и Data, оборачивает ровно то разделение, которое описано здесь.
Одна практическая асимметрия определяет многие архитектуры: перечисленные сабграфы Polymarket не заменяют ни Gamma как каноничный источник читаемых метаданных, ни CLOB как живой стакан. Поэтому почти любой продукт для пользователей, построенный на данных сабграфа, всё равно ходит в Gamma, чтобы отрисовать заголовки. Закладывайте этот join сразу: разрешайте condition ID в заголовки один раз, кешируйте — и позвольте GraphQL-слою делать то, в чём он хорош.
Именно на REST-половине действуют поадресные лимиты из руководства по лимитам Polymarket — 300 запросов за 10 секунд у /markets, 150 у /positions, — и именно в них упирается широкий бэкфилл или загруженный дашборд. Квоты сабграфов существуют отдельно и привязаны к вашему API-ключу, а не к адресу. Если ограничением становится REST-половина конвейера, наши прокси для криптопроектов — это выделенные IPv4-адреса, статичные на весь срок плана, к каждому из которых применяется своя документированная квота; GraphQL-половина при этом масштабируется квотой запросов, так что обе половины считаются независимо.