TL;DR: Polymarket now has two completely separate APIs — the Global crypto-native API on Polygon and the new US CFTC-regulated API launched February 16, 2026. They use different authentication (EIP-712 vs. Ed25519), different SDKs (py-clob-client vs. polymarket-us), different endpoint structures, and different account models. This guide maps every difference side by side, shows equivalent code for both, and provides a pattern for building agents that trade across both platforms.

Why This Guide Exists

On February 16, 2026, Polymarket launched public APIs and SDKs for its US-regulated platform. This created a problem nobody had before: two Polymarket APIs that look superficially similar but are architecturally incompatible.

If you built a bot on the Global Polymarket API using py-clob-client, none of that code works on Polymarket US. The authentication is different. The SDKs are different. The order format is different. The account structure is different. Even the way you identify markets is different.

As of March 2026, no official migration guide exists. The Polymarket docs cover each API independently, but never compare them. Developers are left reading two separate doc sites, two separate GitHub repos, and piecing together the differences through trial and error.

This guide fixes that. Every section maps Global ↔ US equivalents so you can port your bot, choose the right platform, or build an agent that trades on both.

Platform Overview: Two Polymarkets

Before diving into the API layer, understand what you’re building on.

Polymarket Global is the original platform. It runs on the Polygon blockchain. Your account is an Ethereum wallet. Trades settle on-chain as conditional token transfers. Collateral is USDC on Polygon. There is no KYC for users outside restricted jurisdictions. It is the highest-volume prediction market in the world.

Polymarket US is the regulated counterpart. It operates as a CFTC-designated contract market (DCM) after Polymarket acquired QCX LLC in 2025. Your account requires full KYC (government ID, SSN, proof of address via the iOS app). It uses fiat rails with USDC.e. Positions are held within the regulated exchange, not as on-chain tokens you control in your wallet.

DimensionPolymarket GlobalPolymarket US
Regulatory statusCrypto-native, offshoreCFTC-regulated DCM
KYC requiredNo (outside restricted jurisdictions)Yes — ID, SSN, proof of address
CollateralUSDC on PolygonUSDC.e + POL for gas (EOA)
SettlementOn-chain conditional tokens (ERC-1155)Exchange-internal
Account modelEthereum wallet + proxy addressKYC-verified account + developer portal
Geographic accessGlobal minus 33 restricted countriesUS only (all 50 states)
Launched2020 (API matured 2023–2025)Feb 16, 2026 (public API)
LiquidityShared global poolSeparate US liquidity pool

The critical implication for agent builders: these are separate liquidity pools with separate order books. The same event may trade at different prices on Global vs. US. This creates arbitrage opportunities — but also means you cannot move positions between them.

For a full comparison of Polymarket against Kalshi and other platforms, see the Prediction Market API Reference.

Authentication: The Biggest Difference

Authentication is where most developers get stuck. The two platforms use fundamentally different cryptographic models.

Global API: Two-Level EIP-712 + HMAC

The Global Polymarket CLOB API uses a two-level authentication system rooted in Ethereum wallet cryptography.

Level 1 (L1) — Wallet Signature: You sign an EIP-712 typed data message with your Ethereum private key. This proves wallet ownership and is used to create or derive API credentials.

Level 2 (L2) — HMAC-SHA256: The L1 step generates three values: apiKey, secret, and passphrase. These are used as HMAC-SHA256 credentials for all subsequent trading requests. Five HTTP headers (POLY_ADDRESS, POLY_SIGNATURE, POLY_TIMESTAMP, POLY_NONCE, POLY_API_KEY) must accompany every authenticated request.

Even with L2 headers, order placement still requires signing the order payload with your private key. The auth is non-custodial — Polymarket never holds your key.

# Global API — Authentication with py-clob-client
from py_clob_client.client import ClobClient
import os

client = ClobClient(
    host="https://clob.polymarket.com",
    chain_id=137,  # Polygon mainnet
    key=os.getenv("PRIVATE_KEY"),  # Ethereum private key (0x...)
)

# L1 → L2: Create or derive API credentials
creds = client.create_or_derive_api_creds()
client.set_api_creds(creds)
# creds = { "apiKey": "...", "secret": "...", "passphrase": "..." }

