Polymarket Bot Tutorial · Hoofdstuk 8 van 32
Polymarket CLOB API voor bots: REST endpoints voor order book snapshots, WebSocket subscriptions voor real-time updates, parsing van bids/asks, berekenen van mid-prijs en depth, codevoorbeelden.
Wat dit hoofdstuk behandelt
De CLOB API is waar orders worden getekend, verzonden, gematcht en waar het order book leeft. Polymarket heeft twee SDK-generaties — de deprecated v1 en de huidige v2. Dit hoofdstuk behandelt alleen v2; v1 mag niet voorkomen in enige bot die je in 2026 shipt. We wandelen door het REST snapshot-pad, het WebSocket update-kanaal, de parsing-details die nieuwe builders struikelen en de reconnect-logica zonder welke een langlopende bot binnen uren uit sync drift.
Dit is hoofdstuk 8 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.
- CLOB v1 vs v2 (gebruik v2)
- Order book REST snapshot
- WebSocket subscriptions: market en user channels
- Parsen van bids/asks/depth
- Berekenen van mid-prijs en best-bid/ask
- Maker fees, taker fees, rebates
- Code: WS verbinden en price-change events verwerken
- Reconnect en gap-handling
CLOB v1 vs v2 (gebruik v2)
Polymarket onderhoudt twee SDK-generaties. v1 (@polymarket/clob-client op npm, py-clob-client <0.30) is deprecated en mist verschillende order types toegevoegd in 2024. v2 (@polymarket/clob-client-v2 v1.0.2 in Node, py-clob-client 0.34.6+ in Python) is de huidige standaard.
Drie concrete verschillen. v2 ondersteunt de negRisk flag voor multi-outcome markten — vereist sinds de NegRisk exchange eind 2024 lanceerde. v2 ship't TypeScript types voor de WebSocket message-vormen; v1 geeft any terug. v2 hanteert de Gnosis Safe signature flow van augustus 2025 native; v1 vereist custom signing glue.
De rest van dit hoofdstuk is geschreven aannemend v2 overal. Als je v1 code ziet in een oudere tutorial, behandel het als gebroken totdat anders is bewezen — orderplaatsing tegen NegRisk markten zal in het bijzonder stil routeren naar het verkeerde exchange contract onder v1.
Order book REST snapshot
Het REST snapshot-endpoint geeft het volledige book voor een enkele token op een moment terug.
GET https://clob.polymarket.com/book?token_id=<ERC1155_TOKEN_ID>
Respons-vorm:
{
"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"}, ...]
}
Prijzen zijn strings met 2-3 decimalen; sizes zijn strings die share counts vertegenwoordigen (geen dollars). Bids zijn gesorteerd hoog-naar-laag, asks laag-naar-hoog. hash is een dedup-marker — herhaalde polls van een onveranderd book geven dezelfde hash terug en je bot kan verwerking overslaan.
De REST snapshot is de juiste call voor one-off lookups (price check op entry-beslissing). Voor continue monitoring, gebruik het WebSocket kanaal hieronder.
WebSocket subscriptions: market en user channels
Twee WebSocket kanalen tellen.
Market channel: wss://ws-subscriptions-clob.polymarket.com/ws/market. Abonneer op één of veel tokens; ontvang order-book updates wanneer ze gebeuren.
{"type":"Market","markets":["0xCondId1","0xCondId2"]}
Berichten komen aan bij elke wijziging. Types zijn onder andere book (volledige snapshot), price_change (delta), tick_size_change (zeldzaam) en last_trade_price (meest recente fill).
User channel: wss://ws-subscriptions-clob.polymarket.com/ws/user. Geauthenticeerd; ontvang je eigen order events — fills, partial fills, cancellations.
{"type":"User","auth":{"apiKey":"...","secret":"...","passphrase":"..."}}
Het user channel is de schoonste manier om een fill te detecteren. Het pollen van het orders REST-endpoint kost meer en kan state changes tussen polls missen; de WebSocket pusht het event op het moment dat de matcher het bevestigt.
Parsen van bids/asks/depth
Het order book is een lijst van prijs-levels met geaggregeerde size. Twee parse-conventies om goed te krijgen.
Order direction: bids zijn buy orders (iemand wil KOPEN op deze prijs). Wanneer JE bot verkoopt, raak je een bid. Wanneer je bot koopt, lift je een ask. De Polymarket UI toont dezelfde richting; sommige andere exchanges inverteren.
Sortering: bids komen aan gesorteerd aflopend (best bid eerst). asks komen aan gesorteerd oplopend (best ask eerst). Best bid is bids[0]; best ask is asks[0]. Pas op: de publieke WebSocket stuurt soms partial book updates die niet pre-sorted zijn — sorteer defensief opnieuw na elke merge.
Depth op een level is de dollar-waarde die verhandelbaar is: price * size. Top-5-level depth is een veelvoorkomende liquidity metric: sum(b.price * b.size for b in bids[:5]). Als top-5 depth onder 100 $ is, is het book illiquide en de meeste strategy-aannames breken.
Berekenen van mid-prijs en best-bid/ask
Drie afgeleide prijspunten die je bot nodig heeft.
- Best bid / best ask:
bids[0].priceenasks[0].price. De prijzen waar je daadwerkelijk op kunt traden, één share. - Mid-prijs:
(best_bid + best_ask) / 2. Het wiskundige centrum van de spread. Nuttig voor valuation; je trade nooit op de mid. - VWAP prijs voor size N: wandel het book tot cumulatieve size N bereikt, geef de size-weighted average price terug. De daadwerkelijke kost om N shares NU te KOPEN, rekening houdend met sweep naar diepere levels.
Edge case: een lege bid of ask zijde (niemand verkoopt, of niemand koopt) betekent dat het book one-sided is. In Polymarkets marktstructuur gebeurt dit bij afgehandelde of bijna-afgehandelde markten waar één zijde op 0,999 staat en niemand liquiditeit biedt aan de verliezende zijde. Behandel best-bid = 0 of best-ask = 1 als "niet traden" signalen.
Maker fees, taker fees, rebates
Polymarket draait een maker-taker fee model. Cijfers per mei 2026:
- Taker fee: 0 (nul) — orders die bestaande book liquiditeit liften betalen geen fee. Merk op dat gas/netwerkkosten gelden voor proxy operaties.
- Maker rebate: klein positief, programmatisch, uitbetaald per gevulde rested order in eligible reward-program markten. Niet alle markten hebben rewards.
- NegRisk markten: zelfde fee structuur maar op een apart exchange contract; rewards accruen apart.
De zero taker fee maakt Polymarket betekenisvol anders dan traditionele CFD venues — het meeste van de trading-"kost" is de bid-ask spread zelf, geen expliciete fee. Voor een strategie die de spread crossen bij elke trade is de spread tax de echte kost; neem aan 1-3 cent round-trip op typische books, meer op illiquide.
Maker rebates zijn alleen de moeite waard om te chasen wanneer liquidity-rewards-eligible markten lijnen met strategy-ideeën. Hoofdstuk 19 behandelt liquidity-rewards farming als dedicated aanpak.
Code: WS verbinden en price-change events verwerken
Minimaal Node-voorbeeld: connect, subscribe, log elke price-change event voor één 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));
Abonneer comfortabel op tot ~30 tokens per WebSocket connection. Daarboven, split over meerdere connections — de server dropt occasioneel grote subscriptions op de vloer zonder error, wat stille stale book reads produceert.
Reconnect en gap-handling
Een langlopende WebSocket connection zal dropen. Cloudflare cyclet connections elke paar uur; netwerken knipperen; Polymarket deployt soms. Plan ervoor.
Reconnect-strategie: bij close of error, wacht min(2^attempt, 30) seconden met jitter, dan re-subscribe. Reset de attempt counter bij de eerste succesvolle message na reconnect.
Gap handling telt meer dan reconnect-snelheid. Terwijl de WebSocket disconnected was, bewoog het book. Bij elke reconnect, re-fetch de REST snapshot van elke geabonneerde token en reconcile: alle open posities waarvan het book betekenisvol bewoog hebben een state re-check nodig, exits moeten misschien vuren, alarms zijn misschien stale. De "ik miste 30 seconden van book updates" case is de stille killer van langlopende bots — ze blijven draaien op stale state en plaatsen orders op prijzen die niet meer bestaan.
Defensief patroon: snapshot elk geabonneerd book eens per minuut ongeacht WebSocket state, en behandel de WS als een fast-path optimization bovenop de snapshot poll.











