← Back to Skills Marketplace
nwcalvin

Polymarket API Guide

by nwcalvin · GitHub ↗ · v2.0.0 · MIT-0
cross-platform ✓ Security Clean
389
Downloads
0
Stars
1
Active Installs
4
Versions
Install in OpenClaw
/install innotech-polymarket-api
Description
Polymarket API and data access guide. Learn how to connect, find markets, get real-time data via WebSocket, access order books, place orders via CLOB SDK, an...
README (SKILL.md)

Polymarket API & Data Access Guide

Purpose: Comprehensive reference for connecting to, understanding, and using Polymarket APIs
Last Updated: 2026-03-23


🎯 What This Skill Covers

  1. Connect to Polymarket - API endpoints, authentication
  2. Find Markets - Search, filter, time-based pattern discovery
  3. Get Real-time Data - WebSocket usage and event types
  4. Access Order Books - Liquidity, bid/ask spreads, depth
  5. Place Orders - CLOB SDK, market/limit orders, decimal precision
  6. Market Mechanics - How 5-min markets work, winner determination, timing
  7. Known Pitfalls - Data reliability, timing issues, common bugs

This skill does NOT include:

  • ❌ Trading strategies
  • ❌ Signal analysis methodology

🏗️ Architecture Overview

API Components

Component URL Purpose Auth?
Gamma API https://gamma-api.polymarket.com Market info, prices, metadata No
CLOB API https://clob.polymarket.com Order books, trades, market structure No
CLOB Auth API https://clob-auth.polymarket.com JWT token for trading Yes
Data API https://data-api.polymarket.com Historical data, order books No
WebSocket wss://ws-subscriptions-clob.polymarket.com/ws/market Real-time price/book updates No

Data Flow for 5-Minute BTC Up/Down Markets

1. Generate timestamp → slug: btc-updown-5m-{timestamp}
2. Fetch market info from Gamma API → get asset IDs
3. Subscribe to WebSocket with asset IDs → real-time bid/ask
4. Place orders via CLOB SDK → buy UP or DOWN tokens
5. Market closes (5 min) → Polymarket resolves winner
6. Verify winner via Gamma API outcomePrices (1.0 = winner)

🔍 Finding Markets

5-Minute Markets — Timestamp Pattern

import time

