API Reference & Integration

PolyBot communicates with Polymarket exclusively through the official CLOB (Central Limit Order Book) API. This page documents exactly how the integration works — from authentication to order placement to WebSocket streaming — so you can understand what the bot is doing under the hood and troubleshoot connectivity issues.

How PolyBot Uses the API

Every time PolyBot places a trade, the following sequence occurs:

  1. The strategy engine generates a signal (e.g. ML confidence > threshold).
  2. The risk management layer checks daily loss, position cap, and book depth guards.
  3. If all guards pass, PolyBot signs the order payload using your L2 API secret.
  4. A GTC (Good-Till-Cancelled) limit order is posted to POST /order on the CLOB.
  5. PolyBot subscribes to your order's WebSocket channel and waits for a fill confirmation.
  6. If the order isn't filled within fill_timeout_seconds, it is cancelled and retried at the new market price (up to fill_retry_max times).
  7. On bot shutdown, all open orders are cancelled via DELETE /orders before the process exits.

In Paper Mode and Dry-Run Mode, steps 3–7 are fully bypassed — the bot logs what it would have done without touching any real order endpoints.

Getting Your API Credentials

Polymarket uses a two-layer authentication system. Your L1 wallet (MetaMask / WalletConnect) proves ownership of your funds. Your L2 API key is a separate ephemeral keypair that authorises individual API requests without exposing your wallet's private key.

1
Navigate to polymarket.com and connect your wallet. Make sure you're on the Polygon network and have completed any required KYC steps for your region.
2
Open your profile menu (top right) and click "API Keys" or navigate directly to polymarket.com/profile/api-keys.
3
Click "Generate New Key". Polymarket will ask you to sign a message with your wallet (this does not spend gas). This generates your L2 keypair.
4
Copy all three values that appear. They are shown only once — store them in your password manager immediately.
FieldDescriptionExample Format
api_key Public identifier for your L2 key. Used in the POLY-API-KEY header. a1b2c3d4-e5f6-... (UUID format)
api_secret Private key used to sign request payloads. Never share this. ABC123xyz... (base64, 44 chars)
passphrase Additional authentication factor required on every signed request. Alphanumeric string you set at creation
Security Warning: Your api_secret and passphrase should never be committed to Git, shared in Discord, or sent to any third party including PolyBot support. PolyBot never asks for your credentials — all keys are stored locally in your encrypted config.yml.

The CLOB API

The Polymarket CLOB is a centralised matching engine that settles trades on-chain on Polygon. PolyBot interacts with two surfaces:

Base URLs

# REST API
https://clob.polymarket.com

# WebSocket
wss://ws-subscriptions-clob.polymarket.com/ws/

Key REST Endpoints

MethodEndpointPolyBot Uses It For
GET /markets Fetching all active markets for strategy scanning
GET /book?token_id={id} Reading live order book depth for liquidity guards
POST /order Placing GTC limit orders (signed L2 request)
GET /orders?maker_address={addr} Fetching open orders for fill status checks
DELETE /order/{orderId} Cancelling individual unfilled orders
DELETE /orders Cancel-all on graceful bot shutdown
GET /trades?maker_address={addr} Pulling fill history for P&L tracking and retraining

Order Flow

All orders placed by PolyBot are GTC (Good-Till-Cancelled) limit orders. Market orders are not used — they would expose the bot to unbounded slippage, especially in thin books. Instead, PolyBot places the order at the current best ask (for buys) or best bid (for sells) and waits for a fill.

# Internal order construction (simplified)
{
  "order": {
    "salt":         1718000000123,
    "maker":        "0xYourWalletAddress",
    "signer":       "0xYourL2SignerAddress",
    "taker":        "0x0000000000000000000000000000000000000000",
    "tokenId":      "91234567890...",    # YES token ID for this market
    "makerAmount":  "50000000",          # 50 USDC (6 decimal USDC)
    "takerAmount":  "97087378",          # Amount of YES tokens at ~0.515
    "expiration":   "0",                 # GTC — no expiry
    "nonce":        "0",
    "feeRateBps":   "100",               # 1% fee in basis points
    "side":         "BUY",
    "signatureType": 0
  },
  "signature": "0x...",
  "owner": "0xYourL2SignerAddress"
}

