Polymarket Bot Tutorial · Hoofdstuk 7 van 32
Polymarket Gamma API deep dive: /events en /markets endpoints, pagination, tag IDs (864 Tennis, 745 NBA, etc.), filteren op 24h volume, rate limits en Python- en Node-codevoorbeelden.
Wat dit hoofdstuk behandelt
Gamma is Polymarkets catalogus-API — het lijst elk event, elke markt, tag, image en resolved outcome die de front-end toont. De CLOB API tradet; Gamma beschrijft wat tradeable is. De meeste bot-bugs op de discovery-laag komen van de twee verwarren of het missen van het pagination-contract. Dit hoofdstuk is de veldreferentie voor de hoofd-endpoints van Gamma met het exacte parameter-gedrag waarop onze productie-fetchers afhangen.
Dit is hoofdstuk 7 van onze 32-delige serie over het bouwen van een Polymarket trading bot. We behandelen het onderwerp in detail in de secties hieronder. De body content voor elke sectie wordt geschreven en hoofdstuk-per-hoofdstuk uitgerold; FAQ-antwoorden en referenties zijn al compleet en weerspiegelen production-ervaring van het draaien van onze eigen trader.
- Gamma vs CLOB: wanneer welke gebruiken
- /events endpoint anatomie
- /markets endpoint anatomie
- Tags en tag IDs (geverifieerde lijst)
- Filteren: active, closed, volume24hr ordering
- Pagination en limits
- Rate limits en caching
- Code: fetch top 24h-volume markten
Gamma vs CLOB: wanneer welke gebruiken
Twee verschillende services voor twee verschillende jobs.
Gamma (gamma-api.polymarket.com): catalogus. Lijst events, markten, tags, beschrijvingen, images, resolved outcomes, 24-uurs volume, totaal volume, end dates. Read-only HTTP. Geen authenticatie vereist voor de meeste reads. Continu geüpdatet maar eventually consistent — een markt die net gesloten is kan een paar seconden lang closed: false tonen.
CLOB (clob.polymarket.com): trading + order book. Lijst huidige best bid/ask, top-N book depth, recente trades. Geauthenticeerd voor write endpoints (order plaatsen, cancellation). Real-time WebSocket channels beschikbaar voor book updates.
Vuistregel: gebruik Gamma om te vinden wat te traden; gebruik CLOB om het te traden. Een bot die prijzen leest uit Gamma gebruikt stale data — Gamma's prijsvelden updaten minder frequent dan CLOB's order book. Een bot die market-metadata leest uit CLOB maakt meer requests dan nodig.
/events endpoint anatomie
GET /events geeft event-niveau data terug. Een "event" is een Polymarket-pagina; een enkel event kan meerdere markten bevatten (bijv. het 2024 Presidential Election event heeft één markt per kandidaat).
Belangrijke velden:
slug: URL-safe identifier, stabiel voor de levensduur van het event.title,description: human display.endDate(ISO 8601): wanneer het event sluit.active,closed: booleans; combineer in een query met?active=true&closed=falsevoor live events.volume,volume24hr: USD-totalen.tags: array van tag-objecten (zie tags-sectie hieronder).markets: array van child market-objecten (zie/marketsanatomie).
Het enkele meest voorkomende discovery-patroon: GET /events?active=true&closed=false&order=volume24hr&ascending=false&limit=100. Geeft de 100 hoogste-volume momenteel-live events terug.
/markets endpoint anatomie
GET /markets geeft market-niveau data terug. Een markt is één J/N of multi-outcome contract; hij leeft binnen een event.
Belangrijke velden:
slug: URL-safe identifier.question: de titel getoond op de trading-pagina (bijv. "Will Trump be president on January 1, 2027?").outcomes: JSON-string van outcome-namen, bijv.'["Yes","No"]'. Altijd twee elementen voor binary; meer voor NegRisk.outcomePrices: JSON-string van huidige prijzen als decimalen, bijv.'["0.62","0.38"]'. Beide zijden sommeren tot ~1,0 minus spread.clobTokenIds: JSON-string van ERC-1155 token-IDs uitgelijnd met outcomes. Dit zijn de tokens die je daadwerkelijk koopt/verkoopt.negRisk: boolean; true voor multi-outcome sum-to-1 markten. Telt voor order plaatsing (hoofdstuk 11).
De outcomes / outcomePrices / clobTokenIds velden komen aan als JSON-strings, geen geparseerde arrays — JSON-decode ze voor gebruik.
Tags en tag IDs (geverifieerde lijst)
Tags zijn categorische labels (Sport, Crypto, Tennis, NBA, etc.). De geverifieerde productie tag-IDs voor de meest-gebruikte categorieën:
| Tag | ID | Tag | ID |
|---|---|---|---|
| Sport | 1 | NBA | 745 |
| Crypto | 21 | NFL | 450 |
| Politiek | 2 | Tennis | 864 |
| Bitcoin | 100196 | Esports | 702 |
| Ethereum | 100383 | Voetbal | 1059 |
| Verkiezing | 3 | EPL | 739 |
| Midden-Oosten | 1432 | UCL | 2186 |
Filter op tag met ?tag_id=745 voor een specifieke tag, of ?tag_slug=nba met de slug. Slug-based filteren is leesbaarder in code maar iets langzamer; ID-based is de productie-default.
Filteren: active, closed, volume24hr ordering
De vier filter-dimensies die je 95% van de tijd zult gebruiken.
active=true|false:truesluit markten uit die het Polymarket-team heeft verborgen voor de UI.closed=true|false:falsesluit afgehandelde markten uit. De combinatieactive=true&closed=falseis de meest voorkomende live filter.order=volume24hr,order=volume,order=endDate: sorteersleutel. Meest nuttig isvolume24hrvoor het vinden van momenteel-actieve markten.ascending=true|false: default true op de meeste endpoints; je wilt bijna altijdfalsevoor volume-orderings.
Caveat: filteren op tag_id gecombineerd met order=volume24hr en ascending=false geeft soms een lege pagina terug wanneer de tag zeer weinig live markten heeft. Over-fetch altijd (vraag meer aan dan je toont) en post-filter om dit te hanteren.
Pagination en limits
limit param accepteert 1-500 per call. Default is 100 als niet gespecificeerd. Boven 500 capt de server stil — je ontvangt 500 maar de respons heeft geen indicatie van meer.
Pagination is offset-based: ?limit=500&offset=500 voor de tweede pagina. Er is geen cursor-based pagination, dus gelijktijdige inserts kunnen page-boundaries doen schuiven tussen calls. Voor de meeste bot-discovery doelen is dit acceptabel; voor archive-scrapes, sorteer op een stabiel veld (endDate of createdAt) en detecteer overlap per slug.
Praktisch patroon voor "alle live markten": fetch limit=500&order=volume24hr&ascending=false. Dat dekt de top 500 op volume wat in essentie elke markt met niet-triviale activiteit is. Voorbij pagina 1 gaan is zelden nuttig — markten in de staart van de volume-verdeling zijn per definitie niet waar de actie is.
Rate limits en caching
Gamma is gefront door Cloudflare en heeft soft rate limits per IP. Empirische thresholds geobserveerd onder productie-load:
- Tot ~30 req/sec vanaf één IP sustained: prima.
- Bursts van 100+ req/sec: af en toe 429s, retries slagen.
- ~500 req/sec sustained: rate-limit pagina of tijdelijke block (10-60s).
De gepubliceerde response headers bevatten Cache-Control waarden van 30-60 seconden voor de meeste endpoints. Respecteer ze — er is geen voordeel om hetzelfde event 10 keer per minuut opnieuw te fetchen. Productie-caching patroon: in-process LRU + TTL keyed op de volledige URL, 30s TTL. Bespaart request-count en vermindert latency.
Voor high-frequency strategieën, mirror Gamma-data naar een lokale store geüpdatet door een enkel fetcher-proces; laat meerdere consumers van die store lezen. Eén fetcher × veel consumers > veel fetchers × Gamma.
Code: fetch top 24h-volume markten
Referentie-fetcher in drie talen, geeft de top 50 live markten op 24-uurs volume terug.
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'
Het Polymarket gamma /events endpoint ondersteunt GEEN free-text search parameter — ?q=foo of ?search=foo toevoegen geeft stil de default ordering terug. Filter op slug of tag in plaats daarvan.











