Polymarket Bot Tutorial · Capítulo 7 de 32

Análise aprofundada da Gamma API da Polymarket: endpoints /events e /markets, paginação, tag IDs (864 Tennis, 745 NBA, etc), filtro por volume de 24h, rate limits, e exemplos de código em Python e Node.

O que este capítulo cobre

Gamma é a API de catálogo da Polymarket - ela lista cada event, cada market, tag, imagem e resultado resolvido que o front-end exibe. A CLOB API negocia; a Gamma descreve o que está disponível para trade. A maioria dos bugs de bot na camada de descoberta vem de confundir as duas, ou de ignorar o contrato de paginação. Este capítulo é a referência de campo para os principais endpoints da Gamma, com o comportamento exato dos parâmetros de que nossos fetchers de produção dependem.

  • Gamma vs CLOB: quando usar cada um
  • Anatomia do endpoint /events
  • Anatomia do endpoint /markets
  • Tags e tag IDs (lista verificada)
  • Filtros: active, closed, ordenação por volume24hr
  • Paginação e limites
  • Rate limits e caching
  • Código: buscar os mercados com maior volume em 24h

Gamma vs CLOB: quando usar cada um

Dois serviços diferentes para trabalhos diferentes.

Gamma (gamma-api.polymarket.com): catálogo. Lista events, markets, tags, descrições, imagens, resultados resolvidos, volume de 24 horas, volume total, datas de encerramento. Somente HTTP de leitura. Não exige autenticação para a maioria das consultas. É atualizada continuamente, mas de forma eventualmente consistente - um market que acabou de fechar pode ainda mostrar closed: false por alguns segundos.

CLOB (clob.polymarket.com): trading + order book. Lista melhor bid/ask atual, profundidade do book top-N, trades recentes. Autenticado para endpoints de escrita (envio e cancelamento de ordens). Canais WebSocket em tempo real disponíveis para atualizações do book.

Regra prática: use Gamma para encontrar o que operar; use CLOB para operar de fato. Um bot que lê preços da Gamma está usando dados defasados - os campos de preço da Gamma atualizam com menos frequência que o order book da CLOB. Um bot que lê metadados de market na CLOB está fazendo mais requests do que o necessário.

Anatomia do endpoint /events

GET /events retorna dados no nível de event. Um "event" é uma página da Polymarket; um único event pode conter vários markets (por exemplo, o event da Eleição Presidencial de 2024 tem um market por candidato).

Campos principais:

  • slug: identificador seguro para URL, estável durante a vida do event.
  • title, description: exibição para humanos.
  • endDate (ISO 8601): quando o event é encerrado.
  • active, closed: booleanos; combine em uma query com ?active=true&closed=false para events ao vivo.
  • volume, volume24hr: totais em USD.
  • tags: array de objetos tag (veja a seção de tags abaixo).
  • markets: array de objetos market filhos (veja a anatomia de /markets).

O padrão de descoberta mais comum: GET /events?active=true&closed=false&order=volume24hr&ascending=false&limit=100. Retorna os 100 events ao vivo com maior volume.

Anatomia do endpoint /markets

GET /markets retorna dados no nível de market. Um market é um contrato Y/N ou de múltiplos resultados; ele fica dentro de um event.

Campos principais:

  • slug: identificador seguro para URL.
  • question: o título exibido na página de trading (por exemplo, "Will Trump be president on January 1, 2027?").
  • outcomes: string JSON com nomes dos resultados, por exemplo '["Yes","No"]'. Sempre dois elementos para binary; mais para NegRisk.
  • outcomePrices: string JSON com os preços atuais como decimais, por exemplo '["0.62","0.38"]'. Os dois lados somam aproximadamente 1,0 menos o spread.
  • clobTokenIds: string JSON com os token IDs ERC-1155 alinhados aos outcomes. Estes são os tokens que você realmente compra/vende.
  • negRisk: booleano; true para markets de múltiplos outcomes cuja soma é 1. Importa para o envio de ordens (capítulo 11).

Os campos outcomes / outcomePrices / clobTokenIds chegam como strings JSON, não como arrays já parseados - faça JSON-decode antes de usar.

Tags e tag IDs (lista verificada)

Tags são rótulos categóricos (Sports, Crypto, Tennis, NBA, etc.). Os tag IDs de produção verificados para as categorias mais usadas:

TagIDTagID
Sports1NBA745
Crypto21NFL450
Politics2Tennis864
Bitcoin100196Esports702
Ethereum100383Soccer1059
Election3EPL739
Middle East1432UCL2186

Filtre por tag com ?tag_id=745 para uma tag específica, ou ?tag_slug=nba usando o slug. O filtro por slug é mais legível no código, mas um pouco mais lento; por ID é o padrão de produção.

Filtros: active, closed, ordenação por volume24hr