Common failure modes on Global auth: proxy wallet not deployed (user never logged into polymarket.com), nonce mismatch when re-deriving credentials, and timestamp drift causing intermittent 401 errors. See the Security Best Practices guide for key management patterns.

US API: Single-Level Ed25519

Polymarket US uses Ed25519 keypair authentication — the same cryptographic primitive used by Solana, SSH, and many modern APIs. No blockchain wallet involved.

You generate an Ed25519 keypair from the Polymarket US developer portal (polymarket.us/developer) after completing KYC on the iOS app. The SDK signs every request automatically with your private key. There is no two-level system and no separate order signing step.

# US API — Authentication with polymarket-us
from polymarket_us import PolymarketUS
import os

client = PolymarketUS(
    key_id=os.getenv("POLYMARKET_US_KEY_ID"),       # UUID
    secret_key=os.getenv("POLYMARKET_US_SECRET"),    # Base64-encoded Ed25519 private key
)

The private key is shown exactly once at generation. If you lose it, you generate a new keypair. There is no derivation or recovery mechanism.

Auth Comparison Table

AspectGlobal APIUS API
Cryptographic schemeEIP-712 (Ethereum typed data) + HMAC-SHA256Ed25519
Key sourceEthereum private key (wallet)Developer portal keypair
LevelsL1 (wallet sig) → L2 (API creds)Single level
Headers required5 (POLY_*) for tradingSDK handles signing automatically
Order signingSeparate step — private key signs order payloadSDK signs requests; no separate order signing
Key recoveryDerive from same private key + nonceNot recoverable — regenerate
Credential formatapiKey + secret + passphrasekey_id (UUID) + secret_key (Base64 Ed25519)

SDKs: Which Library to Use

Each platform has its own official SDKs. They are not interchangeable.

Global API SDKs

  • Python: py-clob-client — the mature, battle-tested library. Handles L1/L2 auth, order building, signing, and submission. Requires eth-account for wallet operations.
  • TypeScript: @polymarket/clob-client — equivalent TypeScript client using ethers.js (v5).
  • Rust: polymarket-rs — newer Rust client for performance-sensitive use cases.
  • Community: polymarket-apis — third-party unified client wrapping Gamma, CLOB, Data, WebSocket, and GraphQL endpoints with Pydantic validation. Updated March 6, 2026.

For a full breakdown of py-clob-client methods, see the py_clob_client Reference.

US API SDKs

  • Python: polymarket-us — official SDK. Requires Python 3.10+. Supports sync and async (AsyncPolymarketUS). Released February 2026.
  • TypeScript: polymarket-us — official TypeScript/Node SDK. Requires Node 18+. Same resource-oriented design as the Python SDK.

SDK Design Philosophy Comparison

The SDKs reflect fundamentally different design choices.

py-clob-client is low-level and crypto-native. You manage wallet keys, sign orders explicitly, construct order args with token IDs, and interact with the Polygon blockchain. It exposes the raw CLOB mechanics.

polymarket-us is high-level and REST-native. It uses a resource-oriented design (client.orders.create(...), client.events.list(...)) similar to Stripe’s SDK pattern. No blockchain concepts. Markets are referenced by slug, not token ID. The SDK handles all cryptographic signing internally.

# Equivalent: Fetch markets

# Global (py-clob-client) — uses Gamma API for market data
import requests
markets = requests.get(
    "https://gamma-api.polymarket.com/markets",
    params={"active": "true", "limit": 10, "order": "volume24hr", "ascending": "false"}
).json()

# US (polymarket-us) — integrated market endpoint
from polymarket_us import PolymarketUS
client = PolymarketUS()
markets = client.markets.list({"limit": 10})

API Architecture: Split vs. Unified

Global: Three APIs + WebSocket

The Global Polymarket API is split across three distinct services, each with its own base URL:

  • Gamma API (gamma-api.polymarket.com) — Market metadata, event listings, search, categories. Read-only. No auth required.
  • CLOB API (clob.polymarket.com) — Order book, pricing, order placement, cancellation. L2 auth required for trading endpoints.
  • Data API (data-api.polymarket.com) — User positions, trade history, portfolio data. Auth required.
  • WebSocket (ws-subscriptions-clob.polymarket.com) — Real-time price, order book, and user channel streams.

