Tutorial de Bot de Polymarket · Capítulo 8 de 32

API CLOB de Polymarket para bots: endpoints REST para snapshots del libro de órdenes, suscripciones WebSocket para actualizaciones en tiempo real, parsing de bids/asks, cálculo de mid-price y profundidad, ejemplos de código.

Qué cubre este capítulo

La API CLOB es donde se firman, envían y ejecutan órdenes, y donde vive el libro de órdenes. Polymarket tiene dos generaciones de SDK: la v1, ya obsoleta, y la v2 actual. Este capítulo cubre solo v2; la v1 no debería aparecer en ningún bot que lances en 2026. Recorremos la ruta del snapshot REST, el canal de actualización WebSocket, los detalles de parsing que suelen trabar a los nuevos builders y la lógica de reconexión, sin la cual un bot de ejecución prolongada se desincroniza en cuestión de horas.

  • CLOB v1 vs v2 (usar v2)
  • Snapshot REST del libro de órdenes
  • Suscripciones WebSocket: canales de mercado y usuario
  • Parsing de bids/asks/depth
  • Cálculo de mid-price y mejor bid/ask
  • Maker fees, taker fees, rebates
  • Código: conectar WS y procesar eventos de cambio de precio
  • Reconexión y manejo de gaps

CLOB v1 vs v2 (usar v2)

Polymarket mantiene dos generaciones de SDK. v1 (@polymarket/clob-client en npm, py-clob-client <0.30) está deprecado y le faltan varios tipos de órdenes agregados en 2024. v2 (@polymarket/clob-client-v2 v1.0.6 en Node, py-clob-client 0.34.6+ en Python) es el estándar actual.

Tres diferencias concretas. v2 soporta el flag negRisk para mercados de múltiples resultados, requerido desde que el exchange NegRisk se lanzó a fines de 2024. v2 incluye tipos TypeScript para las formas de los mensajes WebSocket; v1 devuelve any. v2 maneja de forma nativa el flujo de firmas de Gnosis Safe de agosto de 2025; v1 requiere glue de firmado personalizado.

El resto de este capítulo está escrito asumiendo v2 en todo momento. Si ves código v1 en un tutorial antiguo, trátalo como roto hasta que se demuestre lo contrario: especialmente la colocación de órdenes en mercados NegRisk, que bajo v1 se enruta silenciosamente al contrato incorrecto del exchange.

Snapshot REST del libro de órdenes

El endpoint REST de snapshot devuelve el libro completo de un solo token en un momento dado.

GET https://clob.polymarket.com/book?token_id=<ERC1155_TOKEN_ID>

Forma de la respuesta:

{
  "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"}, ...]
}

Los precios vienen como strings con 2-3 decimales; los tamaños son strings que representan cantidad de shares (no dólares). Los bids están ordenados de mayor a menor, los asks de menor a mayor. hash es un marcador de deduplicación: consultas repetidas de un libro sin cambios devuelven el mismo hash y tu bot puede omitir el procesamiento.

El snapshot REST es la opción correcta para consultas puntuales (por ejemplo, revisar precio al tomar una decisión de entrada). Para monitoreo continuo, usa el canal WebSocket de abajo.

Suscripciones WebSocket: canales de mercado y usuario

Hay dos canales WebSocket que importan.

Canal de mercado: wss://ws-subscriptions-clob.polymarket.com/ws/market. Suscríbete a uno o varios tokens; recibe actualizaciones del libro de órdenes en tiempo real.

{"type":"Market","markets":["0xCondId1","0xCondId2"]}

Los mensajes llegan con cada cambio. Los tipos incluyen book (snapshot completo), price_change (delta), tick_size_change (raro) y last_trade_price (último fill).

Canal de usuario: wss://ws-subscriptions-clob.polymarket.com/ws/user. Autenticado; recibe tus propios eventos de órdenes: fills, partial fills, cancelaciones.

{"type":"User","auth":{"apiKey":"...","secret":"...","passphrase":"..."}}

El canal de usuario es la forma más limpia de detectar un fill. Hacer polling al endpoint REST de órdenes cuesta más y puede perder cambios de estado entre consultas; el WebSocket empuja el evento en el momento en que el matcher lo reconoce.

Parsing de bids/asks/depth

El libro de órdenes es una lista de niveles de precio con tamaño agregado. Hay dos convenciones de parsing que conviene hacer bien.

Dirección de la orden: bids son órdenes de compra (alguien quiere COMPRAR a este precio). Cuando TU bot vende, golpea un bid. Cuando tu bot compra, levanta un ask. La interfaz de Polymarket muestra la misma dirección; algunos otros exchanges la invierten.

