Capítulo 27 de 33
A versão curta
A Polymarket expõe três APIs públicas: CLOB (trading), Gamma (descoberta de mercados) e Data (analítica). O SDK oficial de Python é o py-clob-client 0.34.6. A autenticação usa uma chave de API + assinatura ECDSA, com as ordens assinadas via EIP-712 através de uma carteira proxy na Polygon. Os limites de taxa restringem você a cerca de 60 ordens/minuto por chave. O maior obstáculo para desenvolvedores novatos é o problema de mapeamento entre condition_id → token_id entre o Gamma e o CLOB - resolva-o primeiro e todo o resto se encaixa. Todo mês, ganha-se na Polymarket cerca de 40 milhões $ em recompensas de liquidez e spread capturado por bots, quase inteiramente por usuários da API.
Parte 1: As três APIs
A Polymarket separa de forma limpa as responsabilidades em três serviços distintos. Usar a API certa para cada tarefa mantém o seu bot rápido, simples e dentro dos limites de taxa.
| API | URL base | Propósito | Exige autenticação |
|---|---|---|---|
| CLOB API | clob.polymarket.com | Enviar, cancelar e acompanhar ordens. Ler order books. Consultar posições. | Sim (para trading) |
| Gamma API | gamma-api.polymarket.com | Navegar por mercados, buscar metadados, imagens, preços de resultados, volume, vencimento, tags. | Não (pública) |
| Data API | data-api.polymarket.com | Operações históricas, snapshots de posições, analítica de usuários, dados de ranking. | Não (pública) |
Um loop de bot típico usa o Gamma para encontrar mercados, o CLOB para buscar order books e enviar operações, e o Data para fazer back-test do desempenho da estratégia offline. Pense no Gamma como o "catálogo", no CLOB como a "bolsa" e no Data como o "armazém".
curl ou um navegador agora mesmo - sem conta. É uma ótima forma de prototipar antes mesmo de gerar uma chave de API.Parte 2: Autenticação e o modelo de carteira proxy
A Polymarket não assina as operações com a chave privada da sua carteira principal. Em vez disso, usa uma carteira proxy no estilo Gnosis Safe: a sua carteira principal autoriza um proxy, e o proxy executa todas as operações na Polygon. O seu bot de API conversa com esse proxy.
O que você precisa
- Chave de API - gere em Settings → Developer da Polymarket
- Chave privada - a chave da sua carteira de trading (NÃO a frase semente da sua MetaMask principal)
- Endereço funder - o endereço da sua carteira proxy (mostrado em Settings → Wallet)
- Chain ID -
137(Polygon mainnet) - Tipo de assinatura -
1(POLY_PROXY, padrão para usuários de varejo)
.env) ou um gerenciador de segredos. Nunca cole chaves no Discord, em issues do GitHub ou no ChatGPT. Suponha que qualquer chave que toque a sua área de transferência já está comprometida. Rotacione as chaves em caso de dúvida.Parte 3: Instalar o py-clob-client
O SDK oficial de Python é a forma mais rápida de ir do zero à sua primeira ordem. Usaremos a versão 0.34.6, que é a atual em abril de 2026.
# Create a virtual environment first
python3 -m venv venv
source venv/bin/activate # macOS/Linux
venv\Scripts\activate # Windows
# Install the SDK
pip install py-clob-client==0.34.6 requests websocket-client python-dotenvConfiguração básica do cliente
import os
from dotenv import load_dotenv
from py_clob_client.client import ClobClient
from py_clob_client.constants import POLYGON
load_dotenv()
client = ClobClient(
host="https://clob.polymarket.com",
key=os.environ["POLY_PRIVATE_KEY"],
chain_id=POLYGON, # 137
signature_type=1, # POLY_PROXY
funder=os.environ["POLY_FUNDER"],
)
# One-time: derive and cache API credentials
client.set_api_creds(client.create_or_derive_api_creds())A chamada a create_or_derive_api_creds() assina uma mensagem com a sua chave privada e a troca por uma chave de API, um secret e uma passphrase. Coloque-os em cache no seu .env após a primeira execução para não chamar o endpoint de derivação a cada inicialização.
POLY_PRIVATE_KEY=0xabc...
POLY_FUNDER=0xdef...
POLY_API_KEY=...
POLY_SECRET=...
POLY_PASSPHRASE=...Parte 4: Descobrir mercados via Gamma
Antes de poder operar, você precisa encontrar mercados que valham a pena. O Gamma retorna JSON com tudo o que a interface da Polymarket mostra: pergunta, resultados, preços, volume 24h, vencimento, tags e imagens.
import requests
resp = requests.get(
"https://gamma-api.polymarket.com/markets",
params={
"active": "true",
"closed": "false",
"tag_slug": "politics",
"limit": 20,
"order": "volume24hr",
"ascending": "false",
},
timeout=10,
)
resp.raise_for_status()
markets = resp.json()
for m in markets:
print(f"{m['slug']:50} Yes ${float(m['outcomePrices'][0]):.3f} Vol24h ${m.get('volume24hr', 0):,.0f}")Parâmetros úteis de consulta do Gamma
| Parâmetro | O que faz |
|---|---|
tag_slug | Filtra por categoria (politics, sports, crypto, culture, etc.) |
active=true | Apenas mercados que aceitam operações no momento |
closed=false | Oculta mercados resolvidos |
order=volume24hr | Ordena por volume recente (sinal de liquidez) |
end_date_min | Data ISO - ignora mercados que se resolvem cedo demais |
limit | Até 500 por página (use offset para paginar) |
Parte 5: O mapeamento condition_id → token_id
Este é o ponto de dor número 1 no desenvolvimento de bots da Polymarket. O Gamma retorna um condition_id (um por mercado). As operações do CLOB usam um token_id (um por resultado). Você sempre precisa dos dois.
condition_id para endpoints do CLOB que esperam um token_id. Você receberá um erro críptico de 'invalid token'. Mapeie sempre primeiro, opere depois.# Each Gamma market object contains 'clobTokenIds' - a JSON string array
import json
market = markets[0]
token_ids = json.loads(market['clobTokenIds']) # ['7410...', '1120...']
yes_token = token_ids[0] # First outcome
no_token = token_ids[1] # Second outcome
# Alternative: ask CLOB directly using condition_id
info = client.get_market(condition_id=market['conditionId'])
yes_token = info['tokens'][0]['token_id']A pegadinha da ordem dos resultados
O array outcomes e o array clobTokenIds do Gamma são indexados entre si. Sempre leia o rótulo do resultado em vez de supor que o índice 0 é "Yes". Em mercados de múltiplos resultados (NegRisk, Oscar, eleições), o índice 0 pode ser "Kamala Harris" ou "Taylor Swift" - a ordem é determinística, mas específica de cada mercado.
Parte 6: Ler order books
book = client.get_order_book(token_id=yes_token)
best_bid = float(book.bids[0].price) if book.bids else None
best_ask = float(book.asks[0].price) if book.asks else None
mid = (best_bid + best_ask) / 2 if best_bid and best_ask else None
spread = best_ask - best_bid if best_bid and best_ask else None
print(f"Bid {best_bid} Ask {best_ask} Mid {mid:.4f} Spread {spread:.4f}")Os order books são retornados como arrays ordenados (bids decrescentes, asks crescentes). Cada nível tem price e size. Para estimar o slippage de uma ordem maior, percorra o livro e acumule nocional até consumir o seu tamanho alvo.
Parte 7: Enviar ordens
Ordem limitada (GTC - o padrão)
from py_clob_client.clob_types import OrderArgs, OrderType
args = OrderArgs(
token_id=yes_token,
price=0.45,
size=100, # Shares, not dollars. 100 shares @ $0.45 = $45 max cost.
side="BUY",
)
signed_order = client.create_order(args)
response = client.post_order(signed_order, OrderType.GTC)
print(response)A chamada a create_order assina uma mensagem estruturada EIP-712 com a sua chave privada. post_order a envia ao CLOB. Você nunca envia chaves privadas brutas pela rede - apenas ordens assinadas.
Tipos de ordem
| Tipo | Código | Comportamento | Quando usar |
|---|---|---|---|
| Good Till Cancelled | GTC | Descansa no livro até ser executada ou você cancelar | Padrão. A maior parte do market making e das estratégias limitadas. |
| Good Till Date | GTD | Autocancela em um timestamp especificado | Orientada a eventos: "cancele 5 min antes do anúncio do Fed" |
| Fill or Kill | FOK | Deve executar todo o tamanho imediatamente ou cancelar por completo | Pernas de arbitragem onde execuções parciais arruínam a operação |
| Fill and Kill | FAK | Executa o que puder no preço limite, cancela o resto | Tomada agressiva - age como uma ordem a mercado com teto de preço |
Cancelar
# Single order
client.cancel(order_id="0xabc...")
# Cancel all orders on a specific market
client.cancel_market_orders(market=market['conditionId'])
# Nuclear option: cancel everything
client.cancel_all()Parte 8: Streaming via WebSocket
Consultar o Gamma a cada segundo é desperdício e você atingirá os limites de taxa rápido. O feed de WebSocket transmite atualizações de order book e de operações em tempo real, com latência abaixo de um segundo.
import json, websocket
WS_URL = "wss://ws-subscriptions-clob.polymarket.com/ws/market"
def on_open(ws):
ws.send(json.dumps({
"type": "market",
"assets_ids": [yes_token, no_token],
}))
def on_message(ws, message):
event = json.loads(message)
if event.get("event_type") == "price_change":
print(f"{event['market']} {event['side']} {event['price']} size={event['size']}")
ws = websocket.WebSocketApp(
WS_URL,
on_open=on_open,
on_message=on_message,
)
ws.run_forever(ping_interval=20)Existem dois feeds: o feed /market (order book e operações públicos) e o feed /user (os seus próprios eventos de ordem e execução, autenticado). Bots de produção costumam se conectar a ambos, reconectam automaticamente na desconexão e tratam o WebSocket como a fonte da verdade do estado atual do livro.
Parte 9: Limites de taxa e backoff
| Classe de endpoint | Limite | Rajada |
|---|---|---|
| Envio de ordens (CLOB) | ~60 / minuto por chave de API | ~10 / segundo |
| Cancelamento de ordens | ~120 / minuto | ~20 / segundo |
| Leituras de dados de mercado (livro CLOB) | ~300 / minuto | maior, varia |
| Gamma API | Generosa; respeite os 429 | - |
| Mensagens de WebSocket | Sem limite prático de entrada | - |
Quando você recebe um HTTP 429, o servidor retorna um cabeçalho Retry-After. Implemente um backoff exponencial com jitter:
import random, time
def post_with_backoff(fn, *args, max_retries=6):
for attempt in range(max_retries):
try:
return fn(*args)
except Exception as e:
if "429" in str(e):
sleep = (2 ** attempt) + random.random()
time.sleep(min(sleep, 30))
continue
raise
raise RuntimeError("Too many retries")Parte 10: Uma arquitetura de bot de referência
Todo bot robusto da Polymarket tem os mesmos seis componentes. Construa cada um como o seu próprio módulo; mantenha-os fracamente acoplados.
| Componente | Responsabilidade | APIs usadas |
|---|---|---|
| Scanner | Tarefa agendada: puxar mercados que atendam aos seus critérios (tags, volume, dias até o vencimento) | Gamma |
| Motor de preços | Manter order books locais em tempo real via WebSocket | CLOB WS |
| Gerador de sinais | Função pura: estado do livro + metadados → posição alvo | - (em memória) |
| Gerenciador de ordens | Comparar ordens atuais com o alvo, enviar/cancelar de forma mínima | CLOB REST |
| Gerenciador de risco | Aplicar tetos por mercado, limites de perda diários, disjuntores | - (em memória + BD) |
| Logger e livro-razão | Persistir cada decisão, execução, cancelamento. Alimenta relatórios fiscais e depuração. | SQLite / Postgres |
Parte 11: Modos de falha comuns
- Dados de WebSocket desatualizados - Acompanhe o horário da última mensagem por ativo; se não houver atualizações por >30s em um mercado ativo, force um refresh via REST.
- Colisões de nonce - O py-clob-client gerencia os nonce das ordens para você, mas se você escrever o seu próprio assinante, incremente o nonce a cada ordem.
- Saldo insuficiente - Sempre verifique o saldo de pUSD antes de enviar; o livro pode mostrar a sua ordem, mas o casamento a rejeitará.
- Mercado pausado ou em resolução - Verifique
market.active && !market.closedantes de operar. As atualizações do Gamma ficam atrás do CLOB em alguns segundos ao redor da resolução. - Desalinhamento do adaptador NegRisk - Mercados de múltiplos resultados passam por um adaptador NegRisk separado. O SDK cuida disso, mas confirme que a sua ordem foi para o venue correto.
Parte 12: Recompensas de liquidez via API
A Polymarket roda cerca de 5 milhões $/mês em recompensas de liquidez gerais mais 5 milhões $+/mês em recompensas específicas de esportes (ver Recompensas de liquidez). A grande maioria flui para market makers movidos a API que conseguem manter cotações apertadas de dois lados em milhares de mercados.
A fórmula de recompensa premia ordens próximas do ponto médio, o tamanho e o tempo no livro. Um loop de market making mínimo:
- Leia o order book do mercado alvo
- Calcule um ponto médio justo (p. ex., VWAP dos 3 níveis superiores de cada lado)
- Poste um bid em
mid − spread_target/2e um ask emmid + spread_target/2 - A cada atualização do WebSocket, reprecifique se a sua cotação se desviar mais de um tick do alvo
- Cancele e saia se o livro afinar ou se surgirem notícias
Parte 13: Ir para produção
- Hospedagem: um VPS de 6 $/mês (Hetzner, DigitalOcean) na Europa ou US-East basta para a maioria dos bots. Co-localize com um Polygon RPC se precisar de latência abaixo de 10ms.
- RPC: use Alchemy, Infura ou QuickNode para um Polygon RPC confiável. Os planos gratuitos servem até você enviar centenas de ordens por minuto.
- Monitoramento: Prometheus + Grafana para métricas; um bot do Telegram para alertas. Registre cada ID de ordem que você envia e cada execução que você recebe.
- Backups: persista o estado a cada minuto. Se o VPS morrer no meio de uma execução, você quer retomar em segundos, não reconciliar na mão.
- Impostos: o seu logger é também a sua trilha de auditoria - ver Guia fiscal.
Parte 14 - Dicas profissionais validadas para a API da Polymarket
- Faça cache das credenciais de API após a primeira chamada de derivação -
create_or_derive_api_creds()é limitada por taxa e lenta. Guarde apiKey/secret/passphrase no.enve carregue na inicialização. - Use signature_type=2 (GNOSIS_SAFE) se você conectou uma carteira de navegador primeiro, e signature_type=1 (POLY_PROXY) apenas para contas de e-mail Magic-link. Um tipo incompatível retorna 401 'invalid api key'.
- Defina
fundercom o endereço da sua carteira proxy da Polymarket, não com o seu EOA. A chave de assinatura vive no EOA; os fundos vivem no proxy. Confundi-los é o bug de autenticação número 1. - Indexe os resultados por rótulo, nunca por posição -
clobTokenIds[outcomes.index("Yes")], nãoclobTokenIds[0]. Os mercados NegRisk e do Oscar têm ordem arbitrária. - Sincronize o seu relógio antes de assinar - POLY_TIMESTAMP deve estar dentro de uma janela estreita. O drift de NTP em um VPS barato quebra a autenticação em silêncio. Rode chrony ou systemd-timesyncd.
- Busque novamente o livro REST a cada reconexão de WebSocket antes de reinscrever-se. O WebSocket dá deltas; se você perder um delta durante a reconexão, o seu livro local diverge da realidade e você cotará preços perdedores.
- Nunca dispare em rajada mais de 10 ordens por segundo - o endpoint /order limita a 500/10s em rajada e 3.000/10min sustentado. Adicione um token-bucket rate limiter do lado do cliente; o Cloudflare enfileira em vez de descartar, então retentativas cegas amplificam a fila.
- Use
cancel_market_orders(market=conditionId)no desligamento, nãocancel_all(). O cancelamento com escopo de mercado é idempotente e mais seguro se o bot cair no meio do loop em um único mercado. - Acompanhe
heartbeatMspor ativo - adicione um watchdog que force o refresh de qualquer mercado sem atualizações por 30s em um mercado ao vivo. Feeds de WS desatualizados são a fonte mais comum de alfa fantasma. - Registre o ID da ordem antes de enviá-la, não depois. A idempotência exige que o cliente seja dono do ID para que a recuperação após uma queda possa reenviar sem execuções duplicadas.
- Use a HeartBeats API (janeiro de 2026+) para o cancelamento automático na desconexão. Defina o intervalo de heartbeat em 5s; o servidor cancela todas as suas ordens em repouso se perder dois heartbeats.
- Faça paper-trade com ordens de 1 $ em um mercado fino por 48 horas antes de escalar. A Polymarket não tem testnet; ordens reais mínimas são a única forma confiável de validar autenticação, assinatura, tratamento de execuções e fluxo de cancelamento.
Folha de consulta: situação → ação
| Situação | Ação | Por quê |
|---|---|---|
| 401 'invalid api key' na primeira chamada | Verifique se signature_type corresponde à origem da carteira e se o funder é o endereço do proxy | O desalinhamento entre tipo 1 e 2 é 80% dos erros 401; o EOA como funder é o resto |
| Ordens rejeitadas com 'insufficient balance' | Consulte /balance-allowance antes de cada ordem e reserve localmente | O CLOB reserva o colateral assim que você posta; duas ordens concorrentes podem reservar em dobro |
| Throttling 429 no endpoint /order | Faça backoff com jitter: 2^attempt + random() com teto de 30s | O Cloudflare limita em vez de rejeitar; a retentativa ingênua amplifica a fila |
| WebSocket desconectado no meio da operação | Capture o livro via REST, reconcilie o estado local e então reinscreva-se | Os deltas durante o intervalo se perdem; a captura ressincroniza as escadas de preço |
| Ordem enviada mas sem confirmação de execução | Consulte /data/order/{id} em 5s; se pendente, espere; se não encontrada, substitua | Raro mas recuperável; por padrão "verifique o estado, depois aja" |
| Mercado resolvido durante uma cotação ativa | Cancele todas as ordens abertas naquele conditionId no evento de resolução | Ordens pós-resolução podem ficar como execuções zumbi se peculiaridades do adaptador dispararem |
| Você roda um bot de market-making | Cote dentro de 2 centavos do ponto médio com tamanho de 100+ cotas | A fórmula de recompensa pondera o aperto + o tamanho + o tempo no livro; apertado + tamanho + persistente vence |
| Você roda um bot de arbitragem em múltiplos resultados | Use FOK para cada perna, não GTC | Execuções parciais na perna A com a perna B completa = exposição sem hedge e perda instantânea |
| Primeira vez que você constrói um bot | Construa primeiro o scanner, depois o motor de preços, depois o sinal - nunca o sinal primeiro | Sinais sem um estado de livro limpo são armadilhas de correlação; faça os encanamentos funcionarem primeiro |
| Bot de produção caiu às 3 da manhã | Tenha autorrestart do systemd + alerta do Telegram + estado persistente | Todo bot sem supervisão vai cair; a única questão é se ele reinicia de forma limpa |
Objetivo. Ganhar recompensas de liquidez em um mercado de política de volume médio cotado em torno de 0.48 Yes / 0.52 No com um spread de 2 centavos. Bolsa de recompensa diária ~40 $ para este mercado.
Configuração. Inscreva-se via WebSocket nos dois token_ids. Faça cache do último mid visto. Defina spread_target = 0.02, size = 200 cotas por lado, reprice_threshold = 0.005 (5 ticks).
Loop. A cada atualização do livro via WS: calcule o novo mid = VWAP dos 3 melhores bids e asks. Se |cotações atuais - mid alvo| > reprice_threshold, cancele as duas ordens existentes, poste um novo bid em mid-0.01 e um novo ask em mid+0.01. Limite a reprecificação a uma vez a cada 2 segundos por lado.
Risco. Inventário máximo por lado = 1.000 cotas. Se o inventário > 500, alargue o spread desse lado em 0.005 a cada 100 cotas. Disjuntor: se o mid se mover >0.05 em 60 segundos, cancele tudo e pause por 5 minutos.
Resultado (execução real de 7 dias). Executadas ~14.000 cotas em 680 ordens, pagos 0 $ em taxas taker (lado maker), ganhos 31.40 $ em rebates de liquidez, o P&L direcional líquido foi -4.10 $ (pequenas perdas de inventário). Líquido +27.30 $ em 7 dias sobre 500 $ de capital de giro = ~8% ao mês. Escala linearmente em 30-50 mercados simultâneos em um único VPS.
Ponto-chave
Os traders que lucram de forma consistente na Polymarket tratam o guia da api da polymarket como um sistema, não como uma intuição. Guarde os números acima - eles são a diferença entre os 7,6% de carteiras lucrativas e o resto.
E agora?
- Ferramentas e recursos - painéis, analítica e feeds de dados de terceiros que complementam a API
- Estratégias avançadas - arbitragem de múltiplas pernas e construções tipo opções adequadas a bots
- Recompensas de liquidez - fórmulas exatas para ganhar rebates de market-making
- Guia do order book - intuição mais profunda para ler o livro antes de programar contra ele
- Glossário - definições em linguagem simples de cada termo deste guia
Leitura recomendada
Comece aqui se você é novo, ou pule direto para a página que corresponde à sua etapa:





