polymarket

Installation
SKILL.md

Polymarket

End-to-end playbook for Polymarket through OpenFinance — research, pricing, order placement, approvals, and user data.

Prerequisite (for trading; data endpoints are public)

  1. User completed openfinance-setup (API key + EVM wallet delegation).
  2. Approvals in place — GET /agent/polymarket/approvals to check, POST /agent/polymarket/approvals to set any missing. One-time gas cost.
  3. Wallet holds MATIC on Polygon for gas and USDC.e (not native USDC) for trading.

Research endpoints (public, no auth)

Events (Gamma API)

Events group related prediction markets — e.g. one "2024 US Election" event contains separate candidate markets.

  • GET /agent/polymarket/events — Browse events from the world's largest prediction market. Returns a list with metadata, outcomes, volumes, and current status. Optional query params: limit, offset, active (ongoing), closed (finished), archived (historical), order (e.g. desc), ascending, slug, tag_id. Use for sports betting odds (IPL, FIFA, NBA, NFL, F1, UFC, cricket, football), political predictions (elections, policy, government), crypto/finance forecasts, entertainment, or any trending real-world event.
  • GET /agent/polymarket/events/:eventId — Single event by ID. Returns metadata, market information, outcomes, volume, liquidity, current probabilities.
  • GET /agent/polymarket/events/slug/:slug — Same as above, looked up by URL slug.
  • GET /agent/polymarket/events/:eventId/volume — Real-time trading volume for the event. Useful for gauging attention / money flow on a sports match, election, or trending topic.

Markets

  • GET /agent/polymarket/markets — List prediction markets with current prices (implied probabilities), volumes, liquidity, and outcome details. Use to browse for sports, politics, crypto, entertainment, trending events. Optional filters: limit, offset, active, closed, slug, market_id, token_id, condition_id, tag_id, liquidity_min, volume_min, start_date_min, start_date_max, end_date_min, end_date_max.
  • GET /agent/polymarket/markets/:marketId — Single market by numeric ID. Returns prices, orderbook depth, volume, liquidity, outcome details.
  • GET /agent/polymarket/markets/slug/:slug — Same by URL slug.
  • GET /agent/polymarket/markets/cid/:conditionId — Same by on-chain CTF condition ID (bytes32 hex). Useful when you already have the condition ID from a user's position.

Every market response contains:

  • condition_id — on-chain CTF condition identifier
  • tokens — YES/NO outcome tokens with their token_ids
  • min_tick_size — required for correct tickSize on orders
  • neg_risk — if true, pass negRisk: true on orders and approvals

Search

  • GET /agent/polymarket/public-search?q=<query> — Search across all events and markets by keyword. Returns matching entries with relevance scoring. Use when the user names a topic — "IPL winner", "FIFA World Cup", "US elections", "Bitcoin price", "Trump", "Modi", "Champions League" — or any trending event, to find betting odds and probabilities on real-world outcomes.

Pricing (CLOB API)

  • GET /agent/polymarket/orderbook/:tokenId — Current orderbook (bids and asks) for a specific outcome token. Returns arrays of buy and sell orders at different price levels with sizes and depths. Use to see market liquidity and available prices before placing an order.
  • POST /agent/polymarket/orderbooks body {tokenIds: [...]} — Same as above but for multiple tokens in a single request. Returns a map of tokenId → orderbook. More efficient than many individual calls.
  • GET /agent/polymarket/price/mid/:tokenId — Mid price for a token, representing the market-implied probability (0, 1). Use to check "what are the odds" or "what is the probability" of an outcome.
  • GET /agent/polymarket/price/:tokenId?side=BUY — Best BUY or SELL price for the token. side query param is required: BUY or SELL.
  • GET /agent/polymarket/prices — Mid prices for every active outcome token. Returns a map of token ID → probability. Use for scanning odds across all active markets at once.
  • GET /agent/polymarket/spread/:tokenId — Bid-ask spread for the token (best ask − best bid). Tight spread = good liquidity; wide = thin book.
  • GET /agent/polymarket/last-trade-price/:tokenId — Price of the most recent executed trade for the token.
  • GET /agent/polymarket/trades/:marketSlug (?limit=50&offset=0) — Recent trade tape for a market (by slug). Returns trades with prices, sizes, timestamps, and side (buy/sell). Use to analyze betting activity and see how odds are shifting.