As quatro dimensões de filtro que você usará em 95% das vezes.

  • active=true|false: true exclui markets que a equipe da Polymarket ocultou da UI.
  • closed=true|false: false exclui markets resolvidos. A combinação active=true&closed=false é o filtro ao vivo mais comum.
  • order=volume24hr, order=volume, order=endDate: chave de ordenação. O mais útil é volume24hr para encontrar markets atualmente ativos.
  • ascending=true|false: o padrão na maioria dos endpoints é true; quase sempre você vai querer false para ordenações por volume.

Aviso: filtrar por tag_id combinado com order=volume24hr e ascending=false às vezes retorna uma página vazia quando a tag tem pouquíssimos markets ao vivo. Sempre faça over-fetch (peça mais do que vai exibir) e aplique pós-filtro para lidar com isso.

Paginação e limites

O parâmetro limit aceita de 1 a 500 por chamada. O padrão é 100 se não for especificado. Acima de 500 o servidor limita silenciosamente - você recebe 500, mas a resposta não indica que há mais.

A paginação é baseada em offset: ?limit=500&offset=500 para a segunda página. Não há paginação baseada em cursor, então inserções concorrentes podem deslocar os limites da página entre chamadas. Para a maioria dos casos de descoberta de bot isso é aceitável; para scrapes de arquivo, ordene por um campo estável (endDate ou createdAt) e detecte sobreposição por slug.

Padrão prático para "todos os markets ao vivo": busque limit=500&order=volume24hr&ascending=false. Isso cobre os 500 principais por volume, que na prática é quase todo market com atividade relevante. Ir além da página 1 raramente é útil - markets na cauda da distribuição de volume, por definição, não são onde a ação está.

Rate limits e caching

A Gamma é protegida pela Cloudflare e tem rate limits suaves por IP. Limiares empíricos observados sob carga de produção:

  • Até cerca de 30 req/sec de um único IP de forma sustentada: ok.
  • Rajadas de 100+ req/sec: ocasionalmente 429s, retries funcionam.
  • Cerca de 500 req/sec sustentados: página de rate limit ou bloqueio temporário (10-60s).

Os response headers publicados incluem valores de Cache-Control de 30-60 segundos para a maioria dos endpoints. Respeite-os - não há benefício em refazer o fetch do mesmo event 10 vezes por minuto. Padrão de caching em produção: LRU em processo + TTL, chaveado pela URL completa, TTL de 30s. Economiza requests e reduz latência.

Para estratégias de alta frequência, replique os dados da Gamma para um armazenamento local atualizado por um único processo fetcher; deixe múltiplos consumidores lerem desse storage. Um fetcher × muitos consumidores > muitos fetchers × Gamma.

Código: buscar os markets com maior volume em 24h

Fetcher de referência em três linguagens, retornando os 50 markets ao vivo com maior volume em 24 horas.

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'

O endpoint /events da Polymarket Gamma NÃO suporta um parâmetro de busca em texto livre - adicionar ?q=foo ou ?search=foo retorna silenciosamente a ordenação padrão. Filtre por slug ou tag em vez disso.

Perguntas frequentes

O que é a Polymarket Gamma API?
Gamma é a API de metadados e descoberta da Polymarket. Ela fornece listas de event/market, títulos, descrições, datas de encerramento, tags e volume agregado. Ela NÃO fornece dados de order book em tempo real - isso fica na CLOB API. Para a maioria dos casos de uso de descoberta e analytics, você começa pela Gamma.
Qual é a diferença entre um event e um market na Polymarket?
Um event agrupa um ou mais markets que compartilham um mesmo tema de pergunta. Um market é um resultado específico de Yes/No com seu próprio order book e token IDs. Um event "2026 NBA Champion" contém 30 markets (um por time). Para events binários de Yes/No, o event tem 1 market subjacente.
Como encontro os tag IDs da Polymarket?
As tags são expostas pelo endpoint gamma /tags. IDs verificados que usamos em produção: 864 Tennis, 745 NBA. Slugs de tag em URLs (?tag_slug=tennis) e query de texto livre (?q=tennis) não são confiáveis - use apenas o tag_id numérico. Consulte /tags antes de confiar em um slug.
Como ordeno os events da Polymarket por volume de 24h?
/events?order=volume24hr&ascending=false - isso é o que alimenta a maioria dos widgets de "trending markets". Combine com active=true&closed=false para filtrar markets expirados ou pausados. O limit padrão é 25; o máximo é 500 por chamada.
Há limites de paginação na Gamma?
Sim. Os endpoints /events e /markets aceitam limit (máximo de 500 por chamada) e offset para paginação. A maioria das libraries não pagina automaticamente - se você precisar do universo completo, faça loop com offset até obter uma página com menos resultados que `limit`.
A Gamma suporta WebSocket?
Não. A Gamma é somente REST. Para atualizações em tempo real (mudanças de preço, novos markets, order book) use o WebSocket da CLOB - coberto no capítulo 8 desta série.