Polymarket Bot Tutorial · Capitolo 7 di 32

Approfondimento della Polymarket Gamma API: endpoint /events e /markets, pagination, tag IDs (864 Tennis, 745 NBA, ecc.), filtering per volume 24h, rate limits e sample di codice Python e Node.

Cosa copre questo capitolo

Gamma è la catalog API di Polymarket: elenca ogni event, ogni market, tag, image e resolved outcome mostrato dal front-end. La CLOB API gestisce i trade; Gamma descrive ciò che è tradeable. La maggior parte dei bug dei bot nel layer di discovery nasce dal confondere le due cose, oppure dal perdere il pagination contract. Questo capitolo è il reference pratico per i principali endpoint di Gamma, con il comportamento esatto dei parametri su cui fanno affidamento i nostri fetcher in produzione.

Questo è il capitolo 7 della nostra serie in 32 parti su come costruire un Polymarket trading bot. Trattiamo l’argomento in profondità nelle sezioni qui sotto. Il contenuto del corpo di ogni sezione viene scritto e pubblicato capitolo per capitolo; le risposte FAQ e i riferimenti sono già completi e riflettono l’esperienza in produzione derivata dall’esecuzione del nostro trader.

  • Gamma vs CLOB: quando usare l’uno o l’altro
  • Anatomia dell’endpoint /events
  • Anatomia dell’endpoint /markets
  • Tags e tag IDs (lista verificata)
  • Filtering: active, closed, ordinamento per volume24hr
  • Pagination e limits
  • Rate limits e caching
  • Code: fetch dei market con volume 24h più alto

Gamma vs CLOB: quando usare l’uno o l’altro

Due servizi diversi per due lavori diversi.

Gamma (gamma-api.polymarket.com): catalog. Elenca events, markets, tags, descriptions, images, resolved outcomes, volume a 24 ore, volume totale, date di fine. HTTP read-only. Per la maggior parte delle letture non richiede autenticazione. Viene aggiornata continuamente ma è eventually consistent: un market appena chiuso può ancora mostrare closed: false per alcuni secondi.

CLOB (clob.polymarket.com): trading + order book. Elenca bid/ask migliori, depth del book top-N, trade recenti. Autenticato per gli endpoint di scrittura (inserimento ordini, cancellazione). Sono disponibili canali WebSocket real-time per gli aggiornamenti del book.

Regola pratica: usa Gamma per trovare cosa tradeare; usa CLOB per tradearlo. Un bot che legge i prezzi da Gamma sta usando dati stale — i campi prezzo di Gamma si aggiornano meno frequentemente dell’order book di CLOB. Un bot che legge i metadati del market da CLOB sta facendo più richieste del necessario.

Anatomia dell’endpoint /events

GET /events restituisce dati a livello di event. Un "event" è una pagina di Polymarket; un singolo event può contenere più markets (ad esempio, l’event 2024 Presidential Election ha un market per ciascun candidato).

Campi chiave:

  • slug: identificatore URL-safe, stabile per tutta la durata dell’event.
  • title, description: visualizzazione umana.
  • endDate (ISO 8601): quando l’event si chiude.
  • active, closed: boolean; combinarli in una query con ?active=true&closed=false per gli event live.
  • volume, volume24hr: totali in USD.
  • tags: array di oggetti tag (vedi la sezione tags sotto).
  • markets: array di oggetti market figli (vedi anatomia di /markets).

Il pattern di discovery più comune in assoluto: GET /events?active=true&closed=false&order=volume24hr&ascending=false&limit=100. Restituisce i 100 event attualmente live con il volume più alto.

Anatomia dell’endpoint /markets

GET /markets restituisce dati a livello di market. Un market è un contratto Y/N o multi-outcome; vive all’interno di un event.

Campi chiave:

  • slug: identificatore URL-safe.
  • question: il titolo mostrato nella trading page (ad esempio "Will Trump be president on January 1, 2027?").
  • outcomes: JSON string dei nomi degli outcome, ad esempio '["Yes","No"]'. Sempre due elementi per i binary; di più per i NegRisk.
  • outcomePrices: JSON string dei prezzi correnti come decimali, ad esempio '["0.62","0.38"]'. Entrambi i lati sommano a circa 1.0 meno lo spread.
  • clobTokenIds: JSON string degli ERC-1155 token IDs allineati con gli outcome. Sono i token che compri/vendi davvero.
  • negRisk: boolean; true per i market multi-outcome che sommano a 1. Importante per l’order placement (capitolo 11).

I campi outcomes / outcomePrices / clobTokenIds arrivano come JSON string, non come array già parsati: fai il JSON-decode prima di usarli.

Tags e tag IDs (lista verificata)

I tag sono etichette categoriali (Sports, Crypto, Tennis, NBA, ecc.). I tag ID verificati in produzione per le categorie più usate:

TagIDTagID
Sports1NBA745
Crypto21NFL450
Politics2Tennis864
Bitcoin100196Esports702
Ethereum100383Soccer1059
Election3EPL739
Middle East1432UCL2186

Filtra per tag con ?tag_id=745 per un tag specifico, oppure con ?tag_slug=nba usando lo slug. Il filtering basato sullo slug è più leggibile nel codice ma leggermente più lento; quello basato sull’ID è il default in produzione.