This separation means building a Global bot requires calling at least two different API services. You query Gamma for market discovery, then switch to CLOB for pricing and execution.

US: Unified REST + WebSocket

The Polymarket US API is a single unified service with 23 REST endpoints and 2 WebSocket endpoints, organized into five resource groups: Markets, Orders, Events, Portfolio, and Account.

Everything routes through one base URL. Market data and trading live in the same API. You reference markets by slug ("btc-100k-2025") rather than by Polygon token ID.

FeatureGlobalUS
Base URLs3 separate services1 unified service
Market identifierToken ID (condition ID hash)Market slug
Price formatDecimal 0.00–1.00String USD value ("0.55")
Order formatOrderArgs(price, size, side, token_id){"marketSlug", "intent", "type", "price", "quantity", "tif"}
REST endpoints50+ across Gamma/CLOB/Data23
WebSocket channelsMarket + User channelsMarket + Private channels
Public rate limitVaries by endpoint60 req/min
WebSocket instrument limitNot explicitly capped10 instruments
Institutional accessBuilder Program (higher limits)Exchange Gateway (FIX 4.4 support)

Placing Orders: Side-by-Side Code

This is where the rubber meets the road. Here is the same operation — buy 100 YES shares at $0.55 — on each platform.

Global API: Order Placement

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

client = ClobClient(
    host="https://clob.polymarket.com",
    chain_id=137,
    key=os.getenv("PRIVATE_KEY"),
)
client.set_api_creds(client.create_or_derive_api_creds())

# You need the token_id — a long condition ID hash
# Typically fetched from the Gamma API first
TOKEN_ID = "71321045863171548570638401..."  # YES token for this market

order_args = OrderArgs(
    price=0.55,
    size=100.0,
    side=BUY,
    token_id=TOKEN_ID,
)

# Sign the order (separate step — uses your private key)
signed_order = client.create_order(order_args)

# Submit to CLOB
resp = client.post_order(signed_order, OrderType.GTC)
print(resp)

US API: Order Placement

from polymarket_us import PolymarketUS
import os

client = PolymarketUS(
    key_id=os.getenv("POLYMARKET_US_KEY_ID"),
    secret_key=os.getenv("POLYMARKET_US_SECRET"),
)

# Reference market by slug — no token ID lookup needed
order = client.orders.create({
    "marketSlug": "btc-100k-2025",
    "intent": "ORDER_INTENT_BUY_LONG",      # BUY YES
    "type": "ORDER_TYPE_LIMIT",
    "price": {"value": "0.55", "currency": "USD"},
    "quantity": 100,
    "tif": "TIME_IN_FORCE_GOOD_TILL_CANCEL",
})
print(order)

Key differences in the order flow:

  • Market reference: Global uses a token ID (hash). US uses a human-readable slug.
  • Side/intent: Global uses BUY/SELL with token-specific sides. US uses explicit intents like ORDER_INTENT_BUY_LONG (buy YES) and ORDER_INTENT_BUY_SHORT (buy NO).
  • Price format: Global takes a float (0.55). US takes a structured object ({"value": "0.55", "currency": "USD"}).
  • Signing: Global requires explicit create_order() signing before submission. US handles signing inside the SDK automatically.
  • Time in force: US uses explicit TIME_IN_FORCE_* enums. Global passes OrderType.GTC / OrderType.FOK as a separate parameter to post_order().

WebSocket Streaming: Real-Time Data

Both platforms offer WebSocket streaming for real-time market data and private order updates. The connection patterns differ.

Global WebSocket

import asyncio
import websockets
import json

async def stream_global():
    uri = "wss://ws-subscriptions-clob.polymarket.com/ws/market"
    async with websockets.connect(uri) as ws:
        subscribe = {
            "type": "subscribe",
            "market": "71321045...",  # Token ID
            "channel": "price"
        }
        await ws.send(json.dumps(subscribe))
        async for message in ws:
            data = json.loads(message)
            print(f"Global price: {data}")

asyncio.run(stream_global())

US WebSocket

import asyncio
from polymarket_us import AsyncPolymarketUS