def get_current_interval(interval_seconds=300):
    """Calculate current 5-minute interval timestamp"""
    current_time = int(time.time())
    return (current_time // interval_seconds) * interval_seconds

def generate_market_timestamps(num_markets=8):
    """Generate N market timestamps: current + next (N-1) intervals"""
    base = get_current_interval()
    return [base + i * 300 for i in range(num_markets)]

# Supported cryptos: btc, eth, sol, xrp
# Slug pattern: {crypto}-updown-5m-{timestamp}
# Example: btc-updown-5m-1772699400

API Search Methods

import requests

# By slug (most reliable for 5-min markets)
resp = requests.get("https://gamma-api.polymarket.com/markets", params={"slug": "btc-updown-5m-1772699400"})

# By keyword search
resp = requests.get("https://gamma-api.polymarket.com/markets", params={"_s": "bitcoin"})

# Active markets
resp = requests.get("https://gamma-api.polymarket.com/markets", params={"active": "true", "limit": 100})

🆔 Asset IDs (Token IDs)

Critical: Each outcome (UP/DOWN) has a unique asset ID required for WS subscriptions and trading.

Getting Asset IDs

import json

def get_asset_ids(market):
    """Get asset IDs from clobTokenIds field (preferred)"""
    clob_token_ids_str = market.get('clobTokenIds')
    if clob_token_ids_str:
        return json.loads(clob_token_ids_str)  # List of 2 IDs: [UP_ID, DOWN_ID]
    return []

Important:

  • clobTokenIds is a JSON string, not an array — must json.loads()
  • ✅ Index 0 = UP, Index 1 = DOWN (for btc-updown markets)
  • ⚠️ Fall back to tokens[].token_id only if clobTokenIds missing

📡 WebSocket — Real-time Data

Connection & Subscription

import aiohttp, asyncio, json, time

async def monitor_market(asset_ids):
    async with aiohttp.ClientSession() as session:
        ws = await session.ws_connect(
            "wss://ws-subscriptions-clob.polymarket.com/ws/market",
            heartbeat=None,
            timeout=aiohttp.ClientWSTimeout(ws_close=30.0)
        )
        # Subscribe
        await ws.send_json({
            "assets_ids": asset_ids,
            "type": "market",
            "custom_feature_enabled": True
        })
        # Heartbeat every 10 seconds
        last_ping = time.time()
        async for msg in ws:
            if msg.data == "PONG": continue
            if time.time() - last_ping >= 10:
                await ws.send_str("PING")
                last_ping = time.time()
            if msg.type == aiohttp.WSMsgType.TEXT:
                data = json.loads(msg.data)
                # Handle events...

⚠️ CRITICAL: Event Type Reliability

Event Type Description Reliability Use?
book Full orderbook snapshot ⭐⭐⭐ ✅ YES
best_bid_ask Best bid/ask update ⭐⭐⭐ ✅ YES
price_change Past trade records ❌ NO
last_trade_price Last trade price ❌ NO

🔥 Key Lesson: price_change = past trades, NOT current orderbook state. Using it as real-time bid/ask causes impossible states (ask \x3C bid). Only use book and best_bid_ask.

⚠️ CRITICAL: Book Event Structure

# ❌ WRONG: bids/asks are NOT under 'book' key
bids = data.get('book', {}).get('bids', [])  # EMPTY!

# ✅ CORRECT: bids/asks at TOP LEVEL
bids = data.get('bids', [])
asks = data.get('asks', [])

Order Book Fields

# Each bid/ask entry:
{
    'price': '0.4550',  # Price level (0-1)
    'size': '7270'      # Size in USD at this price
}

# Liquidity = sum of all bid sizes + sum of all ask sizes
total_liquidity = sum(float(b.get('size', 0)) for b in bids) + sum(float(a.get('size', 0)) for a in asks)

💰 Placing Orders — CLOB SDK

Authentication

from py_clob_client.client import ClobClient
from py_clob_client.clob_types import ApiCreds

host = "https://clob.polymarket.com"
chain_id = 137  # Polygon

client = ClobClient(host, key=key, chain_id=chain_id)
client.set_api_creds(ApiCreds(
    api_key="YOUR_API_KEY",
    api_secret="YOUR_API_SECRET",
    api_passphrase="YOUR_API_PASSPHRASE"
))

🔥 CRITICAL: Decimal Precision Rules

Amount Type Max Decimals Example
Maker amount (tokens) 4 10.7419
Taker amount (USD) 2 3.33
Price 4 0.3100

Rule: Calculate tokens FIRST, then derive USD

# ✅ CORRECT: Explicit precision control
raw_tokens = amount_usd / price           # e.g. 3.33 / 0.31 = 10.74193548
tokens = round(raw_tokens, 4)             # 10.7419 (max 4 decimals)
usd_amount = round(tokens * price, 2)     # 3.33 (max 2 decimals)
price_rounded = round(price, 4)           # 0.3100 (max 4 decimals)

# ❌ WRONG: Let SDK auto-calculate → may produce > 4 decimal tokens
# ❌ WRONG: Market order with SDK auto-calculation → same issue

Limit Order (Recommended — More Control)

from py_clob_client.order_builder.constants import BUY

order_args = OrderArgs(
    token_id=asset_id,
    price=price_rounded,    # 0.3100 (max 4 decimals)
    size=tokens,            # 10.7419 (max 4 decimals)
    side=BUY,
    expiration=0,           # GTC (Good Till Cancelled)
)
# A limit order at market price = instant fill with full precision control

Market Order (From Official Docs)

market_order = client.create_market_order(
    token_id="TOKEN_ID",
    side=BUY,
    amount=100,      # Dollar amount! SDK calculates tokens
    price=0.50,      # Slippage protection (can be 0)
    order_type=OrderType.FOK
)
client.post_order(market_order, OrderType.FOK)

Market Order Notes:

  • amount = USD amount (SDK calculates tokens internally)
  • price = slippage protection ceiling, NOT exact execution price
  • ⚠️ SDK may produce >4 decimal tokens → prefer limit orders for safety

⚠️ ALWAYS Read Official Docs Before Trading

Never guess API behavior — read docs first. Multiple failed versions were caused by not reading official documentation.


⏰ 5-Minute Market Mechanics

How Markets Work

  1. New market every 5 minutes — timestamp-based: btc-updown-5m-{unix_ts}
  2. Market duration: Exactly 5 minutes (300 seconds)
  3. Winner determination: Polymarket resolves based on BTC price movement during the 5-minute interval
    • UP wins → outcomePrices: UP=1.0, DOWN=0.0
    • DOWN wins → outcomePrices: UP=0.0, DOWN=1.0
  4. Market appears on Polymarket: ~30-60 seconds before interval start
  5. Orderbook becomes active: Shortly after market appears

Timing — What Happens When

Time Event
T-60s Market appears on Gamma API
T-30s Orderbook starts getting liquidity
T+0 5-minute interval starts
T+0 ~ T+30s Ask prices around 0.50, active trading
T+240s Most trading done, prices converge
T+300s Market closes
T+300s ~ T+360s Winner being resolved
T+360s+ Gamma API outcomePrices shows 1.0/0.0 (resolved)

⚠️ CRITICAL: Winner Resolution Timing

# ❌ WRONG: Fetch winner immediately after market close
# Gamma API returns trading prices (0.60/0.40), NOT resolved prices (1.0/0.0)
# Can take 60+ seconds to resolve

# ✅ CORRECT: Wait for outcomePrices to show 1.0/0.0
# After market close, poll Gamma API until resolved
# outcomePrices [1.00, 0.00] = UP winner confirmed
# outcomePrices [0.00, 1.00] = DOWN winner confirmed

📊 Data Reliability — What to Trust

Price Data Hierarchy

Data Source Use For Accuracy Latency
book (WS) Orderbook, bid/ask ⭐⭐⭐ Real-time
best_bid_ask (WS) Quick price check ⭐⭐⭐ Real-time
outcomePrices (Gamma) Market probability ⭐⭐ 5-30s delayed
outcomePrices (Gamma, resolved) Winner verification ⭐⭐⭐ 60s+ after close
price_change (WS) Past trades only N/A
best_bid_ask ask price Trading probability ⚠️ NOT true probability

⚠️ best_bid_ask Ask Price ≠ Market Probability

  • Ask price = lowest sell order in orderbook
  • This is not the market's consensus probability
  • It reflects orderbook dynamics, not market sentiment
  • All versions using ask price as probability showed ~50% accuracy

🔄 Market Rotation

Interval-Based Rotation (Correct Method)

def get_current_interval():
    """Get current 5-minute interval boundary"""
    current_time = int(time.time())
    return (current_time // 300) * 300

def should_rotate(current_interval, last_interval):
    """Check if we've entered a new interval"""
    return current_interval != last_interval

# ❌ WRONG: Time-based (rotates at wrong time)
# time_since_rotation = time.time() - last_rotation
# if time_since_rotation >= 300: rotate()  # Off by up to 15 seconds!

# ✅ CORRECT: Interval-based (rotates exactly when interval changes)
# if get_current_interval() != current_base_timestamp: rotate()

⚠️ Known Pitfalls & Lessons Learned

1. Never Use price_change as Orderbook Data

  • price_change = past trade records
  • BUY in price_change = someone bought at this price IN THE PAST
  • This is NOT the current best ask
  • Using it causes impossible states (ask \x3C bid)

2. Decimal Precision Will Break Your Orders

  • Maker amount (tokens): max 4 decimals
  • Taker amount (USD): max 2 decimals
  • Calculate tokens first, derive USD second
  • Never trust SDK auto-calculation
  • Use limit orders for full control

3. Read Official Docs Before Implementing

4. Winner Resolution Takes Time

  • Gamma API doesn't return 1.0/0.0 immediately after close
  • Poll until outcomePrices resolves to 1.0/0.0
  • Verify with Gamma API outcomePrices post-session

⚠️ Pitfall #5: Market Resolution Timing

  • Gamma API doesn't return 1.0/0.0 immediately after close
  • Can take 60+ seconds for outcomePrices to resolve
  • Poll until you see 1.0/0.0, don't assume immediate resolution

6. Market Appearance Timing is Variable

  • Markets don't always appear exactly 60s before start
  • Sometimes 30s, sometimes 90s
  • Fetch ask immediately when market appears — don't delay

7. Ask Price at Market Start ≈ 0.50

  • Fresh market ask is ~0.50 (fair odds)
  • Ask drifts quickly (within seconds) based on BTC movement
  • If you see ask = 0.99, market is already closed/ending

📚 API Reference

Gamma API Endpoints

Endpoint Method Description Auth?
/markets GET List/search markets No
/markets/{id} GET Get market by ID No
/markets?slug={slug} GET Get market by slug No
/markets/{id}/price GET Current prices No

WebSocket Events

Event Direction Reliable? Structure
book S→C bids[], asks[] at top level
best_bid_ask S→C best_bid, best_ask
price_change S→C Past trades, not orderbook
last_trade_price S→C Last trade, not orderbook

Rate Limits

API Limit Best Practice
Gamma API ~100 req/min Use WebSocket instead of polling
Data API ~50 req/min Cache responses
WebSocket No hard limit PING every 10s, batch subscriptions

🔧 CLOB SDK Quick Reference

from py_clob_client.client import ClobClient
from py_clob_client.clob_types import OrderArgs, OrderType, ApiCreds
from py_clob_client.order_builder.constants import BUY

# Initialize
client = ClobClient("https://clob.polymarket.com", key=key, chain_id=137)
client.set_api_creds(ApiCreds(api_key=..., api_secret=..., api_passphrase=...))

# Limit order (recommended)
order = OrderArgs(token_id=ASSET_ID, price=0.50, size=10.0, side=BUY, expiration=0)
# size = tokens (max 4 decimals), price (max 4 decimals)

# Market order
market_order = client.create_market_order(token_id=ASSET_ID, side=BUY, amount=100, price=0, order_type=OrderType.FOK)
# amount = USD, price = slippage ceiling

# Nonces: Must be unique per order. Use counter or UUID.

Official Documentation


📝 Version History

  • v2.0.0 (2026-03-23):

    • ✅ Added CLOB SDK trading section (limit/market orders, decimal precision)
    • ✅ Added 5-min market mechanics (timing, winner determination)
    • ✅ Added data reliability guide (what to trust, what not to)
    • ✅ Added known pitfalls section (7 critical lessons)
    • ✅ Added winner verification timing guide
    • ✅ Added winner verification timing guide
    • ✅ Added market rotation (interval-based vs time-based)
    • ✅ Updated WebSocket reliability table
    • ✅ Removed arbitrage scanner example (not applicable to 5-min markets)
  • v1.2.0 (2026-03-05):

    • ✅ Fixed WebSocket book event structure
    • ✅ Added real-time liquidity tracking
    • ✅ Added multi-cryptocurrency monitoring
  • v1.0.0 (2026-03-03):

    • Initial release
Usage Guidance
This package is coherent for Polymarket data access and trading, but it includes code that will derive API credentials from a wallet private key and place live orders. Before installing or running: 1) Never paste your real private key into code you haven't audited—prefer ephemeral/test keys or API tokens with limited scope. 2) Clarify whether you should supply private_key/wallet_address via environment variables or function arguments; avoid storing long-term secrets in plaintext in the skill folder. 3) Review requirements.txt and the py-clob-client package versions before pip install. 4) Run trading-capable code only in an isolated environment and consider disabling autonomous invocation or requiring explicit user approval when the agent would perform trades. 5) If a key is accidentally exposed, rotate it immediately. If you want just read-only data, use the public endpoints and avoid initializing the PolymarketClient with private keys.
Capability Analysis
Type: OpenClaw Skill Name: innotech-polymarket-api Version: 2.0.0 The 'innotech-polymarket-api' skill bundle is a well-documented and comprehensive guide for interacting with Polymarket APIs. It includes detailed instructions in SKILL.md for an AI agent to handle specific technical requirements, such as decimal precision for trading and correct WebSocket event parsing (e.g., handling bids/asks at the top level in 'lib/polymarket_ws.py'). The provided Python examples and library files (lib/polymarket_client.py) follow standard integration patterns for the Polymarket CLOB SDK and do not exhibit any signs of data exfiltration, malicious execution, or prompt injection. All network activity is directed toward legitimate Polymarket endpoints.
Capability Assessment
Purpose & Capability
The name/description (Polymarket API & CLOB) align with the included examples and libraries: market discovery, WebSocket realtime, orderbook analysis, and a trading client that uses the py-clob-client SDK. All external endpoints are Polymarket-related and there are no unrelated service credentials or binaries requested.
Instruction Scope
SKILL.md plus examples include live trading operations (CLOB SDK), deriving API credentials from a private key, and order placement. Those instructions stay within the declared domain (Polymarket) but they require handling sensitive secrets (private keys). The skill explicitly excludes trading strategies, but does include code that will perform actual trades if given keys and invoked.
Install Mechanism
No install spec in registry; this is an instruction+code bundle. Dependencies are Python packages (requirements.txt and import of py-clob-client). There are no downloads from untrusted URLs or archive extracts in the manifest. Installing via pip for the listed requirements is the expected mechanism.
Credentials
The registry declares no required env vars, but SKILL.md mentions optional POLYMARKET_API_KEY/POLYMARKET_API_SECRET and the library expects a wallet private_key and wallet_address to be supplied (constructor). Requesting a private key (or using an API key/secret) is proportionate for a trading client, but it is sensitive — the skill does not require tokens in env by registry, so secret handling is left to the user. The mapping between 'optional env vars' in docs and the lib's private_key parameter is slightly inconsistent and should be clarified.
Persistence & Privilege
always is false and the skill does not request elevated platform privileges or attempt to modify other skills. It can perform autonomous invocation (default), which is normal, but users should be aware that autonomous operation combined with trading-capable code increases risk if the agent has access to secrets.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install innotech-polymarket-api
  3. After installation, invoke the skill by name or use /innotech-polymarket-api
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v2.0.0
v2.0.0: Added CLOB SDK trading, 5-min market mechanics, data reliability guide, 7 known pitfalls, event reliability matrix, winner verification timing. Rewrote all references. Removed Binance-specific content.
v1.2.0
CRITICAL FIX: WebSocket book event structure (bids/asks at top level), Added real-time liquidity tracking with sizes, Multi-cryptocurrency monitoring (BTC/ETH/SOL/XRP), Clean output best practices, Fixed common data reading mistake
v1.1.0
Added: liquidity tracking, time-based market discovery, WebSocket guide, clobTokenIds documentation, order book access
v1.0.0
Initial release of innotech-polymarket-api skill. - Provides a comprehensive guide to connecting and accessing Polymarket API data. - Covers API endpoints, authentication, market search/filtering, and accessing market/order book/trade data. - Explains real-time data access via WebSocket and Socket.IO, with polling as a fallback. - Includes sample Python code snippets for common tasks. - Details market, price, and order book data structures. - Spells out best practices for data polling and API usage.
Metadata
Slug innotech-polymarket-api
Version 2.0.0
License MIT-0
All-time Installs 1
Active Installs 1
Total Versions 4
Frequently Asked Questions

What is Polymarket API Guide?

Polymarket API and data access guide. Learn how to connect, find markets, get real-time data via WebSocket, access order books, place orders via CLOB SDK, an... It is an AI Agent Skill for Claude Code / OpenClaw, with 389 downloads so far.

How do I install Polymarket API Guide?

Run "/install innotech-polymarket-api" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is Polymarket API Guide free?

Yes, Polymarket API Guide is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does Polymarket API Guide support?

Polymarket API Guide is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created Polymarket API Guide?

It is built and maintained by nwcalvin (@nwcalvin); the current version is v2.0.0.

💬 Comments