Skip to content

Polymarket SDK

Complete reference for ctx.polymarket — programmatic prediction-market trading on Polymarket from worker code.

Polymarket = on-chain prediction markets

This SDK wraps Polymarket's three public APIs:

  • Gamma API for events, markets, and discovery
  • CLOB API for order book / trading (auth via wallet signature)
  • Data API for positions, public trades, fills

19 methods total. Server-only.

Setup

  1. Add a Polymarket trading block to your workspace canvas.
  2. Open the inspector → API Keys → pick a key (Settings → API Keys → Polymarket to add new). Polymarket requires a wallet private key (your Polygon EVM key).
  3. Connect the block to your Worker block via an edge.
  4. ctx.polymarket is now available.
python
def tick(ctx):
    bal = ctx.polymarket.get_balance()
    ctx.log.info(f"USDC: {bal}")

If no Polymarket block is connected, public methods still work, but per-user methods raise:

RuntimeError: No Polymarket block connected. Connect a Polymarket block to this worker.

Why a private key here?

Unlike Hyperliquid (browser-only signing), Polymarket's py-clob-client SDK signs orders with the user's private key server-side. You explicitly opt in by pasting the key — it's stored Fernet-encrypted alongside other API keys. If you don't want a private key on our server, don't add a Polymarket key — public methods still work for read-only research.

Concepts

TermMeaning
EventA real-world question, e.g. "Will Trump win the 2028 election?"
MarketA specific binary outcome under an event ("YES" or "NO")
TokenThe tradable ERC-1155 share representing a single outcome
Token IDThe unique 70-digit numeric identifier for that token
ProbabilityThe token's price between 0 and 1 (0.42 = 42% implied)

Discovery flow: search_events("Trump") → pick event → event["markets"][i]["clobTokenIds"] → trade by token_id.

Public Discovery

These methods don't need a connected Polymarket block.

search_events

Search events by name fragment.

python
ctx.polymarket.search_events(query: str = "", limit: int = 20) -> list
python
results = ctx.polymarket.search_events("election", limit=10)
for ev in results:
    ctx.log.info(f"{ev['title']} ({ev['markets']} markets)")

get_event

Single event with all child markets and token IDs.

python
ctx.polymarket.get_event(event_id: str) -> dict

search_markets

Search markets directly (more granular than events).

python
ctx.polymarket.search_markets(query: str = "", limit: int = 20) -> list

get_market

Detail for one market by id.

python
ctx.polymarket.get_market(market_id: str) -> dict

get_active_markets

List currently-active markets, paginated. Useful for scanners.

python
ctx.polymarket.get_active_markets(
    limit: int = 50,
    offset: int = 0,
    active: bool = True,
    closed: bool = False,
) -> list

get_market_trades

Recent public trades on a market — anyone's executions.

python
ctx.polymarket.get_market_trades(token_id: str, limit: int = 100) -> list

Market Data (auth required for CLOB endpoints)

get_orderbook

L2 order book for a token.

python
ctx.polymarket.get_orderbook(token_id: str) -> dict

Returns: {"market", "asset_id", "bids": [{"price", "size"}], "asks": [{"price", "size"}], "hash"}

get_midpoint

Midpoint price (mean of best bid + best ask) — quick fair-value reference.

python
ctx.polymarket.get_midpoint(token_id: str) -> float
# returns a Python float, e.g. 0.42

get_last_trade_price

The price of the most recent execution.

python
ctx.polymarket.get_last_trade_price(token_id: str) -> dict

get_price

Best bid (side='buy') or best ask (side='sell') for a token.

python
ctx.polymarket.get_price(token_id: str, side: str = "buy") -> dict
python
bid = ctx.polymarket.get_price(token_id, "buy")
ask = ctx.polymarket.get_price(token_id, "sell")
spread_cents = (float(ask["price"]) - float(bid["price"])) * 100

get_spread

Bid/ask spread snapshot for a token.

python
ctx.polymarket.get_spread(token_id: str) -> dict

Account & Positions

get_balance

USDC balance + on-chain allowance for the CLOB.

python
ctx.polymarket.get_balance() -> dict

get_positions

Current outcome-token positions across all markets.

python
ctx.polymarket.get_positions() -> list
python
for p in ctx.polymarket.get_positions():
    if float(p.get("size", 0)) > 0:
        ctx.log.info(f"{p.get('outcome')}: {p['size']} @ "
                     f"avg {p.get('avgPrice')}, "
                     f"PnL ${p.get('cashPnl', 0):.2f}")

get_history

Trade history (your fills with fees).