async def stream_us():
    async with AsyncPolymarketUS(
        key_id="your-key-id",
        secret_key="your-secret-key",
    ) as client:
        # WebSocket connections are async-only
        # Subscribe to market updates via /v1/ws/markets
        # Subscribe to private order updates via /v1/ws/private
        # Up to 10 instruments simultaneously
        events = await client.events.list({"limit": 5, "active": True})
        print(events)

asyncio.run(stream_us())

The US API WebSocket endpoints (/v1/ws/markets and /v1/ws/private) handle up to 10 instruments per connection. For the Global API, WebSocket subscriptions are per-token-ID with no explicitly documented cap, but practical limits apply.

Both platforms strongly recommend WebSocket over REST polling. The US API’s 60 requests-per-minute REST limit makes polling impractical for real-time strategies. The Global API has higher REST limits but WebSocket is still preferred for latency-sensitive agents.

Account Funding: How Agents Pay

This is a critical infrastructure difference that affects your wallet layer architecture.

Global: Fund your Polygon wallet with USDC. The agent’s Ethereum private key controls the wallet. You can use any wallet provider — raw EOA, Safe multisig, Coinbase Agentic Wallet, Lit Protocol session keys. See the Best Agent Wallet for Prediction Markets guide for recommendations.

US: Fund through the Polymarket US platform. USDC.e for purchasing outcome tokens. POL for gas fees if using an EOA wallet. Funding requires a verified account. Your agent cannot hold its own wallet independent of the KYC-verified identity.

This has significant implications for autonomous agents. On Global, an agent can have its own wallet with programmatic spending controls, session keys, and kill switches — the full agent wallet security stack. On US, the agent operates within a KYC-verified account, which raises legal and liability questions about who the “customer” is when an autonomous agent trades.

Decision Framework: Which API Should You Use?

Your SituationUse This APIWhy
US-based developer building for US usersPolymarket USLegal clarity, CFTC compliance, simpler SDK
International developer, global usersPolymarket GlobalNo KYC, more markets, higher liquidity, on-chain composability
Building an arbitrage agentBothPrice discrepancies between US and Global pools create arb opportunities
Prototyping / learningPolymarket GlobalNo KYC friction, Gamma API needs zero auth for reading
Institutional / enterprise deploymentPolymarket USExchange Gateway with FIX 4.4, regulatory audit trail
Need on-chain composability (DeFi integration)Polymarket GlobalConditional tokens are ERC-1155s on Polygon — composable with DeFi
Copy-trading platform for US customersPolymarket USRegulatory requirement for US-facing consumer products

For agents that need cross-platform capabilities, see the Cross-Market Arbitrage Guide for patterns on normalizing data across platforms.

Building a Dual-Stack Agent: Abstraction Pattern

If your agent needs to trade on both platforms (for arbitrage, redundancy, or serving both US and international users), you need an abstraction layer. Here is a minimal pattern:

from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import Optional
import os


@dataclass
class NormalizedMarket:
    """Platform-agnostic market representation."""
    platform: str                # "global" or "us"
    slug: str                    # Human-readable identifier
    token_id: Optional[str]      # Global only — condition ID hash
    question: str
    yes_price: float             # Normalized to 0.00–1.00
    no_price: float
    volume_24h: float


@dataclass
class NormalizedOrder:
    """Platform-agnostic order."""
    market_slug: str
    side: str                    # "YES" or "NO"
    action: str                  # "BUY" or "SELL"
    price: float                 # 0.00–1.00
    quantity: float
    time_in_force: str           # "GTC" or "FOK"


class PredictionMarketClient(ABC):
    """Interface both platforms implement."""

    @abstractmethod
    def get_markets(self, limit: int = 10) -> list[NormalizedMarket]:
        ...

    @abstractmethod
    def place_order(self, order: NormalizedOrder) -> dict:
        ...

    @abstractmethod
    def cancel_all(self) -> dict:
        ...

    @abstractmethod
    def get_positions(self) -> list[dict]:
        ...