Market data (Data API)

  • GET /agent/polymarket/market/:conditionId/open-interest — Total value locked in the market. Returns capital committed to each outcome and overall market size.
  • GET /agent/polymarket/market/:marketId/volume — Historical + current volume statistics for the market.
  • GET /agent/polymarket/market/:marketId/liquidity — Current and historical liquidity depth.
  • GET /agent/polymarket/market/:marketId/trades (?limit=50) — Detailed trade history with metadata (fuller shape than the CLOB /trades endpoint).

User data (public, address-scoped)

:address = user's Polygon EVM address (their Privy EVM wallet address).

  • GET /agent/polymarket/user/:address/positions — Active positions held by the user. Returns outcome tokens, quantities, entry prices, current values, and unrealized PnL per position.
  • GET /agent/polymarket/user/:address/trades (?limit=50&offset=0) — Trade history with prices, sizes, timestamps, markets, outcomes. Use to analyze trading patterns and performance.
  • GET /agent/polymarket/user/:address/portfolio — Full portfolio overview: total value, all positions, realized/unrealized PnL, win rate, performance metrics.
  • GET /agent/polymarket/user/:address/pnl — Standalone PnL stats: realized, unrealized, total, historical performance.

Trading endpoints

All require x-api-key: open_…. Signing is EIP-712 with the caller's Privy-backed Polygon wallet; first call per user derives and caches the Polymarket L2 API credentials server-side.

Placing orders

  • POST /agent/polymarket/order — Place a limit order (GTC or GTD) on the Polymarket CLOB. Body fields:

    {
      "tokenID": "...",          // CLOB outcome asset ID (NOT market/condition ID)
      "price": 0.42,             // probability 0.0–1.0
      "size": 10,                // conditional token units
      "side": "BUY",             // "BUY" | "SELL"
      "orderType": "GTC",        // default "GTC"; "GTD" requires expiration
      "tickSize": "0.01",        // default "0.01"; some markets need "0.001" / "0.0001"
      "negRisk": false,          // true for multi-outcome neg-risk markets
      "postOnly": false,         // only accept if maker (reject if marketable)
      "expiration": 1735689600   // Unix seconds, required when orderType = "GTD"
    }
    

    Returns the order ID and posting status. Use for user prompts like "buy 10 shares at 0.42" or "place a resting bid at X".

  • POST /agent/polymarket/order/market — Place a market order (FOK or FAK). For BUY, amount is USDC to spend; for SELL, amount is shares to sell.

    {
      "tokenID": "...",
      "amount": 10,              // BUY: USDC to spend · SELL: shares to sell
      "side": "BUY",
      "price": 0.42,             // optional cap; omit for pure market
      "orderType": "FOK",        // default "FOK" (all-or-nothing) | "FAK" (fill-and-kill)
      "tickSize": "0.01",
      "negRisk": false
    }
    

    Use for "buy now" intents. FOK fails if full size can't fill; FAK fills what it can and cancels the rest.

  • POST /agent/polymarket/orders — Post multiple limit orders in one batch. Each order is individually signed then posted together. Body: {orders: [ { tokenID, price, size, side, orderType?, tickSize?, negRisk?, expiration? }, ... ], postOnly?: boolean}. Use for ladder-quoting.

Reading orders

  • GET /agent/polymarket/order/:orderId — Get a single order by ID. Returns full order record.
  • GET /agent/polymarket/orders (?id=&market=&asset_id=) — Get all open orders for the authenticated user. Optional filter by id, market (condition_id), or asset_id (token_id).
  • GET /agent/polymarket/order/:orderId/scoring — Check whether an order is currently scoring for Polymarket liquidity rewards. Returns scoring status.

Cancelling orders

  • DELETE /agent/polymarket/order/:orderId — Cancel a single open order by order ID.
  • DELETE /agent/polymarket/orders body {orderHashes: [...]} — Cancel multiple orders by their on-chain order hashes (batch).
  • DELETE /agent/polymarket/orders/all — Cancel every open order for the authenticated user (nuke).
  • DELETE /agent/polymarket/orders/market body {market, asset_id} — Cancel all open orders on a given market (condition_id) or asset (token_id).

Approvals (one-time, on-chain)

Before any trading, USDC.e + CTF must be approved to Polymarket contracts. The backend handles USDC.e (not pUSD/native USDC) and the V1 exchange + conditional tokens spenders.

  • GET /agent/polymarket/approvals (?negRisk=true) — Read current on-chain allowances for Polymarket exchange contracts. Call before trading to confirm the wallet has approved USDC.e + CTF movement. Returns one entry per (token, spender) pair with approved: boolean. Pass negRisk=true to also include NegRiskAdapter/NegRiskExchange approvals — required if trading multi-outcome markets.
  • POST /agent/polymarket/approvals body {negRisk?: boolean} — Submit approval transactions for any missing allowance. Idempotent — only approves what's missing. Returns per-entry status with tx hashes for newly-submitted approvals. User's wallet pays MATIC gas on Polygon.

