Polymarket Bot Tutorial · Chapter 8 of 32
API CLOB da Polymarket para bots: REST endpoints para snapshots do order book, assinaturas WebSocket para atualizações em tempo real, parsing de bids/asks, cálculo de mid-price e depth, exemplos de código.
O que este capítulo cobre
A API CLOB é onde as ordens são assinadas, enviadas, casadas e onde o order book vive. A Polymarket tem duas gerações de SDK - a v1, descontinuada, e a v2 atual. Este capítulo cobre apenas a v2; a v1 não deve aparecer em nenhum bot que você coloque em produção em 2026. Vamos passar pelo caminho do snapshot via REST, pelo canal de atualização via WebSocket, pelos detalhes de parsing que pegam muitos builders de surpresa e pela lógica de reconnect sem a qual um bot de longa execução sai de sync em questão de horas.
- CLOB v1 vs v2 (use v2)
- Snapshot REST do order book
- Assinaturas WebSocket: canais de mercado e usuário
- Parsing de bids/asks/depth
- Cálculo de mid-price e best-bid/ask
- Maker fees, taker fees, rebates
- Código: conectar WS e processar eventos de price-change
- Reconnect e tratamento de gaps
CLOB v1 vs v2 (use v2)
A Polymarket mantém duas gerações de SDK. A v1 (@polymarket/clob-client no npm, py-clob-client <0.30) está descontinuada e não tem vários tipos de ordem adicionados em 2024. A v2 (@polymarket/clob-client-v2 v1.0.6 em Node, py-clob-client 0.34.6+ em Python) é o padrão atual.
Três diferenças concretas. A v2 suporta a flag negRisk para mercados de múltiplos resultados - obrigatória desde o lançamento da exchange NegRisk no fim de 2024. A v2 traz tipos TypeScript para os formatos de mensagem do WebSocket; a v1 retorna any. A v2 lida nativamente com o fluxo de assinatura do Gnosis Safe de agosto de 2025; a v1 exige custom signing glue.
O restante deste capítulo foi escrito assumindo v2 em tudo. Se você encontrar código v1 em um tutorial mais antigo, trate-o como quebrado até prova em contrário - o envio de ordens em mercados NegRisk, em particular, pode ser roteado silenciosamente para o contract de exchange errado sob a v1.
Snapshot REST do order book
O endpoint de snapshot REST retorna o book completo de um único token em um ponto no tempo.
GET https://clob.polymarket.com/book?token_id=<ERC1155_TOKEN_ID>
Formato da resposta:
{
"market": "0x...",
"asset_id": "5413...",
"timestamp": "1715600000000",
"hash": "0x...",
"bids": [{"price":"0.45","size":"120"}, {"price":"0.44","size":"380"}, ...],
"asks": [{"price":"0.47","size":"85"}, {"price":"0.48","size":"210"}, ...]
}
Os preços são strings com 2-3 casas decimais; os sizes são strings representando quantidade de shares (não dólares). Bids vêm ordenados do maior para o menor, asks do menor para o maior. hash é um marcador de deduplicação - polls repetidos de um book inalterado retornam o mesmo hash e seu bot pode pular o processamento.
O snapshot REST é a escolha certa para consultas pontuais (checagem de preço na decisão de entrada). Para monitoramento contínuo, use o canal WebSocket abaixo.
Assinaturas WebSocket: canais de mercado e usuário
Dois canais WebSocket importam.
Canal de mercado: wss://ws-subscriptions-clob.polymarket.com/ws/market. Assine um ou vários tokens; receba atualizações do order book conforme acontecem.
{"type":"Market","markets":["0xCondId1","0xCondId2"]}
As mensagens chegam a cada mudança. Os tipos incluem book (snapshot completo), price_change (delta), tick_size_change (raro) e last_trade_price (último fill).
Canal de usuário: wss://ws-subscriptions-clob.polymarket.com/ws/user. Autenticado; receba seus próprios eventos de ordem - fills, partial fills, cancelamentos.
{"type":"User","auth":{"apiKey":"...","secret":"...","passphrase":"..."}}
O canal de usuário é a forma mais limpa de detectar um fill. Fazer polling no endpoint REST de ordens custa mais e pode perder mudanças de estado entre polls; o WebSocket empurra o evento no momento em que o matcher o reconhece.
Parsing de bids/asks/depth
O order book é uma lista de níveis de preço com size agregado. Dois padrões de parsing precisam estar corretos.
Direção da ordem: bids são ordens de compra (alguém quer COMPRAR a este preço). Quando O SEU bot vende, ele atinge um bid. Quando seu bot compra, ele levanta um ask. A UI da Polymarket mostra a mesma direção; algumas outras exchanges invertem isso.
Ordenação: bids chegam ordenados de forma descendente (melhor bid primeiro). asks chegam ordenados de forma ascendente (melhor ask primeiro). Melhor bid é bids[0]; melhor ask é asks[0]. Atenção: o WebSocket público às vezes envia partial book updates que não vêm pré-ordenados - sempre reordene de forma defensiva após qualquer merge.
A depth em um nível é o valor em dólares negociável: price * size. Depth nos 5 primeiros níveis é uma métrica de liquidez muito usada: sum(b.price * b.size for b in bids[:5]). Se a depth dos 5 primeiros níveis estiver abaixo de US$ 100, o book é ilíquido e a maioria das premissas de strategy quebra.
Cálculo de mid-price e best-bid/ask
Três pontos de preço derivados que seu bot precisa.
- Best bid / best ask:
bids[0].priceeasks[0].price. Os preços em que você realmente pode negociar, uma share. - Mid-price:
(best_bid + best_ask) / 2. O centro matemático do spread. Útil para valuation; você nunca negocia no mid. - Preço VWAP para size N: percorra o book até o size cumulativo atingir N, e retorne o preço médio ponderado por size. O custo real para COMPRAR N shares agora, considerando a varredura para níveis mais profundos.
Caso limite: um lado vazio de bid ou ask (ninguém vendendo, ou ninguém comprando) significa que o book está unilateral. Na estrutura de mercado da Polymarket isso acontece em mercados resolvidos ou quase resolvidos, em que um lado está em 0.999 e ninguém oferece liquidez do lado perdedor. Trate best-bid = 0 ou best-ask = 1 como sinais de "não operar".
Maker fees, taker fees, rebates
Durante a maior parte de sua história, a Polymarket não cobrou nenhuma fee de trading. Isso mudou em 2026: as fees foram introduzidas no início do ano nos mercados crypto de 15 minutos, estendidas aos Sports em 30 de março de 2026 e desde então aplicadas à maioria das categorias. Qualquer tutorial que ainda afirme que a Polymarket é sem fees está desatualizado - e quem ignora isso em uma strategy de alta frequência é comido em silêncio. Veja como o modelo realmente funciona, em meados de 2026.
Primeiro, os dois lados de toda trade. Um maker é quem coloca no book uma ordem limit em repouso que fica ali aguardando; um taker é quem envia uma ordem que é executada imediatamente contra a liquidez já presente. Makers continuam pagando zero fee e ainda recebem um rebate; só os takers pagam uma fee.
A taker fee não é uma porcentagem fixa. Ela segue uma curva que depende tanto do tamanho da ordem quanto do preço:
fee = shares × feeRate × price × (1 - price)
O termo price × (1 - price) é máximo a um preço de 0,50 (um mercado de verdadeiro cara-ou-coroa) e encolhe em direção a 0 ou 1. Em outras palavras, nos mercados mais incertos você paga a fee mais alta e nos quase decididos quase nada. A feeRate é definida por categoria:
- Crypto: feeRate 0,07 (a mais alta, pico efetivo em torno de 1,8%), maker rebate 20%.
- Sports: feeRate 0,03 (pico em torno de 0,75%), maker rebate 25%.
- Finance, Politics, Tech, Mentions: feeRate 0,04, maker rebate 25%.
- Economics, Culture, Weather, geral: feeRate 0,05, maker rebate 25%.
- Geopolitics e grandes eventos mundiais: 0, ainda sem fee.
Um exemplo de cálculo. Suponha que seu bot pegue 100 shares de um mercado crypto ao preço de 0,50. A fee é 100 × 0,07 × 0,50 × (1 - 0,50) = 100 × 0,07 × 0,25 = $1,75. Se em vez disso você pegar as mesmas 100 shares a 0,90, a fee cai para 100 × 0,07 × 0,90 × 0,10 = $0,63, porque o preço está longe do meio incerto. Para um bot, a lição é clara: pegar liquidez em mercados crypto e sports voláteis e quase equilibrados custa o máximo de fee - então é exatamente ali que mais compensa cotar como maker e embolsar o rebate em vez de pagar a fee.
Além da fee explícita, toda vez que você cruza o spread bid-ask, você o paga. O spread é a diferença entre o melhor preço de compra e o melhor preço de venda, e para uma strategy que entra e sai como taker essa diferença é um custo real que se soma à fee. Assuma 1-3 cents de round-trip em books típicos, mais em ilíquidos. Mercados NegRisk (a exchange multi-outcome) usam o mesmo modelo de fee, mas settle em um contract separado, então seus rewards acumulam separadamente. O capítulo 19 cobre liquidity rewards farming, onde embolsar maker rebates é a própria strategy e não apenas um efeito colateral.
Código: conectar WS e processar eventos de price-change
Exemplo mínimo em Node: conectar, assinar, registrar todo evento de price-change para um token.
import WebSocket from "ws";
const ws = new WebSocket("wss://ws-subscriptions-clob.polymarket.com/ws/market");
ws.on("open", () => {
ws.send(JSON.stringify({ type: "Market", markets: ["<CONDITION_ID>"] }));
});
ws.on("message", (data) => {
const msg = JSON.parse(data.toString());
if (msg.event_type === "price_change") {
console.log("price_change", msg.asset_id, msg.changes);
} else if (msg.event_type === "book") {
console.log("book snapshot", msg.bids?.[0], msg.asks?.[0]);
}
});
ws.on("close", () => console.log("closed"));
ws.on("error", (e) => console.error("err", e.message));
É tranquilo assinar até cerca de 30 tokens por conexão WebSocket. Acima disso, distribua em múltiplas conexões - o servidor às vezes derruba assinaturas grandes sem retornar erro, o que gera leituras silenciosamente desatualizadas do book.
Reconnect e tratamento de gaps
Uma conexão WebSocket de longa duração vai cair. O Cloudflare recicla conexões a cada poucas horas; redes oscilam; a Polymarket às vezes faz deploy. Planeje isso.
Estratégia de reconnect: no close ou error, aguarde min(2^attempt, 30) segundos com jitter e então re-subscreva. Zere o contador de tentativas no primeiro mensagem bem-sucedida após o reconnect.
O tratamento de gaps importa mais do que a velocidade do reconnect. Enquanto o WebSocket esteve desconectado, o book se moveu. Em todo reconnect, reconsulte o snapshot REST de cada token assinado e faça a reconciliação: qualquer posição aberta cujo book mudou de forma relevante precisa de uma nova checagem de estado, exits podem precisar disparar, alarms podem estar obsoletos. O caso de "perdi 30 segundos de updates do book" é o assassino silencioso de bots de longa execução - eles continuam rodando com estado antigo e colocam ordens em preços que já não existem.
Padrão defensivo: faça snapshot de cada book assinado uma vez por minuto, independentemente do estado do WebSocket, e trate o WS como uma otimização de fast-path em cima do polling de snapshot.