Ordenamiento: bids llegan ordenados descendente (mejor bid primero). asks llegan ordenados ascendente (mejor ask primero). El mejor bid es bids[0]; el mejor ask es asks[0]. Ojo: el WebSocket público a veces envía actualizaciones parciales del libro que no vienen preordenadas; reordena siempre de forma defensiva después de cualquier merge.

La profundidad en un nivel es el valor en dólares transactable: price * size. La profundidad en los primeros 5 niveles es una métrica común de liquidez: sum(b.price * b.size for b in bids[:5]). Si la profundidad top-5 está por debajo de $100, el libro es ilíquido y la mayoría de las suposiciones de estrategia se rompen.

Cálculo de mid-price y mejor bid/ask

Tres precios derivados que tu bot necesita.

  • Mejor bid / mejor ask: bids[0].price y asks[0].price. Los precios a los que realmente puedes operar, por una share.
  • Mid-price: (best_bid + best_ask) / 2. El centro matemático del spread. Útil para valuación; nunca operas al mid.
  • Precio VWAP para tamaño N: recorre el libro hasta que el tamaño acumulado alcance N, y devuelve el promedio ponderado por tamaño. El costo real de COMPRAR N shares ahora mismo, considerando el barrido hacia niveles más profundos.

Caso límite: un lado vacío del libro de bids o asks (nadie vendiendo, o nadie comprando) significa que el libro es unidireccional. En la estructura de mercado de Polymarket esto ocurre en mercados resueltos o casi resueltos, donde un lado está en 0.999 y nadie ofrece liquidez del lado perdedor. Trata best-bid = 0 o best-ask = 1 como señales de "no operar".

Maker fees, taker fees, rebates

Durante la mayor parte de su historia, Polymarket no cobró ninguna comisión de trading. Eso cambió en 2026: primero se introdujeron fees en los mercados crypto de 15 minutos a principios de año, se ampliaron a Sports el 30 de marzo de 2026 y desde entonces se han desplegado en la mayoría de las categorías. Cualquier tutorial que aún diga que Polymarket es sin comisiones está desactualizado, y equivocarse en esto devora en silencio una estrategia de alta frecuencia. Así funciona realmente el modelo, a mediados de 2026.

Primero, los dos lados de cada operación. Un maker es quien coloca una orden límite pasiva que espera en el libro; un taker es quien envía una orden que se ejecuta de inmediato contra la liquidez existente. Los makers siguen pagando cero fees y además reciben un rebate; solo los takers pagan un fee.

El taker fee no es un porcentaje fijo. Sigue una curva que depende tanto del tamaño de la orden como del precio:

fee = shares × feeRate × price × (1 - price)

El término price × (1 - price) es máximo en un precio de 0,50 (un mercado verdaderamente a cara o cruz) y se reduce hacia 0 o 1. Dicho de otro modo: pagas más fee en los mercados más inciertos y casi nada en los casi resueltos. El feeRate se fija por categoría:

  • Crypto: feeRate 0,07 (el más alto, pico cercano al 1,8 % efectivo), maker rebate 20 %.
  • Sports: feeRate 0,03 (pico cercano al 0,75 %), maker rebate 25 %.
  • Finance, Politics, Tech, Mentions: feeRate 0,04, maker rebate 25 %.
  • Economics, Culture, Weather, general: feeRate 0,05, maker rebate 25 %.
  • Geopolitics y grandes eventos mundiales: 0, todavía sin comisiones.

Un ejemplo con números. Supón que tu bot toma 100 shares de un mercado crypto al precio de 0,50. El fee es 100 × 0,07 × 0,50 × (1 - 0,50) = 100 × 0,07 × 0,25 = 1,75 $. Toma esas mismas 100 shares a 0,90 y el fee baja a 100 × 0,07 × 0,90 × 0,10 = 0,63 $, porque el precio está lejos del medio incierto. Para un bot, la lección es directa: tomar liquidez en mercados crypto y sports volátiles y casi parejos es donde más muerden los fees, así que esos son precisamente los mercados donde cotizar como maker (y cobrar el rebate en vez de pagar el fee) rinde más.