class PolymarketGlobalClient(PredictionMarketClient):
    """Wraps py-clob-client for the Global API."""

    def __init__(self):
        from py_clob_client.client import ClobClient
        self.client = ClobClient(
            host="https://clob.polymarket.com",
            chain_id=137,
            key=os.getenv("PM_GLOBAL_PRIVATE_KEY"),
        )
        self.client.set_api_creds(
            self.client.create_or_derive_api_creds()
        )

    def get_markets(self, limit: int = 10) -> list[NormalizedMarket]:
        import requests
        raw = requests.get(
            "https://gamma-api.polymarket.com/markets",
            params={"active": "true", "limit": limit}
        ).json()
        return [
            NormalizedMarket(
                platform="global",
                slug=m.get("slug", ""),
                token_id=m.get("clobTokenIds", [None])[0],
                question=m.get("question", ""),
                yes_price=float(m.get("outcomePrices", "[0.5,0.5]").strip("[]").split(",")[0]),
                no_price=float(m.get("outcomePrices", "[0.5,0.5]").strip("[]").split(",")[1]),
                volume_24h=float(m.get("volume24hr", 0)),
            )
            for m in raw
        ]

    def place_order(self, order: NormalizedOrder) -> dict:
        from py_clob_client.clob_types import OrderArgs, OrderType
        from py_clob_client.order_builder.constants import BUY, SELL

        # Requires token_id — look up from market data
        # This is a simplified example; production code caches token IDs
        markets = self.get_markets(limit=100)
        market = next((m for m in markets if m.slug == order.market_slug), None)
        if not market or not market.token_id:
            raise ValueError(f"Market not found: {order.market_slug}")

        side = BUY if order.action == "BUY" else SELL
        order_args = OrderArgs(
            price=order.price,
            size=order.quantity,
            side=side,
            token_id=market.token_id,
        )
        signed = self.client.create_order(order_args)
        tif = OrderType.GTC if order.time_in_force == "GTC" else OrderType.FOK
        return self.client.post_order(signed, tif)

    def cancel_all(self) -> dict:
        return self.client.cancel_all()

    def get_positions(self) -> list[dict]:
        # Use the Data API for positions
        import requests
        # Simplified — production code handles pagination
        return []


class PolymarketUSClient(PredictionMarketClient):
    """Wraps polymarket-us for the US API."""

    def __init__(self):
        from polymarket_us import PolymarketUS
        self.client = PolymarketUS(
            key_id=os.getenv("PM_US_KEY_ID"),
            secret_key=os.getenv("PM_US_SECRET_KEY"),
        )

    def get_markets(self, limit: int = 10) -> list[NormalizedMarket]:
        raw = self.client.markets.list({"limit": limit})
        # Normalize US market format to common structure
        return [
            NormalizedMarket(
                platform="us",
                slug=m.get("slug", ""),
                token_id=None,  # US has no token IDs
                question=m.get("question", ""),
                yes_price=float(m.get("yesPrice", 0.5)),
                no_price=float(m.get("noPrice", 0.5)),
                volume_24h=float(m.get("volume24h", 0)),
            )
            for m in raw.get("markets", [])
        ]

    def place_order(self, order: NormalizedOrder) -> dict:
        intent_map = {
            ("BUY", "YES"): "ORDER_INTENT_BUY_LONG",
            ("BUY", "NO"): "ORDER_INTENT_BUY_SHORT",
            ("SELL", "YES"): "ORDER_INTENT_SELL_LONG",
            ("SELL", "NO"): "ORDER_INTENT_SELL_SHORT",
        }
        tif_map = {
            "GTC": "TIME_IN_FORCE_GOOD_TILL_CANCEL",
            "FOK": "TIME_IN_FORCE_FILL_OR_KILL",
        }
        return self.client.orders.create({
            "marketSlug": order.market_slug,
            "intent": intent_map[(order.action, order.side)],
            "type": "ORDER_TYPE_LIMIT",
            "price": {"value": str(order.price), "currency": "USD"},
            "quantity": int(order.quantity),
            "tif": tif_map.get(order.time_in_force, "TIME_IN_FORCE_GOOD_TILL_CANCEL"),
        })

    def cancel_all(self) -> dict:
        return self.client.orders.cancel_all()

    def get_positions(self) -> list[dict]:
        return self.client.portfolio.positions()