Builder attribution (optional)

If POLYMARKET_BUILDER_CODE is set in backend env, orders are auto-tagged for fee attribution. Builder registration is an off-chain onboarding with Polymarket — fees only flow once they've onboarded your code. Until then, tagging is a no-op (but harmless).

  • POST /agent/polymarket/builder/api-key — Create a builder API key tied to the caller's wallet. Returns key/secret/passphrase used to earn attribution fees on orders posted with your builder code.
  • GET /agent/polymarket/builder/api-keys — List the caller's builder API keys.
  • DELETE /agent/polymarket/builder/api-key — Revoke the caller's builder API key.
  • GET /agent/polymarket/builder/trades (?taker=&maker=&market=&asset_id=&next_cursor=) — List trades attributed to this backend's configured builder code. Requires POLYMARKET_BUILDER_CODE set server-side.

Pick the right order type

Route / type When to use
/order (GTC) "Buy X shares at Y" — resting limit until fill or cancel
/order (GTD) Same but auto-cancels at expiration
/order/market (FOK) "Buy now" all-or-nothing fill
/order/market (FAK) Best-effort fill, cancel rest
/orders batch Ladder quoting — multiple price levels atomically

Required parameters

Param What Gotchas
tokenID CLOB outcome asset ID Different from market/condition ID. One per YES/NO side. Read from market's tokens array.
price Probability as decimal 0.0–1.0 0.42 = 42¢. NOT 42 or "42%".
size (limit) Conditional token units USDC spend ≈ size * price.
amount (market) Side-dependent BUY: USDC to spend. SELL: shares.
side "BUY" or "SELL" Case-sensitive.
tickSize Min price increment Default 0.01. Some markets need 0.001 or 0.0001. Wrong tick → 400.
negRisk Multi-outcome market flag Check market metadata; also set {negRisk: true} on approvals.

Pricing conventions

  • Prices are probabilities, range (0, 1). "YES at 23¢" → price: 0.23.
  • YES and NO are separate tokens. Buying YES at 0.23 ≈ selling NO at 0.77.
  • Min tick caps precision. Book at 0.2300 on a 0.01-tick market rejects 0.2305.
  • Implied payoff: BUY YES at 0.23 pays $1 if event resolves YES → ~4.3x.
  • Bid/ask spread signals liquidity: tight on low-volume means market makers; wide means thin book.

Neg-risk markets

Multi-outcome events where outcomes sum to ≤ 100% (not exactly 100%) use the neg-risk adapter. Typical: elections with multiple candidates. Check neg_risk: true on the market metadata.

If neg-risk:

  • Pass negRisk: true in order calls
  • Set approvals with {negRisk: true} — the adapter is a separate spender

Size / notional minimums

~$1 USDC minimum notional. price=0.05, size=10 = $0.50 → rejected. Bump size so price * size >= 1.


Research → trade workflow

  1. GET /agent/polymarket/public-search?q=<topic> — find events
  2. GET /agent/polymarket/events/:eventId — pick a market within the event
  3. Extract token_id for the outcome (YES/NO) you want
  4. GET /agent/polymarket/orderbook/:tokenId — check liquidity + spread
  5. GET /agent/polymarket/price/mid/:tokenId — reference price
  6. Note min_tick_size and neg_risk from market metadata
  7. GET /agent/polymarket/approvals — confirm approvals, set if missing
  8. POST /agent/polymarket/order (or /order/market) — place

Don't

  • Don't ask the user for their private key or Privy credentials; signing is server-side via the delegated wallet.
  • Don't call POST /approvals before every trade — it's gas. Only after GET /approvals shows missing entries.
  • Don't use market orders for speculative entries where slippage matters — use an aggressive limit across the spread.
  • Don't confuse market ID (one per event) with token ID (one per outcome). Orders need tokenID.
  • Don't assume negRisk: false for markets with multiple candidates — check metadata.

MCP note

Same endpoint → tool mapping: polymarket_get_events, polymarket_get_markets, polymarket_search, polymarket_get_orderbook, polymarket_get_user_portfolio, polymarket_place_order, polymarket_place_market_order, polymarket_cancel_order, polymarket_set_approvals, etc.

Related skills

More from openfinance-tech/skills

Installs
5
First Seen
9 days ago