Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 

Repository files navigation

Polymarket Developer Cheatsheet

A single-page reference for everything Polymarket developers need — API endpoints, contract addresses, order struct, signing, V1 → V2 migration, SDK gotchas, and example requests.

Status V2

Last updated: April 18, 2026 (just before V2 cutover)


Table of contents


Endpoints

Purpose URL Auth
Gamma API (markets, events) https://gamma-api.polymarket.com none
Data API (positions, trades, PnL) https://data-api.polymarket.com none
CLOB production (V2 post-April-22) https://clob.polymarket.com HMAC
CLOB V2 staging https://clob-v2.polymarket.com HMAC

Chains & tokens

  • Chain: Polygon mainnet (chainId 137)
  • V1 collateral: USDC.e — 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174
  • V2 collateral: pUSD (ERC-20, 1:1 backed by USDC via CollateralOnramp.wrap())
  • Decimals: 6 (same as USDC on Polygon — amounts are scaled by 10⁶)

Contract addresses

V2 (April 22, 2026 onwards)

Contract Address
CTF Exchange (standard) 0xE111180000d2663C0091e4f400237545B87B996B
NegRisk CTF Exchange 0xe2222d279d744050d28e00520010520000310F59
Collateral Onramp TBD — check docs when published
pUSD TBD — check docs when published

V1 (legacy — stops after April 22, 2026)

Contract Address
CTF Exchange (standard) 0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E
NegRisk CTF Exchange 0xC5d563A36AE78145C45a50134d48A1215220f80a

V1 vs V2 quick diff

Item V1 V2
Python SDK py-clob-client py-clob-client-v2
TS SDK @polymarket/clob-client @polymarket/clob-client-v2
Exchange EIP-712 domain version "1" "2"
ClobAuth EIP-712 domain version "1" "1" (unchanged ⚠️)
Collateral USDC.e pUSD (wrap via onramp)
Order.nonce present removed (replaced by timestamp)
Order.expiration present removed
Order.taker present removed
Order.feeRateBps present removed (protocol-set)
Order.timestamp new (milliseconds)
Order.metadata new (bytes32)
Order.builder new (bytes32)
Builder attribution HMAC headers (POLY_BUILDER_*) signed builderCode field
Fee model embedded feeRateBps fee = C × feeRate × p × (1-p), protocol-set, taker-only
Constructor positional args options object, chainIdchain, tickSizeTtlMs removed

Gamma API

Base: https://gamma-api.polymarket.com — no auth required.

GET /events

List of active event aggregates (multiple markets per event).

curl "https://gamma-api.polymarket.com/events?active=true&closed=false&tag_slug=soccer&limit=50"

Query params:

  • active (bool) — only currently open events
  • closed (bool) — include closed/resolved
  • tag_slugsoccer, nba, nfl, crypto, politics, ufc, tennis, ...
  • limit (int, default 20, max 500)
  • offset (int) — paginate
  • orderstartDate, endDate, volume, liquidity
  • ascending (bool)

Key fields in response per event:

  • id, title, slug, negRisk, startDate, endDate, tags
  • markets[] — each with question, conditionId, clobTokenIds, outcomes, outcomePrices, bestBid, bestAsk, liquidityNum, volumeNum, spread, orderMinSize, orderPriceMinTickSize

GET /markets

Flat list of markets (not grouped by event):

curl "https://gamma-api.polymarket.com/markets?closed=false&limit=100"

CLOB API

Base: https://clob.polymarket.com — HMAC L2 auth required for most endpoints.

Required headers (V2)

POLY_ADDRESS:     <wallet 0x...>
POLY_TIMESTAMP:   <unix seconds>
POLY_API_KEY:     <from create_or_derive_api_creds>
POLY_PASSPHRASE:  <from create_or_derive_api_creds>
POLY_SIGNATURE:   <HMAC-SHA256(secret, timestamp + method + path + body)>

The POLY_BUILDER_* HMAC headers from V1 are removed in V2.

Public endpoints (no auth)

  • GET /book?token_id=<id> — full orderbook
  • GET /midpoint?token_id=<id> — mid price
  • GET /price?token_id=<id>&side=BUY|SELL — best price
  • GET /tick-size?token_id=<id> — minimum tick
  • GET /markets/{conditionId}/clobV2: returns mts, mos, fd, t, rfqe

Authenticated

  • POST /order — submit signed order
  • DELETE /order/{id} — cancel
  • DELETE /orders — cancel all
  • GET /orders — list open orders
  • GET /balance-allowance?asset_type=COLLATERAL — pUSD balance + exchange approval

Orderbook ordering gotcha

Polymarket returns:

  • bids in ASCENDING price order → best bid is bids[-1]
  • asks in DESCENDING price order → best ask is asks[-1]

Many bots silently assume bids[0] / asks[0] and compute the wrong midpoint.


Data API

