Polymarket Bot Tutorial · Розділ 7 із 32
Поглиблений розбір Polymarket Gamma API: endpoints /events і /markets, pagination, tag IDs (864 Tennis, 745 NBA тощо), фільтрація за обсягом за 24 години, rate limits, а також Python і Node code samples.
Що охоплює цей розділ
Gamma - це catalog API Polymarket: вона перелічує кожен event, кожен market, tag, image і resolved outcome, які показує front-end. CLOB API торгує; Gamma описує, що доступне для торгівлі. Більшість bot bugs на рівні discovery виникають через плутанину між цими двома сервісами або через пропущений pagination contract. Цей розділ - польовий довідник по основних endpoints Gamma з точним параметричним поводженням, на яке спираються наші production fetchers.
- Gamma vs CLOB: коли що використовувати
- Анатомія endpoint /events
- Анатомія endpoint /markets
- Tags і tag IDs (verified list)
- Фільтрація: active, closed, ordering за volume24hr
- Pagination і limits
- Rate limits і caching
- Code: отримання top market'ів за 24h-volume
Gamma vs CLOB: коли що використовувати
Два різні сервіси для двох різних задач.
Gamma (gamma-api.polymarket.com): catalog. Перелічує events, markets, tags, descriptions, images, resolved outcomes, 24-hour volume, total volume, end dates. Read-only HTTP. Для більшості reads не потрібна authentication. Оновлюється безперервно, але eventually consistent - market, який щойно закрився, ще кілька секунд може показувати closed: false.
CLOB (clob.polymarket.com): trading + order book. Показує поточні best bid/ask, top-N book depth, recent trades. Для write endpoints потрібна authentication (розміщення ордерів, скасування). Доступні real-time WebSocket channels для оновлень book.
Практичне правило: використовуйте Gamma, щоб знайти, що торгувати; використовуйте CLOB, щоб торгувати цим. Bot, який читає ціни з Gamma, працює зі stale data - fields ціни в Gamma оновлюються рідше, ніж order book у CLOB. Bot, який читає market metadata з CLOB, робить більше requests, ніж потрібно.
Анатомія endpoint /events
GET /events повертає дані на рівні event. "Event" - це сторінка Polymarket; один event може містити кілька markets (наприклад, event 2024 Presidential Election має один market на кожного кандидата).
Ключові fields:
slug: URL-safe ідентифікатор, стабільний протягом життя event.title,description: відображення для людей.endDate(ISO 8601): коли event закривається.active,closed: boolean; поєднуйте їх у query з?active=true&closed=falseдля live events.volume,volume24hr: загальні суми в USD.tags: масив об'єктів tag (див. розділ про tags нижче).markets: масив дочірніх market objects (див. анатомію/markets).
Найпоширеніший шаблон discovery: GET /events?active=true&closed=false&order=volume24hr&ascending=false&limit=100. Повертає 100 live events з найвищим обсягом.
Анатомія endpoint /markets
GET /markets повертає дані на рівні market. Market - це один контракт Y/N або багатовихідний контракт; він знаходиться всередині event.
Ключові fields:
slug: URL-safe ідентифікатор.question: заголовок, що відображається на торговій сторінці (наприклад, "Will Trump be president on January 1, 2027?").outcomes: JSON string із назвами outcome, наприклад'["Yes","No"]'. Для binary завжди два елементи; для NegRisk - більше.outcomePrices: JSON string поточних цін як decimals, наприклад'["0.62","0.38"]'. Обидві сторони сумарно дають ~1.0 мінус spread.clobTokenIds: JSON string ERC-1155 token ID, вирівняних за outcomes. Це токени, які ви фактично купуєте/продаєте.negRisk: boolean; true для багатовихідних markets із сумою до 1. Важливо для розміщення ордерів (розділ 11).
Fields outcomes / outcomePrices / clobTokenIds надходять як JSON strings, а не як розпарсені масиви - зробіть JSON-decode перед використанням.
Tags і tag IDs (verified list)
Tags - це категоріальні labels (Sports, Crypto, Tennis, NBA тощо). Перевірені production tag IDs для найуживаніших категорій:
| Tag | ID | Tag | ID |
|---|---|---|---|
| Sports | 1 | NBA | 745 |
| Crypto | 21 | NFL | 450 |
| Politics | 2 | Tennis | 864 |
| Bitcoin | 100196 | Esports | 702 |
| Ethereum | 100383 | Soccer | 1059 |
| Election | 3 | EPL | 739 |
| Middle East | 1432 | UCL | 2186 |
Фільтруйте за tag за допомогою ?tag_id=745 для конкретного tag або ?tag_slug=nba, використовуючи slug. Фільтрація за slug більш читабельна в code, але трохи повільніша; фільтрація за ID - production default.
Фільтрація: active, closed, ordering за volume24hr
Чотири параметри фільтрації, які ви будете використовувати у 95% випадків.
active=true|false:trueвиключає markets, які команда Polymarket приховала з UI.closed=true|false:falseвиключає resolved markets. Комбінаціяactive=true&closed=false- найпоширеніший live filter.order=volume24hr,order=volume,order=endDate: ключ сортування. Найкорисніший -volume24hrдля пошуку поточних active markets.ascending=true|false: за замовчуванням true на більшості endpoints; для volume ordering майже завжди потрібнеfalse.
Застереження: фільтрація за tag_id у поєднанні з order=volume24hr і ascending=false іноді повертає порожню сторінку, коли у tag дуже мало live markets. Завжди over-fetch (запитуйте більше, ніж показуєте) і post-filter, щоб це обробити.
Pagination і limits
Параметр limit приймає від 1 до 500 на один виклик. Якщо не вказати, значення за замовчуванням - 100. Понад 500 сервер тихо обмежує запит - ви отримаєте 500, але response не міститиме ознак більшого обсягу.
Pagination базується на offset: ?limit=500&offset=500 для другої сторінки. Cursor-based pagination немає, тому паралельні вставки можуть зсувати межі сторінок між викликами. Для більшості задач bot discovery це прийнятно; для archive scrapes сортуйте за стабільним field (endDate або createdAt) і виявляйте overlap за slug.
Практичний шаблон для "усіх live markets": запитуйте limit=500&order=volume24hr&ascending=false. Це покриває топ-500 за volume, тобто практично всі markets із помітною активністю. Переходити далі першої сторінки рідко має сенс - markets у хвості розподілу volume за визначенням не там, де відбувається основна дія.
Rate limits і caching
Gamma стоїть за Cloudflare і має soft rate limits на IP. Емпіричні пороги, які спостерігалися під production load:
- До ~30 req/sec з однієї IP стабільно: нормально.
- Сплески 100+ req/sec: іноді 429, повторні спроби успішні.
- ~500 req/sec стабільно: rate-limit page або тимчасовий block (10-60 с).
Публічні response headers містять значення Cache-Control 30-60 секунд для більшості endpoints. Дотримуйтеся їх - немає користі перезапитувати той самий event 10 разів за хвилину. Production-патерн caching: in-process LRU + TTL, ключований на повний URL, TTL 30 с. Це економить кількість requests і зменшує latency.
Для high-frequency стратегій віддзеркалюйте дані Gamma в local store, який оновлює один fetcher process; кілька consumers читають із цього store. Один fetcher × багато consumers > багато fetchers × Gamma.
Code: отримання top market'ів за 24h-volume
Reference fetcher трьома мовами, який повертає top 50 live markets за 24-hour volume.
Python:
import requests
r = requests.get("https://gamma-api.polymarket.com/events",
params={"active":"true","closed":"false",
"order":"volume24hr","ascending":"false","limit":50},
timeout=10)
for ev in r.json()[:50]:
print(ev["slug"], ev.get("volume24hr"))
Node:
const url = "https://gamma-api.polymarket.com/events?active=true&closed=false" +
"&order=volume24hr&ascending=false&limit=50";
const events = await fetch(url).then(r => r.json());
for (const ev of events) console.log(ev.slug, ev.volume24hr);
Curl:
curl -s "https://gamma-api.polymarket.com/events?active=true&closed=false&order=volume24hr&ascending=false&limit=50" \
| jq '.[].slug'
Endpoint Polymarket gamma /events НЕ підтримує free-text search parameter - додавання ?q=foo або ?search=foo тихо повертає default ordering. Замість цього фільтруйте за slug або tag.