This pattern lets your agent logic operate on NormalizedMarket and NormalizedOrder objects without caring which platform executes the trade. An arbitrage agent, for example, can compare yes_price across both clients and route to whichever has the better price.

For agents using unified APIs like Dome, note that these tools currently target the Global API only. Polymarket US SDK support is not yet available in any third-party unified API as of March 2026.

Troubleshooting: Common Issues on Each Platform

Global API

401 “Invalid api key” on post_order() but cancel_all() works: This is a known issue. The order signing step requires the correct funder (proxy wallet) address. If your proxy wallet was never deployed (you never logged into polymarket.com with this wallet), order submission fails even though cancellation works. Solution: log into polymarket.com once with your wallet to deploy the proxy, or deploy it programmatically.

Intermittent 401 errors on create_or_derive_api_creds(): Timestamp drift. The CLOB API validates request timestamps and rejects requests with excessive skew. Ensure your server’s clock is NTP-synced. Even a few seconds of drift causes intermittent failures.

signature_type confusion: If using a Gnosis Safe or smart contract wallet, you must set signature_type=1 when initializing ClobClient. The default (0) is for EOA wallets. Mismatched signature types cause opaque auth errors.

US API

“Private key displayed only once” — key lost: Generate a new keypair from the developer portal. There is no recovery or derivation mechanism.

Auth errors from timestamp mismatch: The US API uses Ed25519 signatures that include timestamps to prevent replay attacks. If your server clock is off, requests fail silently or return 401. Use NTP synchronization.

Rate limited on REST polling: The 60 requests-per-minute limit on public endpoints is strict. Switch to WebSocket for any real-time data needs. REST should only be used for one-off queries and order management.

KYC required for API access: You cannot generate API keys without completing KYC through the iOS app first. There is no way around this. Use the same authentication method (Apple, Google, or email) across both the app and the developer portal to avoid account mismatch issues.

Migration Checklist: Global → US

If you are porting an existing Global bot to Polymarket US, follow this sequence:

  1. Complete KYC on the Polymarket US iOS app. Generate Ed25519 API keys at polymarket.us/developer. Store the private key immediately — it is shown once.

  2. Install the US SDK: pip install polymarket-us (Python 3.10+) or npm install polymarket-us (Node 18+).

  3. Replace your client initialization. Swap ClobClient for PolymarketUS. Replace Ethereum private key env vars with Ed25519 key ID and secret.

  4. Replace market identifiers. Token IDs → market slugs. You will need to map your existing token ID references to the corresponding US slugs. Some markets may only exist on one platform.

  5. Replace order construction. OrderArgs(price, size, side, token_id)client.orders.create({marketSlug, intent, type, price, quantity, tif}). Side/intent mapping: BUY + YES token → ORDER_INTENT_BUY_LONG.

  6. Remove explicit order signing. The US SDK handles signing internally. Delete any create_order() / sign_order() calls.

  7. Update WebSocket connections. Replace raw websockets connections to wss://ws-subscriptions-clob.polymarket.com with the US SDK’s async WebSocket interface.

  8. Update error handling. The US SDK throws typed exceptions: AuthenticationError, BadRequestError, RateLimitError, NotFoundError, APITimeoutError, APIConnectionError. Map these to your existing error handling logic.

  9. Fund your US account. Load USDC.e through the Polymarket US platform. Your Polygon USDC balance is not usable on US.

  10. Test with small orders. There is no testnet/sandbox for the public Retail API. Start with minimal position sizes. For institutional-scale testing, contact [email protected] for Exchange Gateway sandbox access.

What’s Next

This guide covers the current state as of March 2026. The Polymarket US API is three weeks old and actively evolving. Expect changes to endpoints, rate limits, and SDK capabilities.

For the complete endpoint reference for the Global API, see the Prediction Market API Reference. For wallet infrastructure to power your agent’s fund management, see the Agent Wallet Comparison and Agent Betting Stack framework.

If you are building cross-platform agents that span Polymarket, Kalshi, and sportsbooks, the Unified API Comparison covers the unified API layer — though as noted, these tools do not yet support Polymarket US.

Browse the AgentBets marketplace for agents already trading on these platforms, or list your own agent if you have built something others can use.