Fill Retry Logic

If an order is not filled within fill_timeout_seconds (default: 45s), PolyBot cancels it and re-evaluates whether the signal is still valid. If the strategy still fires, a new order is placed at the updated book price. This continues up to fill_retry_max (default: 3) attempts before the signal is abandoned.

global:
  fill_timeout_seconds: 45   # Cancel unfilled orders after 45s
  fill_retry_max: 3           # Max re-attempts per signal
  fill_retry_delay_seconds: 5 # Wait 5s between retry attempts

WebSocket Subscriptions

PolyBot maintains two persistent WebSocket connections during operation:

1. Price Feed Subscription

Subscribes to real-time price updates for all markets being actively monitored. PolyBot uses this to update the feature vector for the ML model between REST API polls and to detect mid-window price spikes that may trigger Multi-Entry.

# Price feed subscription message (sent on connect)
{
  "auth": {
    "apiKey":     "your-api-key",
    "secret":     "your-api-secret",
    "passphrase": "your-passphrase"
  },
  "type": "Market",
  "markets": ["0xMarketConditionId1", "0xMarketConditionId2"]
}

2. User Order Subscription

Subscribes to fill events for PolyBot's own open orders. When a fill event arrives, PolyBot immediately updates its internal position tracker, records the fill price and size, and notifies the risk management layer.

# User order subscription (authenticated)
{
  "auth": {
    "apiKey":     "your-api-key",
    "secret":     "your-api-secret",
    "passphrase": "your-passphrase"
  },
  "type": "User",
  "markets": []   # Empty = subscribe to all your orders
}

If either WebSocket connection drops, PolyBot attempts reconnection with exponential backoff (1s, 2s, 4s, 8s… up to 60s). If reconnection fails after 5 attempts, a Telegram alert is sent and the bot enters a safe hold state — no new trades until the connection is restored.

Rate Limits

Polymarket's CLOB API enforces the following rate limits. PolyBot is designed to stay comfortably within them under normal operation.

Limit TypeValueHow PolyBot Handles It
REST requests 10 req/s sustained Internal token bucket limiter; queues excess requests
Order placement burst 20 orders/s Multi-Entry orders are batched with 50ms delay between each
WebSocket messages No published limit Subscriptions are batched; single WS per surface
Cancel requests 5 req/s Shutdown cancel-all is throttled to 4 req/s
429 Too Many Requests: If PolyBot encounters a 429 response, it backs off for 2 seconds and retries. Persistent 429 errors are logged with a warning but do not halt the bot — they simply delay the next API call.

Snipe Mode's edge comes from reading the Chainlink BTC/USD price feed directly from the Polygon blockchain — the same feed Polymarket uses to resolve BTC price markets. This is an on-chain read, not an API call, so it is not subject to CLOB rate limits.

# Chainlink BTC/USD Feed on Polygon
Feed Address:  0xc907E116054Ad103354f2D350FD2514433D57F6f
Interface:     AggregatorV3Interface
Function:      latestRoundData()
Returns:       (roundId, answer, startedAt, updatedAt, answeredInRound)

# PolyBot reads the feed via eth_call (no gas required)
# answer is the price in 8 decimal places
# e.g. answer = 6750000000000 → BTC = $67,500.00

PolyBot polls the Chainlink feed once every 5 seconds during the final 60 seconds of each 15-minute window. If the feed price diverges from the current CLOB mid-price by more than the configured min_edge_pct, Snipe Mode fires a trade on the correctly-priced side.

fifteenm_bot:
  chainlink:
    rpc_url: "https://polygon-rpc.com"   # Or your own Polygon RPC
    feed_address: "0xc907E116054Ad103354f2D350FD2514433D57F6f"
    poll_interval_seconds: 5
    confirmation_blocks: 1               # Read after 1 block confirmation