Filtering: active, closed, ordinamento per volume24hr

Le quattro dimensioni di filtering che userai nel 95% dei casi.

  • active=true|false: true esclude i market che il team di Polymarket ha nascosto dalla UI.
  • closed=true|false: false esclude i market resolved. La combinazione active=true&closed=false è il live filter più comune.
  • order=volume24hr, order=volume, order=endDate: chiave di ordinamento. Il più utile è volume24hr per trovare i market attualmente attivi.
  • ascending=true|false: per la maggior parte degli endpoint il default è true; quasi sempre vuoi false per gli ordinamenti per volume.

Caveat: il filtering per tag_id combinato con order=volume24hr e ascending=false a volte restituisce una pagina vuota quando il tag ha pochissimi market live. Over-fetch sempre (richiedi più di quanto mostri) e fai post-filter per gestire questo caso.

Pagination e limits

Il parametro limit accetta da 1 a 500 per chiamata. Il default è 100 se non specificato. Sopra 500 il server applica un cap in modo silenzioso: ricevi 500 ma la response non indica che ce ne siano altri.

La pagination è basata su offset: ?limit=500&offset=500 per la seconda pagina. Non esiste pagination basata su cursor, quindi gli inserimenti concorrenti possono spostare i confini tra le pagine da una chiamata all’altra. Per la maggior parte delle esigenze di discovery di un bot questo è accettabile; per gli scrape di archivio, ordina per un campo stabile (endDate o createdAt) e rileva le sovrapposizioni tramite slug.

Pattern pratico per "tutti i market live": fetch con limit=500&order=volume24hr&ascending=false. Copre i top 500 per volume, che sono sostanzialmente tutti i market con attività non banale. Andare oltre la pagina 1 è raramente utile: i market nella coda della distribuzione del volume, per definizione, non sono dove c’è l’azione.

Rate limits e caching

Gamma è dietro Cloudflare e ha soft rate limits per IP. Soglie empiriche osservate sotto carico di produzione:

  • Fino a circa 30 req/sec da un singolo IP in modo sostenuto: nessun problema.
  • Burst di 100+ req/sec: occasionali 429, i retry hanno successo.
  • Circa 500 req/sec sostenuti: pagina di rate-limit o blocco temporaneo (10-60s).

Gli header di response pubblicati includono valori Cache-Control di 30-60 secondi per la maggior parte degli endpoint. Rispettali: non c’è alcun vantaggio nel rifetchare lo stesso event 10 volte in un minuto. Pattern di caching in produzione: LRU + TTL in-process, indicizzato sulla URL completa, TTL di 30s. Riduce il numero di richieste e la latenza.

Per strategie ad alta frequenza, replica i dati di Gamma in uno store locale aggiornato da un singolo fetcher process; fai leggere più consumer da quello store. Un fetcher × molti consumer > molti fetcher × Gamma.

Code: fetch dei market con volume 24h più alto

Fetcher di riferimento in tre linguaggi, che restituisce i primi 50 live market per volume nelle ultime 24 ore.

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'

L’endpoint /events di Polymarket gamma NON supporta un parametro di free-text search: aggiungere ?q=foo o ?search=foo restituisce in modo silenzioso l’ordinamento di default. Filtra invece per slug o tag.

Domande frequenti

Cos’è la Polymarket Gamma API?
Gamma è la metadata e discovery API di Polymarket. Fornisce liste di event/market, titoli, descrizioni, date di fine, tag e volume aggregato. NON fornisce dati real-time dell’order book: quelli si trovano nella CLOB API. Per la maggior parte dei casi d’uso di discovery e analytics, si parte da Gamma.
Qual è la differenza tra un event e un market su Polymarket?
Un event raggruppa uno o più market che condividono un tema di domanda. Un market è uno specifico outcome Yes/No con il proprio order book e i propri token ID. Un event "2026 NBA Champion" contiene 30 market (uno per team). Per gli event binary Yes/No, l’event ha 1 market sottostante.
Come trovo i Polymarket tag IDs?
I tag sono esposti tramite l’endpoint gamma /tags. Gli ID verificati che usiamo in produzione: 864 Tennis, 745 NBA. I tag slug nelle URL (?tag_slug=tennis) e le query di free-text (?q=tennis) non sono affidabili: usa solo il numerical tag_id. Controlla /tags prima di affidarti a uno slug.
Come ordino gli event Polymarket per volume 24h?
/events?order=volume24hr&ascending=false - è ciò che alimenta la maggior parte dei widget "trending markets". Combinalo con active=true&closed=false per filtrare i market scaduti o in pausa. Il limit di default è 25; il massimo è 500 per chiamata.
Ci sono limiti di pagination su Gamma?
Sì. Gli endpoint /events e /markets accettano limit (massimo 500 per chiamata) e offset per la pagination. La maggior parte delle librerie non fa pagination automaticamente: se ti serve l’universo completo, fai un loop con offset finché non ottieni una pagina con meno risultati di `limit`.
Gamma supporta WebSocket?
No. Gamma è solo REST. Per aggiornamenti real-time (variazioni di prezzo, nuovi market, order book) usa il WebSocket di CLOB, trattato nel capitolo 8 di questa serie.