python
ctx.polymarket.get_history(limit: int = 50) -> list

Orders

create_order

Place a limit order. Polymarket only supports limit orders — no market orders. Use a near-mid price for fast fill.

python
ctx.polymarket.create_order(
    token_id: str,
    side: str,        # "BUY" | "SELL"
    size: float,      # number of shares
    price: float,     # 0..1 probability
) -> dict
python
# Buy 100 YES shares of "BTC > $80k by EOY 2026" at 0.40
r = ctx.polymarket.create_order(
    token_id="71321045679252212594626385532...",
    side="BUY", size=100, price=0.40,
)
order_id = r.get("orderID")

Min size

Polymarket has a minimum order value (~$1 USDC at the time of writing). Orders below that get rejected.

cancel_order

Cancel a single order.

python
ctx.polymarket.cancel_order(order_id: str) -> dict

cancel_all_orders

Cancel ALL open orders. Kill switch.

python
ctx.polymarket.cancel_all_orders() -> dict

get_open_orders

Active (unfilled) orders.

python
ctx.polymarket.get_open_orders() -> list

get_order

Detail of a single order by id.

python
ctx.polymarket.get_order(order_id: str) -> dict

Common Patterns

Public-only research mode

Don't have a Polymarket private key configured? You can still do public market research:

python
def tick(ctx):
    # No block needed — works on Free plan
    events = ctx.polymarket.search_events("Bitcoin", limit=5)
    for ev in events:
        ctx.log.info(f"{ev['title']}: {ev['volume']:.0f} USDC volume")

Error handling

python
def tick(ctx):
    try:
        positions = ctx.polymarket.get_positions()
    except Exception as e:
        ctx.log.error(f"Polymarket unreachable: {e}")
        return

PolymarketError is raised for CLOB errors. Network failures raise httpx.HTTPStatusError.

Cloud-Run proxy

PRO+ workers route Polymarket Gamma + Data traffic through the Cloud Run proxy with rotating exit IPs. The CLOB calls go through py-clob-client directly (it manages its own session).

Recipes

Bid below midpoint, exit at favorable price

python
def tick(ctx):
    token = ctx.state.get("target_token")
    if not token:
        return

    mid = ctx.polymarket.get_midpoint(token)
    spread = ctx.polymarket.get_spread(token)

    # Already in?
    open_orders = ctx.polymarket.get_open_orders()
    if any(o.get("asset_id") == token for o in open_orders):
        return

    # Bid 2 cents below mid
    bid_price = round(mid - 0.02, 2)
    if bid_price < 0.05:   # too cheap to be useful
        return

    ctx.polymarket.create_order(
        token_id=token, side="BUY",
        size=50, price=bid_price,
    )
    ctx.log.info(f"Bid {bid_price} for token, mid={mid:.3f}")

Volume-weighted event scanner

Find the most-traded events of the day to focus research.

python
def tick(ctx):
    events = ctx.polymarket.search_events("", limit=200)

    by_volume = sorted(
        [e for e in events if e.get("active") and float(e.get("volume24hr", 0)) > 0],
        key=lambda x: float(x.get("volume24hr", 0)),
        reverse=True,
    )[:10]

    for e in by_volume:
        vol = float(e.get("volume24hr", 0))
        ctx.log.info(f"{e['title']:60} ${vol:,.0f}")
        ctx.monitor.metric(f"poly_24h_{e['id']}", vol)

Risk-on cleanup before market close

python
import time
from datetime import datetime, timezone

def tick(ctx):
    # 5 minutes before EOD, cancel everything
    now = datetime.now(timezone.utc)
    if now.hour == 23 and now.minute >= 55:
        result = ctx.polymarket.cancel_all_orders()
        ctx.log.info(f"EOD cancel-all: {result}")

Reference

Polymarket endpointSDK method
GET gamma /events?search=search_events
GET gamma /events/{id}get_event
GET gamma /markets?search=search_markets
GET gamma /markets/{id}get_market
GET gamma /markets?active=trueget_active_markets
GET data /trades?market=get_market_trades
POST clob /bookget_orderbook
POST clob /midpointget_midpoint
POST clob /priceget_price
POST clob /spreadget_spread
POST clob /last-trade-priceget_last_trade_price
GET data /positions?user=get_positions
POST clob /balance-allowanceget_balance
POST clob /tradesget_history
POST clob /ordercreate_order
DELETE clob /order/{id}cancel_order
DELETE clob /orderscancel_all_orders
GET clob /ordersget_open_orders
GET clob /order/{id}get_order

AiSpinner Documentation