Docker Compose Environment Variables

The recommended way to supply API credentials to PolyBot is via Docker Compose environment variables. This keeps secrets out of your config.yml and makes it easy to rotate keys without editing multiple files.

# docker-compose.yml
version: "3.9"

services:
  polybot-copy:
    image: polybot/copy-bot:latest
    container_name: polybot_copy
    restart: unless-stopped
    environment:
      - POLY_API_KEY=${POLY_API_KEY}
      - POLY_API_SECRET=${POLY_API_SECRET}
      - POLY_PASSPHRASE=${POLY_PASSPHRASE}
      - POLY_CHAIN_ID=137                    # 137 = Polygon mainnet
      - POLY_WALLET_ADDRESS=${WALLET_ADDRESS}
      - TELEGRAM_BOT_TOKEN=${TG_BOT_TOKEN}
      - TELEGRAM_CHAT_ID=${TG_CHAT_ID}
    volumes:
      - ./config.yml:/app/config.yml:ro
      - ./data:/app/data

  polybot-15m:
    image: polybot/15m-trader:latest
    container_name: polybot_15m
    restart: unless-stopped
    environment:
      - POLY_API_KEY=${POLY_API_KEY}
      - POLY_API_SECRET=${POLY_API_SECRET}
      - POLY_PASSPHRASE=${POLY_PASSPHRASE}
      - POLY_CHAIN_ID=137
      - POLY_WALLET_ADDRESS=${WALLET_ADDRESS}
      - POLYGON_RPC_URL=${POLYGON_RPC_URL}    # For Chainlink reads
      - TELEGRAM_BOT_TOKEN=${TG_BOT_TOKEN}
      - TELEGRAM_CHAT_ID=${TG_CHAT_ID}
    volumes:
      - ./config.yml:/app/config.yml:ro
      - ./data:/app/data
# .env file (same directory as docker-compose.yml)
# Never commit this file to Git — add .env to .gitignore

POLY_API_KEY=a1b2c3d4-e5f6-7890-abcd-ef1234567890
POLY_API_SECRET=YourBase64EncodedSecretHere==
POLY_PASSPHRASE=YourPassphraseHere
WALLET_ADDRESS=0xYourPolygonWalletAddress
POLYGON_RPC_URL=https://polygon-rpc.com
TG_BOT_TOKEN=123456789:ABCdefGHIjklMNOpqrsTUVwxyz
TG_CHAT_ID=-1001234567890
# Start both bots
docker compose up -d

# Check running containers
docker compose ps

# View live logs for 15M bot
docker compose logs -f polybot-15m

# Restart a single service after config change
docker compose restart polybot-copy

Security Best Practices

Note: PolyBot support will never ask for your api_secret or passphrase. If someone in Discord or Telegram claiming to be PolyBot support requests your credentials, it is a scam.

Troubleshooting API Issues

401 Unauthorized — Invalid Key

The most common error. Causes and fixes:

403 Forbidden — Wrong Chain ID

Ensure POLY_CHAIN_ID=137 for Polymarket mainnet. Using 80001 (Mumbai testnet) will result in 403 errors as PolyBot attempts to authenticate against production endpoints.

API Key Expires Mid-Session

L2 keys do not have a time-based expiry, but Polymarket may invalidate them if unusual activity is detected. PolyBot detects a 401 during an active session and immediately sends a Telegram alert with the message "API key invalidated — re-generate and update .env". No trades will be placed until the bot is restarted with valid credentials.

Connection Timeouts to CLOB

If your server is in a restricted region, CLOB requests may time out. Use a VPN or a VPS in an allowed jurisdiction. Check Polymarket's terms for the list of restricted regions.

# Test CLOB connectivity from your server
curl -s https://clob.polymarket.com/markets?limit=1 | python3 -m json.tool

# Expected: JSON with market data
# If timeout: check firewall rules and jurisdiction restrictions

Next Steps