Además del fee explícito, pagas el spread bid-ask cada vez que lo cruzas. El spread es la diferencia entre el mejor precio de compra y el mejor precio de venta, y para una estrategia que entra y sale como taker, esa diferencia es un costo real que se suma al fee. Asume 1-3 centavos ida y vuelta en libros típicos, más en los ilíquidos. Los mercados NegRisk (el exchange multi-resultado) usan el mismo modelo de fees, pero liquidan en un contrato separado, así que sus rewards se acumulan por separado. El capítulo 19 cubre el farming de liquidity rewards, donde cobrar los maker rebates es la estrategia en sí y no solo un efecto secundario.

Código: conectar WS y procesar eventos de cambio de precio

Ejemplo mínimo en Node: conectar, suscribirse y registrar cada evento de price_change para un 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));

Suscribirse cómodamente a hasta ~30 tokens por conexión WebSocket es razonable. Más allá de eso, conviene dividir en varias conexiones: a veces el servidor deja caer suscripciones grandes sin devolver error, lo que genera lecturas silenciosamente obsoletas del libro.

Reconexión y manejo de gaps

Una conexión WebSocket de larga duración se va a cortar. Cloudflare recicla conexiones cada pocas horas; las redes fallan por momentos; Polymarket a veces despliega cambios. Hay que planear para eso.

Estrategia de reconexión: ante close o error, espera min(2^attempt, 30) segundos con jitter y luego vuelve a suscribirte. Reinicia el contador de intentos en el primer mensaje exitoso después de reconectar.

El manejo de gaps importa más que la velocidad de reconexión. Mientras el WebSocket estuvo desconectado, el libro se movió. En cada reconexión, vuelve a pedir el snapshot REST de cada token suscrito y reconcilia: cualquier posición abierta cuyo libro se movió de forma relevante necesita una nueva verificación de estado, las salidas pueden requerir ejecución y las alertas pueden estar desactualizadas. El caso "me perdí 30 segundos de actualizaciones del libro" es el asesino silencioso de los bots de larga duración: siguen corriendo con estado stale y colocan órdenes a precios que ya no existen.

Patrón defensivo: haz snapshot de cada libro suscrito una vez por minuto, independientemente del estado del WebSocket, y trata al WS como una optimización de fast-path encima del polling de snapshots.

Preguntas frecuentes

¿Cuál es el endpoint de la API CLOB de Polymarket?
El endpoint base de CLOB es https://clob.polymarket.com (REST) y wss://ws-subscriptions-clob.polymarket.com/ws/market (WebSocket). Estos son los endpoints V2 usados por @polymarket/clob-client-v2 y py-clob-client.
¿Necesito una API key para leer el libro de órdenes?
No. La lectura del libro de órdenes (snapshots y suscripciones WebSocket) es pública y no requiere autenticación. Solo necesitas una API key para colocar/cancelar órdenes y leer datos específicos de la cuenta (posiciones, fills).
¿Qué tan rápido empuja actualizaciones de precio el WebSocket de CLOB?
Tan rápido como se ejecutan las órdenes. Los mercados activos ven actualizaciones cada pocos cientos de milisegundos; los mercados delgados solo actualizan cuando hay órdenes reales. Tanto los cambios de profundidad como los eventos de trade fluyen por el mismo canal WS; parsea el tipo de evento para manejar cada uno correctamente.
¿Cómo calculo el mid-price de un libro de órdenes de Polymarket?
mid = (best_bid + best_ask) / 2 si ambos existen; si no, usa last_trade_price como fallback. Ten cuidado con libros delgados donde best_bid está muy por debajo de best_ask: el mid puede no significar nada. Considera siempre también el spread antes de tratar al mid como un precio justo.
¿Cuál es la maker fee en Polymarket en 2026?
Los makers pagan 0% y reciben un rebate (20% en crypto, 25% en la mayoría de las demás categorías). Solo los takers pagan un fee, y no es fijo: sigue fee = shares × feeRate × price × (1 - price), así que es máximo en los mercados a cara o cruz cerca de 0,50 y se reduce hacia los extremos. Los feeRates por categoría van de 0,03 (Sports, alrededor del 0,75% de pico efectivo) a 0,07 (Crypto, alrededor del 1,8% de pico efectivo), con Geopolitics todavía sin fees. Esta asimetría maker-taker es por qué los bots activos casi siempre cotizan con órdenes limit pasivas en lugar de cruzar el spread con market orders.
¿Cómo manejo desconexiones de WebSocket?
Reconéctate con backoff exponencial (1s, 2s, 4s, máximo 30s), vuelve a suscribirte a los mismos mercados y vuelve a pedir un snapshot REST para cubrir cualquier gap. Nunca confíes en un libro de órdenes stale: si estuviste desconectado por más de 5 segundos, pide un snapshot fresco antes de colocar órdenes.