Base: https://data-api.polymarket.com — no auth.

  • GET /trades?user=<wallet>&limit=50 — recent trades for a wallet
  • GET /positions?user=<wallet>&sizeThreshold=1 — current open positions
  • GET /value?user=<wallet> — PnL / net worth
  • GET /trades?limit=50 — recent trades across all users (public feed)

Returned trade fields: proxyWallet, side, asset (= tokenId), conditionId, size, price, timestamp, title, outcome, transactionHash.


Order struct (V2)

struct Order {
    uint256 salt;           // random uint256 for uniqueness
    address maker;          // wallet placing the order
    address signer;         // signer (= maker for EOA)
    uint256 tokenId;        // CLOB token (YES or NO)
    uint256 makerAmount;    // amount offered (6-decimals)
    uint256 takerAmount;    // amount expected (6-decimals)
    uint8   side;           // 0 = BUY, 1 = SELL
    uint8   signatureType;  // 0 = EOA, 1 = POLY_PROXY, 2 = POLY_GNOSIS_SAFE
    uint256 timestamp;      // ms (V2: replaces nonce)
    bytes32 metadata;       // V2: app-defined, zero by default
    bytes32 builder;        // V2: builderCode for attribution
}

For BUY orders

  • makerAmount = USD you're putting up (6-decimal USDC units)
  • takerAmount = shares you expect = makerAmount / price
  • side = 0

For SELL orders

  • makerAmount = shares you're selling
  • takerAmount = USD you expect = makerAmount × price
  • side = 1

EIP-712 domains

Exchange (for signing Orders) — version "2" in V2

{
  "name": "Polymarket CTF Exchange",
  "version": "2",
  "chainId": 137,
  "verifyingContract": "0xE111180000d2663C0091e4f400237545B87B996B"
}

NegRisk markets:

{
  "name": "Polymarket Neg Risk CTF Exchange",
  "version": "2",
  "chainId": 137,
  "verifyingContract": "0xe2222d279d744050d28e00520010520000310F59"
}

ClobAuth (for L1 API key derivation) — stays at version "1" in V2 ⚠️

{
  "name": "ClobAuthDomain",
  "version": "1",
  "chainId": 137
}

This is the single biggest pitfall in migrating — both domains have fields literally named version and it's easy to update the wrong one.


Signing flow

L1: API key derivation (one-time per wallet)

  1. Build a ClobAuth typed-data message (uses the ClobAuthDomain)
  2. Sign with wallet private key
  3. POST to /auth/api-key with signature → receive { api_key, api_secret, api_passphrase }
  4. Store these — use them for all subsequent L2 calls

L2: HMAC per request

prehash = timestamp + method.upper() + path + body_json
signature = hmac_sha256(api_secret, prehash).hex()

Attach as POLY_SIGNATURE header.

Order signing

  1. Build V2Order struct
  2. EIP-712 sign it against the Exchange domain (version "2"!)
  3. Submit to POST /order as {...orderFields, signature: "0x..."}

Fees

V2 formula:

fee = C × feeRate × p × (1 − p)

Where:

  • C = trade notional (collateral amount, in USDC units)
  • feeRate = per-market rate, fetched from getClobMarketInfo().fd.rate
  • p = execution price (between 0 and 1)
  • (1 − p) makes fee symmetric (highest at p=0.5, zero at extremes)

Makers pay no fees. Only takers.


Common pitfalls

  1. Domain version mixup — Exchange = "2", Auth = "1". Described above.
  2. Orderbook ordering — bids ASC, asks DESC. Use bids[-1] and asks[-1].
  3. 6-decimal scaling — amounts on-chain are scaled by 10⁶. $100 = 100_000_000.
  4. pUSD collateral — API traders must wrap USDC.e → pUSD themselves before placing V2 orders.
  5. Fee embedded in order — V1 had feeRateBps. V2 doesn't. Don't set it.
  6. Stale py-clob-client — stops working April 22. Install py-clob-client-v2.
  7. chainId constructor kwarg — renamed to chain in V2.
  8. Nonce vs timestamp — V2 uses millisecond timestamp, not nonce. Not interchangeable.
  9. Builder signing — V1 HMAC headers gone, embed builderCode in signed Order struct.
  10. NegRisk vs standard — separate exchange contracts + separate EIP-712 domains. Check event.negRisk to pick the right one.

SDK packages

Python

pip install py-clob-client-v2   # V2 (use this)
pip install py-clob-client      # V1 (stops April 22, 2026)

TypeScript

npm install @polymarket/clob-client-v2   # V2
npm install @polymarket/clob-client      # V1 (stops)

Deprecated in V2

  • @polymarket/builder-signing-sdk — no longer needed, builder attribution is in the signed Order

Useful links


Contributing

Found a gap, mistake, or new endpoint? PRs welcome. This is meant to be the reference, so completeness matters.

License

MIT / CC-BY-4.0 (code examples / prose).

About

Single-page developer reference: endpoints, contract addresses, order struct, EIP-712, V1 to V2 migration, fees, SDK packages

Topics

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors