docs: daily sync Polymarket docs 2026-06-16 - 118 files updated

This commit is contained in:
Etherdrake
2026-06-16 14:13:28 +02:00
parent 46bcbfdd05
commit 72269f5586
122 changed files with 307 additions and 21200 deletions
@@ -1 +1 @@
null
null
@@ -41,6 +41,7 @@ paths:
- OVERALL
- POLITICS
- SPORTS
- ESPORTS
- CRYPTO
- CULTURE
- MENTIONS
@@ -221,6 +221,14 @@ components:
type: string
profileImageOptimized:
type: string
isCombo:
type: boolean
description: >-
True when this row is part of a combinatorial (multi-market)
position. Flag only — combo detail is not embedded here. The row's
conditionId equals the combo's combo_condition_id; pass it to
/v1/activity/combos or /v1/positions/combos via market_id to fetch
legs and detail. Omitted on non-combo rows.
ErrorResponse:
type: object
properties:
@@ -1 +1 @@
null
null
@@ -1 +1 @@
null
null
@@ -124,7 +124,10 @@ components:
description: Whether RFQ (Request for Quote) is enabled for this market
itode:
type: boolean
description: Whether taker order delay is enabled
description: >-
Whether taker order delay is enabled for this market. When true,
marketable orders are held for the 250 ms taker-delay window before
synchronous processing. This field is omitted when false.
ibce:
type: boolean
description: Whether Blockaid check is enabled
@@ -1 +1 @@
null
null
@@ -1 +1 @@
null
null
@@ -1 +1 @@
null
null
@@ -1 +1 @@
null
null
@@ -1 +1 @@
null
null
@@ -1 +1 @@
null
null
@@ -1 +1 @@
null
null
@@ -1,137 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Check if a wallet is deployed
> Returns whether the wallet at the given address is deployed onchain.
Use the `type` query parameter to choose which wallet type to check:
- Pass user's Polymarket `SAFE` address (default): Gnosis Safe (SignatureType `2`).
- Pass user's Polymarket `WALLET` Deposit Wallet address: Deposit Wallet (signatureType `3`). See the [Deposit Wallet Guide](/trading/deposit-wallets) for setup.
Omitting `type` is equivalent to `type=SAFE`.
## OpenAPI
````yaml /api-spec/relayer-openapi.yaml get /deployed
openapi: 3.0.3
info:
title: Polymarket Relayer API
version: 1.0.0
description: HTTP API for the Polymarket Relayer. Submit and track gasless transactions.
servers:
- url: https://relayer-v2.polymarket.com
description: Polymarket Relayer API
security: []
tags:
- name: Relayer
description: Relayer transaction operations
- name: Relayer API Keys
description: >
Relayer API keys let a user authenticate requests to relayer endpoints
without Gamma auth.
However, Relayer API keys can only be created using Gamma auth. Every
address can create a maximum of 100 keys.
The API key auth headers are:
- `RELAYER_API_KEY`
- `RELAYER_API_KEY_ADDRESS`
`RELAYER_API_KEY_ADDRESS` must match the address that owns the key.
paths:
/deployed:
get:
tags:
- Relayer
summary: Check if a wallet is deployed
description: >
Returns whether the wallet at the given address is deployed onchain.
Use the `type` query parameter to choose which wallet type to check:
- Pass user's Polymarket `SAFE` address (default): Gnosis Safe
(SignatureType `2`).
- Pass user's Polymarket `WALLET` Deposit Wallet address: Deposit Wallet
(signatureType `3`). See the [Deposit Wallet
Guide](/trading/deposit-wallets) for setup.
Omitting `type` is equivalent to `type=SAFE`.
parameters:
- name: address
in: query
required: true
description: Address of the wallet to check
schema:
$ref: '#/components/schemas/Address'
example: '0x6d8c4e9aDF5748Af82Dabe2C6225207770d6B4fa'
- name: type
in: query
required: false
description: Wallet type to check. Defaults to `SAFE` when omitted.
schema:
type: string
enum:
- SAFE
- WALLET
default: SAFE
example: WALLET
responses:
'200':
description: Deployment status retrieved successfully
content:
application/json:
schema:
$ref: '#/components/schemas/DeployedResponse'
example:
deployed: true
'400':
description: Bad Request - Missing or invalid address
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
example:
error: invalid address
'500':
description: Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
schemas:
Address:
type: string
description: Ethereum address (0x-prefixed, 40 hex chars)
pattern: ^0x[a-fA-F0-9]{40}$
example: '0x6e0c80c90ea6c15917308F820Eac91Ce2724B5b5'
DeployedResponse:
type: object
properties:
deployed:
type: boolean
description: Whether the wallet is deployed
example: true
ErrorResponse:
type: object
properties:
error:
type: string
required:
- error
````
@@ -1 +1 @@
null
null
@@ -4,7 +4,7 @@
# Cancel multiple orders
> Cancels multiple orders by their IDs. Maximum 3000 orders per request.
> Cancels multiple orders by their IDs. Maximum 1000 orders per request.
Duplicate order IDs in the request are automatically ignored.
Works even in cancel-only mode.
@@ -48,7 +48,7 @@ paths:
- Trade
summary: Cancel multiple orders
description: |
Cancels multiple orders by their IDs. Maximum 3000 orders per request.
Cancels multiple orders by their IDs. Maximum 1000 orders per request.
Duplicate order IDs in the request are automatically ignored.
Works even in cancel-only mode.
operationId: cancelOrders
@@ -60,7 +60,7 @@ paths:
type: array
items:
type: string
maxItems: 3000
maxItems: 1000
example:
- '0xabcdef1234567890abcdef1234567890abcdef12'
- '0xfedcba0987654321fedcba0987654321fedcba09'
@@ -115,7 +115,7 @@ paths:
too_many_orders:
summary: Too many orders
value:
error: 'Too many orders in payload, max allowed: 3000'
error: 'Too many orders in payload, max allowed: 1000'
'401':
description: Unauthorized - Invalid API key or authentication failed
content:
-249
View File
@@ -1,249 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Polymarket Changelog
> Welcome to the Polymarket Changelog. Here you will find any important changes to Polymarket, including but not limited to CLOB, API, UI and Mobile Applications.
<Update label="Jun 1, 2026" description="Increased CLOB order rate limits">
Raised burst and sustained rate limits for several CLOB trading endpoints.
* CLOB POST /order - 120000 every 10 minutes (200/s) - (SUSTAINED)
* CLOB DELETE /order - 120000 every 10 minutes (200/s) - (SUSTAINED)
* CLOB POST /orders - 2000 every 10s (200/s) - (BURST)
* CLOB DELETE /orders - 2000 every 10s (200/s) - (BURST)
See [Rate Limits](/api-reference/rate-limits) for the full table.
</Update>
<Update label="May 18, 2026" description="Data API: builderCode added to /v1/builders/leaderboard and /v1/builders/volume">
* **New field**: Both `GET /v1/builders/leaderboard` and `GET /v1/builders/volume` now include a `builderCode` string on each entry — the builder's onchain attribution code as attached to orders via `builderCode` (see [Migrating to CLOB V2](/v2-migration)).
* **Additive change**: existing clients are unaffected. Legacy builders without a registered code return an empty string.
</Update>
<Update label="May 14, 2026" description="GET /markets/keyset maximum limit reduced to 100">
* **`GET /markets/keyset` limit**: The maximum `limit` value is now `100`. Requests should use `after_cursor`/`next_cursor` to paginate through larger result sets.
</Update>
<Update label="Apr 28, 2026" description="CLOB V2 is live on production">
Polymarket's CLOB V2 upgrade is live on `https://clob.polymarket.com`.
* **Production URL unchanged**: V2 now runs on the standard CLOB host. New integrations should use `https://clob.polymarket.com`.
* **No V1 compatibility**: Legacy V1 SDKs and V1-signed orders are no longer supported on production.
* **Open orders wiped**: Resting orders from before the cutover did not migrate and must be re-created with V2 signing.
* **Migration guide**: See [Migrating to CLOB V2](/v2-migration) for the SDK, raw order signing, pUSD, and builder attribution changes.
</Update>
<Update label="Apr 21, 2026" description="Relayer API: POST /submit returns immediately without transactionHash">
* **Faster `POST /submit` responses**: The Relayer's `POST /submit` endpoint now returns immediately with just `{ transactionID, state: "STATE_NEW" }`. The `transactionHash` field has been removed from the submit response to improve performance.
* **How to get the hash**: Poll [`GET /transaction`](/api-reference/relayer/get-a-transaction-by-id) with the returned `transactionID` to retrieve the onchain `transactionHash` once the transaction has been broadcast.
</Update>
<Update label="Apr 17, 2026" description="CLOB V2: upgrades go live April 28 at ~11:00 UTC, with ~1 hour of downtime">
Polymarket is shipping a coordinated upgrade: **new Exchange contracts, a rewritten CLOB backend, and a new collateral token (pUSD)**.
**Exchange upgrades go live April 28, 2026 at \~11:00 UTC with \~1 hour of downtime.** All integrations must migrate to the V2 SDK before the cutover — there will be no backward compatibility after go-live.
**Full walkthrough:** [Migrating to CLOB V2](/v2-migration). Follow [Discord](https://discord.gg/polymarket), Telegram, and [status.polymarket.com](https://status.polymarket.com) for the exact start time.
**Historical pre-cutover note:** before go-live, integrations could test against `https://clob-v2.polymarket.com`. As of April 28, V2 runs on `https://clob.polymarket.com`.
**What's changing**
* New Exchange contracts (CTF Exchange V2 + Neg Risk CTF Exchange V2)
* **pUSD** replaces USDC.e as the collateral token (standard ERC-20 on Polygon, backed by USDC, backing enforced onchain)
* Order struct: `nonce`, `feeRateBps`, `taker` removed — `timestamp` (ms), `metadata`, `builder` added
* Fees are now set at match time — no more `feeRateBps` on orders
* Builder attribution is native via `builderCode` on orders (no more `builder-signing-sdk`)
* EIP-712 Exchange domain version bumps from `"1"` to `"2"` (ClobAuth stays at `"1"`)
**What you need to do**
* Install the V2 SDK — [`@polymarket/clob-client-v2`](https://www.npmjs.com/package/@polymarket/clob-client-v2) or [`py-clob-client-v2`](https://pypi.org/project/py-clob-client-v2/) — and remove the legacy `clob-client` / `py-clob-client` packages
* Update constructor from positional args to options object; rename `chainId``chain`
* Remove `feeRateBps`, `nonce`, and `taker` from your order creation code
* If you're a builder, copy your code from [Settings → Builder](https://polymarket.com/settings?tab=builder) and attach it to orders
* If you sign orders without the SDK, update the `verifyingContract` and the signed Order fields — see [For API users](/v2-migration#for-api-users)
* Plan for all open orders to be wiped at cutover
**During the window:** Trading will be paused for \~1 hour on April 28 starting around 11:00 UTC. The SDK's hot-swap mechanism will auto-refresh the client when V2 goes live — no manual action needed if you're on the latest SDK.
</Update>
<Update label="Apr 13, 2026" description="Bridge API: added support link for bridging issues">
* **Support contact**: Added a link to [our Bridge API provider's support](https://intercom.help/funxyz/en/articles/10732578-contact-us) (Fun.xyz) for failed, stuck, or compliance-held bridge transactions. See [Deposit Status](/trading/bridge/status).
</Update>
<Update label="Apr 10, 2026" description="New keyset pagination endpoints for markets and events">
* **New endpoints**: Added `GET /markets/keyset` and `GET /events/keyset` for cursor-based pagination, replacing offset-based `GET /markets` and `GET /events`.
* **How it works**: These use an opaque `after_cursor`/`next_cursor` token instead of `offset`, providing stable and efficient paging through large result sets. Same filters, same response shape per item — the only differences are the wrapper response (`{ "markets": [...], "next_cursor": "..." }`) and the rejection of `offset`.
* **Migration**: The existing `GET /markets` and `GET /events` endpoints remain available but will be deprecated in a future release. New integrations should use the keyset variants.
</Update>
<Update label="Apr 9, 2026" description="GET /markets: closed defaults to false">
* **`closed` default change**: The `closed` query parameter on `GET /markets` now defaults to `false`. Closed markets are excluded from results unless you explicitly pass `closed=true`.
</Update>
<Update label="April 8, 2026" description="Increased API Rate Limits">
Increased burst and sustained rate limits for several CLOB trading endpoints.
* CLOB POST /order - 5000 every 10s (500/s) - (BURST)
* CLOB POST /order - 48000 every 10 minutes (80/s)
* CLOB DELETE /order - 5000 every 10s (500/s) - (BURST)
* CLOB DELETE /order - 48000 every 10 minutes (80/s)
* CLOB POST /orders - 1500 every 10s (150/s) - (BURST)
* CLOB POST /orders - 21000 every 10 minutes (35/s)
* CLOB DELETE /cancel-market-orders - 1500 every 10s (150/s) - (BURST)
* CLOB DELETE /cancel-market-orders - 21000 every 10 minutes (35/s)
See [Rate Limits](/api-reference/rate-limits) for the full table.
</Update>
<Update label="Mar 31, 2026" description="REST API Fee Fields Update">
* **Fee calculation source**: Fees should now be calculated using the `feeSchedule` object within a market.
</Update>
<Update label="Mar 30, 2026" description="Fee Structure V2">
* **New fee categories**: Fees now apply to Crypto, Sports, Finance, Politics, Economics, Culture, Weather, Tech, Mentions, and Other / General markets with updated rates per category. Geopolitical and world events markets remain fee-free.
* **Updated documentation**: [Fees](/trading/fees) and [Maker Rebates Program](/market-makers/maker-rebates).
</Update>
<Update label="Mar 17, 2026" description="March Madness: $2M+ in Liquidity Rewards">
* **March Madness Liquidity Rewards**: Adding \$2M+ in liquidity rewards to both live and pregame markets.
* **How it works**: Liquidity rewards are payments for placing competitive bids. Rewards are paid out based on the size of your orders, how close they are to the midpoint, and how consistently they are quoted relative to other liquidity providers. Orders must be active on the book for a minimum of **3.5 seconds** to be eligible.
**Daily reward rates for markets (subject to change):**
**48 hours before GameStartTime:**
* \$7.5k for full game ML market
* \$500 for 5 other markets (most recently created full game spread, most recently created full game total, 1st half ML, most recently created 1st half spread, most recently created 1st half total)
**From game live to game completion (note: rewards are expressed in daily rates):**
* \$60k for full game ML
* \$4k for most recently created full game spread and most recently created full game total
**From game live to halftime (note: rewards are expressed in daily rates):**
* \$8k for 1st half ML, most recently created 1st half spread, most recently created 1st half total
* **Markets**: [Browse March Madness markets](https://polymarket.com/sports/cbb/games)
* **More details**: [Liquidity Rewards documentation](/market-makers/liquidity-rewards#liquidity-rewards)
</Update>
<Update label="Mar 1, 2026" description="Taker Fees & Maker Rebates: All Crypto Markets">
* **Crypto market fees expansion**: Starting March 6, 2026, taker fees and maker rebates extend to all crypto markets including 1H, 4H, daily, and weekly. The same fee structure as existing crypto markets applies. Only new markets created after March 6 are affected.
* **Updated documentation**: [Fees](/trading/fees) and [Maker Rebates Program](/market-makers/maker-rebates) updated to reflect all crypto market coverage.
</Update>
<Update label="Feb 12, 2026" description="5-Minute Crypto Markets">
* **5-minute crypto markets**: Launched with taker fees enabled. Fees follow the same curve as 15-minute crypto markets, peaking at 1.56% at 50% probability.
* **Maker Rebates**: Liquidity providers earn daily USDC rebates funded by taker fees, same as 15-minute crypto markets.
</Update>
<Update label="Feb 11, 2026" description="Taker Fees & Maker Rebates: NCAAB and Serie A">
* **Sports market fees**: Taker fees to be enabled on NCAAB (college basketball) and Serie A markets on February 18, 2026.
* **Per-market rebate calculation**: Rebates are now calculated per market, makers only compete with other makers in the same market.
* **Updated documentation**: [Maker Rebates Program](/market-makers/maker-rebates) updated with sports fee tables and parameters.
</Update>
<Update label="Jan 28, 2026" description="Bridge API: Withdrawal Endpoint">
* **Withdrawal Endpoint**: New `/withdraw` endpoint to bridge USDC.e from Polymarket to any supported chain and token.
* **Multi-chain withdrawals**: Withdraw to EVM chains (Ethereum, Arbitrum, Base, etc.), Solana, and Bitcoin.
* **Updated documentation**: Bridge API docs updated to reflect deposit and withdrawal functionality.
</Update>
<Update label="Jan 16, 2026" description="Docs Update: RTDS documentation">
* RTDS docs updated to reflect RTDS supports **comments** and **crypto prices** only.
* Removed legacy CLOB references and `clob_auth` from RTDS docs.
</Update>
<Update label="Jan 16, 2026" description="Docs Update: Maker Rebates Program">
* **Maker Rebates Program**: Updated funding schedule with distribution method (volume-weighted vs fee-curve weighted).
* **Fee-curve weighted rebates**: Documented fee-equivalent formula and rebate calculation.
* **FAQ**: Clarified how rebates are calculated during fee-curve weighted periods.
</Update>
<Update label="Jan 6, 2026" description="New API Features">
* **Releases**: Daily Releases timing
* **HeartBeats API**: HeartBeats endpoint for monitoring connection status and canceling orders
* **Post Only Orders**: Orders that are rejected if they would immediately match against an existing order
</Update>
<Update label="Jan 5, 2026" description="Taker Fees & Maker Rebates">
* **Taker Fees**: Enabled on 15-minute crypto markets. Fees vary by price and peak at 1.56% at 50% probability.
* **Maker Rebates**: Daily USDC rebates paid to liquidity providers, funded by taker fees.
</Update>
<Update label="Sept 24, 2025" description="Polymarket Real-Time Data Socket (RTDS) official release">
* **Crypto Price Feeds**: Access real-time cryptocurrency prices from two sources (Binance & Chainlink)
* **Comment Streaming**: Real-time updates for comment events including new comments, replies, and reactions
* **Dynamic Subscriptions**: Add, remove, and modify subscriptions without reconnecting
* **TypeScript Client**: Official TypeScript client available at [real-time-data-client](https://github.com/Polymarket/real-time-data-client)
For complete documentation, see [Market Data](/market-data/overview).
</Update>
<Update label="September 15, 2025" description="WSS price_change event update">
* There has been a significant change to the structure of the price change message. This update will be applied at 11PM UTC September 15, 2025. We apologize for the short notice
* Please see the [Market Channel](/market-data/websocket/market-channel) for details.
</Update>
<Update label="August 26, 2025" description="Updated /trades and /activity endpoints">
* Reduced maximum values for query parameters on Data-API /trades and /activity:
* `limit`: 500
* `offset`: 1,000
</Update>
<Update label="August 21, 2025" description="Batch Orders Increase">
* The batch orders limit has been increased from 5 -> 15. Read more about the batch orders functionality [here](/trading/orders/create).
</Update>
<Update label="July 23, 2025" description="Get Book(s) update">
* Were adding new fields to the `get-book` and `get-books` CLOB endpoints to include key market metadata that previously required separate queries.
* `min_order_size`
* type: string
* description: Minimum price increment.
* `neg_risk`
* type: boolean
* description: Boolean indicating whether the market is neg\_risk.
* `tick_size`
* type: string
* description: Minimum price increment.
</Update>
<Update label="June 3, 2025" description="New Batch Orders Endpoint">
* Were excited to roll out a highly requested feature: **order batching**. With this new endpoint, users can now submit up to five trades in a single request. To help you get started, weve included sample code demonstrating how to use it. Please see [Create Orders](/trading/orders/create) for more details.
</Update>
<Update label="June 3, 2025" description="Change to /data/trades">
* We're adding a new `side` field to the `MakerOrder` portion of the trade object. This field will indicate whether the maker order is a `buy` or `sell`, helping to clarify trade events where the maker side was previously ambiguous. For more details, refer to the MakerOrder object on the [Orders](/trading/orders/cancel) page.
</Update>
<Update label="May 28, 2025" description="Websocket Changes">
* The 100 token subscription limit has been removed for the Markets channel. You can now subscribe to as many token IDs as needed for your use case.
* New Subscribe Field `initial_dump`
* Optional field to indicate whether you want to receive the initial order book state when subscribing to a token or list of tokens.
* `default: true`
</Update>
<Update label="May 28, 2025" description="New FAK Order Type">
Were excited to introduce a new order type soon to be available to all users: Fill and Kill (FAK). FAK orders behave similarly to the well-known Fill or Kill (FOK) orders, but with a key difference:
* FAK will fill as many shares as possible immediately at your specified price, and any remaining unfilled portion will be canceled.
* Unlike FOK, which requires the entire order to fill instantly or be canceled, FAK is more flexible and aims to capture partial fills if possible.
</Update>
<Update label="May 15, 2025" description="Increased API Rate Limits">
All API users will enjoy increased rate limits for the CLOB endpoints.
* CLOB - /books (website) (300req - 10s / Throttle requests over the maximum configured rate)
* CLOB - /books (50 req - 10s / Throttle requests over the maximum configured rate)
* CLOB - /price (100req - 10s / Throttle requests over the maximum configured rate)
* CLOB markets/0x (50req / 10s - Throttle requests over the maximum configured rate)
* CLOB POST /order - 500 every 10s (50/s) - (BURST) - Throttle requests over the maximum configured rate
* CLOB POST /order - 3000 every 10 minutes (5/s) - Throttle requests over the maximum configured rate
* CLOB DELETE /order - 500 every 10s (50/s) - (BURST) - Throttle requests over the maximum configured rate
* DELETE /order - 3000 every 10 minutes (5/s) - Throttle requests over the maximum configured rate
</Update>
+13 -8
View File
@@ -61,7 +61,12 @@ Post-only orders will only rest on the book. If a post-only order would match im
</Step>
<Step title="Match or Rest">
**If the order is marketable** (your buy price ≥ lowest ask, or your sell price ≤ highest bid), it matches immediately against resting orders.
**If the order is marketable** (your buy price ≥ lowest ask, or your sell price ≤ highest bid), it matches against resting orders. Some markets apply a short taker delay before matching:
* **Taker delay:** used on selected crypto and finance up/down markets. The order is held for 250 ms, then validation runs again and the order is matched or placed on the book. The API waits for this hold and returns the final order result. To check a specific market, call the public CLOB endpoint `GET https://clob.polymarket.com/clob-markets/{condition_id}` or SDK method `getClobMarketInfo(conditionID)` and look for `itode: true`.
* **Sports/game delay:** enabled on configured sports markets around live game conditions. The order waits for the market's configured delay window before matching.
During either delay, the order is pending and cannot be canceled. If the market, balance, allowance, or risk checks fail when the delay expires, the order is rejected instead of matching.
**If the order is not marketable**, it rests on the book waiting for a counterparty. It remains open until:
@@ -89,12 +94,12 @@ Post-only orders will only rest on the book. If a post-only order would match im
When you place an order, it receives one of these statuses:
| Status | Description |
| ----------- | --------------------------------------------------------------------------- |
| `live` | Order is resting on the book |
| `matched` | Order matched immediately |
| `delayed` | Marketable order subject to a 1-second matching delay (sports markets) |
| `unmatched` | Marketable order placed on the book after the delay expired without a match |
| Status | Description |
| ----------- | ----------------------------------------------------------------------------------------------------------------------- |
| `live` | Order is resting on the book |
| `matched` | Order matched immediately |
| `delayed` | Marketable order accepted into an asynchronous delay window on configured seconds-delay markets, such as sports markets |
| `unmatched` | Marketable order placed on the book after the delay expired without a match |
## Trade Statuses
@@ -119,7 +124,7 @@ Price improvement always benefits the taker. If you place a buy order at `$0.55`
## Cancellation
You can cancel orders at any time before they're matched via the CLOB API.
You can cancel orders at any time before they're matched via the CLOB API, except while a marketable order is in a pending delay window.
Partial fills cannot be cancelled—only the unfilled portion of an order can be cancelled.
+117 -43
View File
@@ -517,16 +517,23 @@ async with await AsyncSecureClient.create(
Create a secure client when you need wallet-scoped reads or trading.
<Note>
Secure clients own multiple network transports. Wrap them in `async with`,
or call `await secure_client.close()` when you are done, to release the
underlying connections. The snippets below show client creation and
subsequent calls as a flat sequence for readability — in real code, keep
the client inside an `async with` block or close it explicitly.
Secure clients own multiple network transports. Wrap them in `async with`, or
call `await secure_client.close()` when you are done, to release the
underlying connections. The snippets below show client creation and subsequent
calls as a flat sequence for readability — in real code, keep the client
inside an `async with` block or close it explicitly.
</Note>
### Private Key Setup
The Python SDK authenticates with a local private key. Pass `wallet` when you want to operate on a Polymarket wallet address that differs from the signer address; if omitted, the client uses the signer address as the account wallet.
The Python SDK authenticates with a local private key. By default,
`AsyncSecureClient.create` uses the signer's deterministic Deposit Wallet as the
account wallet. Pass `wallet` when you want to authenticate an existing wallet,
such as an existing Deposit Wallet, Poly Safe, Poly Proxy, or the signer address
itself for EOA trading.
The examples below pass `wallet` to make account selection explicit. Omit
`wallet` to use the default Deposit Wallet flow.
```python theme={null}
import os
@@ -543,9 +550,10 @@ async with await AsyncSecureClient.create(
Keep private keys and API credentials in your secret manager or local environment. Do not commit them to source control.
### API Key Authentication
### API Key Authorization
Configure an API key when the SDK needs to set up gasless wallet operations.
Configure API key authorization when the SDK needs to deploy a Deposit Wallet or
submit approval transactions.
<CodeGroup>
```python Relayer API Key theme={null}
@@ -584,51 +592,32 @@ Configure an API key when the SDK needs to set up gasless wallet operations.
<Note>
Builder API keys are supported for backwards compatibility with builders that
still use them for gasless workflows. They are not used for order attribution.
still use them for wallet operations. They are not used for order attribution.
Use `builder_code` on orders for attribution.
</Note>
### Trading Setup
Before placing orders, make sure the authenticated wallet has the required trading approvals. If you use gasless wallet operations, configure API key authentication first.
Before placing orders, make sure the authenticated wallet is deployed and has
the required trading approvals. `AsyncSecureClient.create` resolves the signer's
deterministic Deposit Wallet by default and deploys it if needed.
<Note>
From this point forward, snippets in Trading Setup, Trading, Position
Lifecycle, and Wallet Operations submit real on-chain transactions or
live orders against the configured environment when executed. Review
each call before running it against a wallet that holds funds.
Lifecycle, and Wallet Operations submit real on-chain transactions or live
orders against the configured environment when executed. Review each call
before running it against a wallet that holds funds.
</Note>
<Steps>
<Step title="Check Gasless Readiness">
Optionally check whether the deposit wallet for the authenticated EOA is already deployed. The result is informational — call `setup_gasless_wallet()` in the next step regardless, since it is idempotent on deployment and is the call that binds the client to the deposit wallet.
Set up the approvals required for trading.
```python theme={null}
is_gasless_ready = await secure_client.is_gasless_ready()
```
</Step>
```python theme={null}
await secure_client.setup_trading_approvals()
```
<Step title="Set Up Gasless Wallet">
Always call `setup_gasless_wallet()` for gasless workflows. It deploys the deposit wallet if needed and returns a new client bound to the deposit wallet address. Close the previous client when you replace it.
```python theme={null}
gasless_client = await secure_client.setup_gasless_wallet()
await secure_client.close()
secure_client = gasless_client
```
</Step>
<Step title="Set Up Trading Approvals">
Set up the approvals required for trading and wait for the setup transaction to complete.
```python theme={null}
handle = await secure_client.setup_trading_approvals()
outcome = await handle.wait()
# outcome.transaction_hash: TransactionHash
```
</Step>
</Steps>
`setup_trading_approvals()` waits for the setup transaction internally and is
idempotent. If the wallet already has the required approvals, it returns without
submitting a transaction.
### Trading
@@ -828,7 +817,11 @@ Create signed orders separately when you want to review, store, or batch them be
### Position Lifecycle
Use position lifecycle methods to split collateral into outcome tokens, merge complete sets back into collateral, or redeem resolved positions. These examples assume the secure client is configured with API key authentication as shown in [API Key Authentication](#api-key-authentication).
Use position lifecycle methods to split collateral into outcome tokens, merge
complete sets back into collateral, or redeem resolved positions. These examples
assume the secure client is configured with API key authorization as shown in
[API Key Authorization](#api-key-authorization), and that you set up trading
approvals as shown above.
<Tabs>
<Tab title="Split Position">
@@ -880,7 +873,10 @@ Use position lifecycle methods to split collateral into outcome tokens, merge co
### Wallet Operations
Use wallet operation methods for direct token movements from the authenticated wallet. Amounts are in base units. These examples assume the secure client is configured with API key authentication as shown in [API Key Authentication](#api-key-authentication).
Use wallet operation methods for direct token movements from the authenticated
wallet. Amounts are in base units. These examples assume the secure client is
configured with API key authorization as shown in [API Key
Authorization](#api-key-authorization).
```python theme={null}
import os
@@ -1103,3 +1099,81 @@ Secure clients expose the API credentials created for the authenticated session.
```
</Tab>
</Tabs>
## Changelog
### `0.1.0b7`
* Point Combos RFQ endpoints at the production domains: `combos-rfq-api.polymarket.com` (REST) and `combos-rfq-gateway-quoter.polymarket.com` (quoter WebSocket).
### `0.1.0b6`
* Added `list_combo_markets` for fetching the Combo market catalog with SDK pagination. See [Combos](/market-makers/combos).
* Parse RFQ quote rejections that use the `SUBMISSION_WINDOW_CLOSED` gateway error code.
### `0.1.0b5`
* Added Combos support for multi-leg RFQ positions. See [Combos](/market-makers/combos).
* Added notebook-friendly model display for Jupyter workflows.
* `ConditionId` is now deprecated in favor of `CtfConditionId`; existing
`ConditionId` exports remain available as deprecated aliases.
### `0.1.0b4`
* Added dataframe conversion support for SDK models and response collections.
**Secure client setup now defaults to the Deposit Wallet flow**
`AsyncSecureClient.create` can now derive and use the signer's deterministic
Deposit Wallet when you omit `wallet`. If you already know which Polymarket
wallet you want to use, keep passing `wallet`.
```diff theme={null}
secure_client = await AsyncSecureClient.create(
private_key=os.environ["POLYMARKET_PRIVATE_KEY"],
- wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
)
```
If you want to keep account selection explicit, no change is required:
```python theme={null}
secure_client = await AsyncSecureClient.create(
private_key=os.environ["POLYMARKET_PRIVATE_KEY"],
wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
)
```
**`setup_trading_approvals()` now waits internally**
You no longer need to wait on the returned handle. Call the method once before
trading; it is safe to call again if approvals are already set.
```diff theme={null}
-handle = await secure_client.setup_trading_approvals()
-await handle.wait()
+await secure_client.setup_trading_approvals()
```
**Gasless setup helpers are deprecated**
You no longer need to call `is_gasless_ready()` or `setup_gasless_wallet()` in
the normal setup path. Create the secure client, then set up trading approvals.
```diff theme={null}
-ready = await secure_client.is_gasless_ready()
-
-if not ready:
- secure_client = await secure_client.setup_gasless_wallet()
-
await secure_client.setup_trading_approvals()
```
### `0.1.0b1`
First beta release of the unified Python SDK. Install the beta package with your
package manager:
```bash theme={null}
uv add polymarket-client
```
+108 -31
View File
@@ -404,7 +404,7 @@ Use discovery methods to browse events, markets, teams, tags, comments, sports m
});
const userComments = client.listCommentsByUserAddress({
address: "0x1234...",
address: "0x1234",
pageSize: 10,
order: "DESC",
});
@@ -473,6 +473,15 @@ for await (const event of stream) {
Create a secure client when you need wallet-scoped reads or trading.
By default, `createSecureClient` uses the signer's deterministic Deposit Wallet
as the account wallet. The SDK deploys that wallet if needed during client
creation. Pass `wallet` only when you want to authenticate an existing wallet,
such as an existing Deposit Wallet, Poly Safe, Poly Proxy, or the signer address
itself for EOA trading.
The examples below pass `wallet` to make account selection explicit. Omit
`wallet` to use the default Deposit Wallet flow.
### Wallet Integrations
The SDK is intended to support a variety of wallet libraries. At launch, we support [Viem](https://viem.sh), [Privy](https://www.privy.io/docs), and [Ethers v5](https://docs.ethers.org/v5/). We will expand support for more libraries based on demand.
@@ -595,17 +604,20 @@ The SDK is intended to support a variety of wallet libraries. At launch, we supp
### Trading Setup
Before placing orders, configure API key authentication if you need gasless wallet setup, then make sure the authenticated wallet has the required trading approvals.
Before placing orders, make sure the authenticated wallet is deployed and has
the required trading approvals. `createSecureClient` resolves the signer's
deterministic Deposit Wallet by default and deploys it if needed.
<Steps>
<Step title="Configure API Key Authentication">
Configure an API key when the SDK needs to set up gasless wallet operations.
<Step title="Configure API Key Authorization">
Configure API key authorization when the SDK needs to deploy a Deposit Wallet or
submit approval transactions.
<CodeGroup>
```ts Relayer API Key theme={null}
import { createSecureClient, relayerApiKey } from "@polymarket/client";
let secureClient = await createSecureClient({
const secureClient = await createSecureClient({
wallet: "YOUR_POLYMARKET_WALLET_ADDRESS",
signer,
apiKey: relayerApiKey({
@@ -619,7 +631,7 @@ Before placing orders, configure API key authentication if you need gasless wall
import { createSecureClient } from "@polymarket/client";
import { builderApiKey } from "@polymarket/client/node";
let secureClient = await createSecureClient({
const secureClient = await createSecureClient({
wallet: "YOUR_POLYMARKET_WALLET_ADDRESS",
signer,
apiKey: builderApiKey({
@@ -633,36 +645,21 @@ Before placing orders, configure API key authentication if you need gasless wall
<Note>
Builder API keys are supported for backwards compatibility with builders that
still use them for gasless workflows. They are not used for order attribution.
still use them for wallet operations. They are not used for order attribution.
Use `builderCode` on orders for attribution.
</Note>
</Step>
<Step title="Check Gasless Readiness">
Check whether the authenticated wallet is already ready for gasless transactions.
```ts theme={null}
const isGaslessReady = await secureClient.isGaslessReady();
```
</Step>
<Step title="Set Up Gasless Wallet">
If needed, set up the gasless wallet and continue with the returned secure client.
```ts theme={null}
if (!isGaslessReady) {
secureClient = await secureClient.setupGaslessWallet();
}
```
</Step>
<Step title="Set Up Trading Approvals">
Set up the approvals required for trading and wait for the setup transaction to complete.
Then set up trading approvals.
```ts theme={null}
const handle = await secureClient.setupTradingApprovals();
await handle.wait();
await secureClient.setupTradingApprovals();
```
`setupTradingApprovals()` waits for the setup transaction internally and is
idempotent. If the wallet already has the required approvals, it returns without
submitting a transaction.
</Step>
</Steps>
@@ -766,7 +763,7 @@ Order placement returns a discriminated response. Check `response.ok` before rea
side: OrderSide.BUY,
price: 0.52,
size: 10,
builderCode: "0xabc123...",
builderCode: "0xabc123",
});
if (response.ok) {
@@ -840,7 +837,9 @@ Create signed orders separately when you want to review, store, or batch them be
### Position Lifecycle
Use position lifecycle methods to split collateral into outcome tokens, merge complete sets back into collateral, or redeem resolved positions. These examples assume the secure client is configured with API key authentication as shown in [Trading Setup](#trading-setup).
Use position lifecycle methods to split collateral into outcome tokens, merge
complete sets back into collateral, or redeem resolved positions. These examples
assume you created a secure client and set up trading approvals as shown above.
<Tabs>
<Tab title="Split Position">
@@ -884,7 +883,8 @@ Use position lifecycle methods to split collateral into outcome tokens, merge co
### Wallet Operations
Use wallet operation methods for direct token movements from the authenticated wallet. These examples assume the secure client is configured with API key authentication as shown in [Trading Setup](#trading-setup).
Use wallet operation methods for direct token movements from the authenticated
wallet. These examples assume you created a secure client as shown above.
```ts theme={null}
const handle = await secureClient.transferErc20({
@@ -1100,3 +1100,80 @@ Secure clients expose the API credentials created for the authenticated session.
```
</Tab>
</Tabs>
## Changelog
### `0.1.0-beta.6`
* Point Combos RFQ endpoints at the production domains: `combos-rfq-api.polymarket.com` (REST) and `combos-rfq-gateway-quoter.polymarket.com` (quoter WebSocket).
### `0.1.0-beta.5`
* Added `listComboMarkets` for fetching the Combo market catalog with typed bindings and SDK-owned pagination. See [Combos](/market-makers/combos).
* Parse RFQ quote rejections that use the `SUBMISSION_WINDOW_CLOSED` gateway error code.
### `0.1.0-beta.4`
* Added Combos support for multi-leg RFQ positions. See [Combos](/market-makers/combos).
* Reject whitespace-only search queries and trim leading or trailing search input.
* `ConditionId` is now deprecated in favor of `CtfConditionId`; existing
`ConditionId` exports remain available as deprecated aliases.
### `0.1.0-beta.3`
**Secure client setup now defaults to the Deposit Wallet flow**
`createSecureClient` can now derive and use the signer's deterministic Deposit
Wallet when you omit `wallet`. If you already know which Polymarket wallet you
want to use, keep passing `wallet`.
```diff theme={null}
const secureClient = await createSecureClient({
- wallet: "YOUR_POLYMARKET_WALLET_ADDRESS",
signer,
});
```
If you want to keep account selection explicit, no change is required:
```ts theme={null}
const secureClient = await createSecureClient({
wallet: "YOUR_POLYMARKET_WALLET_ADDRESS",
signer,
});
```
**`setupTradingApprovals()` now waits internally**
You no longer need to wait on the returned handle. Call the method once before
trading; it is safe to call again if approvals are already set.
```diff theme={null}
-const handle = await secureClient.setupTradingApprovals();
-await handle.wait();
+await secureClient.setupTradingApprovals();
```
**Gasless setup helpers are deprecated**
You no longer need to call `isGaslessReady()` or `setupGaslessWallet()` in the
normal setup path. Create the secure client, then set up trading approvals.
```diff theme={null}
-const ready = await secureClient.isGaslessReady();
-
-if (!ready) {
- secureClient = await secureClient.setupGaslessWallet();
-}
-
await secureClient.setupTradingApprovals();
```
### `0.1.0-beta.2`
First beta release of the unified TypeScript SDK. Install the beta package with
your package manager:
```bash theme={null}
pnpm add @polymarket/client@beta
```
-437
View File
@@ -1,437 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Authentication
> How to authenticate requests to the CLOB API
The CLOB API uses two levels of authentication: **L1 (Private Key)** and **L2 (API Key)**. Either can be accomplished using the CLOB client or REST API.
## Public vs Authenticated
<CardGroup cols={1}>
<Card title="Public (No Auth)" icon="unlock">
The **Gamma API**, **Data API**, and CLOB read endpoints (orderbook, prices, spreads) require no authentication.
</Card>
<Card title="Authenticated (CLOB)" icon="lock">
CLOB trading endpoints (placing orders, cancellations, heartbeat) require all 5 `POLY_*` L2 HTTP headers.
</Card>
</CardGroup>
***
## Two-Level Authentication Model
The CLOB uses two levels of authentication: L1 (Private Key) and L2 (API Key). Either can be accomplished using the CLOB client or REST API
### L1 Authentication
L1 authentication uses the wallet's private key to sign an EIP-712 message used in the request header. It proves ownership and control over the private key. The private key stays in control of the user and all trading activity remains non-custodial.
**Used for:**
* Creating API credentials
* Deriving existing API credentials
* Signing and creating user's orders locally
### L2 Authentication
L2 uses API credentials (apiKey, secret, passphrase) generated from L1 authentication. These are used solely to authenticate requests made to the CLOB API. Requests are signed using HMAC-SHA256.
**Used for:**
* Cancel or get user's open orders
* Check user's balances and allowances
* Post user's signed orders
<Info>
Even with L2 authentication headers, methods that create user orders still
require the user to sign the order payload.
</Info>
***
## Getting API Credentials
Before making authenticated requests, you need to obtain API credentials using L1 authentication.
### Using the SDK
<Tabs>
<Tab title="TypeScript">
```typescript theme={null}
import { ClobClient } from "@polymarket/clob-client-v2";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const signer = createWalletClient({ account, transport: http() });
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137, // Polygon mainnet
signer,
});
// Creates new credentials or derives existing ones
const credentials = await client.createOrDeriveApiKey();
console.log(credentials);
// {
// key: "550e8400-e29b-41d4-a716-446655440000",
// secret: "base64EncodedSecretString",
// passphrase: "randomPassphraseString"
// }
```
</Tab>
<Tab title="Python">
```python theme={null}
from py_clob_client_v2 import ClobClient
import os
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137, # Polygon mainnet
key=os.getenv("PRIVATE_KEY")
)
# Creates new credentials or derives existing ones
credentials = client.create_or_derive_api_key()
print(credentials)
# {
# "apiKey": "550e8400-e29b-41d4-a716-446655440000",
# "secret": "base64EncodedSecretString",
# "passphrase": "randomPassphraseString"
# }
```
</Tab>
<Tab title="Rust">
```rust theme={null}
use std::str::FromStr;
use polymarket_client_sdk_v2::POLYGON;
use polymarket_client_sdk_v2::auth::{LocalSigner, Signer};
use polymarket_client_sdk_v2::clob::{Client, Config};
let private_key = std::env::var("POLYMARKET_PRIVATE_KEY")?;
let signer = LocalSigner::from_str(&private_key)?
.with_chain_id(Some(POLYGON));
// Creates new credentials or derives existing ones,
// then initializes the authenticated client — all in one step
let client = Client::new("https://clob.polymarket.com", Config::default())?
.authentication_builder(&signer)
.authenticate()
.await?;
let credentials = client.credentials();
println!("API Key: {}", credentials.key());
```
</Tab>
</Tabs>
<Warning>
**Never commit private keys to version control.** Always use environment
variables or secure key management systems.
</Warning>
### Using the REST API
While we highly recommend using our provided clients to handle signing and authentication, the following is for developers who choose NOT to use our [Python](https://github.com/Polymarket/py-clob-client-v2) or [TypeScript](https://github.com/Polymarket/clob-client-v2) clients.
**Create API Credentials**
```bash theme={null}
POST https://clob.polymarket.com/auth/api-key
```
**Derive API Credentials**
```bash theme={null}
GET https://clob.polymarket.com/auth/derive-api-key
```
Required L1 headers:
| Header | Description |
| ---------------- | ---------------------- |
| `POLY_ADDRESS` | Polygon signer address |
| `POLY_SIGNATURE` | CLOB EIP-712 signature |
| `POLY_TIMESTAMP` | Current UNIX timestamp |
| `POLY_NONCE` | Nonce (default: 0) |
The `POLY_SIGNATURE` is generated by signing the following EIP-712 struct:
<Accordion title="EIP-712 Signing Example">
<CodeGroup>
```typescript TypeScript theme={null}
const domain = {
name: "ClobAuthDomain",
version: "1",
chainId: chainId, // Polygon Chain ID 137
};
const types = {
ClobAuth: [
{ name: "address", type: "address" },
{ name: "timestamp", type: "string" },
{ name: "nonce", type: "uint256" },
{ name: "message", type: "string" },
],
};
const value = {
address: signingAddress, // The Signing address
timestamp: ts, // The CLOB API server timestamp
nonce: nonce, // The nonce used
message: "This message attests that I control the given wallet",
};
const sig = await signer._signTypedData(domain, types, value);
```
```python Python theme={null}
domain = {
"name": "ClobAuthDomain",
"version": "1",
"chainId": chainId, # Polygon Chain ID 137
}
types = {
"ClobAuth": [
{"name": "address", "type": "address"},
{"name": "timestamp", "type": "string"},
{"name": "nonce", "type": "uint256"},
{"name": "message", "type": "string"},
]
}
value = {
"address": signingAddress, # The signing address
"timestamp": ts, # The CLOB API server timestamp
"nonce": nonce, # The nonce used
"message": "This message attests that I control the given wallet",
}
sig = signer.sign_typed_data(domain, types, value)
```
</CodeGroup>
</Accordion>
Reference implementations:
* [TypeScript](https://github.com/Polymarket/clob-client-v2/blob/main/src/signing/eip712.ts)
* [Python](https://github.com/Polymarket/py-clob-client-v2/blob/main/py_clob_client_v2/signing/eip712.py)
Response:
```json theme={null}
{
"apiKey": "550e8400-e29b-41d4-a716-446655440000",
"secret": "base64EncodedSecretString",
"passphrase": "randomPassphraseString"
}
```
**You'll need all three values for L2 authentication.**
***
## L2 Authentication Headers
All trading endpoints require these 5 headers:
| Header | Description |
| ----------------- | ----------------------------- |
| `POLY_ADDRESS` | Polygon signer address |
| `POLY_SIGNATURE` | HMAC signature for request |
| `POLY_TIMESTAMP` | Current UNIX timestamp |
| `POLY_API_KEY` | User's API `apiKey` value |
| `POLY_PASSPHRASE` | User's API `passphrase` value |
The `POLY_SIGNATURE` for L2 is an HMAC-SHA256 signature created using the user's API credentials `secret` value. Reference implementations can be found in the [TypeScript](https://github.com/Polymarket/clob-client-v2/blob/main/src/signing/hmac.ts) and [Python](https://github.com/Polymarket/py-clob-client-v2/blob/main/py_clob_client_v2/signing/hmac.py) clients.
### CLOB Client
<Tabs>
<Tab title="TypeScript">
```typescript theme={null}
import { ClobClient, Side } from "@polymarket/clob-client-v2";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const signer = createWalletClient({ account, transport: http() });
const depositWalletAddress = process.env.DEPOSIT_WALLET_ADDRESS!;
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer,
creds: apiCreds, // Generated from L1 auth, API credentials enable L2 methods
signatureType: 3, // POLY_1271, explained below
funderAddress: depositWalletAddress, // deposit wallet funder
});
// Now you can trade!
const order = await client.createAndPostOrder(
{ tokenID: "123456", price: 0.65, size: 100, side: Side.BUY },
{ tickSize: "0.01", negRisk: false }
);
```
</Tab>
<Tab title="Python">
```python theme={null}
from py_clob_client_v2 import ClobClient, OrderArgs, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
import os
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=os.getenv("PRIVATE_KEY"),
creds=api_creds, # Generated from L1 auth, API credentials enable L2 methods
signature_type=3, # POLY_1271, explained below
funder=os.getenv("DEPOSIT_WALLET_ADDRESS")
)
# Now you can trade!
order = client.create_and_post_order(
OrderArgs(token_id="123456", price=0.65, size=100, side=BUY),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
)
```
</Tab>
<Tab title="Rust">
```rust theme={null}
use polymarket_client_sdk_v2::clob::types::{Side, SignatureType};
use polymarket_client_sdk_v2::types::dec;
let deposit_wallet = std::env::var("DEPOSIT_WALLET_ADDRESS")?.parse()?;
let client = Client::new("https://clob.polymarket.com", Config::default())?
.authentication_builder(&signer)
.funder(deposit_wallet)
.signature_type(SignatureType::Poly1271)
.authenticate()
.await?;
// Now you can trade!
let order = client.limit_order()
.token_id("123456".parse()?)
.price(dec!(0.65))
.size(dec!(100))
.side(Side::Buy)
.build().await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</Tab>
</Tabs>
<Info>
Even with L2 authentication headers, methods that create user orders still
require the user to sign the order payload.
</Info>
***
## Signature Types and Funder
When initializing the L2 client, you must specify your wallet **signatureType** and the **funder** address which holds the funds:
| Signature Type | Value | Description |
| -------------- | ----- | -------------------------------------------------------------------------------------------------------------------------- |
| EOA | `0` | Standard Ethereum wallet (MetaMask). Funder is the EOA address and will need POL to pay gas on transactions. |
| POLY\_PROXY | `1` | Existing Polymarket proxy wallet flow, commonly used by users who logged in via Magic Link email/Google. |
| GNOSIS\_SAFE | `2` | Existing Gnosis Safe wallet flow. Existing Safe users can continue using this type. |
| POLY\_1271 | `3` | Deposit wallet flow for new API users. The funder is the deposit wallet address and orders are validated through ERC-1271. |
<Tip>
New API users should use deposit wallets with `POLY_1271`. Existing Safe and
Proxy users are unaffected and can keep using their current funder address and
signature type. See the [Deposit Wallet Guide](/trading/deposit-wallets) for
setup details.
</Tip>
***
## Security Best Practices
<AccordionGroup>
<Accordion title="Never expose private keys">
Store private keys in environment variables or secure key management systems. Never commit them to version control.
```bash theme={null}
# .env (never commit this file)
PRIVATE_KEY=0x...
```
</Accordion>
<Accordion title="Implement request signing on the server">
Never expose your API secret in client-side code. All authenticated requests should originate from your backend.
</Accordion>
</AccordionGroup>
***
## Troubleshooting
<AccordionGroup>
<Accordion title="Error - INVALID_SIGNATURE">
Your wallet's private key is incorrect or improperly formatted.
**Solutions:**
* Verify your private key is a valid hex string (starts with "0x")
* Ensure you're using the correct key for the intended address
* Check that the key has proper permissions
</Accordion>
<Accordion title="Error - NONCE_ALREADY_USED">
The nonce you provided has already been used to create an API key.
**Solutions:**
* Use `deriveApiKey()` with the same nonce to retrieve existing credentials
* Or use a different nonce with `createApiKey()`
</Accordion>
<Accordion title="Error - Invalid Funder Address">
Your funder address is incorrect or doesn't match your wallet.
**Solution:** Check your Polymarket profile address at [polymarket.com/settings](https://polymarket.com/settings).
If it does not exist or user has never logged into Polymarket.com, deploy it first before creating L2 authentication.
</Accordion>
<Accordion title="Lost both credentials and nonce">
Unfortunately, there's no way to recover lost API credentials without the nonce. You'll need to create new credentials:
```typescript theme={null}
// Create fresh credentials with a new nonce
const newCreds = await client.createApiKey();
// Save the nonce this time!
```
</Accordion>
</AccordionGroup>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Place Your First Order" icon="plus" href="/trading/quickstart">
Learn how to create and submit orders.
</Card>
<Card title="Geographic Restrictions" icon="globe" href="/api-reference/geoblock">
Check trading availability by region.
</Card>
</CardGroup>
@@ -1,305 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Builder Methods
> Methods for querying orders and trades attributed to your builder code.
## Overview
Builder attribution in V2 is handled natively through the order struct — you attach your **builder code** (a `bytes32` identifier from your [Builder Profile](https://polymarket.com/settings?tab=builder)) to every order you submit. No separate client configuration is required.
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient } from "@polymarket/clob-client-v2";
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer,
creds: apiCreds,
signatureType,
funderAddress,
});
// Attach your builder code on every order
const response = await client.createAndPostOrder(
{
tokenID: "0x...",
price: 0.55,
size: 100,
side: Side.BUY,
builderCode: process.env.POLY_BUILDER_CODE!,
},
{ tickSize: "0.01", negRisk: false },
);
```
```python Python theme={null}
from py_clob_client_v2 import ClobClient
from py_clob_client_v2 import OrderArgs, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
import os
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=os.getenv("PRIVATE_KEY"),
creds=creds,
signature_type=signature_type,
funder=funder,
)
# Attach your builder code on every order
response = client.create_and_post_order(
OrderArgs(
token_id="0x...",
price=0.55,
size=100,
side=BUY,
builder_code=os.environ["POLY_BUILDER_CODE"],
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
)
```
</CodeGroup>
<Info>
See [Order Attribution](/trading/orders/attribution) for the full attribution flow.
</Info>
***
## Methods
***
### getOrder
Get details for a specific order by ID.
```typescript Signature theme={null}
async getOrder(orderID: string): Promise<OpenOrder>
```
<CodeGroup>
```typescript TypeScript theme={null}
const order = await client.getOrder("0xb816482a...");
console.log(order);
```
```python Python theme={null}
order = client.get_order("0xb816482a...")
print(order)
```
</CodeGroup>
***
### getOpenOrders
Get all open orders attributed to your builder code.
```typescript Signature theme={null}
async getOpenOrders(
params?: OpenOrderParams,
only_first_page?: boolean,
): Promise<OpenOrder[]>
```
**Params**
<ResponseField name="id" type="string">
Optional. Filter by order ID.
</ResponseField>
<ResponseField name="market" type="string">
Optional. Filter by market condition ID.
</ResponseField>
<ResponseField name="asset_id" type="string">
Optional. Filter by token ID.
</ResponseField>
```typescript TypeScript theme={null}
// All open orders for this builder
const orders = await client.getOpenOrders();
// Filtered by market
const marketOrders = await client.getOpenOrders({
market: "0xbd31dc8a...",
});
```
***
### getBuilderTrades
Retrieves all trades attributed to your builder code. Use this to track which trades were routed through your platform.
```typescript Signature theme={null}
async getBuilderTrades(
params?: TradeParams,
): Promise<BuilderTradesPaginatedResponse>
```
**Params (`TradeParams`)**
<ResponseField name="id" type="string">
Optional. Filter trades by trade ID.
</ResponseField>
<ResponseField name="maker_address" type="string">
Optional. Filter trades by maker address.
</ResponseField>
<ResponseField name="market" type="string">
Optional. Filter trades by market condition ID.
</ResponseField>
<ResponseField name="asset_id" type="string">
Optional. Filter trades by asset (token) ID.
</ResponseField>
<ResponseField name="before" type="string">
Optional. Return trades created before this cursor value.
</ResponseField>
<ResponseField name="after" type="string">
Optional. Return trades created after this cursor value.
</ResponseField>
**Response (`BuilderTradesPaginatedResponse`)**
<ResponseField name="trades" type="BuilderTrade[]">
Array of trades attributed to the builder account.
</ResponseField>
<ResponseField name="next_cursor" type="string">
Cursor string for fetching the next page of results.
</ResponseField>
<ResponseField name="limit" type="number">
Maximum number of trades returned per page.
</ResponseField>
<ResponseField name="count" type="number">
Total number of trades returned in this response.
</ResponseField>
**`BuilderTrade` fields**
<ResponseField name="id" type="string">
Unique identifier for the trade.
</ResponseField>
<ResponseField name="tradeType" type="string">
Type of the trade.
</ResponseField>
<ResponseField name="takerOrderHash" type="string">
Hash of the taker order associated with this trade.
</ResponseField>
<ResponseField name="builder" type="string">
Builder code attributed to this trade.
</ResponseField>
<ResponseField name="market" type="string">
Condition ID of the market this trade belongs to.
</ResponseField>
<ResponseField name="assetId" type="string">
Token ID of the asset traded.
</ResponseField>
<ResponseField name="side" type="string">
Side of the trade (e.g. BUY or SELL).
</ResponseField>
<ResponseField name="size" type="string">
Size of the trade in shares.
</ResponseField>
<ResponseField name="sizeUsdc" type="string">
Size of the trade denominated in USDC.
</ResponseField>
<ResponseField name="price" type="string">
Price at which the trade was executed.
</ResponseField>
<ResponseField name="status" type="string">
Current status of the trade.
</ResponseField>
<ResponseField name="outcome" type="string">
Outcome label associated with the traded asset.
</ResponseField>
<ResponseField name="outcomeIndex" type="number">
Index of the outcome within the market.
</ResponseField>
<ResponseField name="owner" type="string">
Address of the order owner (taker).
</ResponseField>
<ResponseField name="maker" type="string">
Address of the maker in the trade.
</ResponseField>
<ResponseField name="transactionHash" type="string">
On-chain transaction hash for the trade.
</ResponseField>
<ResponseField name="matchTime" type="string">
Timestamp when the trade was matched.
</ResponseField>
<ResponseField name="bucketIndex" type="number">
Bucket index used for trade grouping.
</ResponseField>
<ResponseField name="fee" type="string">
Fee charged for the trade in shares.
</ResponseField>
<ResponseField name="feeUsdc" type="string">
Fee charged for the trade denominated in USDC.
</ResponseField>
<ResponseField name="err_msg" type="string | null">
Optional. Error message if the trade encountered an issue, otherwise null.
</ResponseField>
<ResponseField name="createdAt" type="string | null">
Timestamp when the trade record was created, or null if unavailable.
</ResponseField>
<ResponseField name="updatedAt" type="string | null">
Timestamp when the trade record was last updated, or null if unavailable.
</ResponseField>
***
## See Also
<CardGroup cols={2}>
<Card title="Builders Program" icon="hammer" href="/builders/overview">
Learn about the Builders Program and its benefits.
</Card>
<Card title="Order Attribution" icon="key" href="/trading/orders/attribution">
Attach your builder code to orders for volume credit.
</Card>
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
Place and manage orders with API credentials.
</Card>
<Card title="Gasless Transactions" icon="gas-pump" href="/trading/gasless">
Execute onchain operations without paying gas.
</Card>
</CardGroup>
-403
View File
@@ -1,403 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# L1 Methods
> These methods require a wallet signer (private key) but do not require user API credentials. Use these for initial setup.
## Client Initialization
L1 methods require the client to initialize with a signer.
<Tabs>
<Tab title="TypeScript">
```typescript theme={null}
import { ClobClient } from "@polymarket/clob-client-v2";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const signer = createWalletClient({ account, transport: http() });
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer, // Signer required for L1 methods
});
// Ready to create user API credentials
const apiKey = await client.createApiKey();
```
</Tab>
<Tab title="Python">
```python theme={null}
from py_clob_client_v2 import ClobClient
import os
private_key = os.getenv("PRIVATE_KEY")
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=private_key # Signer required for L1 methods
)
# Ready to create user API credentials
api_key = client.create_api_key()
```
</Tab>
</Tabs>
<Warning>
Never commit private keys to version control. Always use environment variables
or a secure key management system.
</Warning>
***
## API Key Management
***
### createApiKey
Creates a new API key (L2 credentials) for the wallet signer.
```typescript Signature theme={null}
async createApiKey(nonce?: number): Promise<ApiKeyCreds>
```
<ResponseField name="nonce" type="number">
Optional custom nonce for deterministic key generation. Optional.
</ResponseField>
<ResponseField name="apiKey" type="string">
The generated API key string.
</ResponseField>
<ResponseField name="secret" type="string">
The secret associated with the API key.
</ResponseField>
<ResponseField name="passphrase" type="string">
The passphrase associated with the API key.
</ResponseField>
***
### deriveApiKey
Derives an existing API key using a specific nonce. If you've already created credentials with a particular nonce, this returns the same credentials.
```typescript Signature theme={null}
async deriveApiKey(nonce?: number): Promise<ApiKeyCreds>
```
<ResponseField name="nonce" type="number">
The nonce used when originally creating the key. Optional.
</ResponseField>
<ResponseField name="apiKey" type="string">
The derived API key string.
</ResponseField>
<ResponseField name="secret" type="string">
The secret associated with the API key.
</ResponseField>
<ResponseField name="passphrase" type="string">
The passphrase associated with the API key.
</ResponseField>
***
### createOrDeriveApiKey
Convenience method that attempts to derive an API key with the default nonce, or creates a new one if it doesn't exist. **Recommended for initial setup.**
```typescript Signature theme={null}
async createOrDeriveApiKey(nonce?: number): Promise<ApiKeyCreds>
```
<ResponseField name="apiKey" type="string">
The API key string, either derived or newly created.
</ResponseField>
<ResponseField name="secret" type="string">
The secret associated with the API key.
</ResponseField>
<ResponseField name="passphrase" type="string">
The passphrase associated with the API key.
</ResponseField>
***
## Order Signing
<Note>
In CLOB V2, `expiration` is still accepted in order payloads for GTD/order
expiry handling, but it is not part of the EIP-712 signed order struct. The
signed struct uses `timestamp`, `metadata`, and `builder` instead of the V1
`expiration`, `nonce`, `feeRateBps`, and `taker` fields.
</Note>
### createOrder
Create and sign a limit order locally without posting it to the CLOB. Use this when you want to sign orders in advance or implement custom submission logic. Submit via [`postOrder()`](/trading/clients/l2#postorder) or [`postOrders()`](/trading/clients/l2#postorders).
```typescript Signature theme={null}
async createOrder(
userOrder: UserOrder,
options?: Partial<CreateOrderOptions>
): Promise<SignedOrder>
```
<ResponseField name="tokenID" type="string">
The token ID of the market outcome to trade.
</ResponseField>
<ResponseField name="price" type="number">
The limit price for the order.
</ResponseField>
<ResponseField name="size" type="number">
The size (number of shares) for the order.
</ResponseField>
<ResponseField name="side" type="Side">
The side of the order (buy or sell).
</ResponseField>
<ResponseField name="expiration" type="number">
Optional expiration timestamp included in the order payload for GTD/order
expiry handling. This is not part of the CLOB V2 EIP-712 signed order struct.
</ResponseField>
<ResponseField name="tickSize" type="TickSize">
The tick size used for order validation (CreateOrderOptions).
</ResponseField>
<ResponseField name="negRisk" type="boolean">
Optional flag for negative risk markets (CreateOrderOptions). Optional.
</ResponseField>
<ResponseField name="salt" type="string">
A random salt value for the signed order.
</ResponseField>
<ResponseField name="maker" type="string">
The maker's address.
</ResponseField>
<ResponseField name="signer" type="string">
The signer's address.
</ResponseField>
<ResponseField name="tokenId" type="string">
The token ID in the signed order.
</ResponseField>
<ResponseField name="makerAmount" type="string">
The maker amount as a string.
</ResponseField>
<ResponseField name="takerAmount" type="string">
The taker amount as a string.
</ResponseField>
<ResponseField name="side" type="number">
The side of the order as a number (0 = BUY, 1 = SELL).
</ResponseField>
<ResponseField name="expiration" type="string">
The expiration timestamp included in the order payload. This is not part of
the CLOB V2 EIP-712 signed order struct.
</ResponseField>
<ResponseField name="timestamp" type="string">
Order creation timestamp in milliseconds, used for order uniqueness in CLOB
V2.
</ResponseField>
<ResponseField name="metadata" type="string">
Reserved `bytes32` metadata field.
</ResponseField>
<ResponseField name="builder" type="string">
Builder code (`bytes32`) for attribution, or zero if no builder code is
attached.
</ResponseField>
<ResponseField name="signatureType" type="number">
The type identifier for the signature scheme used.
</ResponseField>
<ResponseField name="signature" type="string">
The cryptographic signature of the order.
</ResponseField>
***
### createMarketOrder
Create and sign a market order locally without posting it to the CLOB. Submit via [`postOrder()`](/trading/clients/l2#postorder) or [`postOrders()`](/trading/clients/l2#postorders).
```typescript Signature theme={null}
async createMarketOrder(
userMarketOrder: UserMarketOrder,
options?: Partial<CreateOrderOptions>
): Promise<SignedOrder>
```
<ResponseField name="tokenID" type="string">
The token ID of the market outcome to trade.
</ResponseField>
<ResponseField name="amount" type="number">
The order amount. For BUY orders this is a dollar amount; for SELL orders this
is the number of shares.
</ResponseField>
<ResponseField name="side" type="Side">
The side of the order (buy or sell).
</ResponseField>
<ResponseField name="price" type="number">
Optional price limit for the market order. Optional.
</ResponseField>
<ResponseField name="orderType" type="OrderType.FOK | OrderType.FAK">
Optional order type, either FOK (Fill-Or-Kill) or FAK (Fill-And-Kill).
Optional.
</ResponseField>
<ResponseField name="salt" type="string">
A random salt value for the signed order.
</ResponseField>
<ResponseField name="maker" type="string">
The maker's address.
</ResponseField>
<ResponseField name="signer" type="string">
The signer's address.
</ResponseField>
<ResponseField name="tokenId" type="string">
The token ID in the signed order.
</ResponseField>
<ResponseField name="makerAmount" type="string">
The maker amount as a string.
</ResponseField>
<ResponseField name="takerAmount" type="string">
The taker amount as a string.
</ResponseField>
<ResponseField name="side" type="number">
The side of the order as a number (0 = BUY, 1 = SELL).
</ResponseField>
<ResponseField name="expiration" type="string">
The expiration timestamp included in the order payload. This is not part of
the CLOB V2 EIP-712 signed order struct.
</ResponseField>
<ResponseField name="timestamp" type="string">
Order creation timestamp in milliseconds, used for order uniqueness in CLOB
V2.
</ResponseField>
<ResponseField name="metadata" type="string">
Reserved `bytes32` metadata field.
</ResponseField>
<ResponseField name="builder" type="string">
Builder code (`bytes32`) for attribution, or zero if no builder code is
attached.
</ResponseField>
<ResponseField name="signatureType" type="number">
The type identifier for the signature scheme used.
</ResponseField>
<ResponseField name="signature" type="string">
The cryptographic signature of the order.
</ResponseField>
***
## Troubleshooting
<AccordionGroup>
<Accordion title="Error - INVALID_SIGNATURE">
Your wallet's private key is incorrect or improperly formatted.
**Solution:**
* Verify your private key is a valid hex string (starts with `0x`)
* Ensure you're using the correct key for the intended address
* Check that the key has proper permissions
</Accordion>
<Accordion title="Error - NONCE_ALREADY_USED">
The nonce you provided has already been used to create an API key.
**Solution:**
* Use `deriveApiKey()` with the same nonce to retrieve existing credentials
* Or use a different nonce with `createApiKey()`
</Accordion>
<Accordion title="Error - Invalid Funder Address">
Your funder address is incorrect or doesn't match your wallet.
**Solution:** New API users should use the deposit wallet address as the
funder with signature type `3`. Existing Safe and Proxy users should use
their current smart-wallet address.
</Accordion>
<Accordion title="Lost API credentials but have nonce">
Use `deriveApiKey()` with the original nonce:
```typescript theme={null}
const recovered = await client.deriveApiKey(originalNonce);
```
</Accordion>
<Accordion title="Lost both credentials and nonce">
There's no way to recover lost credentials without the nonce. Create new ones:
```typescript theme={null}
// Create fresh credentials with a new nonce
const newCreds = await client.createApiKey();
// Save the nonce this time!
```
</Accordion>
</AccordionGroup>
***
## See Also
<CardGroup cols={2}>
<Card title="Authentication" icon="shield" href="/api-reference/authentication">
Deep dive into L1 and L2 authentication.
</Card>
<Card title="Trading Quickstart" icon="bolt" href="/trading/quickstart">
Initialize the client and place your first order.
</Card>
<Card title="Public Methods" icon="globe" href="/trading/clients/public">
Access market data, orderbooks, and prices without auth.
</Card>
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
Place and manage orders with API credentials.
</Card>
</CardGroup>
-752
View File
@@ -1,752 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# L2 Methods
> These methods require user API credentials (L2 headers). Use these for placing trades and managing your positions.
## Client Initialization
L2 methods require the client to initialize with a signer, signature type, API credentials, and funder address.
<Tabs>
<Tab title="TypeScript">
```typescript theme={null}
import { ClobClient } from "@polymarket/clob-client-v2";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const signer = createWalletClient({ account, transport: http() });
const apiCreds = {
key: process.env.API_KEY,
secret: process.env.SECRET,
passphrase: process.env.PASSPHRASE,
};
const depositWalletAddress = process.env.DEPOSIT_WALLET_ADDRESS!;
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer,
creds: apiCreds,
signatureType: 3, // POLY_1271
funderAddress: depositWalletAddress,
});
// Ready to send authenticated requests
const order = await client.postOrder(signedOrder);
```
</Tab>
<Tab title="Python">
```python theme={null}
from py_clob_client_v2 import ClobClient
from py_clob_client_v2 import ApiCreds
import os
api_creds = ApiCreds(
api_key=os.getenv("API_KEY"),
api_secret=os.getenv("SECRET"),
api_passphrase=os.getenv("PASSPHRASE")
)
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=os.getenv("PRIVATE_KEY"),
creds=api_creds,
signature_type=3, # POLY_1271
funder=os.getenv("DEPOSIT_WALLET_ADDRESS")
)
# Ready to send authenticated requests
order = client.post_order(signed_order)
```
</Tab>
</Tabs>
***
## Order Creation and Management
***
### createAndPostOrder
Convenience method that creates, signs, and posts a limit order in a single call. Use when you want to buy or sell at a specific price.
```typescript Signature theme={null}
async createAndPostOrder(
userOrder: UserOrder,
options?: Partial<CreateOrderOptions>,
orderType?: OrderType.GTC | OrderType.GTD, // Defaults to GTC
): Promise<OrderResponse>
```
**Params**
<ResponseField name="tokenID" type="string">
The token ID of the outcome to trade.
</ResponseField>
<ResponseField name="price" type="number">
The limit price for the order.
</ResponseField>
<ResponseField name="size" type="number">
The size of the order.
</ResponseField>
<ResponseField name="side" type="Side">
The side of the order (buy or sell).
</ResponseField>
<ResponseField name="expiration" type="number">
Optional expiration timestamp for the order.
</ResponseField>
<ResponseField name="tickSize" type="TickSize">
Tick size for the order. One of `"0.1"`, `"0.01"`, `"0.001"`, `"0.0001"`.
</ResponseField>
<ResponseField name="negRisk" type="boolean">
Optional. Whether the market uses negative risk.
</ResponseField>
**Response**
<ResponseField name="success" type="boolean">
Whether the order was successfully placed.
</ResponseField>
<ResponseField name="errorMsg" type="string">
Error message if the order was not successful.
</ResponseField>
<ResponseField name="orderID" type="string">
The ID of the placed order.
</ResponseField>
<ResponseField name="transactionsHashes" type="string[]">
Array of transaction hashes associated with the order.
</ResponseField>
<ResponseField name="status" type="string">
The current status of the order.
</ResponseField>
<ResponseField name="takingAmount" type="string">
The amount being taken in the order.
</ResponseField>
<ResponseField name="makingAmount" type="string">
The amount being made in the order.
</ResponseField>
***
### createAndPostMarketOrder
Convenience method that creates, signs, and posts a market order in a single call. Use when you want to buy or sell at the current market price.
```typescript Signature theme={null}
async createAndPostMarketOrder(
userMarketOrder: UserMarketOrder,
options?: Partial<CreateOrderOptions>,
orderType?: OrderType.FOK | OrderType.FAK, // Defaults to FOK
): Promise<OrderResponse>
```
**Params**
<ResponseField name="tokenID" type="string">
The token ID of the outcome to trade.
</ResponseField>
<ResponseField name="amount" type="number">
The amount for the market order.
</ResponseField>
<ResponseField name="side" type="Side">
The side of the order (buy or sell).
</ResponseField>
<ResponseField name="price" type="number">
Optional price hint for the market order.
</ResponseField>
<ResponseField name="orderType" type="OrderType.FOK | OrderType.FAK">
Optional order type override. Defaults to FOK.
</ResponseField>
**Response**
<ResponseField name="success" type="boolean">
Whether the order was successfully placed.
</ResponseField>
<ResponseField name="errorMsg" type="string">
Error message if the order was not successful.
</ResponseField>
<ResponseField name="orderID" type="string">
The ID of the placed order.
</ResponseField>
<ResponseField name="transactionsHashes" type="string[]">
Array of transaction hashes associated with the order.
</ResponseField>
<ResponseField name="status" type="string">
The current status of the order.
</ResponseField>
<ResponseField name="takingAmount" type="string">
The amount being taken in the order.
</ResponseField>
<ResponseField name="makingAmount" type="string">
The amount being made in the order.
</ResponseField>
***
### postOrder
Posts a pre-signed order to the CLOB. Use with [`createOrder()`](/trading/clients/l1#createorder) or [`createMarketOrder()`](/trading/clients/l1#createmarketorder) from L1 methods.
```typescript Signature theme={null}
async postOrder(
order: SignedOrder,
orderType?: OrderType, // Defaults to GTC
postOnly?: boolean, // Defaults to false
): Promise<OrderResponse>
```
***
### postOrders
Posts up to 15 pre-signed orders in a single batch.
```typescript Signature theme={null}
async postOrders(
args: PostOrdersArgs[],
): Promise<OrderResponse[]>
```
**Params**
<ResponseField name="order" type="SignedOrder">
The pre-signed order to post.
</ResponseField>
<ResponseField name="orderType" type="OrderType">
The order type (e.g. GTC, FOK, FAK).
</ResponseField>
<ResponseField name="postOnly" type="boolean">
Optional. Whether to post the order as post-only. Defaults to false.
</ResponseField>
***
### cancelOrder
Cancels a single open order.
```typescript Signature theme={null}
async cancelOrder(orderID: string): Promise<CancelOrdersResponse>
```
**Response**
<ResponseField name="canceled" type="string[]">
Array of order IDs that were successfully canceled.
</ResponseField>
<ResponseField name="not_canceled" type="Record<string, any>">
Map of order IDs to reasons why they could not be canceled.
</ResponseField>
***
### cancelOrders
Cancels multiple orders in a single batch.
```typescript Signature theme={null}
async cancelOrders(orderIDs: string[]): Promise<CancelOrdersResponse>
```
***
### cancelAll
Cancels all open orders.
```typescript Signature theme={null}
async cancelAll(): Promise<CancelOrdersResponse>
```
***
### cancelMarketOrders
Cancels all open orders for a specific market.
```typescript Signature theme={null}
async cancelMarketOrders(
payload: OrderMarketCancelParams
): Promise<CancelOrdersResponse>
```
**Params**
<ResponseField name="market" type="string">
Optional. The market condition ID to cancel orders for.
</ResponseField>
<ResponseField name="asset_id" type="string">
Optional. The token ID to cancel orders for.
</ResponseField>
***
## Order and Trade Queries
***
### getOrder
Get details for a specific order by ID.
```typescript Signature theme={null}
async getOrder(orderID: string): Promise<OpenOrder>
```
**Response**
<ResponseField name="id" type="string">
The unique order ID.
</ResponseField>
<ResponseField name="status" type="string">
The current status of the order.
</ResponseField>
<ResponseField name="owner" type="string">
The API key of the order owner.
</ResponseField>
<ResponseField name="maker_address" type="string">
The on-chain address of the order maker.
</ResponseField>
<ResponseField name="market" type="string">
The market condition ID the order belongs to.
</ResponseField>
<ResponseField name="asset_id" type="string">
The token ID the order is for.
</ResponseField>
<ResponseField name="side" type="string">
The side of the order (BUY or SELL).
</ResponseField>
<ResponseField name="original_size" type="string">
The original size of the order when it was placed.
</ResponseField>
<ResponseField name="size_matched" type="string">
The amount of the order that has been matched so far.
</ResponseField>
<ResponseField name="price" type="string">
The limit price of the order.
</ResponseField>
<ResponseField name="associate_trades" type="string[]">
Array of trade IDs associated with this order.
</ResponseField>
<ResponseField name="outcome" type="string">
The outcome label for the order's token.
</ResponseField>
<ResponseField name="created_at" type="number">
Unix timestamp of when the order was created.
</ResponseField>
<ResponseField name="expiration" type="string">
The expiration time of the order.
</ResponseField>
<ResponseField name="order_type" type="string">
The order type (e.g. GTC, FOK, FAK, GTD).
</ResponseField>
***
### getOpenOrders
Get all your open orders.
```typescript Signature theme={null}
async getOpenOrders(
params?: OpenOrderParams,
only_first_page?: boolean,
): Promise<OpenOrder[]>
```
**Params**
<ResponseField name="id" type="string">
Optional. Filter by order ID.
</ResponseField>
<ResponseField name="market" type="string">
Optional. Filter by market condition ID.
</ResponseField>
<ResponseField name="asset_id" type="string">
Optional. Filter by token ID.
</ResponseField>
***
### getTrades
Get your trade history (filled orders).
```typescript Signature theme={null}
async getTrades(
params?: TradeParams,
only_first_page?: boolean,
): Promise<Trade[]>
```
**Params**
<ResponseField name="id" type="string">
Optional. Filter by trade ID.
</ResponseField>
<ResponseField name="maker_address" type="string">
Optional. Filter by maker address.
</ResponseField>
<ResponseField name="market" type="string">
Optional. Filter by market condition ID.
</ResponseField>
<ResponseField name="asset_id" type="string">
Optional. Filter by token ID.
</ResponseField>
<ResponseField name="before" type="string">
Optional. Return trades before this timestamp.
</ResponseField>
<ResponseField name="after" type="string">
Optional. Return trades after this timestamp.
</ResponseField>
**Response**
<ResponseField name="id" type="string">
The unique trade ID.
</ResponseField>
<ResponseField name="taker_order_id" type="string">
The order ID of the taker side.
</ResponseField>
<ResponseField name="market" type="string">
The market condition ID for the trade.
</ResponseField>
<ResponseField name="asset_id" type="string">
The token ID for the trade.
</ResponseField>
<ResponseField name="side" type="Side">
The side of the trade (BUY or SELL).
</ResponseField>
<ResponseField name="size" type="string">
The size of the trade.
</ResponseField>
<ResponseField name="fee_rate_bps" type="string">
The fee rate in basis points.
</ResponseField>
<ResponseField name="price" type="string">
The price at which the trade was matched.
</ResponseField>
<ResponseField name="status" type="string">
The current status of the trade.
</ResponseField>
<ResponseField name="match_time" type="string">
The time at which the trade was matched.
</ResponseField>
<ResponseField name="last_update" type="string">
The time of the last update to this trade.
</ResponseField>
<ResponseField name="outcome" type="string">
The outcome label for the traded token.
</ResponseField>
<ResponseField name="bucket_index" type="number">
The bucket index for the trade.
</ResponseField>
<ResponseField name="owner" type="string">
The API key of the trade owner.
</ResponseField>
<ResponseField name="maker_address" type="string">
The on-chain address of the maker.
</ResponseField>
<ResponseField name="maker_orders" type="MakerOrder[]">
Array of maker order objects that participated in this trade. Each
`MakerOrder` contains the following fields:
</ResponseField>
<ResponseField name="maker_orders[].order_id" type="string">
The maker order ID.
</ResponseField>
<ResponseField name="maker_orders[].owner" type="string">
The API key of the maker order owner.
</ResponseField>
<ResponseField name="maker_orders[].maker_address" type="string">
The on-chain address of the maker order maker.
</ResponseField>
<ResponseField name="maker_orders[].matched_amount" type="string">
The amount matched for this maker order.
</ResponseField>
<ResponseField name="maker_orders[].price" type="string">
The price of the maker order.
</ResponseField>
<ResponseField name="maker_orders[].fee_rate_bps" type="string">
The fee rate in basis points for the maker order.
</ResponseField>
<ResponseField name="maker_orders[].asset_id" type="string">
The token ID for the maker order.
</ResponseField>
<ResponseField name="maker_orders[].outcome" type="string">
The outcome label for the maker order's token.
</ResponseField>
<ResponseField name="maker_orders[].side" type="Side">
The side of the maker order (BUY or SELL).
</ResponseField>
<ResponseField name="transaction_hash" type="string">
The on-chain transaction hash for the trade.
</ResponseField>
<ResponseField name="trader_side" type="&#x22;TAKER&#x22; | &#x22;MAKER&#x22;">
Whether the authenticated user is the taker or a maker in this trade.
</ResponseField>
***
### getTradesPaginated
Get trade history with pagination for large result sets.
```typescript Signature theme={null}
async getTradesPaginated(
params?: TradeParams,
): Promise<TradesPaginatedResponse>
```
**Response**
<ResponseField name="trades" type="Trade[]">
Array of trade objects for the current page.
</ResponseField>
<ResponseField name="limit" type="number">
The maximum number of trades returned per page.
</ResponseField>
<ResponseField name="count" type="number">
The total number of trades matching the query.
</ResponseField>
***
## Balance and Allowances
***
### getBalanceAllowance
Get your balance and allowance for specific tokens.
```typescript Signature theme={null}
async getBalanceAllowance(
params?: BalanceAllowanceParams
): Promise<BalanceAllowanceResponse>
```
**Params**
<ResponseField name="asset_type" type="AssetType">
The type of asset to query. One of `"COLLATERAL"` or `"CONDITIONAL"`.
</ResponseField>
<ResponseField name="token_id" type="string">
Optional. The token ID to query (required when `asset_type` is `CONDITIONAL`).
</ResponseField>
**Response**
<ResponseField name="balance" type="string">
The current balance for the specified asset.
</ResponseField>
<ResponseField name="allowance" type="string">
The current allowance for the specified asset.
</ResponseField>
***
### updateBalanceAllowance
Updates the cached balance and allowance for specific tokens.
```typescript Signature theme={null}
async updateBalanceAllowance(
params?: BalanceAllowanceParams
): Promise<void>
```
***
## API Key Management
***
### getApiKeys
Get all API keys associated with your account.
```typescript Signature theme={null}
async getApiKeys(): Promise<ApiKeysResponse>
```
**Response**
<ResponseField name="apiKeys" type="ApiKeyCreds[]">
Array of API key credential objects associated with the account.
</ResponseField>
***
### deleteApiKey
Deletes (revokes) the currently authenticated API key.
```typescript Signature theme={null}
async deleteApiKey(): Promise<any>
```
***
## Notifications
***
### getNotifications
Retrieves all event notifications for the authenticated user. Records are automatically removed after 48 hours.
```typescript Signature theme={null}
async getNotifications(): Promise<Notification[]>
```
**Response**
<ResponseField name="id" type="number">
Unique notification ID.
</ResponseField>
<ResponseField name="owner" type="string">
The user's API key, or an empty string for global notifications.
</ResponseField>
<ResponseField name="payload" type="any">
Type-specific payload data for the notification.
</ResponseField>
<ResponseField name="timestamp" type="number">
Optional Unix timestamp of when the notification was created.
</ResponseField>
<ResponseField name="type" type="number">
Notification type (see below).
</ResponseField>
| Name | Value | Description |
| ------------------ | ----- | ---------------------------------------- |
| Order Cancellation | `1` | User's order was canceled |
| Order Fill | `2` | User's order was filled (maker or taker) |
| Market Resolved | `4` | Market was resolved |
***
### dropNotifications
Mark notifications as read/dismissed.
```typescript Signature theme={null}
async dropNotifications(params?: DropNotificationParams): Promise<void>
```
**Params**
<ResponseField name="ids" type="string[]">
Array of notification IDs to dismiss.
</ResponseField>
***
## See Also
<CardGroup cols={2}>
<Card title="Authentication" icon="shield" href="/api-reference/authentication">
Deep dive into L1 and L2 authentication.
</Card>
<Card title="L1 Methods" icon="key" href="/trading/clients/l1">
Sign orders and derive API credentials with your private key.
</Card>
<Card title="Public Methods" icon="globe" href="/trading/clients/public">
Read market data and orderbooks without auth.
</Card>
<Card title="WebSocket" icon="bolt" href="/market-data/websocket/overview">
Real-time market data streaming.
</Card>
</CardGroup>
@@ -1,99 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Clients & SDKs
> Official open-source libraries for interacting with Polymarket
Polymarket provides official open-source clients in TypeScript, Python, and Rust. All three support the full CLOB API including market data, order management, and authentication.
## Installation
<CodeGroup>
```bash TypeScript theme={null}
npm install @polymarket/clob-client-v2 viem
```
```bash Python theme={null}
pip install py-clob-client-v2
```
```bash Rust theme={null}
cargo add polymarket_client_sdk_v2 --features clob
```
</CodeGroup>
## Quick Example
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient } from "@polymarket/clob-client-v2";
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer,
creds: apiCreds,
});
const markets = await client.getMarkets();
```
```python Python theme={null}
from py_clob_client_v2 import ClobClient
client = ClobClient(
"https://clob.polymarket.com",
key=private_key,
chain_id=137,
creds=api_creds,
)
markets = client.get_markets()
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::{Client, Config};
let client = Client::new("https://clob.polymarket.com", Config::default())?
.authentication_builder(&signer)
.authenticate()
.await?;
let markets = client.markets(None).await?;
```
</CodeGroup>
## Source Code
| Language | Package | Repository |
| ---------- | ---------------------------- | ------------------------------------------------------------------------------------------ |
| TypeScript | `@polymarket/clob-client-v2` | [github.com/Polymarket/clob-client-v2](https://github.com/Polymarket/clob-client-v2) |
| Python | `py-clob-client-v2` | [github.com/Polymarket/py-clob-client-v2](https://github.com/Polymarket/py-clob-client-v2) |
| Rust | `polymarket_client_sdk_v2` | [github.com/Polymarket/rs-clob-client-v2](https://github.com/Polymarket/rs-clob-client-v2) |
Each repository includes working examples in the `/examples` directory.
## Relayer SDK
For [gasless transactions](/trading/gasless), the relayer client handles deposit
wallet creation and signed wallet batches for new API users. Existing Safe and
Proxy wallet flows remain supported.
| Language | Package | Repository |
| ---------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
| TypeScript | `@polymarket/builder-relayer-client` | [github.com/Polymarket/builder-relayer-client](https://github.com/Polymarket/builder-relayer-client) |
| Python | `py-builder-relayer-client` | [github.com/Polymarket/py-builder-relayer-client](https://github.com/Polymarket/py-builder-relayer-client) |
## Next Steps
<CardGroup cols={2}>
<Card title="Quickstart" icon="rocket" href="/quickstart">
Set up your client and place your first order.
</Card>
<Card title="Authentication" icon="lock" href="/api-reference/authentication">
Understand L1/L2 auth and API credentials.
</Card>
</CardGroup>
@@ -1,748 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Public Methods
> These methods can be called without a signer or user credentials. Use these for reading market data, prices, and order books.
## Client Initialization
Public methods require the client to initialize with the host URL and Polygon chain ID.
<Tabs>
<Tab title="TypeScript">
```typescript theme={null}
import { ClobClient } from "@polymarket/clob-client-v2";
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
});
// Ready to call public methods
const markets = await client.getMarkets();
```
</Tab>
<Tab title="Python">
```python theme={null}
from py_clob_client_v2 import ClobClient
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137
)
# Ready to call public methods
markets = client.get_markets()
```
</Tab>
</Tabs>
***
## Health Check
***
### getOk
Health check endpoint to verify the CLOB service is operational.
```typescript Signature theme={null}
async getOk(): Promise<any>
```
***
## Markets
***
### getMarket
Get details for a single market by condition ID.
```typescript Signature theme={null}
async getMarket(conditionId: string): Promise<Market>
```
<ResponseField name="accepting_order_timestamp" type="string">
Timestamp from which the market started accepting orders, or null if not set.
</ResponseField>
<ResponseField name="accepting_orders" type="boolean">
Whether the market is currently accepting orders.
</ResponseField>
<ResponseField name="active" type="boolean">
Whether the market is active.
</ResponseField>
<ResponseField name="archived" type="boolean">
Whether the market has been archived.
</ResponseField>
<ResponseField name="closed" type="boolean">
Whether the market is closed.
</ResponseField>
<ResponseField name="condition_id" type="string">
The unique condition ID for the market.
</ResponseField>
<ResponseField name="description" type="string">
Human-readable description of the market.
</ResponseField>
<ResponseField name="enable_order_book" type="boolean">
Whether the order book is enabled for this market.
</ResponseField>
<ResponseField name="end_date_iso" type="string">
ISO 8601 end date of the market.
</ResponseField>
<ResponseField name="fpmm" type="string">
Address of the Fixed Product Market Maker contract.
</ResponseField>
<ResponseField name="game_start_time" type="string">
Start time of the underlying game or event.
</ResponseField>
<ResponseField name="icon" type="string">
URL of the market icon image.
</ResponseField>
<ResponseField name="image" type="string">
URL of the market image.
</ResponseField>
<ResponseField name="is_50_50_outcome" type="boolean">
Whether the market has equal 50/50 outcomes.
</ResponseField>
<ResponseField name="maker_base_fee" type="number">
Base fee charged to makers in basis points.
</ResponseField>
<ResponseField name="market_slug" type="string">
URL-friendly slug identifier for the market.
</ResponseField>
<ResponseField name="minimum_order_size" type="number">
Minimum order size allowed in this market.
</ResponseField>
<ResponseField name="minimum_tick_size" type="number">
Minimum price increment allowed in this market.
</ResponseField>
<ResponseField name="neg_risk" type="boolean">
Whether the market uses negative risk (binary complementary tokens).
</ResponseField>
<ResponseField name="neg_risk_market_id" type="string">
Negative risk market identifier, if applicable.
</ResponseField>
<ResponseField name="neg_risk_request_id" type="string">
Negative risk request identifier, if applicable.
</ResponseField>
<ResponseField name="notifications_enabled" type="boolean">
Whether notifications are enabled for this market.
</ResponseField>
<ResponseField name="question" type="string">
The market question text.
</ResponseField>
<ResponseField name="question_id" type="string">
Unique identifier for the market question.
</ResponseField>
<ResponseField name="rewards" type="object">
Object containing reward config: `max_spread` (number), `min_size` (number), `rates` (any)
</ResponseField>
<ResponseField name="seconds_delay" type="number">
Delay in seconds before orders are processed.
</ResponseField>
<ResponseField name="tags" type="string[]">
List of tags associated with the market.
</ResponseField>
<ResponseField name="taker_base_fee" type="number">
Base fee charged to takers in basis points.
</ResponseField>
<ResponseField name="tokens" type="MarketToken[]">
Array of market tokens, each containing `outcome` (string), `price` (number), `token_id` (string), and `winner` (boolean).
</ResponseField>
***
### getMarkets
Get details for multiple markets paginated.
```typescript Signature theme={null}
async getMarkets(): Promise<PaginationPayload>
```
<ResponseField name="limit" type="number">
Maximum number of results per page.
</ResponseField>
<ResponseField name="count" type="number">
Total number of markets returned.
</ResponseField>
<ResponseField name="data" type="Market[]">
Array of Market objects. See `getMarket()` for the full Market structure.
</ResponseField>
***
### getSimplifiedMarkets
Get simplified market data paginated for faster loading.
```typescript Signature theme={null}
async getSimplifiedMarkets(): Promise<PaginationPayload>
```
<ResponseField name="limit" type="number">
Maximum number of results per page.
</ResponseField>
<ResponseField name="count" type="number">
Total number of markets returned.
</ResponseField>
<ResponseField name="data" type="SimplifiedMarket[]">
Array of simplified market objects, each containing `accepting_orders` (boolean), `active` (boolean), `archived` (boolean), `closed` (boolean), `condition_id` (string), `rewards` (object with `rates`, `min_size`, `max_spread`), and `tokens` (SimplifiedToken\[]) with `outcome` (string), `price` (number), `token_id` (string).
</ResponseField>
***
### getSamplingMarkets
Get markets eligible for sampling/liquidity rewards.
```typescript Signature theme={null}
async getSamplingMarkets(): Promise<PaginationPayload>
```
***
### getSamplingSimplifiedMarkets
Get simplified market data for markets eligible for sampling/liquidity rewards.
```typescript Signature theme={null}
async getSamplingSimplifiedMarkets(): Promise<PaginationPayload>
```
***
## Order Books and Prices
***
### calculateMarketPrice
Calculate the estimated price for a market order of a given size.
```typescript Signature theme={null}
async calculateMarketPrice(
tokenID: string,
side: Side,
amount: number,
orderType: OrderType = OrderType.FOK
): Promise<number>
```
<ResponseField name="tokenID" type="string">
The token ID to calculate the market price for.
</ResponseField>
<ResponseField name="side" type="Side">
The side of the order. One of: `BUY`, `SELL`
</ResponseField>
<ResponseField name="amount" type="number">
The size of the order to calculate price for.
</ResponseField>
<ResponseField name="orderType" type="OrderType">
The order type. One of: `GTC` (Good Till Cancelled), `FOK` (Fill or Kill), `GTD` (Good Till Date), `FAK` (Fill and Kill). Defaults to `FOK`.
</ResponseField>
<ResponseField name="returns" type="number">
The calculated estimated market price for the given order size.
</ResponseField>
***
### getOrderBook
Get the order book for a specific token ID.
```typescript Signature theme={null}
async getOrderBook(tokenID: string): Promise<OrderBookSummary>
```
<ResponseField name="market" type="string">
The market condition ID.
</ResponseField>
<ResponseField name="asset_id" type="string">
The token/asset ID for this order book.
</ResponseField>
<ResponseField name="timestamp" type="string">
Timestamp of the order book snapshot.
</ResponseField>
<ResponseField name="bids" type="OrderSummary[]">
Array of bid entries, each with `price` (string) and `size` (string).
</ResponseField>
<ResponseField name="asks" type="OrderSummary[]">
Array of ask entries, each with `price` (string) and `size` (string).
</ResponseField>
<ResponseField name="min_order_size" type="string">
Minimum order size for this market.
</ResponseField>
<ResponseField name="tick_size" type="string">
Minimum price increment for this market.
</ResponseField>
<ResponseField name="neg_risk" type="boolean">
Whether the market uses negative risk.
</ResponseField>
<ResponseField name="hash" type="string">
Hash of the order book state.
</ResponseField>
***
### getOrderBooks
Get order books for multiple token IDs.
```typescript Signature theme={null}
async getOrderBooks(params: BookParams[]): Promise<OrderBookSummary[]>
```
<ResponseField name="token_id" type="string">
The token ID to fetch the order book for.
</ResponseField>
<ResponseField name="side" type="Side">
The side of the book to query. One of: `BUY`, `SELL`
</ResponseField>
<ResponseField name="returns" type="OrderBookSummary[]">
Array of OrderBookSummary objects. See `getOrderBook()` for the full structure.
</ResponseField>
***
### getPrice
Get the current best price for buying or selling a token ID.
```typescript Signature theme={null}
async getPrice(
tokenID: string,
side: "BUY" | "SELL"
): Promise<any>
```
<ResponseField name="price" type="string">
The current best price for the requested side.
</ResponseField>
***
### getPrices
Get the current best prices for multiple token IDs.
```typescript Signature theme={null}
async getPrices(params: BookParams[]): Promise<PricesResponse>
```
<ResponseField name="returns" type="PricesResponse">
A map of token IDs to their prices. Each entry contains an optional `BUY` (string) and/or `SELL` (string) price.
</ResponseField>
***
### getMidpoint
Get the midpoint price (average of best bid and best ask) for a token ID.
```typescript Signature theme={null}
async getMidpoint(tokenID: string): Promise<any>
```
<ResponseField name="mid" type="string">
The midpoint price, calculated as the average of best bid and best ask.
</ResponseField>
***
### getMidpoints
Get the midpoint prices for multiple token IDs.
```typescript Signature theme={null}
async getMidpoints(params: BookParams[]): Promise<any>
```
<ResponseField name="returns" type="object">
A map of token IDs to their midpoint price strings. Each key is a token ID and its value is the midpoint price as a string.
</ResponseField>
***
### getSpread
Get the spread (difference between best ask and best bid) for a token ID.
```typescript Signature theme={null}
async getSpread(tokenID: string): Promise<SpreadResponse>
```
<ResponseField name="spread" type="string">
The spread value, calculated as the difference between best ask and best bid.
</ResponseField>
***
### getSpreads
Get the spreads for multiple token IDs.
```typescript Signature theme={null}
async getSpreads(params: BookParams[]): Promise<SpreadsResponse>
```
<ResponseField name="returns" type="object">
A map of token IDs to their spread strings. Each key is a token ID and its value is the spread as a string.
</ResponseField>
***
### getPricesHistory
Get historical price data for a token.
```typescript Signature theme={null}
async getPricesHistory(params: PriceHistoryFilterParams): Promise<MarketPrice[]>
```
<ResponseField name="market" type="string">
The token ID to fetch price history for.
</ResponseField>
<ResponseField name="startTs" type="number">
Optional start timestamp (Unix seconds) for the price history range.
</ResponseField>
<ResponseField name="endTs" type="number">
Optional end timestamp (Unix seconds) for the price history range.
</ResponseField>
<ResponseField name="fidelity" type="number">
Optional fidelity/resolution of the price history data.
</ResponseField>
<ResponseField name="interval" type="PriceHistoryInterval">
Time interval for the price history. One of: `max`, `1w`, `1d`, `6h`, `1h`
</ResponseField>
<ResponseField name="t" type="number">
Unix timestamp of the price data point.
</ResponseField>
<ResponseField name="p" type="number">
Price value at the corresponding timestamp.
</ResponseField>
***
## Trades
***
### getLastTradePrice
Get the price of the most recent trade for a token.
```typescript Signature theme={null}
async getLastTradePrice(tokenID: string): Promise<LastTradePrice>
```
<ResponseField name="price" type="string">
The price of the most recent trade.
</ResponseField>
<ResponseField name="side" type="string">
The side of the most recent trade.
</ResponseField>
***
### getLastTradesPrices
Get the most recent trade prices for multiple tokens.
```typescript Signature theme={null}
async getLastTradesPrices(params: BookParams[]): Promise<LastTradePriceWithToken[]>
```
<ResponseField name="price" type="string">
The price of the most recent trade for the token.
</ResponseField>
<ResponseField name="side" type="string">
The side of the most recent trade.
</ResponseField>
<ResponseField name="token_id" type="string">
The token ID this trade price corresponds to.
</ResponseField>
***
### getMarketTradesEvents
Get recent trade events for a market.
```typescript Signature theme={null}
async getMarketTradesEvents(conditionID: string): Promise<MarketTradeEvent[]>
```
<ResponseField name="event_type" type="string">
The type of trade event.
</ResponseField>
<ResponseField name="market" type="object">
Object containing market info: `condition_id` (string), `asset_id` (string), `question` (string), `icon` (string), `slug` (string).
</ResponseField>
<ResponseField name="user" type="object">
Object containing user info: `address` (string), `username` (string), `profile_picture` (string), `optimized_profile_picture` (string), `pseudonym` (string).
</ResponseField>
<ResponseField name="side" type="Side">
The side of the trade. One of: `BUY`, `SELL`
</ResponseField>
<ResponseField name="size" type="string">
The size of the trade.
</ResponseField>
<ResponseField name="fee_rate_bps" type="string">
The fee rate in basis points for the trade.
</ResponseField>
<ResponseField name="price" type="string">
The price at which the trade was executed.
</ResponseField>
<ResponseField name="outcome" type="string">
The outcome label for the traded token.
</ResponseField>
<ResponseField name="outcome_index" type="number">
The index of the outcome in the market.
</ResponseField>
<ResponseField name="transaction_hash" type="string">
The on-chain transaction hash for the trade.
</ResponseField>
<ResponseField name="timestamp" type="string">
The timestamp of when the trade event occurred.
</ResponseField>
***
## Market Parameters
***
### getClobMarketInfo
Fetch all CLOB-level parameters for a market in a single call — tokens, tick size, base fees, rewards config, RFQ status, and fee details.
```typescript Signature theme={null}
async getClobMarketInfo(conditionID: string): Promise<ClobMarketDetails>
```
<ResponseField name="conditionID" type="string">
The condition ID of the market.
</ResponseField>
**Response (`ClobMarketDetails`)**
<ResponseField name="gst" type="string | null">
Game start time (used for sports markets), ISO 8601 timestamp or `null`.
</ResponseField>
<ResponseField name="r" type="object">
Rewards configuration for the market.
</ResponseField>
<ResponseField name="t" type="ClobToken[]">
Tokens for this market. Each entry has:
* `t` (string) — token ID
* `o` (string) — outcome label (e.g. `Yes`, `No`)
</ResponseField>
<ResponseField name="mos" type="number">
Minimum order size.
</ResponseField>
<ResponseField name="mts" type="number">
Minimum tick size (price increment).
</ResponseField>
<ResponseField name="mbf" type="number">
Maker base fee in basis points.
</ResponseField>
<ResponseField name="tbf" type="number">
Taker base fee in basis points.
</ResponseField>
<ResponseField name="rfqe" type="boolean">
Whether RFQ (Request for Quote) is enabled for this market.
</ResponseField>
<ResponseField name="itode" type="boolean">
Whether taker order delay is enabled.
</ResponseField>
<ResponseField name="ibce" type="boolean">
Whether Blockaid check is enabled.
</ResponseField>
<ResponseField name="fd" type="object">
Fee curve parameters:
* `r` (number) — fee rate
* `e` (number) — fee curve exponent
* `to` (boolean) — whether fees apply to takers only
</ResponseField>
<ResponseField name="oas" type="number">
Minimum order age in seconds.
</ResponseField>
***
### getFeeRateBps
Get the fee rate in basis points for a token.
```typescript Signature theme={null}
async getFeeRateBps(tokenID: string): Promise<number>
```
<ResponseField name="returns" type="number">
The fee rate in basis points for the specified token.
</ResponseField>
***
### getFeeExponent
Get the fee curve exponent for a token. The exponent shapes the fee curve used by the protocol when calculating fees at match time.
```typescript Signature theme={null}
async getFeeExponent(tokenID: string): Promise<number>
```
<ResponseField name="returns" type="number">
The fee curve exponent for the specified token's market.
</ResponseField>
***
### getTickSize
Get the tick size (minimum price increment) for a market.
```typescript Signature theme={null}
async getTickSize(tokenID: string): Promise<TickSize>
```
<ResponseField name="returns" type="string">
The tick size for the market. One of: `0.1`, `0.01`, `0.001`, `0.0001`
</ResponseField>
***
### getNegRisk
Check if a market uses negative risk (binary complementary tokens).
```typescript Signature theme={null}
async getNegRisk(tokenID: string): Promise<boolean>
```
<ResponseField name="returns" type="boolean">
Whether the market uses negative risk.
</ResponseField>
***
## Time and Server Info
### getServerTime
Get the current server timestamp.
```typescript Signature theme={null}
async getServerTime(): Promise<number>
```
<ResponseField name="returns" type="number">
Unix timestamp in seconds representing the current server time.
</ResponseField>
***
## See Also
<CardGroup cols={2}>
<Card title="L1 Methods" icon="key" href="/trading/clients/l1">
Private key authentication to create or derive API credentials.
</Card>
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
Place orders, cancel orders, and query your trades.
</Card>
<Card title="REST API Reference" icon="code" href="/api-reference/introduction">
Complete REST endpoint documentation.
</Card>
<Card title="WebSocket" icon="bolt" href="/market-data/websocket/overview">
Real-time market data streaming.
</Card>
</CardGroup>
-217
View File
@@ -1,217 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Geographic Restrictions
> Check geographic restrictions before placing orders on the Polymarket API
Polymarket restricts order placement from certain geographic locations due to regulatory requirements and compliance with international sanctions. Before placing orders, builders should verify the location.
<Warning>
Orders submitted from blocked regions will be rejected. Implement geoblock
checks in your application to provide users with appropriate feedback before
they attempt to trade.
</Warning>
***
## Geoblock Endpoint
Check the geographic eligibility of the requesting IP address:
```bash theme={null}
GET https://polymarket.com/api/geoblock
```
<Note>This endpoint is on `polymarket.com`, not the API servers.</Note>
### Response
```json theme={null}
{
"blocked": true,
"ip": "203.0.113.42",
"country": "US",
"region": "NY"
}
```
| Field | Type | Description |
| --------- | ------- | ----------------------------------------------- |
| `blocked` | boolean | Whether the user is blocked from placing orders |
| `ip` | string | Detected IP address |
| `country` | string | ISO 3166-1 alpha-2 country code |
| `region` | string | Region/state code |
***
## Blocked Countries
The following countries are restricted from placing orders on Polymarket. Countries marked as **close-only** can close existing positions but cannot open new ones. Countries marked as **frontend UI restricted** are blocked only on the Polymarket frontend; the API itself is not restricted:
| Country Code | Country Name | Status |
| ------------ | ------------------------------------ | ---------------------- |
| AU | Australia | Blocked |
| BE | Belgium | Blocked |
| BY | Belarus | Blocked |
| BI | Burundi | Blocked |
| CF | Central African Republic | Blocked |
| CD | Congo (Kinshasa) | Blocked |
| CU | Cuba | Blocked |
| DE | Germany | Blocked |
| ET | Ethiopia | Blocked |
| FR | France | Blocked |
| GB | United Kingdom | Blocked |
| IR | Iran | Blocked |
| IQ | Iraq | Blocked |
| IT | Italy | Blocked |
| JP | Japan | Frontend UI restricted |
| KP | North Korea | Blocked |
| LB | Lebanon | Blocked |
| LY | Libya | Blocked |
| MM | Myanmar | Blocked |
| NI | Nicaragua | Blocked |
| NL | Netherlands | Blocked |
| PL | Poland | Close-only |
| RU | Russia | Blocked |
| SG | Singapore | Close-only |
| SO | Somalia | Blocked |
| SS | South Sudan | Blocked |
| SD | Sudan | Blocked |
| SY | Syria | Blocked |
| TH | Thailand | Close-only |
| TW | Taiwan | Close-only |
| UM | United States Minor Outlying Islands | Blocked |
| US | United States | Blocked |
| VE | Venezuela | Blocked |
| YE | Yemen | Blocked |
| ZW | Zimbabwe | Blocked |
***
## Blocked Regions
In addition to fully blocked countries, the following specific regions within otherwise accessible countries are also restricted:
| Country | Region | Region Code |
| ------------ | ------- | ----------- |
| Canada (CA) | Ontario | ON |
| Ukraine (UA) | Crimea | 43 |
| Ukraine (UA) | Donetsk | 14 |
| Ukraine (UA) | Luhansk | 09 |
***
## Blocking Logic
The geoblocking system includes:
1. **OFAC-Sanctioned Countries**: Countries sanctioned by the U.S. Office of Foreign Assets Control (OFAC)
2. **Additional Regulatory Restrictions**: Countries added for specific regulatory compliance reasons
***
## Server Infrastructure
* **Primary Servers**: eu-west-2
* **Closest Non-Georestricted Region**: eu-west-1
<Tip>
**Direct co-location available.** Users who complete the [KYC/KYB
form](https://docs.google.com/forms/d/e/1FAIpQLSfY-3Dl3yxq8HKFjFad8YzKZmm0k3Gdg29HD6gL-K-AmI6KXw/viewform) can get access to co-locate
directly in `eu-west-2` for the lowest possible latency to Polymarket's
primary servers.
</Tip>
***
## Usage Examples
<Tabs>
<Tab title="TypeScript">
```typescript theme={null}
interface GeoblockResponse {
blocked: boolean;
ip: string;
country: string;
region: string;
}
async function checkGeoblock(): Promise<GeoblockResponse> {
const response = await fetch("https://polymarket.com/api/geoblock");
return response.json();
}
// Usage
const geo = await checkGeoblock();
if (geo.blocked) {
console.log(`Trading not available in ${geo.country}`);
} else {
console.log("Trading available");
}
```
</Tab>
<Tab title="Python">
```python theme={null}
import requests
def check_geoblock() -> dict:
response = requests.get("https://polymarket.com/api/geoblock")
return response.json()
# Usage
geo = check_geoblock()
if geo["blocked"]:
print(f"Trading not available in {geo['country']}")
else:
print("Trading available")
```
</Tab>
<Tab title="Rust">
```rust theme={null}
use polymarket_client_sdk_v2::clob::{Client, Config};
let client = Client::new("https://clob.polymarket.com", Config::default())?;
let geo = client.check_geoblock().await?;
if geo.blocked {
println!("Trading not available in {}", geo.country);
} else {
println!("Trading available");
}
```
</Tab>
</Tabs>
***
## Why These Restrictions
Geographic restrictions are implemented to ensure compliance with:
* International sanctions and embargoes
* Local financial regulations
* Gambling and prediction market laws
* Anti-money laundering (AML) requirements
* Know Your Customer (KYC) regulations
If you believe you are incorrectly restricted or have questions about geographic availability, please contact [Polymarket Support](https://polymarket.com/support).
***
## Next Steps
<CardGroup cols={2}>
<Card title="Authentication" icon="key" href="/api-reference/authentication">
Learn how to authenticate trading requests.
</Card>
<Card title="Place Orders" icon="plus" href="/trading/quickstart">
Start placing orders (from eligible regions).
</Card>
</CardGroup>
-265
View File
@@ -1,265 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Overview
> Trading on the Polymarket CLOB
Polymarket's CLOB (Central Limit Order Book) is a hybrid-decentralized trading system — offchain order matching with onchain settlement via the [Exchange contract](https://github.com/Polymarket/ctf-exchange/tree/main/src) ([audited by Chainsecurity](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)). All trading is non-custodial. Orders are [EIP-712](https://eips.ethereum.org/EIPS/eip-712) signed messages, and matched trades settle atomically on Polygon. The operator cannot set prices or execute unauthorized trades.
We recommend using the open-source SDK clients, which handle order signing, authentication, and submission:
<CardGroup cols={3}>
<Card title="TypeScript Client" icon="github" href="https://github.com/Polymarket/clob-client-v2">
<p className="font-mono text-[0.8rem]">
npm install @polymarket/clob-client-v2 viem
</p>
</Card>
<Card title="Python Client" icon="github" href="https://github.com/Polymarket/py-clob-client-v2">
<p className="font-mono text-[0.8rem]">pip install py-clob-client-v2</p>
</Card>
<Card title="Rust Client" icon="github" href="https://github.com/Polymarket/rs-clob-client-v2">
<p className="font-mono text-[0.8rem]">
cargo add polymarket\_client\_sdk\_v2 --features clob
</p>
</Card>
</CardGroup>
<Info>
You can also use the REST API directly, but you'll need to manage [EIP-712
order
signing](https://github.com/Polymarket/clob-client-v2/blob/main/src/signing/eip712.ts)
and [HMAC authentication
headers](https://github.com/Polymarket/clob-client-v2/blob/main/src/signing/hmac.ts)
yourself. See [REST API Headers](#rest-api-headers) below.
</Info>
***
## Authentication
The CLOB uses two levels of authentication:
| Level | Method | Purpose |
| ------ | ------------------------------- | ----------------------------------------- |
| **L1** | EIP-712 signature (private key) | Create or derive API credentials |
| **L2** | HMAC-SHA256 (API credentials) | Place orders, cancel orders, query trades |
You use your private key once to derive **L2 credentials** (API key, secret, passphrase), which authenticate all subsequent trading requests.
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient } from "@polymarket/clob-client-v2";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const signer = createWalletClient({ account, transport: http() });
// Derive L2 API credentials
const tempClient = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer,
});
const apiCreds = await tempClient.createOrDeriveApiKey();
```
```python Python theme={null}
from py_clob_client_v2 import ClobClient
import os
private_key = os.getenv("PRIVATE_KEY")
# Derive L2 API credentials
temp_client = ClobClient("https://clob.polymarket.com", key=private_key, chain_id=137)
api_creds = temp_client.create_or_derive_api_key()
```
```rust Rust theme={null}
use std::str::FromStr;
use polymarket_client_sdk_v2::POLYGON;
use polymarket_client_sdk_v2::auth::{LocalSigner, Signer};
use polymarket_client_sdk_v2::clob::{Client, Config};
let private_key = std::env::var("POLYMARKET_PRIVATE_KEY")?;
let signer = LocalSigner::from_str(&private_key)?
.with_chain_id(Some(POLYGON));
// Derive L2 API credentials and initialize client in one step
let client = Client::new("https://clob.polymarket.com", Config::default())?
.authentication_builder(&signer)
.authenticate()
.await?;
```
</CodeGroup>
***
## Signature Types
When initializing the trading client, you must specify your wallet's **signature type** and **funder address**:
| Wallet Type | ID | When to Use | Funder Address |
| ---------------- | --- | -------------------------------------------------------------------------------------------------------------- | --------------------------- |
| **EOA** | `0` | Standalone wallet — you pay your own gas (POL for gas) | Your EOA wallet address |
| **POLY\_PROXY** | `1` | Existing Polymarket proxy wallet flow | Your proxy wallet address |
| **GNOSIS\_SAFE** | `2` | Existing Gnosis Safe wallet flow | Your Safe wallet address |
| **POLY\_1271** | `3` | Deposit wallet flow for new API users. Orders are signed by the owner/session signer and validated by ERC-1271 | Your deposit wallet address |
<Note>
New API users should use deposit wallets with signature type `3`. Existing
Proxy and Safe users are unaffected and can keep using signature types `1` and
`2`. Type `0` is for standalone EOA wallets only.
</Note>
### Initialize the Trading Client
<CodeGroup>
```typescript TypeScript theme={null}
const depositWalletAddress = process.env.DEPOSIT_WALLET_ADDRESS!;
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer,
creds: apiCreds,
signatureType: 3, // POLY_1271
funderAddress: depositWalletAddress,
});
```
```python Python theme={null}
deposit_wallet_address = os.getenv("DEPOSIT_WALLET_ADDRESS")
client = ClobClient(
"https://clob.polymarket.com",
key=private_key,
chain_id=137,
creds=api_creds,
signature_type=3, # POLY_1271
funder=deposit_wallet_address
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::SignatureType;
let deposit_wallet = std::env::var("DEPOSIT_WALLET_ADDRESS")?.parse()?;
let client = Client::new("https://clob.polymarket.com", Config::default())?
.authentication_builder(&signer)
.funder(deposit_wallet)
.signature_type(SignatureType::Poly1271)
.authenticate()
.await?;
```
</CodeGroup>
***
## REST API Headers
If you're using the REST API directly (without the SDK), you need to attach authentication headers to each request.
**L1 Headers** — for creating or deriving API credentials:
| Header | Description |
| ---------------- | ------------------- |
| `POLY_ADDRESS` | Your wallet address |
| `POLY_SIGNATURE` | EIP-712 signature |
| `POLY_TIMESTAMP` | Unix timestamp |
| `POLY_NONCE` | Request nonce |
**L2 Headers** — for all trading operations (orders, cancellations, queries):
| Header | Description |
| ----------------- | ------------------------------------ |
| `POLY_ADDRESS` | Your wallet address |
| `POLY_SIGNATURE` | HMAC-SHA256 signature of the request |
| `POLY_TIMESTAMP` | Unix timestamp |
| `POLY_API_KEY` | Your API key |
| `POLY_PASSPHRASE` | Your API passphrase |
<Note>
Even with L2 authentication, methods that create orders still require the
user's private key for EIP-712 order payload signing. L2 credentials
authenticate the request, but the order itself must be signed by the key.
</Note>
***
## Client Methods
<CardGroup cols={2}>
<Card title="Public Methods" icon="globe" href="/trading/clients/public">
Market data, orderbooks, prices, and spreads — no auth required.
</Card>
<Card title="L1 Methods" icon="key" href="/trading/clients/l1">
Sign orders and derive API credentials with your private key.
</Card>
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
Place orders, cancel orders, query trades, and manage notifications.
</Card>
<Card title="Builder Methods" icon="hammer" href="/trading/clients/builder">
Track orders and trades attributed to your builder code.
</Card>
</CardGroup>
***
## Server Infrastructure
The CLOB matching engine runs in the following regions:
* **Primary Servers**: eu-west-2
* **Closest Non-Georestricted Region**: eu-west-1
<Tip>
**Direct co-location available.** Users who complete the [KYC/KYB
form](https://docs.google.com/forms/d/e/1FAIpQLSfY-3Dl3yxq8HKFjFad8YzKZmm0k3Gdg29HD6gL-K-AmI6KXw/viewform) can get access to co-locate
directly in `eu-west-2` for the lowest possible latency to Polymarket's
primary servers. See [Geographic
Restrictions](/api-reference/geoblock#server-infrastructure) for full
geographic availability details.
</Tip>
***
## What Is in This Section
<CardGroup cols={2}>
<Card title="Quickstart" icon="bolt" href="/trading/quickstart">
Place your first order end-to-end
</Card>
<Card title="Orderbook" icon="chart-bar" href="/trading/orderbook">
Reading the orderbook, prices, spreads, and midpoints
</Card>
<Card title="Orders" icon="list-check" href="/trading/orders/create">
Order types, tick sizes, creating, cancelling, and querying orders
</Card>
<Card title="Fees" icon="receipt" href="/trading/fees">
Fee structure, fee-enabled markets, and maker rebates
</Card>
<Card title="Gasless Transactions" icon="gas-pump" href="/trading/gasless">
Execute onchain operations without paying gas
</Card>
<Card title="CTF Tokens" icon="coins" href="/trading/ctf/overview">
Split, merge, and redeem outcome tokens
</Card>
<Card title="Bridge" icon="bridge" href="/trading/bridge/deposit">
Deposit and withdraw funds across chains
</Card>
</CardGroup>
@@ -1,391 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Cancel Order
> Cancel single, multiple, or all open orders
All cancel endpoints require [L2 authentication](/trading/overview#authentication). The response always includes `canceled` (list of cancelled order IDs) and `not_canceled` (map of order IDs to failure reasons).
***
## Cancel a Single Order
<CodeGroup>
```typescript TypeScript theme={null}
const resp = await client.cancelOrder("0xb816482a...");
console.log(resp);
// { canceled: ["0xb816482a..."], not_canceled: {} }
```
```python Python theme={null}
resp = client.cancel(order_id="0xb816482a...")
print(resp)
# {"canceled": ["0xb816482a..."], "not_canceled": {}}
```
```rust Rust theme={null}
let resp = client.cancel_order("0xb816482a...").await?;
println!("{:?}", resp);
// CancelOrdersResponse { canceled: ["0xb816482a..."], not_canceled: {} }
```
```bash REST theme={null}
curl -X DELETE "https://clob.polymarket.com/order" \
-H "Content-Type: application/json" \
-H "POLY_ADDRESS: ..." \
-H "POLY_SIGNATURE: ..." \
-H "POLY_TIMESTAMP: ..." \
-H "POLY_API_KEY: ..." \
-H "POLY_PASSPHRASE: ..." \
-d '{"orderID": "0xb816482a..."}'
```
</CodeGroup>
***
## Cancel Multiple Orders
<CodeGroup>
```typescript TypeScript theme={null}
const resp = await client.cancelOrders(["0xb816482a...", "0xc927593b..."]);
```
```python Python theme={null}
resp = client.cancel_orders([
"0xb816482a...",
"0xc927593b...",
])
```
```rust Rust theme={null}
let resp = client.cancel_orders(&["0xb816482a...", "0xc927593b..."]).await?;
```
```bash REST theme={null}
curl -X DELETE "https://clob.polymarket.com/orders" \
-H "Content-Type: application/json" \
-H "POLY_ADDRESS: ..." \
-H "POLY_SIGNATURE: ..." \
-H "POLY_TIMESTAMP: ..." \
-H "POLY_API_KEY: ..." \
-H "POLY_PASSPHRASE: ..." \
-d '["0xb816482a...", "0xc927593b..."]'
```
</CodeGroup>
***
## Cancel All Orders
Cancel every open order across all markets:
<CodeGroup>
```typescript TypeScript theme={null}
const resp = await client.cancelAll();
```
```python Python theme={null}
resp = client.cancel_all()
```
```rust Rust theme={null}
let resp = client.cancel_all_orders().await?;
```
```bash REST theme={null}
curl -X DELETE "https://clob.polymarket.com/cancel-all" \
-H "POLY_ADDRESS: ..." \
-H "POLY_SIGNATURE: ..." \
-H "POLY_TIMESTAMP: ..." \
-H "POLY_API_KEY: ..." \
-H "POLY_PASSPHRASE: ..."
```
</CodeGroup>
***
## Cancel by Market
Cancel all orders for a specific market, optionally filtered to a single token. Both `market` and `asset_id` are optional — omit both to cancel all orders.
<CodeGroup>
```typescript TypeScript theme={null}
const resp = await client.cancelMarketOrders({
market: "0xbd31dc8a...", // optional: condition ID
asset_id: "52114319501245...", // optional: specific token
});
```
```python Python theme={null}
resp = client.cancel_market_orders(
market="0xbd31dc8a...",
asset_id="52114319501245...", # optional
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::request::CancelMarketOrderRequest;
let request = CancelMarketOrderRequest::builder()
.market("0xbd31dc8a...".parse()?)
.asset_id("52114319501245...".parse()?)
.build();
let resp = client.cancel_market_orders(&request).await?;
```
```bash REST theme={null}
curl -X DELETE "https://clob.polymarket.com/cancel-market-orders" \
-H "Content-Type: application/json" \
-H "POLY_ADDRESS: ..." \
-H "POLY_SIGNATURE: ..." \
-H "POLY_TIMESTAMP: ..." \
-H "POLY_API_KEY: ..." \
-H "POLY_PASSPHRASE: ..." \
-d '{"market": "0xbd31dc8a...", "asset_id": "52114319501245..."}'
```
</CodeGroup>
***
## Querying Orders
### Get a Single Order
<CodeGroup>
```typescript TypeScript theme={null}
const order = await client.getOrder("0xb816482a...");
console.log(order.status, order.size_matched);
```
```python Python theme={null}
order = client.get_order("0xb816482a...")
print(order["status"], order["size_matched"])
```
```rust Rust theme={null}
let order = client.order("0xb816482a...").await?;
println!("{:?} {}", order.status, order.size_matched);
```
</CodeGroup>
### Get Open Orders
Retrieve all open orders, optionally filtered by market or token:
<CodeGroup>
```typescript TypeScript theme={null}
// All open orders
const orders = await client.getOpenOrders();
// Filtered by market
const marketOrders = await client.getOpenOrders({
market: "0xbd31dc8a...",
});
// Filtered by token
const tokenOrders = await client.getOpenOrders({
asset_id: "52114319501245...",
});
```
```python Python theme={null}
from py_clob_client_v2 import OpenOrderParams
# All open orders
orders = client.get_orders()
# Filtered by market
market_orders = client.get_orders(
OpenOrderParams(market="0xbd31dc8a...")
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::request::OrdersRequest;
// All open orders
let orders = client.orders(&OrdersRequest::default(), None).await?;
// Filtered by market
let request = OrdersRequest::builder()
.market("0xbd31dc8a...".parse()?)
.build();
let market_orders = client.orders(&request, None).await?;
```
</CodeGroup>
### OpenOrder Object
| Field | Type | Description |
| ------------------ | --------- | ------------------------------------------ |
| `id` | string | Order ID |
| `status` | string | Current order status |
| `market` | string | Condition ID |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `original_size` | string | Size at placement |
| `size_matched` | string | Amount filled |
| `price` | string | Limit price |
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
| `order_type` | string | Order type (GTC, GTD, FOK, FAK) |
| `maker_address` | string | Funder address |
| `owner` | string | API key of the order owner |
| `associate_trades` | string\[] | Trade IDs this order has been included in |
| `expiration` | string | Unix expiration timestamp (`0` if none) |
| `created_at` | string | Unix creation timestamp |
***
## Trade History
When an order is matched, it creates a trade. Trades progress through these statuses:
| Status | Terminal | Description |
| ----------- | -------- | --------------------------------------- |
| `MATCHED` | No | Matched and sent for onchain submission |
| `MINED` | No | Mined on the chain, no finality yet |
| `CONFIRMED` | Yes | Achieved finality — trade successful |
| `RETRYING` | No | Transaction failed — being retried |
| `FAILED` | Yes | Failed permanently |
<CodeGroup>
```typescript TypeScript theme={null}
// All trades
const trades = await client.getTrades();
// Filtered by market
const marketTrades = await client.getTrades({
market: "0xbd31dc8a...",
});
```
```python Python theme={null}
from py_clob_client_v2 import TradeParams
trades = client.get_trades()
market_trades = client.get_trades(
TradeParams(market="0xbd31dc8a...")
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::request::TradesRequest;
// All trades
let trades = client.trades(&TradesRequest::default(), None).await?;
// Filtered by market
let request = TradesRequest::builder()
.market("0xbd31dc8a...".parse()?)
.build();
let market_trades = client.trades(&request, None).await?;
```
</CodeGroup>
Additional filter parameters: `id`, `maker_address`, `asset_id`, `before`, `after`.
The Rust SDK uses cursor-based pagination via the `next_cursor` parameter:
<CodeGroup>
```typescript TypeScript theme={null}
const page = await client.getTradesPaginated({ market: "0xbd31dc8a..." });
console.log(page.trades, page.count); // trades array + total count
```
```python Python theme={null}
page = client.get_trades_paginated(TradeParams(market="0xbd31dc8a..."))
```
```rust Rust theme={null}
// First page
let page = client.trades(&request, None).await?;
println!("{} trades, cursor: {}", page.data.len(), page.next_cursor);
// Next page
let page2 = client.trades(&request, Some(page.next_cursor)).await?;
```
</CodeGroup>
### Trade Object
| Field | Type | Description |
| ------------------ | ------------- | ------------------------------------ |
| `id` | string | Trade ID |
| `taker_order_id` | string | Taker order hash |
| `market` | string | Condition ID |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `size` | string | Trade size |
| `price` | string | Execution price |
| `fee_rate_bps` | string | Fee rate in basis points |
| `status` | string | Trade status (see table above) |
| `match_time` | string | Unix timestamp when matched |
| `last_update` | string | Unix timestamp of last status change |
| `outcome` | string | Human-readable outcome (e.g., "Yes") |
| `maker_address` | string | Maker's funder address |
| `owner` | string | API key of the trade owner |
| `transaction_hash` | string | Onchain transaction hash |
| `bucket_index` | number | Index for trade reconciliation |
| `trader_side` | string | `TAKER` or `MAKER` |
| `maker_orders` | MakerOrder\[] | Maker orders that filled this trade |
<Note>
A single trade can be split across multiple onchain transactions due to gas
limits. Use `bucket_index` and `match_time` to reconcile related transactions
back to a single logical trade.
</Note>
***
## Order Scoring
Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:
<CodeGroup>
```typescript TypeScript theme={null}
// Single order
const scoring = await client.isOrderScoring({ orderId: "0x..." });
// Multiple orders
const batch = await client.areOrdersScoring({
orderIds: ["0x...", "0x..."],
});
```
```python Python theme={null}
from py_clob_client_v2 import OrderScoringParams, OrdersScoringParams
scoring = client.is_order_scoring(
OrderScoringParams(orderId="0x...")
)
batch = client.are_orders_scoring(
OrdersScoringParams(orderIds=["0x...", "0x..."])
)
```
```rust Rust theme={null}
// Single order
let scoring = client.is_order_scoring("0x...").await?;
// Multiple orders
let batch = client.are_orders_scoring(&["0x...", "0x..."]).await?;
```
</CodeGroup>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Order Attribution" icon="tag" href="/trading/orders/attribution">
Attribute orders to your builder account for volume credit
</Card>
<Card title="Fees" icon="receipt" href="/trading/fees">
Understand fee structures and maker rebates
</Card>
</CardGroup>
@@ -1,544 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Overview
> Order types, tick sizes, and querying orders
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
The underlying order primitive is structured, hashed, and signed using the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) standard, then executed onchain via the Exchange contract. Preparing orders manually is involved, so we recommend using the open-source [TypeScript](https://github.com/Polymarket/clob-client-v2) or [Python](https://github.com/Polymarket/py-clob-client-v2) SDK clients, which handle signing and submission for you.
<Info>
If you prefer to use the REST API directly, you'll need to manage order
signing yourself. See [Authentication](/api-reference/authentication) for details on
constructing the required headers.
</Info>
***
## Order Types
| Type | Behavior | Use Case |
| ---------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------- |
| **GTC** (Good-Til-Cancelled) | Rests on the book until filled or cancelled | Default for passive limit orders |
| **GTD** (Good-Til-Date) | Active until a specified expiration time (UTC seconds timestamp), unless filled or cancelled first | Auto-expire orders before known events |
| **FOK** (Fill-Or-Kill) | Must be filled immediately and entirely, or the whole order is cancelled | All-or-nothing execution |
| **FAK** (Fill-And-Kill) | Fills as many shares as available immediately, then cancels any unfilled remainder | Partial immediate execution |
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
* **BUY**: specify the dollar amount you want to spend
* **SELL**: specify the number of shares you want to sell
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
<Note>
**GTD expiration**: There is a security threshold of one minute. If you need
the order to expire in 90 seconds, the correct expiration value is `now + 1
minute + 30 seconds`.
</Note>
### Post-Only Orders
Post-only orders are limit orders that will only rest on the book and not match immediately on entry.
* If a post-only order would cross the spread (i.e., it is marketable), it will be **rejected** rather than executed.
* Post-only **cannot** be combined with market order types (FOK or FAK). If `postOnly = true` is sent with a market order type, the order will be rejected.
* Post-only can only be used with **GTC** and **GTD** order types.
***
## Tick Sizes
Markets have different minimum price increments (tick sizes). Your order price must conform to the market's tick size, or the order will be rejected.
| Tick Size | Price Precision | Example Prices |
| --------- | --------------- | ---------------------- |
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
Retrieve the tick size for a market using the SDK:
<CodeGroup>
```typescript TypeScript theme={null}
const tickSize = await client.getTickSize(tokenID);
// Returns: "0.1" | "0.01" | "0.001" | "0.0001"
```
```python Python theme={null}
tick_size = client.get_tick_size(token_id)
# Returns: "0.1" | "0.01" | "0.001" | "0.0001"
```
```rust Rust theme={null}
let resp = client.tick_size(token_id).await?;
// resp.minimum_tick_size: TickSize::Tenth | Hundredth | Thousandth | TenThousandth
```
</CodeGroup>
<Tip>
You can also check the `minimum_tick_size` field on a market object returned
by the [Markets API](/market-data/fetching-markets).
</Tip>
***
## Negative Risk
Multi-outcome events (e.g., "Who will win the election?" with 3+ candidates) use a different exchange contract called the **Neg Risk CTF Exchange**. When placing orders on these markets, you must pass `negRisk: true` in the order options.
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{
tickSize: "0.01",
negRisk: true, // Required for multi-outcome markets
},
);
```
```python Python theme={null}
from py_clob_client_v2 import OrderArgs, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
response = client.create_and_post_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
),
options=PartialCreateOrderOptions(
tick_size="0.01",
neg_risk=True, # Required for multi-outcome markets
)
)
```
```rust Rust theme={null}
// The Rust SDK auto-detects neg risk from the token ID — no flag needed.
// The order builder fetches neg_risk and uses the correct exchange contract.
let order = client
.limit_order()
.token_id("TOKEN_ID".parse()?)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field:
<CodeGroup>
```typescript TypeScript theme={null}
const isNegRisk = await client.getNegRisk(tokenID);
```
```python Python theme={null}
is_neg_risk = client.get_neg_risk(token_id)
```
```rust Rust theme={null}
let is_neg_risk = client.neg_risk(token_id).await?;
```
</CodeGroup>
***
## Allowances
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
* **Buying**: the funder must have set a **pUSD** allowance greater than or equal to the spending amount.
* **Selling**: the funder must have set a **conditional token** allowance greater than or equal to the selling amount.
This allows the Exchange contract to execute settlement according to your signed order instructions.
***
## Validity Checks
Orders are continually monitored to make sure they remain valid. This includes tracking:
* Underlying balances
* Allowances
<Warning>
Any maker caught intentionally abusing these checks will be blacklisted.
</Warning>
There are also limits on order placement per market. You can only place orders that sum to less than or equal to your available balance for each market. For example, if you have 500 pUSD in your funding wallet, you can place one order to buy 1000 YES at \$0.50 — but any additional buy orders in that market will be rejected since your entire balance is reserved for the first order.
The max size you can place for an order is:
$$
\text{maxOrderSize} = \text{underlyingAssetBalance} - \sum(\text{orderSize} - \text{orderFillAmount})
$$
***
## Querying Orders
All query endpoints require [L2 authentication](/api-reference/authentication). [Builder-authenticated](/trading/clients/builder) clients can also query orders attributed to their builder account using the same methods.
### Get a Single Order
Retrieve details for a specific order by its ID:
<CodeGroup>
```typescript TypeScript theme={null}
const order = await client.getOrder("0xb816482a...");
console.log(order);
```
```python Python theme={null}
order = client.get_order("0xb816482a...")
print(order)
```
```rust Rust theme={null}
let order = client.order("0xb816482a...").await?;
println!("{order:?}");
```
</CodeGroup>
### Get Open Orders
Retrieve your open orders, optionally filtered by market or asset:
<CodeGroup>
```typescript TypeScript theme={null}
// All open orders
const orders = await client.getOpenOrders();
// Filtered by market
const marketOrders = await client.getOpenOrders({
market: "0xbd31dc8a...",
});
// Filtered by asset
const assetOrders = await client.getOpenOrders({
asset_id: "52114319501245...",
});
```
```python Python theme={null}
from py_clob_client_v2 import OpenOrderParams
# All open orders
orders = client.get_orders()
# Filtered by market
market_orders = client.get_orders(
OpenOrderParams(
market="0xbd31dc8a...",
)
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::request::OrdersRequest;
// All open orders
let orders = client.orders(&OrdersRequest::default(), None).await?;
// Filtered by market
let request = OrdersRequest::builder()
.market("0xbd31dc8a...".parse()?)
.build();
let market_orders = client.orders(&request, None).await?;
// Filtered by asset
let request = OrdersRequest::builder()
.asset_id("52114319501245...".parse()?)
.build();
let asset_orders = client.orders(&request, None).await?;
```
</CodeGroup>
### OpenOrder Object
Each order returned contains these fields:
| Field | Type | Description |
| ------------------ | --------- | ------------------------------------------------------------ |
| `id` | string | Order ID |
| `status` | string | Current order status |
| `market` | string | Market ID (condition ID) |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `original_size` | string | Original order size at placement |
| `size_matched` | string | Amount that has been filled |
| `price` | string | Limit price |
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
| `order_type` | string | Order type (GTC, GTD, FOK, FAK) |
| `maker_address` | string | Funder address |
| `owner` | string | API key of the order owner |
| `expiration` | string | Unix timestamp when the order expires (`0` if no expiration) |
| `associate_trades` | string\[] | Trade IDs this order has been partially included in |
| `created_at` | string | Unix timestamp when the order was created |
***
## Trade History
When an order is matched, it creates a trade. Trades go through the following statuses:
| Status | Terminal? | Description |
| ----------- | --------- | -------------------------------------------------------------------- |
| `MATCHED` | No | Matched and sent to the executor service for onchain submission |
| `MINED` | No | Observed as mined on the chain, no finality threshold yet |
| `CONFIRMED` | Yes | Achieved strong probabilistic finality — trade successful |
| `RETRYING` | No | Transaction failed (revert or reorg) — being retried by the operator |
| `FAILED` | Yes | Trade failed permanently and is not being retried |
### Trade Object
Each trade contains these fields:
| Field | Type | Description |
| ------------------ | ------ | ------------------------------------------------------------ |
| `id` | string | Trade ID |
| `taker_order_id` | string | Taker order ID (hash) |
| `market` | string | Market ID (condition ID) |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `size` | string | Trade size |
| `fee_rate_bps` | string | Fee rate in basis points |
| `price` | string | Trade price |
| `status` | string | Trade status (see table above) |
| `match_time` | string | Unix timestamp when the trade was matched |
| `last_update` | string | Unix timestamp of last status update |
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
| `owner` | string | API key ID of the trade owner |
| `maker_address` | string | Funder address |
| `trader_side` | string | Whether you were `TAKER` or `MAKER` in this trade |
| `transaction_hash` | string | Onchain transaction hash (available after mining) |
| `maker_orders` | array | Array of maker orders matched against this trade (see below) |
### MakerOrder Fields
Each entry in the `maker_orders` array contains:
| Field | Type | Description |
| ---------------- | ------ | ---------------------------- |
| `order_id` | string | Maker order ID (hash) |
| `owner` | string | Maker's API key ID |
| `maker_address` | string | Maker's funder address |
| `matched_amount` | string | Amount matched in this trade |
| `price` | string | Maker order price |
| `fee_rate_bps` | string | Maker fee rate in bps |
| `asset_id` | string | Token ID |
| `outcome` | string | Outcome name |
| `side` | string | `BUY` or `SELL` |
Retrieve your trades with the SDK:
<CodeGroup>
```typescript TypeScript theme={null}
// All trades
const trades = await client.getTrades();
// Filtered by market
const marketTrades = await client.getTrades({
market: "0xbd31dc8a...",
});
// With pagination
const paginatedTrades = await client.getTradesPaginated({
market: "0xbd31dc8a...",
});
```
```python Python theme={null}
from py_clob_client_v2 import TradeParams
# All trades
trades = client.get_trades()
# Filtered by market
market_trades = client.get_trades(
TradeParams(
market="0xbd31dc8a...",
)
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::request::TradesRequest;
// All trades
let trades = client.trades(&TradesRequest::default(), None).await?;
// Filtered by market
let request = TradesRequest::builder()
.market("0xbd31dc8a...".parse()?)
.build();
let market_trades = client.trades(&request, None).await?;
```
</CodeGroup>
***
## Heartbeat
The heartbeat endpoint maintains session liveness for order safety. If a valid heartbeat is not received within **10 seconds** (with up to a 5-second buffer), **all of your open orders will be cancelled**.
<CodeGroup>
```typescript TypeScript theme={null}
// Send heartbeats in a loop
let heartbeatId = "";
setInterval(async () => {
const resp = await client.postHeartbeat(heartbeatId);
heartbeatId = resp.heartbeat_id;
}, 5000);
```
```python Python theme={null}
import time
heartbeat_id = ""
while True:
resp = client.post_heartbeat(heartbeat_id)
heartbeat_id = resp["heartbeat_id"]
time.sleep(5)
```
```rust Rust theme={null}
// With the `heartbeats` feature, auto-send in background:
Client::start_heartbeats(&mut client)?;
// Or manually:
let resp = client.post_heartbeat(None).await?; // None for first call
let resp = client.post_heartbeat(Some(resp.heartbeat_id)).await?;
```
</CodeGroup>
* On each request, include the most recent `heartbeat_id` you received. For your first request, use an empty string.
* If you send an invalid or expired `heartbeat_id`, the server responds with a `400 Bad Request` and provides the correct `heartbeat_id` in the response. Update your client and retry.
***
## Order Scoring
Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:
<CodeGroup>
```typescript TypeScript theme={null}
// Single order
const scoring = await client.isOrderScoring({ orderId: "0x..." });
console.log(scoring); // { scoring: true }
// Multiple orders
const batchScoring = await client.areOrdersScoring({
orderIds: ["0x...", "0x..."],
});
```
```python Python theme={null}
from py_clob_client_v2 import OrderScoringParams, OrdersScoringParams
# Single order
scoring = client.is_order_scoring(
OrderScoringParams(orderId="0x...")
)
# Multiple orders
batch_scoring = client.are_orders_scoring(
OrdersScoringParams(orderIds=["0x...", "0x..."])
)
```
```rust Rust theme={null}
// Single order
let scoring = client.is_order_scoring("0x...").await?;
println!("Scoring: {}", scoring.scoring);
// Multiple orders
let batch = client.are_orders_scoring(&["0x...", "0x..."]).await?;
```
</CodeGroup>
***
## Onchain Order Info
When a trade is settled onchain, the Exchange contract emits an `OrderFilled` event with the following fields:
| Field | Description |
| ------------------- | --------------------------------------------------------------------------------------------- |
| `orderHash` | Unique hash for the filled order |
| `maker` | The user who generated the order and source of funds |
| `taker` | The user filling the order, or the Exchange contract if multiple limit orders are filled |
| `makerAssetId` | ID of the asset given out. If `0`, the order is a **BUY** (giving pUSD for outcome tokens) |
| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving pUSD for outcome tokens) |
| `makerAmountFilled` | Amount of the asset given out |
| `takerAmountFilled` | Amount of the asset received |
| `fee` | Fees paid by the order maker |
***
## Error Messages
When placing an order, the response may include an `errorMsg` if the order could not be placed. If `success` is `false`, there was a server-side error:
| Error | Description |
| ---------------------------------- | ------------------------------------------------------ |
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
| `INVALID_ORDER_MIN_SIZE` | Order size is below the minimum threshold |
| `INVALID_ORDER_DUPLICATED` | Identical order has already been placed |
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Funder doesn't have sufficient balance or allowance |
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
| `INVALID_ORDER_ERROR` | System error while inserting order |
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only flag used with a market order type (FOK/FAK) |
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
| `EXECUTION_ERROR` | System error while executing trade |
| `ORDER_DELAYED` | Order placement delayed due to market conditions |
| `DELAYING_ORDER_ERROR` | System error while delaying order |
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
| `MARKET_NOT_READY` | Market is not yet accepting orders |
### Insert Statuses
When an order is successfully placed, the response includes a `status` field:
| Status | Description |
| ----------- | -------------------------------------------------------------------- |
| `matched` | Order placed and matched with a resting order |
| `live` | Order placed and resting on the book |
| `delayed` | Order is marketable but subject to a matching delay |
| `unmatched` | Order is marketable but failed to delay — placement still successful |
***
## Security
Polymarket's Exchange contract has been audited by Chainsecurity ([View Audit](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)).
The operator's privileges are limited to order matching and ensuring correct ordering. Operators cannot set prices or execute unauthorized trades.
***
## Next Steps
<CardGroup cols={2}>
<Card title="Create Order" icon="plus" href="/trading/orders/create">
Build, sign, and submit orders
</Card>
<Card title="Cancel Order" icon="xmark" href="/trading/orders/cancel">
Cancel single, multiple, or all orders
</Card>
</CardGroup>
@@ -1,699 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Create Order
> Build, sign, and submit orders
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
<Info>
The SDK handles EIP-712 signing and submission for you. If you prefer the REST
API directly, see [Authentication](/api-reference/authentication) for
constructing the required headers and the [API
Reference](/api-reference/introduction) for full endpoint documentation
including the raw order object fields and request/response schemas.
</Info>
***
## Order Types
| Type | Behavior | Use Case |
| ------- | -------------------------------------------------------------------- | ------------------------------- |
| **GTC** | Good-Til-Cancelled — rests on the book until filled or cancelled | Default for limit orders |
| **GTD** | Good-Til-Date — active until a specified expiration time | Auto-expire before known events |
| **FOK** | Fill-Or-Kill — must fill immediately and entirely, or cancel | All-or-nothing market orders |
| **FAK** | Fill-And-Kill — fills what's available immediately, cancels the rest | Partial-fill market orders |
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
* **BUY**: specify the dollar amount you want to spend
* **SELL**: specify the number of shares you want to sell
***
## Limit Orders
The simplest way to place a limit order — create, sign, and submit in one call:
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient, Side, OrderType } from "@polymarket/clob-client-v2";
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{
tickSize: "0.01",
negRisk: false,
},
OrderType.GTC,
);
console.log("Order ID:", response.orderID);
console.log("Status:", response.status);
```
```python Python theme={null}
from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
response = client.create_and_post_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
order_type=OrderType.GTC
)
print("Order ID:", response["orderID"])
print("Status:", response["status"])
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::Side;
use polymarket_client_sdk_v2::types::dec;
let token_id = "TOKEN_ID".parse()?;
let order = client
.limit_order()
.token_id(token_id)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
println!("Order ID: {}", response.order_id);
println!("Status: {:?}", response.status);
```
</CodeGroup>
### Two-Step Sign Then Submit
For more control, you can separate signing from submission. This is useful for batch orders or custom submission logic:
<CodeGroup>
```typescript TypeScript theme={null}
// Step 1: Create and sign locally
const signedOrder = await client.createOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{ tickSize: "0.01", negRisk: false },
);
// Step 2: Submit to the CLOB
const response = await client.postOrder(signedOrder, OrderType.GTC);
```
```python Python theme={null}
# Step 1: Create and sign locally
signed_order = client.create_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False)
)
# Step 2: Submit to the CLOB
response = client.post_order(signed_order, OrderType.GTC)
```
```rust Rust theme={null}
// Step 1: Create order (auto-fetches tick size, neg risk, fee rate)
let order = client
.limit_order()
.token_id("TOKEN_ID".parse()?)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.build()
.await?;
// Step 2: Sign and submit separately
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
***
## GTD Orders
GTD orders auto-expire at a specified time. Useful for quoting around known events.
<CodeGroup>
```typescript TypeScript theme={null}
// Expire in 1 hour (+ 60s security threshold buffer)
const expiration = Math.floor(Date.now() / 1000) + 60 + 3600;
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
expiration,
},
{ tickSize: "0.01", negRisk: false },
OrderType.GTD,
);
```
```python Python theme={null}
import time
# Expire in 1 hour (+ 60s security threshold buffer)
expiration = int(time.time()) + 60 + 3600
response = client.create_and_post_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
expiration=expiration,
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
order_type=OrderType.GTD
)
```
```rust Rust theme={null}
use chrono::{TimeDelta, Utc};
use polymarket_client_sdk_v2::clob::types::OrderType;
let order = client
.limit_order()
.token_id("TOKEN_ID".parse()?)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.order_type(OrderType::GTD)
.expiration(Utc::now() + TimeDelta::hours(1))
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
<Note>
There is a security threshold of one minute on GTD expiration. To set an
effective lifetime of N seconds, use `now + 60 + N`. For example, for a
30-second effective lifetime, set the expiration to `now + 60 + 30`.
</Note>
***
## Market Orders
Market orders execute immediately against resting liquidity using FOK or FAK types:
<CodeGroup>
```typescript TypeScript theme={null}
import { Side, OrderType } from "@polymarket/clob-client-v2";
// FOK BUY: spend exactly $100 or cancel entirely
const buyOrder = await client.createMarketOrder(
{
tokenID: "TOKEN_ID",
side: Side.BUY,
amount: 100, // dollar amount
price: 0.5, // worst-price limit (slippage protection)
},
{ tickSize: "0.01", negRisk: false },
);
await client.postOrder(buyOrder, OrderType.FOK);
// FOK SELL: sell exactly 200 shares or cancel entirely
const sellOrder = await client.createMarketOrder(
{
tokenID: "TOKEN_ID",
side: Side.SELL,
amount: 200, // number of shares
price: 0.45, // worst-price limit (slippage protection)
},
{ tickSize: "0.01", negRisk: false },
);
await client.postOrder(sellOrder, OrderType.FOK);
```
```python Python theme={null}
from py_clob_client_v2.order_builder.constants import BUY, SELL
from py_clob_client_v2 import MarketOrderArgs, OrderType, PartialCreateOrderOptions
# FOK BUY: spend exactly $100 or cancel entirely
buy_order = client.create_market_order(
order_args=MarketOrderArgs(
token_id="TOKEN_ID",
side=BUY,
amount=100, # dollar amount
price=0.50, # worst-price limit (slippage protection)
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
)
client.post_order(buy_order, OrderType.FOK)
# FOK SELL: sell exactly 200 shares or cancel entirely
sell_order = client.create_market_order(
order_args=MarketOrderArgs(
token_id="TOKEN_ID",
side=SELL,
amount=200, # number of shares
price=0.45, # worst-price limit (slippage protection)
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
)
client.post_order(sell_order, OrderType.FOK)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::{Amount, OrderType, Side};
let token_id = "TOKEN_ID".parse()?;
// FOK BUY: spend exactly $100 or cancel entirely
let buy = client
.market_order()
.token_id(token_id)
.amount(Amount::usdc(dec!(100))?)
.price(dec!(0.50)) // worst-price limit (slippage protection)
.side(Side::Buy)
.order_type(OrderType::FOK)
.build()
.await?;
let signed = client.sign(&signer, buy).await?;
client.post_order(signed).await?;
// FOK SELL: sell exactly 200 shares or cancel entirely
let sell = client
.market_order()
.token_id(token_id)
.amount(Amount::shares(dec!(200))?)
.price(dec!(0.45)) // worst-price limit (slippage protection)
.side(Side::Sell)
.order_type(OrderType::FOK)
.build()
.await?;
let signed = client.sign(&signer, sell).await?;
client.post_order(signed).await?;
```
</CodeGroup>
* **FOK** — fill entirely or cancel the whole order
* **FAK** — fill what's available, cancel the rest
The `price` field on market orders acts as a **worst-price limit** (slippage protection), not a target execution price.
### One-Step Market Order
For convenience, `createAndPostMarketOrder` handles creation, signing, and submission in one call:
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.createAndPostMarketOrder(
{
tokenID: "TOKEN_ID",
side: Side.BUY,
amount: 100,
price: 0.5,
},
{ tickSize: "0.01", negRisk: false },
OrderType.FOK,
);
```
```python Python theme={null}
from py_clob_client_v2 import MarketOrderArgs, OrderType, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
response = client.create_and_post_market_order(
order_args=MarketOrderArgs(
token_id="TOKEN_ID",
side=BUY,
amount=100,
price=0.50,
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
order_type=OrderType.FOK,
)
```
```rust Rust theme={null}
let order = client
.market_order()
.token_id("TOKEN_ID".parse()?)
.amount(Amount::usdc(dec!(100))?)
.price(dec!(0.50))
.side(Side::Buy)
.order_type(OrderType::FOK)
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
***
## Post-Only Orders
Post-only orders guarantee you're always the maker. If the order would match immediately (cross the spread), it's rejected instead of executed.
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.postOrder(signedOrder, OrderType.GTC, true);
```
```python Python theme={null}
response = client.post_order(signed_order, OrderType.GTC, post_only=True)
```
```rust Rust theme={null}
let order = client
.limit_order()
.token_id("TOKEN_ID".parse()?)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.post_only(true)
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
* Only works with **GTC** and **GTD** order types
* Rejected if combined with FOK or FAK
***
## Batch Orders
Place up to **15 orders** in a single request:
<CodeGroup>
```typescript TypeScript theme={null}
import { OrderType, Side, PostOrdersArgs } from "@polymarket/clob-client-v2";
const orders: PostOrdersArgs[] = [
{
order: await client.createOrder(
{
tokenID: "TOKEN_ID",
price: 0.48,
side: Side.BUY,
size: 500,
},
{ tickSize: "0.01", negRisk: false },
),
orderType: OrderType.GTC,
},
{
order: await client.createOrder(
{
tokenID: "TOKEN_ID",
price: 0.52,
side: Side.SELL,
size: 500,
},
{ tickSize: "0.01", negRisk: false },
),
orderType: OrderType.GTC,
},
];
const response = await client.postOrders(orders);
```
```python Python theme={null}
from py_clob_client_v2 import OrderArgs, OrderType, PostOrdersV2Args, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY, SELL
response = client.post_orders([
PostOrdersV2Args(
order=client.create_order(OrderArgs(
price=0.48,
size=500,
side=BUY,
token_id="TOKEN_ID",
), options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False)),
orderType=OrderType.GTC,
),
PostOrdersV2Args(
order=client.create_order(OrderArgs(
price=0.52,
size=500,
side=SELL,
token_id="TOKEN_ID",
), options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False)),
orderType=OrderType.GTC,
),
])
```
```rust Rust theme={null}
let token_id = "TOKEN_ID".parse()?;
let bid = client
.limit_order()
.token_id(token_id)
.price(dec!(0.48))
.size(dec!(500))
.side(Side::Buy)
.build()
.await?;
let ask = client
.limit_order()
.token_id(token_id)
.price(dec!(0.52))
.size(dec!(500))
.side(Side::Sell)
.build()
.await?;
let signed_bid = client.sign(&signer, bid).await?;
let signed_ask = client.sign(&signer, ask).await?;
let response = client.post_orders(vec![signed_bid, signed_ask]).await?;
```
</CodeGroup>
***
## Order Options
Every order requires two market-specific options: `tickSize` and `negRisk`. For
details on signature types (`0` = EOA, `1` = POLY\_PROXY, `2` = GNOSIS\_SAFE,
`3` = POLY\_1271 deposit wallet), see
[Authentication](/api-reference/authentication#signature-types-and-funder).
### Tick Sizes
Your order price must conform to the market's tick size, or the order is rejected.
| Tick Size | Precision | Example Prices |
| --------- | ---------- | ---------------------- |
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
<CodeGroup>
```typescript TypeScript theme={null}
const tickSize = await client.getTickSize("TOKEN_ID");
```
```python Python theme={null}
tick_size = client.get_tick_size("TOKEN_ID")
```
```rust Rust theme={null}
let token_id = "TOKEN_ID".parse()?;
let tick_size = client.tick_size(token_id).await?;
```
</CodeGroup>
### Negative Risk
Multi-outcome events (3+ outcomes) use the Neg Risk CTF Exchange. Pass `negRisk: true` for these markets.
<CodeGroup>
```typescript TypeScript theme={null}
const isNegRisk = await client.getNegRisk("TOKEN_ID");
```
```python Python theme={null}
is_neg_risk = client.get_neg_risk("TOKEN_ID")
```
```rust Rust theme={null}
let token_id = "TOKEN_ID".parse()?;
let is_neg_risk = client.neg_risk(token_id).await?;
```
</CodeGroup>
<Tip>
Both values are also available on the market object: `minimum_tick_size` and
`neg_risk`. In Rust, the order builder auto-fetches both — you don't need to
look them up manually.
</Tip>
***
## Prerequisites
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
* **BUY orders**: pUSD allowance >= spending amount
* **SELL orders**: conditional token allowance >= selling amount
Order size is limited by your available balance minus amounts reserved by existing open orders:
$$
\text{maxOrderSize} = \text{balance} - \sum(\text{openOrderSize} - \text{filledAmount})
$$
<Warning>
Orders are continuously monitored for validity — balances and allowances are
tracked in real time. Any maker caught intentionally abusing these checks will
be blacklisted.
</Warning>
### Sports Markets
Sports markets have additional behaviors:
* Outstanding limit orders are **automatically cancelled** once the game begins, clearing the entire order book at the official start time
* Marketable orders have a **1-second placement delay** before matching
* Game start times can shift — monitor your orders closely, as they may not be cleared if the start time changes unexpectedly
***
## Response
A successful order placement returns:
```json theme={null}
{
"success": true,
"errorMsg": "",
"orderID": "0xabc123...",
"takingAmount": "",
"makingAmount": "",
"status": "live",
"transactionsHashes": [],
"tradeIDs": []
}
```
### Statuses
| Status | Description |
| ----------- | ------------------------------------------------------------- |
| `live` | Order resting on the book |
| `matched` | Order matched immediately with a resting order |
| `delayed` | Marketable order accepted into an asynchronous matching delay |
| `unmatched` | Marketable but failed to delay — placement still successful |
<Note>
Selected crypto and finance up/down markets apply a 250 ms taker delay to
marketable orders. To check a specific market, call `GET
https://clob.polymarket.com/clob-markets/{condition_id}` or SDK
`getClobMarketInfo(conditionID)` and look for `itode: true`. The API waits for
this short hold and returns the final order result, so these orders usually
return `matched`, `live`, or `unmatched` rather than `delayed`. Orders cannot
be canceled while they are pending in the delay window.
</Note>
### Error Messages
| Error | Description |
| ---------------------------------- | ----------------------------------------------- |
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
| `INVALID_ORDER_MIN_SIZE` | Order size below the minimum threshold |
| `INVALID_ORDER_DUPLICATED` | Identical order already placed |
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Insufficient balance or allowance |
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only used with FOK/FAK |
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
| `INVALID_ORDER_ERROR` | System error inserting the order |
| `EXECUTION_ERROR` | System error executing the trade |
| `ORDER_DELAYED` | Order match delayed due to market conditions |
| `DELAYING_ORDER_ERROR` | System error while delaying the order |
| `MARKET_NOT_READY` | Market not yet accepting orders |
***
## Heartbeat
The heartbeat endpoint maintains session liveness. If a valid heartbeat is not received within **10 seconds** (with a 5-second buffer), **all open orders are cancelled**.
<CodeGroup>
```typescript TypeScript theme={null}
let heartbeatId = "";
setInterval(async () => {
const resp = await client.postHeartbeat(heartbeatId);
heartbeatId = resp.heartbeat_id;
}, 5000);
```
```python Python theme={null}
import time
heartbeat_id = ""
while True:
resp = client.post_heartbeat(heartbeat_id)
heartbeat_id = resp["heartbeat_id"]
time.sleep(5)
```
```rust Rust theme={null}
// With the `heartbeats` feature, the Rust SDK can auto-send heartbeats
// in a background task — no manual loop needed:
Client::start_heartbeats(&mut client)?;
// ... your trading logic ...
client.stop_heartbeats().await?;
// Or send manually:
let resp = client.post_heartbeat(None).await?; // None for first call
let resp = client.post_heartbeat(Some(resp.heartbeat_id)).await?;
```
</CodeGroup>
* Include the most recent `heartbeat_id` in each request. Use an empty string for the first request.
* If you send an expired ID, the server responds with `400` and the correct ID. Update and retry.
***
## Next Steps
<CardGroup cols={2}>
<Card title="Cancel Orders" icon="xmark" href="/trading/orders/cancel">
Cancel single, multiple, or all open orders
</Card>
<Card title="Order Attribution" icon="tag" href="/trading/orders/attribution">
Attribute orders to your builder account for volume credit
</Card>
</CardGroup>
-699
View File
@@ -1,699 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Create Order
> Build, sign, and submit orders
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
<Info>
The SDK handles EIP-712 signing and submission for you. If you prefer the REST
API directly, see [Authentication](/api-reference/authentication) for
constructing the required headers and the [API
Reference](/api-reference/introduction) for full endpoint documentation
including the raw order object fields and request/response schemas.
</Info>
***
## Order Types
| Type | Behavior | Use Case |
| ------- | -------------------------------------------------------------------- | ------------------------------- |
| **GTC** | Good-Til-Cancelled — rests on the book until filled or cancelled | Default for limit orders |
| **GTD** | Good-Til-Date — active until a specified expiration time | Auto-expire before known events |
| **FOK** | Fill-Or-Kill — must fill immediately and entirely, or cancel | All-or-nothing market orders |
| **FAK** | Fill-And-Kill — fills what's available immediately, cancels the rest | Partial-fill market orders |
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
* **BUY**: specify the dollar amount you want to spend
* **SELL**: specify the number of shares you want to sell
***
## Limit Orders
The simplest way to place a limit order — create, sign, and submit in one call:
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient, Side, OrderType } from "@polymarket/clob-client-v2";
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{
tickSize: "0.01",
negRisk: false,
},
OrderType.GTC,
);
console.log("Order ID:", response.orderID);
console.log("Status:", response.status);
```
```python Python theme={null}
from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
response = client.create_and_post_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
order_type=OrderType.GTC
)
print("Order ID:", response["orderID"])
print("Status:", response["status"])
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::Side;
use polymarket_client_sdk_v2::types::dec;
let token_id = "TOKEN_ID".parse()?;
let order = client
.limit_order()
.token_id(token_id)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
println!("Order ID: {}", response.order_id);
println!("Status: {:?}", response.status);
```
</CodeGroup>
### Two-Step Sign Then Submit
For more control, you can separate signing from submission. This is useful for batch orders or custom submission logic:
<CodeGroup>
```typescript TypeScript theme={null}
// Step 1: Create and sign locally
const signedOrder = await client.createOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{ tickSize: "0.01", negRisk: false },
);
// Step 2: Submit to the CLOB
const response = await client.postOrder(signedOrder, OrderType.GTC);
```
```python Python theme={null}
# Step 1: Create and sign locally
signed_order = client.create_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False)
)
# Step 2: Submit to the CLOB
response = client.post_order(signed_order, OrderType.GTC)
```
```rust Rust theme={null}
// Step 1: Create order (auto-fetches tick size, neg risk, fee rate)
let order = client
.limit_order()
.token_id("TOKEN_ID".parse()?)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.build()
.await?;
// Step 2: Sign and submit separately
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
***
## GTD Orders
GTD orders auto-expire at a specified time. Useful for quoting around known events.
<CodeGroup>
```typescript TypeScript theme={null}
// Expire in 1 hour (+ 60s security threshold buffer)
const expiration = Math.floor(Date.now() / 1000) + 60 + 3600;
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
expiration,
},
{ tickSize: "0.01", negRisk: false },
OrderType.GTD,
);
```
```python Python theme={null}
import time
# Expire in 1 hour (+ 60s security threshold buffer)
expiration = int(time.time()) + 60 + 3600
response = client.create_and_post_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
expiration=expiration,
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
order_type=OrderType.GTD
)
```
```rust Rust theme={null}
use chrono::{TimeDelta, Utc};
use polymarket_client_sdk_v2::clob::types::OrderType;
let order = client
.limit_order()
.token_id("TOKEN_ID".parse()?)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.order_type(OrderType::GTD)
.expiration(Utc::now() + TimeDelta::hours(1))
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
<Note>
There is a security threshold of one minute on GTD expiration. To set an
effective lifetime of N seconds, use `now + 60 + N`. For example, for a
30-second effective lifetime, set the expiration to `now + 60 + 30`.
</Note>
***
## Market Orders
Market orders execute immediately against resting liquidity using FOK or FAK types:
<CodeGroup>
```typescript TypeScript theme={null}
import { Side, OrderType } from "@polymarket/clob-client-v2";
// FOK BUY: spend exactly $100 or cancel entirely
const buyOrder = await client.createMarketOrder(
{
tokenID: "TOKEN_ID",
side: Side.BUY,
amount: 100, // dollar amount
price: 0.5, // worst-price limit (slippage protection)
},
{ tickSize: "0.01", negRisk: false },
);
await client.postOrder(buyOrder, OrderType.FOK);
// FOK SELL: sell exactly 200 shares or cancel entirely
const sellOrder = await client.createMarketOrder(
{
tokenID: "TOKEN_ID",
side: Side.SELL,
amount: 200, // number of shares
price: 0.45, // worst-price limit (slippage protection)
},
{ tickSize: "0.01", negRisk: false },
);
await client.postOrder(sellOrder, OrderType.FOK);
```
```python Python theme={null}
from py_clob_client_v2.order_builder.constants import BUY, SELL
from py_clob_client_v2 import MarketOrderArgs, OrderType, PartialCreateOrderOptions
# FOK BUY: spend exactly $100 or cancel entirely
buy_order = client.create_market_order(
order_args=MarketOrderArgs(
token_id="TOKEN_ID",
side=BUY,
amount=100, # dollar amount
price=0.50, # worst-price limit (slippage protection)
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
)
client.post_order(buy_order, OrderType.FOK)
# FOK SELL: sell exactly 200 shares or cancel entirely
sell_order = client.create_market_order(
order_args=MarketOrderArgs(
token_id="TOKEN_ID",
side=SELL,
amount=200, # number of shares
price=0.45, # worst-price limit (slippage protection)
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
)
client.post_order(sell_order, OrderType.FOK)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::{Amount, OrderType, Side};
let token_id = "TOKEN_ID".parse()?;
// FOK BUY: spend exactly $100 or cancel entirely
let buy = client
.market_order()
.token_id(token_id)
.amount(Amount::usdc(dec!(100))?)
.price(dec!(0.50)) // worst-price limit (slippage protection)
.side(Side::Buy)
.order_type(OrderType::FOK)
.build()
.await?;
let signed = client.sign(&signer, buy).await?;
client.post_order(signed).await?;
// FOK SELL: sell exactly 200 shares or cancel entirely
let sell = client
.market_order()
.token_id(token_id)
.amount(Amount::shares(dec!(200))?)
.price(dec!(0.45)) // worst-price limit (slippage protection)
.side(Side::Sell)
.order_type(OrderType::FOK)
.build()
.await?;
let signed = client.sign(&signer, sell).await?;
client.post_order(signed).await?;
```
</CodeGroup>
* **FOK** — fill entirely or cancel the whole order
* **FAK** — fill what's available, cancel the rest
The `price` field on market orders acts as a **worst-price limit** (slippage protection), not a target execution price.
### One-Step Market Order
For convenience, `createAndPostMarketOrder` handles creation, signing, and submission in one call:
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.createAndPostMarketOrder(
{
tokenID: "TOKEN_ID",
side: Side.BUY,
amount: 100,
price: 0.5,
},
{ tickSize: "0.01", negRisk: false },
OrderType.FOK,
);
```
```python Python theme={null}
from py_clob_client_v2 import MarketOrderArgs, OrderType, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
response = client.create_and_post_market_order(
order_args=MarketOrderArgs(
token_id="TOKEN_ID",
side=BUY,
amount=100,
price=0.50,
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
order_type=OrderType.FOK,
)
```
```rust Rust theme={null}
let order = client
.market_order()
.token_id("TOKEN_ID".parse()?)
.amount(Amount::usdc(dec!(100))?)
.price(dec!(0.50))
.side(Side::Buy)
.order_type(OrderType::FOK)
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
***
## Post-Only Orders
Post-only orders guarantee you're always the maker. If the order would match immediately (cross the spread), it's rejected instead of executed.
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.postOrder(signedOrder, OrderType.GTC, true);
```
```python Python theme={null}
response = client.post_order(signed_order, OrderType.GTC, post_only=True)
```
```rust Rust theme={null}
let order = client
.limit_order()
.token_id("TOKEN_ID".parse()?)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.post_only(true)
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
* Only works with **GTC** and **GTD** order types
* Rejected if combined with FOK or FAK
***
## Batch Orders
Place up to **15 orders** in a single request:
<CodeGroup>
```typescript TypeScript theme={null}
import { OrderType, Side, PostOrdersArgs } from "@polymarket/clob-client-v2";
const orders: PostOrdersArgs[] = [
{
order: await client.createOrder(
{
tokenID: "TOKEN_ID",
price: 0.48,
side: Side.BUY,
size: 500,
},
{ tickSize: "0.01", negRisk: false },
),
orderType: OrderType.GTC,
},
{
order: await client.createOrder(
{
tokenID: "TOKEN_ID",
price: 0.52,
side: Side.SELL,
size: 500,
},
{ tickSize: "0.01", negRisk: false },
),
orderType: OrderType.GTC,
},
];
const response = await client.postOrders(orders);
```
```python Python theme={null}
from py_clob_client_v2 import OrderArgs, OrderType, PostOrdersV2Args, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY, SELL
response = client.post_orders([
PostOrdersV2Args(
order=client.create_order(OrderArgs(
price=0.48,
size=500,
side=BUY,
token_id="TOKEN_ID",
), options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False)),
orderType=OrderType.GTC,
),
PostOrdersV2Args(
order=client.create_order(OrderArgs(
price=0.52,
size=500,
side=SELL,
token_id="TOKEN_ID",
), options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False)),
orderType=OrderType.GTC,
),
])
```
```rust Rust theme={null}
let token_id = "TOKEN_ID".parse()?;
let bid = client
.limit_order()
.token_id(token_id)
.price(dec!(0.48))
.size(dec!(500))
.side(Side::Buy)
.build()
.await?;
let ask = client
.limit_order()
.token_id(token_id)
.price(dec!(0.52))
.size(dec!(500))
.side(Side::Sell)
.build()
.await?;
let signed_bid = client.sign(&signer, bid).await?;
let signed_ask = client.sign(&signer, ask).await?;
let response = client.post_orders(vec![signed_bid, signed_ask]).await?;
```
</CodeGroup>
***
## Order Options
Every order requires two market-specific options: `tickSize` and `negRisk`. For
details on signature types (`0` = EOA, `1` = POLY\_PROXY, `2` = GNOSIS\_SAFE,
`3` = POLY\_1271 deposit wallet), see
[Authentication](/api-reference/authentication#signature-types-and-funder).
### Tick Sizes
Your order price must conform to the market's tick size, or the order is rejected.
| Tick Size | Precision | Example Prices |
| --------- | ---------- | ---------------------- |
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
<CodeGroup>
```typescript TypeScript theme={null}
const tickSize = await client.getTickSize("TOKEN_ID");
```
```python Python theme={null}
tick_size = client.get_tick_size("TOKEN_ID")
```
```rust Rust theme={null}
let token_id = "TOKEN_ID".parse()?;
let tick_size = client.tick_size(token_id).await?;
```
</CodeGroup>
### Negative Risk
Multi-outcome events (3+ outcomes) use the Neg Risk CTF Exchange. Pass `negRisk: true` for these markets.
<CodeGroup>
```typescript TypeScript theme={null}
const isNegRisk = await client.getNegRisk("TOKEN_ID");
```
```python Python theme={null}
is_neg_risk = client.get_neg_risk("TOKEN_ID")
```
```rust Rust theme={null}
let token_id = "TOKEN_ID".parse()?;
let is_neg_risk = client.neg_risk(token_id).await?;
```
</CodeGroup>
<Tip>
Both values are also available on the market object: `minimum_tick_size` and
`neg_risk`. In Rust, the order builder auto-fetches both — you don't need to
look them up manually.
</Tip>
***
## Prerequisites
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
* **BUY orders**: pUSD allowance >= spending amount
* **SELL orders**: conditional token allowance >= selling amount
Order size is limited by your available balance minus amounts reserved by existing open orders:
$$
\text{maxOrderSize} = \text{balance} - \sum(\text{openOrderSize} - \text{filledAmount})
$$
<Warning>
Orders are continuously monitored for validity — balances and allowances are
tracked in real time. Any maker caught intentionally abusing these checks will
be blacklisted.
</Warning>
### Sports Markets
Sports markets have additional behaviors:
* Outstanding limit orders are **automatically cancelled** once the game begins, clearing the entire order book at the official start time
* Marketable orders have a **1-second placement delay** before matching
* Game start times can shift — monitor your orders closely, as they may not be cleared if the start time changes unexpectedly
***
## Response
A successful order placement returns:
```json theme={null}
{
"success": true,
"errorMsg": "",
"orderID": "0xabc123...",
"takingAmount": "",
"makingAmount": "",
"status": "live",
"transactionsHashes": [],
"tradeIDs": []
}
```
### Statuses
| Status | Description |
| ----------- | ------------------------------------------------------------- |
| `live` | Order resting on the book |
| `matched` | Order matched immediately with a resting order |
| `delayed` | Marketable order accepted into an asynchronous matching delay |
| `unmatched` | Marketable but failed to delay — placement still successful |
<Note>
Selected crypto and finance up/down markets apply a 250 ms taker delay to
marketable orders. To check a specific market, call `GET
https://clob.polymarket.com/clob-markets/{condition_id}` or SDK
`getClobMarketInfo(conditionID)` and look for `itode: true`. The API waits for
this short hold and returns the final order result, so these orders usually
return `matched`, `live`, or `unmatched` rather than `delayed`. Orders cannot
be canceled while they are pending in the delay window.
</Note>
### Error Messages
| Error | Description |
| ---------------------------------- | ----------------------------------------------- |
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
| `INVALID_ORDER_MIN_SIZE` | Order size below the minimum threshold |
| `INVALID_ORDER_DUPLICATED` | Identical order already placed |
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Insufficient balance or allowance |
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only used with FOK/FAK |
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
| `INVALID_ORDER_ERROR` | System error inserting the order |
| `EXECUTION_ERROR` | System error executing the trade |
| `ORDER_DELAYED` | Order match delayed due to market conditions |
| `DELAYING_ORDER_ERROR` | System error while delaying the order |
| `MARKET_NOT_READY` | Market not yet accepting orders |
***
## Heartbeat
The heartbeat endpoint maintains session liveness. If a valid heartbeat is not received within **10 seconds** (with a 5-second buffer), **all open orders are cancelled**.
<CodeGroup>
```typescript TypeScript theme={null}
let heartbeatId = "";
setInterval(async () => {
const resp = await client.postHeartbeat(heartbeatId);
heartbeatId = resp.heartbeat_id;
}, 5000);
```
```python Python theme={null}
import time
heartbeat_id = ""
while True:
resp = client.post_heartbeat(heartbeat_id)
heartbeat_id = resp["heartbeat_id"]
time.sleep(5)
```
```rust Rust theme={null}
// With the `heartbeats` feature, the Rust SDK can auto-send heartbeats
// in a background task — no manual loop needed:
Client::start_heartbeats(&mut client)?;
// ... your trading logic ...
client.stop_heartbeats().await?;
// Or send manually:
let resp = client.post_heartbeat(None).await?; // None for first call
let resp = client.post_heartbeat(Some(resp.heartbeat_id)).await?;
```
</CodeGroup>
* Include the most recent `heartbeat_id` in each request. Use an empty string for the first request.
* If you send an expired ID, the server responds with `400` and the correct ID. Update and retry.
***
## Next Steps
<CardGroup cols={2}>
<Card title="Cancel Orders" icon="xmark" href="/trading/orders/cancel">
Cancel single, multiple, or all open orders
</Card>
<Card title="Order Attribution" icon="tag" href="/trading/orders/attribution">
Attribute orders to your builder account for volume credit
</Card>
</CardGroup>
@@ -1,544 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Overview
> Order types, tick sizes, and querying orders
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
The underlying order primitive is structured, hashed, and signed using the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) standard, then executed onchain via the Exchange contract. Preparing orders manually is involved, so we recommend using the open-source [TypeScript](https://github.com/Polymarket/clob-client-v2) or [Python](https://github.com/Polymarket/py-clob-client-v2) SDK clients, which handle signing and submission for you.
<Info>
If you prefer to use the REST API directly, you'll need to manage order
signing yourself. See [Authentication](/api-reference/authentication) for details on
constructing the required headers.
</Info>
***
## Order Types
| Type | Behavior | Use Case |
| ---------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------- |
| **GTC** (Good-Til-Cancelled) | Rests on the book until filled or cancelled | Default for passive limit orders |
| **GTD** (Good-Til-Date) | Active until a specified expiration time (UTC seconds timestamp), unless filled or cancelled first | Auto-expire orders before known events |
| **FOK** (Fill-Or-Kill) | Must be filled immediately and entirely, or the whole order is cancelled | All-or-nothing execution |
| **FAK** (Fill-And-Kill) | Fills as many shares as available immediately, then cancels any unfilled remainder | Partial immediate execution |
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
* **BUY**: specify the dollar amount you want to spend
* **SELL**: specify the number of shares you want to sell
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
<Note>
**GTD expiration**: There is a security threshold of one minute. If you need
the order to expire in 90 seconds, the correct expiration value is `now + 1
minute + 30 seconds`.
</Note>
### Post-Only Orders
Post-only orders are limit orders that will only rest on the book and not match immediately on entry.
* If a post-only order would cross the spread (i.e., it is marketable), it will be **rejected** rather than executed.
* Post-only **cannot** be combined with market order types (FOK or FAK). If `postOnly = true` is sent with a market order type, the order will be rejected.
* Post-only can only be used with **GTC** and **GTD** order types.
***
## Tick Sizes
Markets have different minimum price increments (tick sizes). Your order price must conform to the market's tick size, or the order will be rejected.
| Tick Size | Price Precision | Example Prices |
| --------- | --------------- | ---------------------- |
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
Retrieve the tick size for a market using the SDK:
<CodeGroup>
```typescript TypeScript theme={null}
const tickSize = await client.getTickSize(tokenID);
// Returns: "0.1" | "0.01" | "0.001" | "0.0001"
```
```python Python theme={null}
tick_size = client.get_tick_size(token_id)
# Returns: "0.1" | "0.01" | "0.001" | "0.0001"
```
```rust Rust theme={null}
let resp = client.tick_size(token_id).await?;
// resp.minimum_tick_size: TickSize::Tenth | Hundredth | Thousandth | TenThousandth
```
</CodeGroup>
<Tip>
You can also check the `minimum_tick_size` field on a market object returned
by the [Markets API](/market-data/fetching-markets).
</Tip>
***
## Negative Risk
Multi-outcome events (e.g., "Who will win the election?" with 3+ candidates) use a different exchange contract called the **Neg Risk CTF Exchange**. When placing orders on these markets, you must pass `negRisk: true` in the order options.
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{
tickSize: "0.01",
negRisk: true, // Required for multi-outcome markets
},
);
```
```python Python theme={null}
from py_clob_client_v2 import OrderArgs, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
response = client.create_and_post_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
),
options=PartialCreateOrderOptions(
tick_size="0.01",
neg_risk=True, # Required for multi-outcome markets
)
)
```
```rust Rust theme={null}
// The Rust SDK auto-detects neg risk from the token ID — no flag needed.
// The order builder fetches neg_risk and uses the correct exchange contract.
let order = client
.limit_order()
.token_id("TOKEN_ID".parse()?)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field:
<CodeGroup>
```typescript TypeScript theme={null}
const isNegRisk = await client.getNegRisk(tokenID);
```
```python Python theme={null}
is_neg_risk = client.get_neg_risk(token_id)
```
```rust Rust theme={null}
let is_neg_risk = client.neg_risk(token_id).await?;
```
</CodeGroup>
***
## Allowances
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
* **Buying**: the funder must have set a **pUSD** allowance greater than or equal to the spending amount.
* **Selling**: the funder must have set a **conditional token** allowance greater than or equal to the selling amount.
This allows the Exchange contract to execute settlement according to your signed order instructions.
***
## Validity Checks
Orders are continually monitored to make sure they remain valid. This includes tracking:
* Underlying balances
* Allowances
<Warning>
Any maker caught intentionally abusing these checks will be blacklisted.
</Warning>
There are also limits on order placement per market. You can only place orders that sum to less than or equal to your available balance for each market. For example, if you have 500 pUSD in your funding wallet, you can place one order to buy 1000 YES at \$0.50 — but any additional buy orders in that market will be rejected since your entire balance is reserved for the first order.
The max size you can place for an order is:
$$
\text{maxOrderSize} = \text{underlyingAssetBalance} - \sum(\text{orderSize} - \text{orderFillAmount})
$$
***
## Querying Orders
All query endpoints require [L2 authentication](/api-reference/authentication). [Builder-authenticated](/trading/clients/builder) clients can also query orders attributed to their builder account using the same methods.
### Get a Single Order
Retrieve details for a specific order by its ID:
<CodeGroup>
```typescript TypeScript theme={null}
const order = await client.getOrder("0xb816482a...");
console.log(order);
```
```python Python theme={null}
order = client.get_order("0xb816482a...")
print(order)
```
```rust Rust theme={null}
let order = client.order("0xb816482a...").await?;
println!("{order:?}");
```
</CodeGroup>
### Get Open Orders
Retrieve your open orders, optionally filtered by market or asset:
<CodeGroup>
```typescript TypeScript theme={null}
// All open orders
const orders = await client.getOpenOrders();
// Filtered by market
const marketOrders = await client.getOpenOrders({
market: "0xbd31dc8a...",
});
// Filtered by asset
const assetOrders = await client.getOpenOrders({
asset_id: "52114319501245...",
});
```
```python Python theme={null}
from py_clob_client_v2 import OpenOrderParams
# All open orders
orders = client.get_orders()
# Filtered by market
market_orders = client.get_orders(
OpenOrderParams(
market="0xbd31dc8a...",
)
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::request::OrdersRequest;
// All open orders
let orders = client.orders(&OrdersRequest::default(), None).await?;
// Filtered by market
let request = OrdersRequest::builder()
.market("0xbd31dc8a...".parse()?)
.build();
let market_orders = client.orders(&request, None).await?;
// Filtered by asset
let request = OrdersRequest::builder()
.asset_id("52114319501245...".parse()?)
.build();
let asset_orders = client.orders(&request, None).await?;
```
</CodeGroup>
### OpenOrder Object
Each order returned contains these fields:
| Field | Type | Description |
| ------------------ | --------- | ------------------------------------------------------------ |
| `id` | string | Order ID |
| `status` | string | Current order status |
| `market` | string | Market ID (condition ID) |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `original_size` | string | Original order size at placement |
| `size_matched` | string | Amount that has been filled |
| `price` | string | Limit price |
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
| `order_type` | string | Order type (GTC, GTD, FOK, FAK) |
| `maker_address` | string | Funder address |
| `owner` | string | API key of the order owner |
| `expiration` | string | Unix timestamp when the order expires (`0` if no expiration) |
| `associate_trades` | string\[] | Trade IDs this order has been partially included in |
| `created_at` | string | Unix timestamp when the order was created |
***
## Trade History
When an order is matched, it creates a trade. Trades go through the following statuses:
| Status | Terminal? | Description |
| ----------- | --------- | -------------------------------------------------------------------- |
| `MATCHED` | No | Matched and sent to the executor service for onchain submission |
| `MINED` | No | Observed as mined on the chain, no finality threshold yet |
| `CONFIRMED` | Yes | Achieved strong probabilistic finality — trade successful |
| `RETRYING` | No | Transaction failed (revert or reorg) — being retried by the operator |
| `FAILED` | Yes | Trade failed permanently and is not being retried |
### Trade Object
Each trade contains these fields:
| Field | Type | Description |
| ------------------ | ------ | ------------------------------------------------------------ |
| `id` | string | Trade ID |
| `taker_order_id` | string | Taker order ID (hash) |
| `market` | string | Market ID (condition ID) |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `size` | string | Trade size |
| `fee_rate_bps` | string | Fee rate in basis points |
| `price` | string | Trade price |
| `status` | string | Trade status (see table above) |
| `match_time` | string | Unix timestamp when the trade was matched |
| `last_update` | string | Unix timestamp of last status update |
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
| `owner` | string | API key ID of the trade owner |
| `maker_address` | string | Funder address |
| `trader_side` | string | Whether you were `TAKER` or `MAKER` in this trade |
| `transaction_hash` | string | Onchain transaction hash (available after mining) |
| `maker_orders` | array | Array of maker orders matched against this trade (see below) |
### MakerOrder Fields
Each entry in the `maker_orders` array contains:
| Field | Type | Description |
| ---------------- | ------ | ---------------------------- |
| `order_id` | string | Maker order ID (hash) |
| `owner` | string | Maker's API key ID |
| `maker_address` | string | Maker's funder address |
| `matched_amount` | string | Amount matched in this trade |
| `price` | string | Maker order price |
| `fee_rate_bps` | string | Maker fee rate in bps |
| `asset_id` | string | Token ID |
| `outcome` | string | Outcome name |
| `side` | string | `BUY` or `SELL` |
Retrieve your trades with the SDK:
<CodeGroup>
```typescript TypeScript theme={null}
// All trades
const trades = await client.getTrades();
// Filtered by market
const marketTrades = await client.getTrades({
market: "0xbd31dc8a...",
});
// With pagination
const paginatedTrades = await client.getTradesPaginated({
market: "0xbd31dc8a...",
});
```
```python Python theme={null}
from py_clob_client_v2 import TradeParams
# All trades
trades = client.get_trades()
# Filtered by market
market_trades = client.get_trades(
TradeParams(
market="0xbd31dc8a...",
)
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::request::TradesRequest;
// All trades
let trades = client.trades(&TradesRequest::default(), None).await?;
// Filtered by market
let request = TradesRequest::builder()
.market("0xbd31dc8a...".parse()?)
.build();
let market_trades = client.trades(&request, None).await?;
```
</CodeGroup>
***
## Heartbeat
The heartbeat endpoint maintains session liveness for order safety. If a valid heartbeat is not received within **10 seconds** (with up to a 5-second buffer), **all of your open orders will be cancelled**.
<CodeGroup>
```typescript TypeScript theme={null}
// Send heartbeats in a loop
let heartbeatId = "";
setInterval(async () => {
const resp = await client.postHeartbeat(heartbeatId);
heartbeatId = resp.heartbeat_id;
}, 5000);
```
```python Python theme={null}
import time
heartbeat_id = ""
while True:
resp = client.post_heartbeat(heartbeat_id)
heartbeat_id = resp["heartbeat_id"]
time.sleep(5)
```
```rust Rust theme={null}
// With the `heartbeats` feature, auto-send in background:
Client::start_heartbeats(&mut client)?;
// Or manually:
let resp = client.post_heartbeat(None).await?; // None for first call
let resp = client.post_heartbeat(Some(resp.heartbeat_id)).await?;
```
</CodeGroup>
* On each request, include the most recent `heartbeat_id` you received. For your first request, use an empty string.
* If you send an invalid or expired `heartbeat_id`, the server responds with a `400 Bad Request` and provides the correct `heartbeat_id` in the response. Update your client and retry.
***
## Order Scoring
Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:
<CodeGroup>
```typescript TypeScript theme={null}
// Single order
const scoring = await client.isOrderScoring({ orderId: "0x..." });
console.log(scoring); // { scoring: true }
// Multiple orders
const batchScoring = await client.areOrdersScoring({
orderIds: ["0x...", "0x..."],
});
```
```python Python theme={null}
from py_clob_client_v2 import OrderScoringParams, OrdersScoringParams
# Single order
scoring = client.is_order_scoring(
OrderScoringParams(orderId="0x...")
)
# Multiple orders
batch_scoring = client.are_orders_scoring(
OrdersScoringParams(orderIds=["0x...", "0x..."])
)
```
```rust Rust theme={null}
// Single order
let scoring = client.is_order_scoring("0x...").await?;
println!("Scoring: {}", scoring.scoring);
// Multiple orders
let batch = client.are_orders_scoring(&["0x...", "0x..."]).await?;
```
</CodeGroup>
***
## Onchain Order Info
When a trade is settled onchain, the Exchange contract emits an `OrderFilled` event with the following fields:
| Field | Description |
| ------------------- | --------------------------------------------------------------------------------------------- |
| `orderHash` | Unique hash for the filled order |
| `maker` | The user who generated the order and source of funds |
| `taker` | The user filling the order, or the Exchange contract if multiple limit orders are filled |
| `makerAssetId` | ID of the asset given out. If `0`, the order is a **BUY** (giving pUSD for outcome tokens) |
| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving pUSD for outcome tokens) |
| `makerAmountFilled` | Amount of the asset given out |
| `takerAmountFilled` | Amount of the asset received |
| `fee` | Fees paid by the order maker |
***
## Error Messages
When placing an order, the response may include an `errorMsg` if the order could not be placed. If `success` is `false`, there was a server-side error:
| Error | Description |
| ---------------------------------- | ------------------------------------------------------ |
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
| `INVALID_ORDER_MIN_SIZE` | Order size is below the minimum threshold |
| `INVALID_ORDER_DUPLICATED` | Identical order has already been placed |
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Funder doesn't have sufficient balance or allowance |
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
| `INVALID_ORDER_ERROR` | System error while inserting order |
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only flag used with a market order type (FOK/FAK) |
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
| `EXECUTION_ERROR` | System error while executing trade |
| `ORDER_DELAYED` | Order placement delayed due to market conditions |
| `DELAYING_ORDER_ERROR` | System error while delaying order |
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
| `MARKET_NOT_READY` | Market is not yet accepting orders |
### Insert Statuses
When an order is successfully placed, the response includes a `status` field:
| Status | Description |
| ----------- | -------------------------------------------------------------------- |
| `matched` | Order placed and matched with a resting order |
| `live` | Order placed and resting on the book |
| `delayed` | Order is marketable but subject to a matching delay |
| `unmatched` | Order is marketable but failed to delay — placement still successful |
***
## Security
Polymarket's Exchange contract has been audited by Chainsecurity ([View Audit](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)).
The operator's privileges are limited to order matching and ensuring correct ordering. Operators cannot set prices or execute unauthorized trades.
***
## Next Steps
<CardGroup cols={2}>
<Card title="Create Order" icon="plus" href="/trading/orders/create">
Build, sign, and submit orders
</Card>
<Card title="Cancel Order" icon="xmark" href="/trading/orders/cancel">
Cancel single, multiple, or all orders
</Card>
</CardGroup>
-544
View File
@@ -1,544 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Overview
> Order types, tick sizes, and querying orders
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
The underlying order primitive is structured, hashed, and signed using the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) standard, then executed onchain via the Exchange contract. Preparing orders manually is involved, so we recommend using the open-source [TypeScript](https://github.com/Polymarket/clob-client-v2) or [Python](https://github.com/Polymarket/py-clob-client-v2) SDK clients, which handle signing and submission for you.
<Info>
If you prefer to use the REST API directly, you'll need to manage order
signing yourself. See [Authentication](/api-reference/authentication) for details on
constructing the required headers.
</Info>
***
## Order Types
| Type | Behavior | Use Case |
| ---------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------- |
| **GTC** (Good-Til-Cancelled) | Rests on the book until filled or cancelled | Default for passive limit orders |
| **GTD** (Good-Til-Date) | Active until a specified expiration time (UTC seconds timestamp), unless filled or cancelled first | Auto-expire orders before known events |
| **FOK** (Fill-Or-Kill) | Must be filled immediately and entirely, or the whole order is cancelled | All-or-nothing execution |
| **FAK** (Fill-And-Kill) | Fills as many shares as available immediately, then cancels any unfilled remainder | Partial immediate execution |
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
* **BUY**: specify the dollar amount you want to spend
* **SELL**: specify the number of shares you want to sell
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
<Note>
**GTD expiration**: There is a security threshold of one minute. If you need
the order to expire in 90 seconds, the correct expiration value is `now + 1
minute + 30 seconds`.
</Note>
### Post-Only Orders
Post-only orders are limit orders that will only rest on the book and not match immediately on entry.
* If a post-only order would cross the spread (i.e., it is marketable), it will be **rejected** rather than executed.
* Post-only **cannot** be combined with market order types (FOK or FAK). If `postOnly = true` is sent with a market order type, the order will be rejected.
* Post-only can only be used with **GTC** and **GTD** order types.
***
## Tick Sizes
Markets have different minimum price increments (tick sizes). Your order price must conform to the market's tick size, or the order will be rejected.
| Tick Size | Price Precision | Example Prices |
| --------- | --------------- | ---------------------- |
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
Retrieve the tick size for a market using the SDK:
<CodeGroup>
```typescript TypeScript theme={null}
const tickSize = await client.getTickSize(tokenID);
// Returns: "0.1" | "0.01" | "0.001" | "0.0001"
```
```python Python theme={null}
tick_size = client.get_tick_size(token_id)
# Returns: "0.1" | "0.01" | "0.001" | "0.0001"
```
```rust Rust theme={null}
let resp = client.tick_size(token_id).await?;
// resp.minimum_tick_size: TickSize::Tenth | Hundredth | Thousandth | TenThousandth
```
</CodeGroup>
<Tip>
You can also check the `minimum_tick_size` field on a market object returned
by the [Markets API](/market-data/fetching-markets).
</Tip>
***
## Negative Risk
Multi-outcome events (e.g., "Who will win the election?" with 3+ candidates) use a different exchange contract called the **Neg Risk CTF Exchange**. When placing orders on these markets, you must pass `negRisk: true` in the order options.
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{
tickSize: "0.01",
negRisk: true, // Required for multi-outcome markets
},
);
```
```python Python theme={null}
from py_clob_client_v2 import OrderArgs, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
response = client.create_and_post_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
),
options=PartialCreateOrderOptions(
tick_size="0.01",
neg_risk=True, # Required for multi-outcome markets
)
)
```
```rust Rust theme={null}
// The Rust SDK auto-detects neg risk from the token ID — no flag needed.
// The order builder fetches neg_risk and uses the correct exchange contract.
let order = client
.limit_order()
.token_id("TOKEN_ID".parse()?)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field:
<CodeGroup>
```typescript TypeScript theme={null}
const isNegRisk = await client.getNegRisk(tokenID);
```
```python Python theme={null}
is_neg_risk = client.get_neg_risk(token_id)
```
```rust Rust theme={null}
let is_neg_risk = client.neg_risk(token_id).await?;
```
</CodeGroup>
***
## Allowances
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
* **Buying**: the funder must have set a **pUSD** allowance greater than or equal to the spending amount.
* **Selling**: the funder must have set a **conditional token** allowance greater than or equal to the selling amount.
This allows the Exchange contract to execute settlement according to your signed order instructions.
***
## Validity Checks
Orders are continually monitored to make sure they remain valid. This includes tracking:
* Underlying balances
* Allowances
<Warning>
Any maker caught intentionally abusing these checks will be blacklisted.
</Warning>
There are also limits on order placement per market. You can only place orders that sum to less than or equal to your available balance for each market. For example, if you have 500 pUSD in your funding wallet, you can place one order to buy 1000 YES at \$0.50 — but any additional buy orders in that market will be rejected since your entire balance is reserved for the first order.
The max size you can place for an order is:
$$
\text{maxOrderSize} = \text{underlyingAssetBalance} - \sum(\text{orderSize} - \text{orderFillAmount})
$$
***
## Querying Orders
All query endpoints require [L2 authentication](/api-reference/authentication). [Builder-authenticated](/trading/clients/builder) clients can also query orders attributed to their builder account using the same methods.
### Get a Single Order
Retrieve details for a specific order by its ID:
<CodeGroup>
```typescript TypeScript theme={null}
const order = await client.getOrder("0xb816482a...");
console.log(order);
```
```python Python theme={null}
order = client.get_order("0xb816482a...")
print(order)
```
```rust Rust theme={null}
let order = client.order("0xb816482a...").await?;
println!("{order:?}");
```
</CodeGroup>
### Get Open Orders
Retrieve your open orders, optionally filtered by market or asset:
<CodeGroup>
```typescript TypeScript theme={null}
// All open orders
const orders = await client.getOpenOrders();
// Filtered by market
const marketOrders = await client.getOpenOrders({
market: "0xbd31dc8a...",
});
// Filtered by asset
const assetOrders = await client.getOpenOrders({
asset_id: "52114319501245...",
});
```
```python Python theme={null}
from py_clob_client_v2 import OpenOrderParams
# All open orders
orders = client.get_orders()
# Filtered by market
market_orders = client.get_orders(
OpenOrderParams(
market="0xbd31dc8a...",
)
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::request::OrdersRequest;
// All open orders
let orders = client.orders(&OrdersRequest::default(), None).await?;
// Filtered by market
let request = OrdersRequest::builder()
.market("0xbd31dc8a...".parse()?)
.build();
let market_orders = client.orders(&request, None).await?;
// Filtered by asset
let request = OrdersRequest::builder()
.asset_id("52114319501245...".parse()?)
.build();
let asset_orders = client.orders(&request, None).await?;
```
</CodeGroup>
### OpenOrder Object
Each order returned contains these fields:
| Field | Type | Description |
| ------------------ | --------- | ------------------------------------------------------------ |
| `id` | string | Order ID |
| `status` | string | Current order status |
| `market` | string | Market ID (condition ID) |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `original_size` | string | Original order size at placement |
| `size_matched` | string | Amount that has been filled |
| `price` | string | Limit price |
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
| `order_type` | string | Order type (GTC, GTD, FOK, FAK) |
| `maker_address` | string | Funder address |
| `owner` | string | API key of the order owner |
| `expiration` | string | Unix timestamp when the order expires (`0` if no expiration) |
| `associate_trades` | string\[] | Trade IDs this order has been partially included in |
| `created_at` | string | Unix timestamp when the order was created |
***
## Trade History
When an order is matched, it creates a trade. Trades go through the following statuses:
| Status | Terminal? | Description |
| ----------- | --------- | -------------------------------------------------------------------- |
| `MATCHED` | No | Matched and sent to the executor service for onchain submission |
| `MINED` | No | Observed as mined on the chain, no finality threshold yet |
| `CONFIRMED` | Yes | Achieved strong probabilistic finality — trade successful |
| `RETRYING` | No | Transaction failed (revert or reorg) — being retried by the operator |
| `FAILED` | Yes | Trade failed permanently and is not being retried |
### Trade Object
Each trade contains these fields:
| Field | Type | Description |
| ------------------ | ------ | ------------------------------------------------------------ |
| `id` | string | Trade ID |
| `taker_order_id` | string | Taker order ID (hash) |
| `market` | string | Market ID (condition ID) |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `size` | string | Trade size |
| `fee_rate_bps` | string | Fee rate in basis points |
| `price` | string | Trade price |
| `status` | string | Trade status (see table above) |
| `match_time` | string | Unix timestamp when the trade was matched |
| `last_update` | string | Unix timestamp of last status update |
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
| `owner` | string | API key ID of the trade owner |
| `maker_address` | string | Funder address |
| `trader_side` | string | Whether you were `TAKER` or `MAKER` in this trade |
| `transaction_hash` | string | Onchain transaction hash (available after mining) |
| `maker_orders` | array | Array of maker orders matched against this trade (see below) |
### MakerOrder Fields
Each entry in the `maker_orders` array contains:
| Field | Type | Description |
| ---------------- | ------ | ---------------------------- |
| `order_id` | string | Maker order ID (hash) |
| `owner` | string | Maker's API key ID |
| `maker_address` | string | Maker's funder address |
| `matched_amount` | string | Amount matched in this trade |
| `price` | string | Maker order price |
| `fee_rate_bps` | string | Maker fee rate in bps |
| `asset_id` | string | Token ID |
| `outcome` | string | Outcome name |
| `side` | string | `BUY` or `SELL` |
Retrieve your trades with the SDK:
<CodeGroup>
```typescript TypeScript theme={null}
// All trades
const trades = await client.getTrades();
// Filtered by market
const marketTrades = await client.getTrades({
market: "0xbd31dc8a...",
});
// With pagination
const paginatedTrades = await client.getTradesPaginated({
market: "0xbd31dc8a...",
});
```
```python Python theme={null}
from py_clob_client_v2 import TradeParams
# All trades
trades = client.get_trades()
# Filtered by market
market_trades = client.get_trades(
TradeParams(
market="0xbd31dc8a...",
)
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::request::TradesRequest;
// All trades
let trades = client.trades(&TradesRequest::default(), None).await?;
// Filtered by market
let request = TradesRequest::builder()
.market("0xbd31dc8a...".parse()?)
.build();
let market_trades = client.trades(&request, None).await?;
```
</CodeGroup>
***
## Heartbeat
The heartbeat endpoint maintains session liveness for order safety. If a valid heartbeat is not received within **10 seconds** (with up to a 5-second buffer), **all of your open orders will be cancelled**.
<CodeGroup>
```typescript TypeScript theme={null}
// Send heartbeats in a loop
let heartbeatId = "";
setInterval(async () => {
const resp = await client.postHeartbeat(heartbeatId);
heartbeatId = resp.heartbeat_id;
}, 5000);
```
```python Python theme={null}
import time
heartbeat_id = ""
while True:
resp = client.post_heartbeat(heartbeat_id)
heartbeat_id = resp["heartbeat_id"]
time.sleep(5)
```
```rust Rust theme={null}
// With the `heartbeats` feature, auto-send in background:
Client::start_heartbeats(&mut client)?;
// Or manually:
let resp = client.post_heartbeat(None).await?; // None for first call
let resp = client.post_heartbeat(Some(resp.heartbeat_id)).await?;
```
</CodeGroup>
* On each request, include the most recent `heartbeat_id` you received. For your first request, use an empty string.
* If you send an invalid or expired `heartbeat_id`, the server responds with a `400 Bad Request` and provides the correct `heartbeat_id` in the response. Update your client and retry.
***
## Order Scoring
Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:
<CodeGroup>
```typescript TypeScript theme={null}
// Single order
const scoring = await client.isOrderScoring({ orderId: "0x..." });
console.log(scoring); // { scoring: true }
// Multiple orders
const batchScoring = await client.areOrdersScoring({
orderIds: ["0x...", "0x..."],
});
```
```python Python theme={null}
from py_clob_client_v2 import OrderScoringParams, OrdersScoringParams
# Single order
scoring = client.is_order_scoring(
OrderScoringParams(orderId="0x...")
)
# Multiple orders
batch_scoring = client.are_orders_scoring(
OrdersScoringParams(orderIds=["0x...", "0x..."])
)
```
```rust Rust theme={null}
// Single order
let scoring = client.is_order_scoring("0x...").await?;
println!("Scoring: {}", scoring.scoring);
// Multiple orders
let batch = client.are_orders_scoring(&["0x...", "0x..."]).await?;
```
</CodeGroup>
***
## Onchain Order Info
When a trade is settled onchain, the Exchange contract emits an `OrderFilled` event with the following fields:
| Field | Description |
| ------------------- | --------------------------------------------------------------------------------------------- |
| `orderHash` | Unique hash for the filled order |
| `maker` | The user who generated the order and source of funds |
| `taker` | The user filling the order, or the Exchange contract if multiple limit orders are filled |
| `makerAssetId` | ID of the asset given out. If `0`, the order is a **BUY** (giving pUSD for outcome tokens) |
| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving pUSD for outcome tokens) |
| `makerAmountFilled` | Amount of the asset given out |
| `takerAmountFilled` | Amount of the asset received |
| `fee` | Fees paid by the order maker |
***
## Error Messages
When placing an order, the response may include an `errorMsg` if the order could not be placed. If `success` is `false`, there was a server-side error:
| Error | Description |
| ---------------------------------- | ------------------------------------------------------ |
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
| `INVALID_ORDER_MIN_SIZE` | Order size is below the minimum threshold |
| `INVALID_ORDER_DUPLICATED` | Identical order has already been placed |
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Funder doesn't have sufficient balance or allowance |
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
| `INVALID_ORDER_ERROR` | System error while inserting order |
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only flag used with a market order type (FOK/FAK) |
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
| `EXECUTION_ERROR` | System error while executing trade |
| `ORDER_DELAYED` | Order placement delayed due to market conditions |
| `DELAYING_ORDER_ERROR` | System error while delaying order |
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
| `MARKET_NOT_READY` | Market is not yet accepting orders |
### Insert Statuses
When an order is successfully placed, the response includes a `status` field:
| Status | Description |
| ----------- | -------------------------------------------------------------------- |
| `matched` | Order placed and matched with a resting order |
| `live` | Order placed and resting on the book |
| `delayed` | Order is marketable but subject to a matching delay |
| `unmatched` | Order is marketable but failed to delay — placement still successful |
***
## Security
Polymarket's Exchange contract has been audited by Chainsecurity ([View Audit](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)).
The operator's privileges are limited to order matching and ensuring correct ordering. Operators cannot set prices or execute unauthorized trades.
***
## Next Steps
<CardGroup cols={2}>
<Card title="Create Order" icon="plus" href="/trading/orders/create">
Build, sign, and submit orders
</Card>
<Card title="Cancel Order" icon="xmark" href="/trading/orders/cancel">
Cancel single, multiple, or all orders
</Card>
</CardGroup>
@@ -1,544 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Overview
> Order types, tick sizes, and querying orders
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
The underlying order primitive is structured, hashed, and signed using the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) standard, then executed onchain via the Exchange contract. Preparing orders manually is involved, so we recommend using the open-source [TypeScript](https://github.com/Polymarket/clob-client-v2) or [Python](https://github.com/Polymarket/py-clob-client-v2) SDK clients, which handle signing and submission for you.
<Info>
If you prefer to use the REST API directly, you'll need to manage order
signing yourself. See [Authentication](/api-reference/authentication) for details on
constructing the required headers.
</Info>
***
## Order Types
| Type | Behavior | Use Case |
| ---------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------- |
| **GTC** (Good-Til-Cancelled) | Rests on the book until filled or cancelled | Default for passive limit orders |
| **GTD** (Good-Til-Date) | Active until a specified expiration time (UTC seconds timestamp), unless filled or cancelled first | Auto-expire orders before known events |
| **FOK** (Fill-Or-Kill) | Must be filled immediately and entirely, or the whole order is cancelled | All-or-nothing execution |
| **FAK** (Fill-And-Kill) | Fills as many shares as available immediately, then cancels any unfilled remainder | Partial immediate execution |
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
* **BUY**: specify the dollar amount you want to spend
* **SELL**: specify the number of shares you want to sell
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
<Note>
**GTD expiration**: There is a security threshold of one minute. If you need
the order to expire in 90 seconds, the correct expiration value is `now + 1
minute + 30 seconds`.
</Note>
### Post-Only Orders
Post-only orders are limit orders that will only rest on the book and not match immediately on entry.
* If a post-only order would cross the spread (i.e., it is marketable), it will be **rejected** rather than executed.
* Post-only **cannot** be combined with market order types (FOK or FAK). If `postOnly = true` is sent with a market order type, the order will be rejected.
* Post-only can only be used with **GTC** and **GTD** order types.
***
## Tick Sizes
Markets have different minimum price increments (tick sizes). Your order price must conform to the market's tick size, or the order will be rejected.
| Tick Size | Price Precision | Example Prices |
| --------- | --------------- | ---------------------- |
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
Retrieve the tick size for a market using the SDK:
<CodeGroup>
```typescript TypeScript theme={null}
const tickSize = await client.getTickSize(tokenID);
// Returns: "0.1" | "0.01" | "0.001" | "0.0001"
```
```python Python theme={null}
tick_size = client.get_tick_size(token_id)
# Returns: "0.1" | "0.01" | "0.001" | "0.0001"
```
```rust Rust theme={null}
let resp = client.tick_size(token_id).await?;
// resp.minimum_tick_size: TickSize::Tenth | Hundredth | Thousandth | TenThousandth
```
</CodeGroup>
<Tip>
You can also check the `minimum_tick_size` field on a market object returned
by the [Markets API](/market-data/fetching-markets).
</Tip>
***
## Negative Risk
Multi-outcome events (e.g., "Who will win the election?" with 3+ candidates) use a different exchange contract called the **Neg Risk CTF Exchange**. When placing orders on these markets, you must pass `negRisk: true` in the order options.
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{
tickSize: "0.01",
negRisk: true, // Required for multi-outcome markets
},
);
```
```python Python theme={null}
from py_clob_client_v2 import OrderArgs, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
response = client.create_and_post_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
),
options=PartialCreateOrderOptions(
tick_size="0.01",
neg_risk=True, # Required for multi-outcome markets
)
)
```
```rust Rust theme={null}
// The Rust SDK auto-detects neg risk from the token ID — no flag needed.
// The order builder fetches neg_risk and uses the correct exchange contract.
let order = client
.limit_order()
.token_id("TOKEN_ID".parse()?)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field:
<CodeGroup>
```typescript TypeScript theme={null}
const isNegRisk = await client.getNegRisk(tokenID);
```
```python Python theme={null}
is_neg_risk = client.get_neg_risk(token_id)
```
```rust Rust theme={null}
let is_neg_risk = client.neg_risk(token_id).await?;
```
</CodeGroup>
***
## Allowances
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
* **Buying**: the funder must have set a **pUSD** allowance greater than or equal to the spending amount.
* **Selling**: the funder must have set a **conditional token** allowance greater than or equal to the selling amount.
This allows the Exchange contract to execute settlement according to your signed order instructions.
***
## Validity Checks
Orders are continually monitored to make sure they remain valid. This includes tracking:
* Underlying balances
* Allowances
<Warning>
Any maker caught intentionally abusing these checks will be blacklisted.
</Warning>
There are also limits on order placement per market. You can only place orders that sum to less than or equal to your available balance for each market. For example, if you have 500 pUSD in your funding wallet, you can place one order to buy 1000 YES at \$0.50 — but any additional buy orders in that market will be rejected since your entire balance is reserved for the first order.
The max size you can place for an order is:
$$
\text{maxOrderSize} = \text{underlyingAssetBalance} - \sum(\text{orderSize} - \text{orderFillAmount})
$$
***
## Querying Orders
All query endpoints require [L2 authentication](/api-reference/authentication). [Builder-authenticated](/trading/clients/builder) clients can also query orders attributed to their builder account using the same methods.
### Get a Single Order
Retrieve details for a specific order by its ID:
<CodeGroup>
```typescript TypeScript theme={null}
const order = await client.getOrder("0xb816482a...");
console.log(order);
```
```python Python theme={null}
order = client.get_order("0xb816482a...")
print(order)
```
```rust Rust theme={null}
let order = client.order("0xb816482a...").await?;
println!("{order:?}");
```
</CodeGroup>
### Get Open Orders
Retrieve your open orders, optionally filtered by market or asset:
<CodeGroup>
```typescript TypeScript theme={null}
// All open orders
const orders = await client.getOpenOrders();
// Filtered by market
const marketOrders = await client.getOpenOrders({
market: "0xbd31dc8a...",
});
// Filtered by asset
const assetOrders = await client.getOpenOrders({
asset_id: "52114319501245...",
});
```
```python Python theme={null}
from py_clob_client_v2 import OpenOrderParams
# All open orders
orders = client.get_orders()
# Filtered by market
market_orders = client.get_orders(
OpenOrderParams(
market="0xbd31dc8a...",
)
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::request::OrdersRequest;
// All open orders
let orders = client.orders(&OrdersRequest::default(), None).await?;
// Filtered by market
let request = OrdersRequest::builder()
.market("0xbd31dc8a...".parse()?)
.build();
let market_orders = client.orders(&request, None).await?;
// Filtered by asset
let request = OrdersRequest::builder()
.asset_id("52114319501245...".parse()?)
.build();
let asset_orders = client.orders(&request, None).await?;
```
</CodeGroup>
### OpenOrder Object
Each order returned contains these fields:
| Field | Type | Description |
| ------------------ | --------- | ------------------------------------------------------------ |
| `id` | string | Order ID |
| `status` | string | Current order status |
| `market` | string | Market ID (condition ID) |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `original_size` | string | Original order size at placement |
| `size_matched` | string | Amount that has been filled |
| `price` | string | Limit price |
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
| `order_type` | string | Order type (GTC, GTD, FOK, FAK) |
| `maker_address` | string | Funder address |
| `owner` | string | API key of the order owner |
| `expiration` | string | Unix timestamp when the order expires (`0` if no expiration) |
| `associate_trades` | string\[] | Trade IDs this order has been partially included in |
| `created_at` | string | Unix timestamp when the order was created |
***
## Trade History
When an order is matched, it creates a trade. Trades go through the following statuses:
| Status | Terminal? | Description |
| ----------- | --------- | -------------------------------------------------------------------- |
| `MATCHED` | No | Matched and sent to the executor service for onchain submission |
| `MINED` | No | Observed as mined on the chain, no finality threshold yet |
| `CONFIRMED` | Yes | Achieved strong probabilistic finality — trade successful |
| `RETRYING` | No | Transaction failed (revert or reorg) — being retried by the operator |
| `FAILED` | Yes | Trade failed permanently and is not being retried |
### Trade Object
Each trade contains these fields:
| Field | Type | Description |
| ------------------ | ------ | ------------------------------------------------------------ |
| `id` | string | Trade ID |
| `taker_order_id` | string | Taker order ID (hash) |
| `market` | string | Market ID (condition ID) |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `size` | string | Trade size |
| `fee_rate_bps` | string | Fee rate in basis points |
| `price` | string | Trade price |
| `status` | string | Trade status (see table above) |
| `match_time` | string | Unix timestamp when the trade was matched |
| `last_update` | string | Unix timestamp of last status update |
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
| `owner` | string | API key ID of the trade owner |
| `maker_address` | string | Funder address |
| `trader_side` | string | Whether you were `TAKER` or `MAKER` in this trade |
| `transaction_hash` | string | Onchain transaction hash (available after mining) |
| `maker_orders` | array | Array of maker orders matched against this trade (see below) |
### MakerOrder Fields
Each entry in the `maker_orders` array contains:
| Field | Type | Description |
| ---------------- | ------ | ---------------------------- |
| `order_id` | string | Maker order ID (hash) |
| `owner` | string | Maker's API key ID |
| `maker_address` | string | Maker's funder address |
| `matched_amount` | string | Amount matched in this trade |
| `price` | string | Maker order price |
| `fee_rate_bps` | string | Maker fee rate in bps |
| `asset_id` | string | Token ID |
| `outcome` | string | Outcome name |
| `side` | string | `BUY` or `SELL` |
Retrieve your trades with the SDK:
<CodeGroup>
```typescript TypeScript theme={null}
// All trades
const trades = await client.getTrades();
// Filtered by market
const marketTrades = await client.getTrades({
market: "0xbd31dc8a...",
});
// With pagination
const paginatedTrades = await client.getTradesPaginated({
market: "0xbd31dc8a...",
});
```
```python Python theme={null}
from py_clob_client_v2 import TradeParams
# All trades
trades = client.get_trades()
# Filtered by market
market_trades = client.get_trades(
TradeParams(
market="0xbd31dc8a...",
)
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::request::TradesRequest;
// All trades
let trades = client.trades(&TradesRequest::default(), None).await?;
// Filtered by market
let request = TradesRequest::builder()
.market("0xbd31dc8a...".parse()?)
.build();
let market_trades = client.trades(&request, None).await?;
```
</CodeGroup>
***
## Heartbeat
The heartbeat endpoint maintains session liveness for order safety. If a valid heartbeat is not received within **10 seconds** (with up to a 5-second buffer), **all of your open orders will be cancelled**.
<CodeGroup>
```typescript TypeScript theme={null}
// Send heartbeats in a loop
let heartbeatId = "";
setInterval(async () => {
const resp = await client.postHeartbeat(heartbeatId);
heartbeatId = resp.heartbeat_id;
}, 5000);
```
```python Python theme={null}
import time
heartbeat_id = ""
while True:
resp = client.post_heartbeat(heartbeat_id)
heartbeat_id = resp["heartbeat_id"]
time.sleep(5)
```
```rust Rust theme={null}
// With the `heartbeats` feature, auto-send in background:
Client::start_heartbeats(&mut client)?;
// Or manually:
let resp = client.post_heartbeat(None).await?; // None for first call
let resp = client.post_heartbeat(Some(resp.heartbeat_id)).await?;
```
</CodeGroup>
* On each request, include the most recent `heartbeat_id` you received. For your first request, use an empty string.
* If you send an invalid or expired `heartbeat_id`, the server responds with a `400 Bad Request` and provides the correct `heartbeat_id` in the response. Update your client and retry.
***
## Order Scoring
Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:
<CodeGroup>
```typescript TypeScript theme={null}
// Single order
const scoring = await client.isOrderScoring({ orderId: "0x..." });
console.log(scoring); // { scoring: true }
// Multiple orders
const batchScoring = await client.areOrdersScoring({
orderIds: ["0x...", "0x..."],
});
```
```python Python theme={null}
from py_clob_client_v2 import OrderScoringParams, OrdersScoringParams
# Single order
scoring = client.is_order_scoring(
OrderScoringParams(orderId="0x...")
)
# Multiple orders
batch_scoring = client.are_orders_scoring(
OrdersScoringParams(orderIds=["0x...", "0x..."])
)
```
```rust Rust theme={null}
// Single order
let scoring = client.is_order_scoring("0x...").await?;
println!("Scoring: {}", scoring.scoring);
// Multiple orders
let batch = client.are_orders_scoring(&["0x...", "0x..."]).await?;
```
</CodeGroup>
***
## Onchain Order Info
When a trade is settled onchain, the Exchange contract emits an `OrderFilled` event with the following fields:
| Field | Description |
| ------------------- | --------------------------------------------------------------------------------------------- |
| `orderHash` | Unique hash for the filled order |
| `maker` | The user who generated the order and source of funds |
| `taker` | The user filling the order, or the Exchange contract if multiple limit orders are filled |
| `makerAssetId` | ID of the asset given out. If `0`, the order is a **BUY** (giving pUSD for outcome tokens) |
| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving pUSD for outcome tokens) |
| `makerAmountFilled` | Amount of the asset given out |
| `takerAmountFilled` | Amount of the asset received |
| `fee` | Fees paid by the order maker |
***
## Error Messages
When placing an order, the response may include an `errorMsg` if the order could not be placed. If `success` is `false`, there was a server-side error:
| Error | Description |
| ---------------------------------- | ------------------------------------------------------ |
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
| `INVALID_ORDER_MIN_SIZE` | Order size is below the minimum threshold |
| `INVALID_ORDER_DUPLICATED` | Identical order has already been placed |
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Funder doesn't have sufficient balance or allowance |
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
| `INVALID_ORDER_ERROR` | System error while inserting order |
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only flag used with a market order type (FOK/FAK) |
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
| `EXECUTION_ERROR` | System error while executing trade |
| `ORDER_DELAYED` | Order placement delayed due to market conditions |
| `DELAYING_ORDER_ERROR` | System error while delaying order |
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
| `MARKET_NOT_READY` | Market is not yet accepting orders |
### Insert Statuses
When an order is successfully placed, the response includes a `status` field:
| Status | Description |
| ----------- | -------------------------------------------------------------------- |
| `matched` | Order placed and matched with a resting order |
| `live` | Order placed and resting on the book |
| `delayed` | Order is marketable but subject to a matching delay |
| `unmatched` | Order is marketable but failed to delay — placement still successful |
***
## Security
Polymarket's Exchange contract has been audited by Chainsecurity ([View Audit](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)).
The operator's privileges are limited to order matching and ensuring correct ordering. Operators cannot set prices or execute unauthorized trades.
***
## Next Steps
<CardGroup cols={2}>
<Card title="Create Order" icon="plus" href="/trading/orders/create">
Build, sign, and submit orders
</Card>
<Card title="Cancel Order" icon="xmark" href="/trading/orders/cancel">
Cancel single, multiple, or all orders
</Card>
</CardGroup>
-544
View File
@@ -1,544 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Overview
> Order types, tick sizes, and querying orders
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
The underlying order primitive is structured, hashed, and signed using the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) standard, then executed onchain via the Exchange contract. Preparing orders manually is involved, so we recommend using the open-source [TypeScript](https://github.com/Polymarket/clob-client-v2) or [Python](https://github.com/Polymarket/py-clob-client-v2) SDK clients, which handle signing and submission for you.
<Info>
If you prefer to use the REST API directly, you'll need to manage order
signing yourself. See [Authentication](/api-reference/authentication) for details on
constructing the required headers.
</Info>
***
## Order Types
| Type | Behavior | Use Case |
| ---------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------- |
| **GTC** (Good-Til-Cancelled) | Rests on the book until filled or cancelled | Default for passive limit orders |
| **GTD** (Good-Til-Date) | Active until a specified expiration time (UTC seconds timestamp), unless filled or cancelled first | Auto-expire orders before known events |
| **FOK** (Fill-Or-Kill) | Must be filled immediately and entirely, or the whole order is cancelled | All-or-nothing execution |
| **FAK** (Fill-And-Kill) | Fills as many shares as available immediately, then cancels any unfilled remainder | Partial immediate execution |
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
* **BUY**: specify the dollar amount you want to spend
* **SELL**: specify the number of shares you want to sell
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
<Note>
**GTD expiration**: There is a security threshold of one minute. If you need
the order to expire in 90 seconds, the correct expiration value is `now + 1
minute + 30 seconds`.
</Note>
### Post-Only Orders
Post-only orders are limit orders that will only rest on the book and not match immediately on entry.
* If a post-only order would cross the spread (i.e., it is marketable), it will be **rejected** rather than executed.
* Post-only **cannot** be combined with market order types (FOK or FAK). If `postOnly = true` is sent with a market order type, the order will be rejected.
* Post-only can only be used with **GTC** and **GTD** order types.
***
## Tick Sizes
Markets have different minimum price increments (tick sizes). Your order price must conform to the market's tick size, or the order will be rejected.
| Tick Size | Price Precision | Example Prices |
| --------- | --------------- | ---------------------- |
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
Retrieve the tick size for a market using the SDK:
<CodeGroup>
```typescript TypeScript theme={null}
const tickSize = await client.getTickSize(tokenID);
// Returns: "0.1" | "0.01" | "0.001" | "0.0001"
```
```python Python theme={null}
tick_size = client.get_tick_size(token_id)
# Returns: "0.1" | "0.01" | "0.001" | "0.0001"
```
```rust Rust theme={null}
let resp = client.tick_size(token_id).await?;
// resp.minimum_tick_size: TickSize::Tenth | Hundredth | Thousandth | TenThousandth
```
</CodeGroup>
<Tip>
You can also check the `minimum_tick_size` field on a market object returned
by the [Markets API](/market-data/fetching-markets).
</Tip>
***
## Negative Risk
Multi-outcome events (e.g., "Who will win the election?" with 3+ candidates) use a different exchange contract called the **Neg Risk CTF Exchange**. When placing orders on these markets, you must pass `negRisk: true` in the order options.
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{
tickSize: "0.01",
negRisk: true, // Required for multi-outcome markets
},
);
```
```python Python theme={null}
from py_clob_client_v2 import OrderArgs, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
response = client.create_and_post_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
),
options=PartialCreateOrderOptions(
tick_size="0.01",
neg_risk=True, # Required for multi-outcome markets
)
)
```
```rust Rust theme={null}
// The Rust SDK auto-detects neg risk from the token ID — no flag needed.
// The order builder fetches neg_risk and uses the correct exchange contract.
let order = client
.limit_order()
.token_id("TOKEN_ID".parse()?)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field:
<CodeGroup>
```typescript TypeScript theme={null}
const isNegRisk = await client.getNegRisk(tokenID);
```
```python Python theme={null}
is_neg_risk = client.get_neg_risk(token_id)
```
```rust Rust theme={null}
let is_neg_risk = client.neg_risk(token_id).await?;
```
</CodeGroup>
***
## Allowances
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
* **Buying**: the funder must have set a **pUSD** allowance greater than or equal to the spending amount.
* **Selling**: the funder must have set a **conditional token** allowance greater than or equal to the selling amount.
This allows the Exchange contract to execute settlement according to your signed order instructions.
***
## Validity Checks
Orders are continually monitored to make sure they remain valid. This includes tracking:
* Underlying balances
* Allowances
<Warning>
Any maker caught intentionally abusing these checks will be blacklisted.
</Warning>
There are also limits on order placement per market. You can only place orders that sum to less than or equal to your available balance for each market. For example, if you have 500 pUSD in your funding wallet, you can place one order to buy 1000 YES at \$0.50 — but any additional buy orders in that market will be rejected since your entire balance is reserved for the first order.
The max size you can place for an order is:
$$
\text{maxOrderSize} = \text{underlyingAssetBalance} - \sum(\text{orderSize} - \text{orderFillAmount})
$$
***
## Querying Orders
All query endpoints require [L2 authentication](/api-reference/authentication). [Builder-authenticated](/trading/clients/builder) clients can also query orders attributed to their builder account using the same methods.
### Get a Single Order
Retrieve details for a specific order by its ID:
<CodeGroup>
```typescript TypeScript theme={null}
const order = await client.getOrder("0xb816482a...");
console.log(order);
```
```python Python theme={null}
order = client.get_order("0xb816482a...")
print(order)
```
```rust Rust theme={null}
let order = client.order("0xb816482a...").await?;
println!("{order:?}");
```
</CodeGroup>
### Get Open Orders
Retrieve your open orders, optionally filtered by market or asset:
<CodeGroup>
```typescript TypeScript theme={null}
// All open orders
const orders = await client.getOpenOrders();
// Filtered by market
const marketOrders = await client.getOpenOrders({
market: "0xbd31dc8a...",
});
// Filtered by asset
const assetOrders = await client.getOpenOrders({
asset_id: "52114319501245...",
});
```
```python Python theme={null}
from py_clob_client_v2 import OpenOrderParams
# All open orders
orders = client.get_orders()
# Filtered by market
market_orders = client.get_orders(
OpenOrderParams(
market="0xbd31dc8a...",
)
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::request::OrdersRequest;
// All open orders
let orders = client.orders(&OrdersRequest::default(), None).await?;
// Filtered by market
let request = OrdersRequest::builder()
.market("0xbd31dc8a...".parse()?)
.build();
let market_orders = client.orders(&request, None).await?;
// Filtered by asset
let request = OrdersRequest::builder()
.asset_id("52114319501245...".parse()?)
.build();
let asset_orders = client.orders(&request, None).await?;
```
</CodeGroup>
### OpenOrder Object
Each order returned contains these fields:
| Field | Type | Description |
| ------------------ | --------- | ------------------------------------------------------------ |
| `id` | string | Order ID |
| `status` | string | Current order status |
| `market` | string | Market ID (condition ID) |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `original_size` | string | Original order size at placement |
| `size_matched` | string | Amount that has been filled |
| `price` | string | Limit price |
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
| `order_type` | string | Order type (GTC, GTD, FOK, FAK) |
| `maker_address` | string | Funder address |
| `owner` | string | API key of the order owner |
| `expiration` | string | Unix timestamp when the order expires (`0` if no expiration) |
| `associate_trades` | string\[] | Trade IDs this order has been partially included in |
| `created_at` | string | Unix timestamp when the order was created |
***
## Trade History
When an order is matched, it creates a trade. Trades go through the following statuses:
| Status | Terminal? | Description |
| ----------- | --------- | -------------------------------------------------------------------- |
| `MATCHED` | No | Matched and sent to the executor service for onchain submission |
| `MINED` | No | Observed as mined on the chain, no finality threshold yet |
| `CONFIRMED` | Yes | Achieved strong probabilistic finality — trade successful |
| `RETRYING` | No | Transaction failed (revert or reorg) — being retried by the operator |
| `FAILED` | Yes | Trade failed permanently and is not being retried |
### Trade Object
Each trade contains these fields:
| Field | Type | Description |
| ------------------ | ------ | ------------------------------------------------------------ |
| `id` | string | Trade ID |
| `taker_order_id` | string | Taker order ID (hash) |
| `market` | string | Market ID (condition ID) |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `size` | string | Trade size |
| `fee_rate_bps` | string | Fee rate in basis points |
| `price` | string | Trade price |
| `status` | string | Trade status (see table above) |
| `match_time` | string | Unix timestamp when the trade was matched |
| `last_update` | string | Unix timestamp of last status update |
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
| `owner` | string | API key ID of the trade owner |
| `maker_address` | string | Funder address |
| `trader_side` | string | Whether you were `TAKER` or `MAKER` in this trade |
| `transaction_hash` | string | Onchain transaction hash (available after mining) |
| `maker_orders` | array | Array of maker orders matched against this trade (see below) |
### MakerOrder Fields
Each entry in the `maker_orders` array contains:
| Field | Type | Description |
| ---------------- | ------ | ---------------------------- |
| `order_id` | string | Maker order ID (hash) |
| `owner` | string | Maker's API key ID |
| `maker_address` | string | Maker's funder address |
| `matched_amount` | string | Amount matched in this trade |
| `price` | string | Maker order price |
| `fee_rate_bps` | string | Maker fee rate in bps |
| `asset_id` | string | Token ID |
| `outcome` | string | Outcome name |
| `side` | string | `BUY` or `SELL` |
Retrieve your trades with the SDK:
<CodeGroup>
```typescript TypeScript theme={null}
// All trades
const trades = await client.getTrades();
// Filtered by market
const marketTrades = await client.getTrades({
market: "0xbd31dc8a...",
});
// With pagination
const paginatedTrades = await client.getTradesPaginated({
market: "0xbd31dc8a...",
});
```
```python Python theme={null}
from py_clob_client_v2 import TradeParams
# All trades
trades = client.get_trades()
# Filtered by market
market_trades = client.get_trades(
TradeParams(
market="0xbd31dc8a...",
)
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::request::TradesRequest;
// All trades
let trades = client.trades(&TradesRequest::default(), None).await?;
// Filtered by market
let request = TradesRequest::builder()
.market("0xbd31dc8a...".parse()?)
.build();
let market_trades = client.trades(&request, None).await?;
```
</CodeGroup>
***
## Heartbeat
The heartbeat endpoint maintains session liveness for order safety. If a valid heartbeat is not received within **10 seconds** (with up to a 5-second buffer), **all of your open orders will be cancelled**.
<CodeGroup>
```typescript TypeScript theme={null}
// Send heartbeats in a loop
let heartbeatId = "";
setInterval(async () => {
const resp = await client.postHeartbeat(heartbeatId);
heartbeatId = resp.heartbeat_id;
}, 5000);
```
```python Python theme={null}
import time
heartbeat_id = ""
while True:
resp = client.post_heartbeat(heartbeat_id)
heartbeat_id = resp["heartbeat_id"]
time.sleep(5)
```
```rust Rust theme={null}
// With the `heartbeats` feature, auto-send in background:
Client::start_heartbeats(&mut client)?;
// Or manually:
let resp = client.post_heartbeat(None).await?; // None for first call
let resp = client.post_heartbeat(Some(resp.heartbeat_id)).await?;
```
</CodeGroup>
* On each request, include the most recent `heartbeat_id` you received. For your first request, use an empty string.
* If you send an invalid or expired `heartbeat_id`, the server responds with a `400 Bad Request` and provides the correct `heartbeat_id` in the response. Update your client and retry.
***
## Order Scoring
Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:
<CodeGroup>
```typescript TypeScript theme={null}
// Single order
const scoring = await client.isOrderScoring({ orderId: "0x..." });
console.log(scoring); // { scoring: true }
// Multiple orders
const batchScoring = await client.areOrdersScoring({
orderIds: ["0x...", "0x..."],
});
```
```python Python theme={null}
from py_clob_client_v2 import OrderScoringParams, OrdersScoringParams
# Single order
scoring = client.is_order_scoring(
OrderScoringParams(orderId="0x...")
)
# Multiple orders
batch_scoring = client.are_orders_scoring(
OrdersScoringParams(orderIds=["0x...", "0x..."])
)
```
```rust Rust theme={null}
// Single order
let scoring = client.is_order_scoring("0x...").await?;
println!("Scoring: {}", scoring.scoring);
// Multiple orders
let batch = client.are_orders_scoring(&["0x...", "0x..."]).await?;
```
</CodeGroup>
***
## Onchain Order Info
When a trade is settled onchain, the Exchange contract emits an `OrderFilled` event with the following fields:
| Field | Description |
| ------------------- | --------------------------------------------------------------------------------------------- |
| `orderHash` | Unique hash for the filled order |
| `maker` | The user who generated the order and source of funds |
| `taker` | The user filling the order, or the Exchange contract if multiple limit orders are filled |
| `makerAssetId` | ID of the asset given out. If `0`, the order is a **BUY** (giving pUSD for outcome tokens) |
| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving pUSD for outcome tokens) |
| `makerAmountFilled` | Amount of the asset given out |
| `takerAmountFilled` | Amount of the asset received |
| `fee` | Fees paid by the order maker |
***
## Error Messages
When placing an order, the response may include an `errorMsg` if the order could not be placed. If `success` is `false`, there was a server-side error:
| Error | Description |
| ---------------------------------- | ------------------------------------------------------ |
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
| `INVALID_ORDER_MIN_SIZE` | Order size is below the minimum threshold |
| `INVALID_ORDER_DUPLICATED` | Identical order has already been placed |
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Funder doesn't have sufficient balance or allowance |
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
| `INVALID_ORDER_ERROR` | System error while inserting order |
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only flag used with a market order type (FOK/FAK) |
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
| `EXECUTION_ERROR` | System error while executing trade |
| `ORDER_DELAYED` | Order placement delayed due to market conditions |
| `DELAYING_ORDER_ERROR` | System error while delaying order |
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
| `MARKET_NOT_READY` | Market is not yet accepting orders |
### Insert Statuses
When an order is successfully placed, the response includes a `status` field:
| Status | Description |
| ----------- | -------------------------------------------------------------------- |
| `matched` | Order placed and matched with a resting order |
| `live` | Order placed and resting on the book |
| `delayed` | Order is marketable but subject to a matching delay |
| `unmatched` | Order is marketable but failed to delay — placement still successful |
***
## Security
Polymarket's Exchange contract has been audited by Chainsecurity ([View Audit](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)).
The operator's privileges are limited to order matching and ensuring correct ordering. Operators cannot set prices or execute unauthorized trades.
***
## Next Steps
<CardGroup cols={2}>
<Card title="Create Order" icon="plus" href="/trading/orders/create">
Build, sign, and submit orders
</Card>
<Card title="Cancel Order" icon="xmark" href="/trading/orders/cancel">
Cancel single, multiple, or all orders
</Card>
</CardGroup>
-299
View File
@@ -1,299 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Quickstart
> Place your first order on Polymarket
This guide walks you through placing an order on Polymarket end-to-end.
<Steps>
<Step title="Install the SDK">
<CodeGroup>
```bash TypeScript theme={null}
npm install @polymarket/clob-client-v2 viem
```
```bash Python theme={null}
pip install py-clob-client-v2
```
```bash Rust theme={null}
cargo add polymarket_client_sdk_v2 --features clob
```
</CodeGroup>
</Step>
<Step title="Set Up Your Client">
Derive your API credentials and initialize the trading client. This example uses
a deposit wallet with signature type `3` (`POLY_1271`), which is the wallet path
for new API users:
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient, SignatureTypeV2 } from "@polymarket/clob-client-v2";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const HOST = "https://clob.polymarket.com";
const CHAIN_ID = 137; // Polygon mainnet
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const signer = createWalletClient({ account, transport: http() });
const depositWalletAddress = process.env.DEPOSIT_WALLET_ADDRESS!;
// Derive API credentials
const tempClient = new ClobClient({ host: HOST, chain: CHAIN_ID, signer });
const apiCreds = await tempClient.createOrDeriveApiKey();
// Initialize trading client
const client = new ClobClient({
host: HOST,
chain: CHAIN_ID,
signer,
creds: apiCreds,
signatureType: SignatureTypeV2.POLY_1271,
funderAddress: depositWalletAddress,
});
```
```python Python theme={null}
from py_clob_client_v2 import ClobClient, SignatureTypeV2
import os
host = "https://clob.polymarket.com"
chain = 137 # Polygon mainnet
private_key = os.getenv("PRIVATE_KEY")
deposit_wallet_address = os.getenv("DEPOSIT_WALLET_ADDRESS")
# Derive API credentials
temp_client = ClobClient(host, key=private_key, chain_id=chain)
api_creds = temp_client.create_or_derive_api_key()
# Initialize trading client
client = ClobClient(
host,
key=private_key,
chain_id=chain,
creds=api_creds,
signature_type=SignatureTypeV2.POLY_1271,
funder=deposit_wallet_address
)
```
```rust Rust theme={null}
use std::str::FromStr;
use polymarket_client_sdk_v2::POLYGON;
use polymarket_client_sdk_v2::auth::{LocalSigner, Signer};
use polymarket_client_sdk_v2::clob::types::SignatureType;
use polymarket_client_sdk_v2::clob::{Client, Config};
let private_key = std::env::var("POLYMARKET_PRIVATE_KEY")?;
let signer = LocalSigner::from_str(&private_key)?
.with_chain_id(Some(POLYGON));
let deposit_wallet = std::env::var("DEPOSIT_WALLET_ADDRESS")?.parse()?;
// Derive API credentials and initialize client
let client = Client::new("https://clob.polymarket.com", Config::default())?
.authentication_builder(&signer)
.funder(deposit_wallet)
.signature_type(SignatureType::Poly1271)
.authenticate()
.await?;
```
</CodeGroup>
<Note>
Existing EOA, Safe, and Proxy integrations can keep using their current
signature type and funder address. See [Signature
Types](/trading/overview#signature-types) for all wallet types.
</Note>
<Warning>
Before trading from a deposit wallet, the deposit wallet needs **pUSD** and
the required trading approvals. See the [Deposit Wallet
Guide](/trading/deposit-wallets) for wallet creation, funding, approvals, and
balance sync.
</Warning>
</Step>
<Step title="Place an Order">
Get a token ID from the [Markets API](/market-data/fetching-markets), then create and submit your order:
<CodeGroup>
```typescript TypeScript theme={null}
import { Side, OrderType } from "@polymarket/clob-client-v2";
const response = await client.createAndPostOrder(
{
tokenID: "YOUR_TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{
tickSize: "0.01",
negRisk: false, // Set to true for multi-outcome markets
},
OrderType.GTC,
);
console.log("Order ID:", response.orderID);
console.log("Status:", response.status);
```
```python Python theme={null}
from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
response = client.create_and_post_order(
OrderArgs(
token_id="YOUR_TOKEN_ID",
price=0.50,
size=10,
side=BUY,
),
options=PartialCreateOrderOptions(
tick_size="0.01",
neg_risk=False, # Set to True for multi-outcome markets
),
order_type=OrderType.GTC
)
print("Order ID:", response["orderID"])
print("Status:", response["status"])
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::Side;
use polymarket_client_sdk_v2::types::dec;
let token_id = "YOUR_TOKEN_ID".parse()?;
// Tick size and neg risk are auto-fetched by the order builder
let order = client
.limit_order()
.token_id(token_id)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.build()
.await?;
let signed_order = client.sign(&signer, order).await?;
let response = client.post_order(signed_order).await?;
println!("Order ID: {}", response.order_id);
println!("Status: {:?}", response.status);
```
</CodeGroup>
<Tip>
Look up a market's `tickSize` and `negRisk` values using the SDK's
`getTickSize()` and `getNegRisk()` methods, or from the market object returned
by the API.
</Tip>
</Step>
<Step title="Check Your Orders">
<CodeGroup>
```typescript TypeScript theme={null}
// View all open orders
const openOrders = await client.getOpenOrders();
console.log(`You have ${openOrders.length} open orders`);
// View your trade history
const trades = await client.getTrades();
console.log(`You've made ${trades.length} trades`);
// Cancel an order
await client.cancelOrder(response.orderID);
```
```python Python theme={null}
# View all open orders
open_orders = client.get_orders()
print(f"You have {len(open_orders)} open orders")
# View your trade history
trades = client.get_trades()
print(f"You've made {len(trades)} trades")
# Cancel an order
client.cancel(order_id=response["orderID"])
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::request::{OrdersRequest, TradesRequest};
// View all open orders
let open_orders = client.orders(&OrdersRequest::default(), None).await?;
println!("You have {} open orders", open_orders.data.len());
// View your trade history
let trades = client.trades(&TradesRequest::default(), None).await?;
println!("You've made {} trades", trades.data.len());
// Cancel an order
client.cancel_order(&response.order_id).await?;
```
</CodeGroup>
</Step>
</Steps>
***
## Troubleshooting
<AccordionGroup>
<Accordion title="L2 AUTH NOT AVAILABLE - Invalid Signature">
Wrong private key, signature type, or funder address for the derived API credentials.
* Check that `signatureType` matches your account type (`0`, `1`, `2`, or `3`)
* Ensure `funder` is correct for your wallet type
* Re-derive credentials with `createOrDeriveApiKey()` if unsure
</Accordion>
<Accordion title="Order rejected - insufficient balance">
Your funder address doesn't have enough tokens:
* **BUY orders**: need pUSD in your funder address
* **SELL orders**: need outcome tokens in your funder address
* Ensure you have more pUSD than what's committed in open orders
</Accordion>
<Accordion title="Order rejected - insufficient allowance">
You need to approve the Exchange contract to spend your tokens. Deposit wallet
approvals must be executed from the deposit wallet through a relayer `WALLET`
batch. Existing Safe and Proxy users should use their current relayer approval
flow.
</Accordion>
<Accordion title="What is my funder address">
Your funder address is the wallet where your funds are held:
* **EOA (type 0)**: Your wallet address directly
* **Deposit wallet (type 3)**: The deposit wallet deployed for the owner or session signer
* **Proxy/Safe wallet (type 1 or 2)**: Existing Polymarket.com wallet address
New API users should create a deposit wallet. Existing Proxy and Safe users
can continue using their current wallet address.
</Accordion>
<Accordion title="Blocked by Cloudflare or Geoblock">
You're trying to place a trade from a restricted region. See [Geographic Restrictions](/api-reference/geoblock) for details.
</Accordion>
</AccordionGroup>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Create Orders" icon="plus" href="/trading/orders/create">
Order types, tick sizes, and error handling
</Card>
<Card title="Order Attribution" icon="tag" href="/trading/orders/attribution">
Attribute orders to your builder account for volume credit
</Card>
</CardGroup>
File diff suppressed because one or more lines are too long
-143
View File
@@ -1,143 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Get prices history
> Retrieve historical price data for a market.
## OpenAPI
````yaml /api-spec/clob-openapi.yaml get /prices-history
openapi: 3.1.0
info:
title: Polymarket CLOB API
description: Polymarket CLOB API Reference
license:
name: MIT
identifier: MIT
version: 1.0.0
servers:
- url: https://clob.polymarket.com
description: Production CLOB API
- url: https://clob-staging.polymarket.com
description: Staging CLOB API
security: []
tags:
- name: Trade
description: Trade endpoints
- name: Markets
description: Market data endpoints
- name: Account
description: Account and authentication endpoints
- name: Notifications
description: User notification endpoints
- name: Rewards
description: Rewards and earnings endpoints
- name: Rebates
description: Maker rebate endpoints
paths:
/prices-history:
get:
tags:
- Markets
summary: Get prices history
description: Retrieve historical price data for a market.
operationId: getPricesHistory
parameters:
- name: market
in: query
required: true
description: The market (asset id) to query.
schema:
type: string
- name: startTs
in: query
required: false
description: Filter by items after this unix timestamp.
schema:
type: number
format: double
- name: endTs
in: query
required: false
description: Filter by items before this unix timestamp.
schema:
type: number
format: double
- name: interval
in: query
required: false
description: Time interval for data aggregation.
schema:
type: string
enum:
- max
- all
- 1m
- 1w
- 1d
- 6h
- 1h
- name: fidelity
in: query
required: false
description: Accuracy of the data expressed in minutes. Default is 1 minute.
schema:
type: integer
responses:
'200':
description: Successful response with price history
content:
application/json:
schema:
$ref: '#/components/schemas/PricesHistoryResponse'
'400':
description: Bad Request - Missing or invalid query parameters
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security: []
components:
schemas:
PricesHistoryResponse:
type: object
properties:
history:
type: array
items:
$ref: '#/components/schemas/MarketPrice'
ErrorResponse:
type: object
required:
- error
properties:
error:
type: string
description: Error message
code:
type: string
description: Machine-readable error code, when provided
retry_after_seconds:
type: integer
description: Number of seconds to wait before retrying, when provided
MarketPrice:
type: object
properties:
t:
type: integer
format: uint32
p:
type: number
format: float
````
@@ -1,265 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Overview
> Trading on the Polymarket CLOB
Polymarket's CLOB (Central Limit Order Book) is a hybrid-decentralized trading system — offchain order matching with onchain settlement via the [Exchange contract](https://github.com/Polymarket/ctf-exchange/tree/main/src) ([audited by Chainsecurity](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)). All trading is non-custodial. Orders are [EIP-712](https://eips.ethereum.org/EIPS/eip-712) signed messages, and matched trades settle atomically on Polygon. The operator cannot set prices or execute unauthorized trades.
We recommend using the open-source SDK clients, which handle order signing, authentication, and submission:
<CardGroup cols={3}>
<Card title="TypeScript Client" icon="github" href="https://github.com/Polymarket/clob-client-v2">
<p className="font-mono text-[0.8rem]">
npm install @polymarket/clob-client-v2 viem
</p>
</Card>
<Card title="Python Client" icon="github" href="https://github.com/Polymarket/py-clob-client-v2">
<p className="font-mono text-[0.8rem]">pip install py-clob-client-v2</p>
</Card>
<Card title="Rust Client" icon="github" href="https://github.com/Polymarket/rs-clob-client-v2">
<p className="font-mono text-[0.8rem]">
cargo add polymarket\_client\_sdk\_v2 --features clob
</p>
</Card>
</CardGroup>
<Info>
You can also use the REST API directly, but you'll need to manage [EIP-712
order
signing](https://github.com/Polymarket/clob-client-v2/blob/main/src/signing/eip712.ts)
and [HMAC authentication
headers](https://github.com/Polymarket/clob-client-v2/blob/main/src/signing/hmac.ts)
yourself. See [REST API Headers](#rest-api-headers) below.
</Info>
***
## Authentication
The CLOB uses two levels of authentication:
| Level | Method | Purpose |
| ------ | ------------------------------- | ----------------------------------------- |
| **L1** | EIP-712 signature (private key) | Create or derive API credentials |
| **L2** | HMAC-SHA256 (API credentials) | Place orders, cancel orders, query trades |
You use your private key once to derive **L2 credentials** (API key, secret, passphrase), which authenticate all subsequent trading requests.
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient } from "@polymarket/clob-client-v2";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const signer = createWalletClient({ account, transport: http() });
// Derive L2 API credentials
const tempClient = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer,
});
const apiCreds = await tempClient.createOrDeriveApiKey();
```
```python Python theme={null}
from py_clob_client_v2 import ClobClient
import os
private_key = os.getenv("PRIVATE_KEY")
# Derive L2 API credentials
temp_client = ClobClient("https://clob.polymarket.com", key=private_key, chain_id=137)
api_creds = temp_client.create_or_derive_api_key()
```
```rust Rust theme={null}
use std::str::FromStr;
use polymarket_client_sdk_v2::POLYGON;
use polymarket_client_sdk_v2::auth::{LocalSigner, Signer};
use polymarket_client_sdk_v2::clob::{Client, Config};
let private_key = std::env::var("POLYMARKET_PRIVATE_KEY")?;
let signer = LocalSigner::from_str(&private_key)?
.with_chain_id(Some(POLYGON));
// Derive L2 API credentials and initialize client in one step
let client = Client::new("https://clob.polymarket.com", Config::default())?
.authentication_builder(&signer)
.authenticate()
.await?;
```
</CodeGroup>
***
## Signature Types
When initializing the trading client, you must specify your wallet's **signature type** and **funder address**:
| Wallet Type | ID | When to Use | Funder Address |
| ---------------- | --- | -------------------------------------------------------------------------------------------------------------- | --------------------------- |
| **EOA** | `0` | Standalone wallet — you pay your own gas (POL for gas) | Your EOA wallet address |
| **POLY\_PROXY** | `1` | Existing Polymarket proxy wallet flow | Your proxy wallet address |
| **GNOSIS\_SAFE** | `2` | Existing Gnosis Safe wallet flow | Your Safe wallet address |
| **POLY\_1271** | `3` | Deposit wallet flow for new API users. Orders are signed by the owner/session signer and validated by ERC-1271 | Your deposit wallet address |
<Note>
New API users should use deposit wallets with signature type `3`. Existing
Proxy and Safe users are unaffected and can keep using signature types `1` and
`2`. Type `0` is for standalone EOA wallets only.
</Note>
### Initialize the Trading Client
<CodeGroup>
```typescript TypeScript theme={null}
const depositWalletAddress = process.env.DEPOSIT_WALLET_ADDRESS!;
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer,
creds: apiCreds,
signatureType: 3, // POLY_1271
funderAddress: depositWalletAddress,
});
```
```python Python theme={null}
deposit_wallet_address = os.getenv("DEPOSIT_WALLET_ADDRESS")
client = ClobClient(
"https://clob.polymarket.com",
key=private_key,
chain_id=137,
creds=api_creds,
signature_type=3, # POLY_1271
funder=deposit_wallet_address
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::SignatureType;
let deposit_wallet = std::env::var("DEPOSIT_WALLET_ADDRESS")?.parse()?;
let client = Client::new("https://clob.polymarket.com", Config::default())?
.authentication_builder(&signer)
.funder(deposit_wallet)
.signature_type(SignatureType::Poly1271)
.authenticate()
.await?;
```
</CodeGroup>
***
## REST API Headers
If you're using the REST API directly (without the SDK), you need to attach authentication headers to each request.
**L1 Headers** — for creating or deriving API credentials:
| Header | Description |
| ---------------- | ------------------- |
| `POLY_ADDRESS` | Your wallet address |
| `POLY_SIGNATURE` | EIP-712 signature |
| `POLY_TIMESTAMP` | Unix timestamp |
| `POLY_NONCE` | Request nonce |
**L2 Headers** — for all trading operations (orders, cancellations, queries):
| Header | Description |
| ----------------- | ------------------------------------ |
| `POLY_ADDRESS` | Your wallet address |
| `POLY_SIGNATURE` | HMAC-SHA256 signature of the request |
| `POLY_TIMESTAMP` | Unix timestamp |
| `POLY_API_KEY` | Your API key |
| `POLY_PASSPHRASE` | Your API passphrase |
<Note>
Even with L2 authentication, methods that create orders still require the
user's private key for EIP-712 order payload signing. L2 credentials
authenticate the request, but the order itself must be signed by the key.
</Note>
***
## Client Methods
<CardGroup cols={2}>
<Card title="Public Methods" icon="globe" href="/trading/clients/public">
Market data, orderbooks, prices, and spreads — no auth required.
</Card>
<Card title="L1 Methods" icon="key" href="/trading/clients/l1">
Sign orders and derive API credentials with your private key.
</Card>
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
Place orders, cancel orders, query trades, and manage notifications.
</Card>
<Card title="Builder Methods" icon="hammer" href="/trading/clients/builder">
Track orders and trades attributed to your builder code.
</Card>
</CardGroup>
***
## Server Infrastructure
The CLOB matching engine runs in the following regions:
* **Primary Servers**: eu-west-2
* **Closest Non-Georestricted Region**: eu-west-1
<Tip>
**Direct co-location available.** Users who complete the [KYC/KYB
form](https://docs.google.com/forms/d/e/1FAIpQLSfY-3Dl3yxq8HKFjFad8YzKZmm0k3Gdg29HD6gL-K-AmI6KXw/viewform) can get access to co-locate
directly in `eu-west-2` for the lowest possible latency to Polymarket's
primary servers. See [Geographic
Restrictions](/api-reference/geoblock#server-infrastructure) for full
geographic availability details.
</Tip>
***
## What Is in This Section
<CardGroup cols={2}>
<Card title="Quickstart" icon="bolt" href="/trading/quickstart">
Place your first order end-to-end
</Card>
<Card title="Orderbook" icon="chart-bar" href="/trading/orderbook">
Reading the orderbook, prices, spreads, and midpoints
</Card>
<Card title="Orders" icon="list-check" href="/trading/orders/create">
Order types, tick sizes, creating, cancelling, and querying orders
</Card>
<Card title="Fees" icon="receipt" href="/trading/fees">
Fee structure, fee-enabled markets, and maker rebates
</Card>
<Card title="Gasless Transactions" icon="gas-pump" href="/trading/gasless">
Execute onchain operations without paying gas
</Card>
<Card title="CTF Tokens" icon="coins" href="/trading/ctf/overview">
Split, merge, and redeem outcome tokens
</Card>
<Card title="Bridge" icon="bridge" href="/trading/bridge/deposit">
Deposit and withdraw funds across chains
</Card>
</CardGroup>
-265
View File
@@ -1,265 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Overview
> Trading on the Polymarket CLOB
Polymarket's CLOB (Central Limit Order Book) is a hybrid-decentralized trading system — offchain order matching with onchain settlement via the [Exchange contract](https://github.com/Polymarket/ctf-exchange/tree/main/src) ([audited by Chainsecurity](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)). All trading is non-custodial. Orders are [EIP-712](https://eips.ethereum.org/EIPS/eip-712) signed messages, and matched trades settle atomically on Polygon. The operator cannot set prices or execute unauthorized trades.
We recommend using the open-source SDK clients, which handle order signing, authentication, and submission:
<CardGroup cols={3}>
<Card title="TypeScript Client" icon="github" href="https://github.com/Polymarket/clob-client-v2">
<p className="font-mono text-[0.8rem]">
npm install @polymarket/clob-client-v2 viem
</p>
</Card>
<Card title="Python Client" icon="github" href="https://github.com/Polymarket/py-clob-client-v2">
<p className="font-mono text-[0.8rem]">pip install py-clob-client-v2</p>
</Card>
<Card title="Rust Client" icon="github" href="https://github.com/Polymarket/rs-clob-client-v2">
<p className="font-mono text-[0.8rem]">
cargo add polymarket\_client\_sdk\_v2 --features clob
</p>
</Card>
</CardGroup>
<Info>
You can also use the REST API directly, but you'll need to manage [EIP-712
order
signing](https://github.com/Polymarket/clob-client-v2/blob/main/src/signing/eip712.ts)
and [HMAC authentication
headers](https://github.com/Polymarket/clob-client-v2/blob/main/src/signing/hmac.ts)
yourself. See [REST API Headers](#rest-api-headers) below.
</Info>
***
## Authentication
The CLOB uses two levels of authentication:
| Level | Method | Purpose |
| ------ | ------------------------------- | ----------------------------------------- |
| **L1** | EIP-712 signature (private key) | Create or derive API credentials |
| **L2** | HMAC-SHA256 (API credentials) | Place orders, cancel orders, query trades |
You use your private key once to derive **L2 credentials** (API key, secret, passphrase), which authenticate all subsequent trading requests.
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient } from "@polymarket/clob-client-v2";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const signer = createWalletClient({ account, transport: http() });
// Derive L2 API credentials
const tempClient = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer,
});
const apiCreds = await tempClient.createOrDeriveApiKey();
```
```python Python theme={null}
from py_clob_client_v2 import ClobClient
import os
private_key = os.getenv("PRIVATE_KEY")
# Derive L2 API credentials
temp_client = ClobClient("https://clob.polymarket.com", key=private_key, chain_id=137)
api_creds = temp_client.create_or_derive_api_key()
```
```rust Rust theme={null}
use std::str::FromStr;
use polymarket_client_sdk_v2::POLYGON;
use polymarket_client_sdk_v2::auth::{LocalSigner, Signer};
use polymarket_client_sdk_v2::clob::{Client, Config};
let private_key = std::env::var("POLYMARKET_PRIVATE_KEY")?;
let signer = LocalSigner::from_str(&private_key)?
.with_chain_id(Some(POLYGON));
// Derive L2 API credentials and initialize client in one step
let client = Client::new("https://clob.polymarket.com", Config::default())?
.authentication_builder(&signer)
.authenticate()
.await?;
```
</CodeGroup>
***
## Signature Types
When initializing the trading client, you must specify your wallet's **signature type** and **funder address**:
| Wallet Type | ID | When to Use | Funder Address |
| ---------------- | --- | -------------------------------------------------------------------------------------------------------------- | --------------------------- |
| **EOA** | `0` | Standalone wallet — you pay your own gas (POL for gas) | Your EOA wallet address |
| **POLY\_PROXY** | `1` | Existing Polymarket proxy wallet flow | Your proxy wallet address |
| **GNOSIS\_SAFE** | `2` | Existing Gnosis Safe wallet flow | Your Safe wallet address |
| **POLY\_1271** | `3` | Deposit wallet flow for new API users. Orders are signed by the owner/session signer and validated by ERC-1271 | Your deposit wallet address |
<Note>
New API users should use deposit wallets with signature type `3`. Existing
Proxy and Safe users are unaffected and can keep using signature types `1` and
`2`. Type `0` is for standalone EOA wallets only.
</Note>
### Initialize the Trading Client
<CodeGroup>
```typescript TypeScript theme={null}
const depositWalletAddress = process.env.DEPOSIT_WALLET_ADDRESS!;
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer,
creds: apiCreds,
signatureType: 3, // POLY_1271
funderAddress: depositWalletAddress,
});
```
```python Python theme={null}
deposit_wallet_address = os.getenv("DEPOSIT_WALLET_ADDRESS")
client = ClobClient(
"https://clob.polymarket.com",
key=private_key,
chain_id=137,
creds=api_creds,
signature_type=3, # POLY_1271
funder=deposit_wallet_address
)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::SignatureType;
let deposit_wallet = std::env::var("DEPOSIT_WALLET_ADDRESS")?.parse()?;
let client = Client::new("https://clob.polymarket.com", Config::default())?
.authentication_builder(&signer)
.funder(deposit_wallet)
.signature_type(SignatureType::Poly1271)
.authenticate()
.await?;
```
</CodeGroup>
***
## REST API Headers
If you're using the REST API directly (without the SDK), you need to attach authentication headers to each request.
**L1 Headers** — for creating or deriving API credentials:
| Header | Description |
| ---------------- | ------------------- |
| `POLY_ADDRESS` | Your wallet address |
| `POLY_SIGNATURE` | EIP-712 signature |
| `POLY_TIMESTAMP` | Unix timestamp |
| `POLY_NONCE` | Request nonce |
**L2 Headers** — for all trading operations (orders, cancellations, queries):
| Header | Description |
| ----------------- | ------------------------------------ |
| `POLY_ADDRESS` | Your wallet address |
| `POLY_SIGNATURE` | HMAC-SHA256 signature of the request |
| `POLY_TIMESTAMP` | Unix timestamp |
| `POLY_API_KEY` | Your API key |
| `POLY_PASSPHRASE` | Your API passphrase |
<Note>
Even with L2 authentication, methods that create orders still require the
user's private key for EIP-712 order payload signing. L2 credentials
authenticate the request, but the order itself must be signed by the key.
</Note>
***
## Client Methods
<CardGroup cols={2}>
<Card title="Public Methods" icon="globe" href="/trading/clients/public">
Market data, orderbooks, prices, and spreads — no auth required.
</Card>
<Card title="L1 Methods" icon="key" href="/trading/clients/l1">
Sign orders and derive API credentials with your private key.
</Card>
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
Place orders, cancel orders, query trades, and manage notifications.
</Card>
<Card title="Builder Methods" icon="hammer" href="/trading/clients/builder">
Track orders and trades attributed to your builder code.
</Card>
</CardGroup>
***
## Server Infrastructure
The CLOB matching engine runs in the following regions:
* **Primary Servers**: eu-west-2
* **Closest Non-Georestricted Region**: eu-west-1
<Tip>
**Direct co-location available.** Users who complete the [KYC/KYB
form](https://docs.google.com/forms/d/e/1FAIpQLSfY-3Dl3yxq8HKFjFad8YzKZmm0k3Gdg29HD6gL-K-AmI6KXw/viewform) can get access to co-locate
directly in `eu-west-2` for the lowest possible latency to Polymarket's
primary servers. See [Geographic
Restrictions](/api-reference/geoblock#server-infrastructure) for full
geographic availability details.
</Tip>
***
## What Is in This Section
<CardGroup cols={2}>
<Card title="Quickstart" icon="bolt" href="/trading/quickstart">
Place your first order end-to-end
</Card>
<Card title="Orderbook" icon="chart-bar" href="/trading/orderbook">
Reading the orderbook, prices, spreads, and midpoints
</Card>
<Card title="Orders" icon="list-check" href="/trading/orders/create">
Order types, tick sizes, creating, cancelling, and querying orders
</Card>
<Card title="Fees" icon="receipt" href="/trading/fees">
Fee structure, fee-enabled markets, and maker rebates
</Card>
<Card title="Gasless Transactions" icon="gas-pump" href="/trading/gasless">
Execute onchain operations without paying gas
</Card>
<Card title="CTF Tokens" icon="coins" href="/trading/ctf/overview">
Split, merge, and redeem outcome tokens
</Card>
<Card title="Bridge" icon="bridge" href="/trading/bridge/deposit">
Deposit and withdraw funds across chains
</Card>
</CardGroup>
@@ -1,235 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Market Channel
> Real-time orderbook, price, and trade data
Public channel for market data updates (level 2 price data). Subscribe with asset IDs to receive orderbook snapshots, price changes, trade executions, and market events.
## Endpoint
```
wss://ws-subscriptions-clob.polymarket.com/ws/market
```
## Subscription
```json theme={null}
{
"assets_ids": ["<token_id_1>", "<token_id_2>"],
"type": "market",
"custom_feature_enabled": true
}
```
Set `custom_feature_enabled: true` to receive `best_bid_ask`, `new_market`, and `market_resolved` events.
## Message Types
Each message includes an `event_type` field identifying the type.
### book
Emitted when first subscribed to a market and when there is a trade that affects the book.
```json theme={null}
{
"event_type": "book",
"asset_id": "65818619657568813474341868652308942079804919287380422192892211131408793125422",
"market": "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
"bids": [
{ "price": ".48", "size": "30" },
{ "price": ".49", "size": "20" },
{ "price": ".50", "size": "15" }
],
"asks": [
{ "price": ".52", "size": "25" },
{ "price": ".53", "size": "60" },
{ "price": ".54", "size": "10" }
],
"timestamp": "123456789000",
"hash": "0x0...."
}
```
### price\_change
Emitted when a new order is placed or an order is cancelled.
```json theme={null}
{
"market": "0x5f65177b394277fd294cd75650044e32ba009a95022d88a0c1d565897d72f8f1",
"price_changes": [
{
"asset_id": "71321045679252212594626385532706912750332728571942532289631379312455583992563",
"price": "0.5",
"size": "200",
"side": "BUY",
"hash": "56621a121a47ed9333273e21c83b660cff37ae50",
"best_bid": "0.5",
"best_ask": "1"
},
{
"asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426",
"price": "0.5",
"size": "200",
"side": "SELL",
"hash": "1895759e4df7a796bf4f1c5a5950b748306923e2",
"best_bid": "0",
"best_ask": "0.5"
}
],
"timestamp": "1757908892351",
"event_type": "price_change"
}
```
A `size` of `"0"` means the price level has been removed from the book.
### tick\_size\_change
Emitted when the minimum tick size of a market changes. This happens when the book's price reaches the limits: price > 0.96 or price \< 0.04.
```json theme={null}
{
"event_type": "tick_size_change",
"asset_id": "65818619657568813474341868652308942079804919287380422192892211131408793125422",
"market": "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
"old_tick_size": "0.01",
"new_tick_size": "0.001",
"timestamp": "100000000"
}
```
### last\_trade\_price
Emitted when a maker and taker order is matched, creating a trade event.
```json theme={null}
{
"asset_id": "114122071509644379678018727908709560226618148003371446110114509806601493071694",
"event_type": "last_trade_price",
"fee_rate_bps": "0",
"market": "0x6a67b9d828d53862160e470329ffea5246f338ecfffdf2cab45211ec578b0347",
"price": "0.456",
"side": "BUY",
"size": "219.217767",
"timestamp": "1750428146322"
}
```
### best\_bid\_ask
<Note>Requires `custom_feature_enabled: true`.</Note>
Emitted when the best bid or ask prices for a market change.
```json theme={null}
{
"event_type": "best_bid_ask",
"market": "0x0005c0d312de0be897668695bae9f32b624b4a1ae8b140c49f08447fcc74f442",
"asset_id": "85354956062430465315924116860125388538595433819574542752031640332592237464430",
"best_bid": "0.73",
"best_ask": "0.77",
"spread": "0.04",
"timestamp": "1766789469958"
}
```
### new\_market
<Note>Requires `custom_feature_enabled: true`.</Note>
Emitted when a new market is created.
The payload also includes market metadata fields such as `tags`,
`condition_id`, `active`, `clob_token_ids`, `sports_market_type`, `line`,
`game_start_time`, `order_price_min_tick_size`, `group_item_title`,
`taker_base_fee`, `fees_enabled`, and `fee_schedule`.
Where a `FeeSchedule` object is of the form:
| Name | Type | Description |
| ------------ | ------- | --------------------------------- |
| exponent | string | fee curve exponent |
| rate | string | fee rate |
| taker\_only | boolean | whether fee applies to taker only |
| rebate\_rate | string | maker rebate rate |
```json theme={null}
{
"id": "1031769",
"question": "Will NVIDIA (NVDA) close above $240 end of January?",
"market": "0x311d0c4b6671ab54af4970c06fcf58662516f5168997bdda209ec3db5aa6b0c1",
"slug": "nvda-above-240-on-january-30-2026",
"description": "This market will resolve to \"Yes\" if the official closing price...",
"assets_ids": [
"76043073756653678226373981964075571318267289248134717369284518995922789326425",
"31690934263385727664202099278545688007799199447969475608906331829650099442770"
],
"outcomes": ["Yes", "No"],
"event_message": {
"id": "125819",
"ticker": "nvda-above-in-january-2026",
"slug": "nvda-above-in-january-2026",
"title": "Will NVIDIA (NVDA) close above ___ end of January?",
"description": "This market will resolve to \"Yes\" if the official closing price..."
},
"timestamp": "1766790415550",
"event_type": "new_market",
"tags": ["stocks"],
"condition_id": "0x311d0c4b6671ab54af4970c06fcf58662516f5168997bdda209ec3db5aa6b0c1",
"active": true,
"clob_token_ids": [
"76043073756653678226373981964075571318267289248134717369284518995922789326425",
"31690934263385727664202099278545688007799199447969475608906331829650099442770"
],
"sports_market_type": "",
"line": "",
"game_start_time": "",
"order_price_min_tick_size": "0.01",
"group_item_title": "NVDA above $240",
"taker_base_fee": "0",
"fees_enabled": true,
"fee_schedule": {
"exponent": "2",
"rate": "0.02",
"taker_only": true,
"rebate_rate": "0"
}
}
```
### market\_resolved
<Note>Requires `custom_feature_enabled: true`.</Note>
Emitted when a market is resolved.
```json theme={null}
{
"id": "1031769",
"question": "Will NVIDIA (NVDA) close above $240 end of January?",
"market": "0x311d0c4b6671ab54af4970c06fcf58662516f5168997bdda209ec3db5aa6b0c1",
"slug": "nvda-above-240-on-january-30-2026",
"description": "This market will resolve to \"Yes\" if the official closing price...",
"assets_ids": [
"76043073756653678226373981964075571318267289248134717369284518995922789326425",
"31690934263385727664202099278545688007799199447969475608906331829650099442770"
],
"outcomes": ["Yes", "No"],
"winning_asset_id": "76043073756653678226373981964075571318267289248134717369284518995922789326425",
"winning_outcome": "Yes",
"event_message": {
"id": "125819",
"ticker": "nvda-above-in-january-2026",
"slug": "nvda-above-in-january-2026",
"title": "Will NVIDIA (NVDA) close above ___ end of January?",
"description": "This market will resolve to \"Yes\" if the official closing price..."
},
"timestamp": "1766790415550",
"event_type": "market_resolved"
}
```
@@ -1,124 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# User Channel
> Authenticated order and trade updates
Authenticated channel for updates related to your orders and trades, filtered by API key.
## Endpoint
```
wss://ws-subscriptions-clob.polymarket.com/ws/user
```
## Authentication
Include API credentials in your subscription message:
```json theme={null}
{
"auth": {
"apiKey": "your-api-key",
"secret": "your-api-secret",
"passphrase": "your-passphrase"
},
"markets": ["0x1234...condition_id"],
"type": "user"
}
```
<Warning>
Never expose your API credentials in client-side code. Use the user channel
only from server environments.
</Warning>
## Message Types
Each message includes a `type` field identifying the event.
### trade
Emitted when:
* A market order is matched (`MATCHED`)
* A limit order for the user is included in a trade (`MATCHED`)
* Subsequent status changes for the trade (`MINED`, `CONFIRMED`, `RETRYING`, `FAILED`)
```json theme={null}
{
"asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426",
"event_type": "trade",
"id": "28c4d2eb-bbea-40e7-a9f0-b2fdb56b2c2e",
"last_update": "1672290701",
"maker_orders": [
{
"asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426",
"matched_amount": "10",
"order_id": "0xff354cd7ca7539dfa9c28d90943ab5779a4eac34b9b37a757d7b32bdfb11790b",
"outcome": "YES",
"owner": "9180014b-33c8-9240-a14b-bdca11c0a465",
"price": "0.57"
}
],
"market": "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
"matchtime": "1672290701",
"outcome": "YES",
"owner": "9180014b-33c8-9240-a14b-bdca11c0a465",
"price": "0.57",
"side": "BUY",
"size": "10",
"status": "MATCHED",
"taker_order_id": "0x06bc63e346ed4ceddce9efd6b3af37c8f8f440c92fe7da6b2d0f9e4ccbc50c42",
"timestamp": "1672290701",
"trade_owner": "9180014b-33c8-9240-a14b-bdca11c0a465",
"type": "TRADE"
}
```
#### Trade Statuses
```
MATCHED → MINED → CONFIRMED
↓ ↑
RETRYING ───┘
FAILED
```
| Status | Terminal | Description |
| ----------- | -------- | ----------------------------------------------------------------------------------------------- |
| `MATCHED` | No | Trade has been matched and sent to the executor service by the operator |
| `MINED` | No | Trade observed to be mined into the chain, no finality threshold established |
| `CONFIRMED` | Yes | Trade has achieved strong probabilistic finality and was successful |
| `RETRYING` | No | Trade transaction has failed (revert or reorg) and is being retried/resubmitted by the operator |
| `FAILED` | Yes | Trade has failed and is not being retried |
### order
Emitted when:
* An order is placed (`PLACEMENT`)
* An order is updated — some of it is matched (`UPDATE`)
* An order is cancelled (`CANCELLATION`)
```json theme={null}
{
"asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426",
"associate_trades": null,
"event_type": "order",
"id": "0xff354cd7ca7539dfa9c28d90943ab5779a4eac34b9b37a757d7b32bdfb11790b",
"market": "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
"order_owner": "9180014b-33c8-9240-a14b-bdca11c0a465",
"original_size": "10",
"outcome": "YES",
"owner": "9180014b-33c8-9240-a14b-bdca11c0a465",
"price": "0.57",
"side": "SELL",
"size_matched": "0",
"timestamp": "1672290687",
"type": "PLACEMENT"
}
```
-181
View File
@@ -1,181 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Overview
> Real-time market data and trading updates via WebSocket
Polymarket provides WebSocket channels for near real-time streaming of orderbook data, trades, and personal order activity. There are four available channels: `market`, `user`, `sports`, and `RTDS` (Real-Time Data Socket).
## Channels
| Channel | Endpoint | Auth |
| ----------------------------------- | ------------------------------------------------------ | -------- |
| Market | `wss://ws-subscriptions-clob.polymarket.com/ws/market` | No |
| User | `wss://ws-subscriptions-clob.polymarket.com/ws/user` | Yes |
| Sports | `wss://sports-api.polymarket.com/ws` | No |
| [RTDS](/market-data/websocket/rtds) | `wss://ws-live-data.polymarket.com` | Optional |
### Market Channel
| Type | Description | Custom Feature |
| ------------------ | ----------------------- | -------------- |
| `book` | Full orderbook snapshot | No |
| `price_change` | Price level updates | No |
| `tick_size_change` | Tick size changes | No |
| `last_trade_price` | Trade executions | No |
| `best_bid_ask` | Best prices update | Yes |
| `new_market` | New market created | Yes |
| `market_resolved` | Market resolution | Yes |
Types marked "Custom Feature" require `custom_feature_enabled: true` in your subscription.
### User Channel
| Type | Description |
| ------- | --------------------------------------------- |
| `trade` | Trade lifecycle updates (MATCHED → CONFIRMED) |
| `order` | Order placements, updates, and cancellations |
### Sports
| Type | Description |
| -------------- | ------------------------------------- |
| `sport_result` | Live game scores, periods, and status |
## Subscribing
Send a subscription message after connecting to specify which data you want to receive.
### Market Channel
```json theme={null}
{
"assets_ids": [
"21742633143463906290569050155826241533067272736897614950488156847949938836455",
"48331043336612883890938759509493159234755048973500640148014422747788308965732"
],
"type": "market",
"custom_feature_enabled": true
}
```
| Field | Type | Description |
| ------------------------ | --------- | ----------------------------------------------------------------- |
| `assets_ids` | string\[] | Token IDs to subscribe to |
| `type` | string | Channel identifier |
| `custom_feature_enabled` | boolean | Enable `best_bid_ask`, `new_market`, and `market_resolved` events |
### User Channel
```json theme={null}
{
"auth": {
"apiKey": "your-api-key",
"secret": "your-api-secret",
"passphrase": "your-passphrase"
},
"markets": ["0x1234...condition_id"],
"type": "user"
}
```
<Note>
The `auth` fields (`apiKey`, `secret`, `passphrase`) are **only required for
the user channel**. For the market channel, these fields are optional and can
be omitted.
</Note>
| Field | Type | Description |
| --------- | --------- | -------------------------------------------------- |
| `auth` | object | API credentials (`apiKey`, `secret`, `passphrase`) |
| `markets` | string\[] | Condition IDs to receive events for |
| `type` | string | Channel identifier |
<Note>
The user channel subscribes by **condition IDs** (market identifiers), not
asset IDs. Each market has one condition ID but two asset IDs (Yes and No
tokens).
</Note>
### Sports Channel
No subscription message required. Connect and start receiving data for all active sports events.
## Dynamic Subscription
Modify subscriptions without reconnecting.
### Subscribe to more assets
```json theme={null}
{
"assets_ids": ["new_asset_id_1", "new_asset_id_2"],
"operation": "subscribe",
"custom_feature_enabled": true
}
```
### Unsubscribe from assets
```json theme={null}
{
"assets_ids": ["asset_id_to_remove"],
"operation": "unsubscribe"
}
```
For the user channel, use `markets` instead of `assets_ids`:
```json theme={null}
{
"markets": ["0x1234...condition_id"],
"operation": "subscribe"
}
```
## Heartbeats
### Market and User Channels
Send `PING` every 10 seconds. The server responds with `PONG`.
```
PING
```
### Sports Channel
The server sends `ping` every 5 seconds. Respond with `pong` within 10 seconds.
```
pong
```
<Warning>
If you don't respond to the server's ping within 10 seconds, the connection
will be closed.
</Warning>
## Troubleshooting
<Accordion title="Connection closes immediately after opening">
Send a valid subscription message immediately after connecting. The server may
close connections that don't subscribe within a timeout period.
</Accordion>
<Accordion title="Connection drops after about 10 seconds">
You're not sending heartbeats. Send `PING` every 10 seconds for market/user
channels, or respond to server `ping` with `pong` for the sports channel.
</Accordion>
<Accordion title="Not receiving any messages">
1. Verify your asset IDs or condition IDs are correct 2. Check that the
markets are active (not resolved) 3. Set `custom_feature_enabled: true` if
expecting `best_bid_ask`, `new_market`, or `market_resolved` events
</Accordion>
<Accordion title="Authentication failed - user channel">
Verify your API credentials are correct and haven't expired.
</Accordion>
@@ -1,181 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Overview
> Real-time market data and trading updates via WebSocket
Polymarket provides WebSocket channels for near real-time streaming of orderbook data, trades, and personal order activity. There are four available channels: `market`, `user`, `sports`, and `RTDS` (Real-Time Data Socket).
## Channels
| Channel | Endpoint | Auth |
| ----------------------------------- | ------------------------------------------------------ | -------- |
| Market | `wss://ws-subscriptions-clob.polymarket.com/ws/market` | No |
| User | `wss://ws-subscriptions-clob.polymarket.com/ws/user` | Yes |
| Sports | `wss://sports-api.polymarket.com/ws` | No |
| [RTDS](/market-data/websocket/rtds) | `wss://ws-live-data.polymarket.com` | Optional |
### Market Channel
| Type | Description | Custom Feature |
| ------------------ | ----------------------- | -------------- |
| `book` | Full orderbook snapshot | No |
| `price_change` | Price level updates | No |
| `tick_size_change` | Tick size changes | No |
| `last_trade_price` | Trade executions | No |
| `best_bid_ask` | Best prices update | Yes |
| `new_market` | New market created | Yes |
| `market_resolved` | Market resolution | Yes |
Types marked "Custom Feature" require `custom_feature_enabled: true` in your subscription.
### User Channel
| Type | Description |
| ------- | --------------------------------------------- |
| `trade` | Trade lifecycle updates (MATCHED → CONFIRMED) |
| `order` | Order placements, updates, and cancellations |
### Sports
| Type | Description |
| -------------- | ------------------------------------- |
| `sport_result` | Live game scores, periods, and status |
## Subscribing
Send a subscription message after connecting to specify which data you want to receive.
### Market Channel
```json theme={null}
{
"assets_ids": [
"21742633143463906290569050155826241533067272736897614950488156847949938836455",
"48331043336612883890938759509493159234755048973500640148014422747788308965732"
],
"type": "market",
"custom_feature_enabled": true
}
```
| Field | Type | Description |
| ------------------------ | --------- | ----------------------------------------------------------------- |
| `assets_ids` | string\[] | Token IDs to subscribe to |
| `type` | string | Channel identifier |
| `custom_feature_enabled` | boolean | Enable `best_bid_ask`, `new_market`, and `market_resolved` events |
### User Channel
```json theme={null}
{
"auth": {
"apiKey": "your-api-key",
"secret": "your-api-secret",
"passphrase": "your-passphrase"
},
"markets": ["0x1234...condition_id"],
"type": "user"
}
```
<Note>
The `auth` fields (`apiKey`, `secret`, `passphrase`) are **only required for
the user channel**. For the market channel, these fields are optional and can
be omitted.
</Note>
| Field | Type | Description |
| --------- | --------- | -------------------------------------------------- |
| `auth` | object | API credentials (`apiKey`, `secret`, `passphrase`) |
| `markets` | string\[] | Condition IDs to receive events for |
| `type` | string | Channel identifier |
<Note>
The user channel subscribes by **condition IDs** (market identifiers), not
asset IDs. Each market has one condition ID but two asset IDs (Yes and No
tokens).
</Note>
### Sports Channel
No subscription message required. Connect and start receiving data for all active sports events.
## Dynamic Subscription
Modify subscriptions without reconnecting.
### Subscribe to more assets
```json theme={null}
{
"assets_ids": ["new_asset_id_1", "new_asset_id_2"],
"operation": "subscribe",
"custom_feature_enabled": true
}
```
### Unsubscribe from assets
```json theme={null}
{
"assets_ids": ["asset_id_to_remove"],
"operation": "unsubscribe"
}
```
For the user channel, use `markets` instead of `assets_ids`:
```json theme={null}
{
"markets": ["0x1234...condition_id"],
"operation": "subscribe"
}
```
## Heartbeats
### Market and User Channels
Send `PING` every 10 seconds. The server responds with `PONG`.
```
PING
```
### Sports Channel
The server sends `ping` every 5 seconds. Respond with `pong` within 10 seconds.
```
pong
```
<Warning>
If you don't respond to the server's ping within 10 seconds, the connection
will be closed.
</Warning>
## Troubleshooting
<Accordion title="Connection closes immediately after opening">
Send a valid subscription message immediately after connecting. The server may
close connections that don't subscribe within a timeout period.
</Accordion>
<Accordion title="Connection drops after about 10 seconds">
You're not sending heartbeats. Send `PING` every 10 seconds for market/user
channels, or respond to server `ping` with `pong` for the sports channel.
</Accordion>
<Accordion title="Not receiving any messages">
1. Verify your asset IDs or condition IDs are correct 2. Check that the
markets are active (not resolved) 3. Set `custom_feature_enabled: true` if
expecting `best_bid_ask`, `new_market`, or `market_resolved` events
</Accordion>
<Accordion title="Authentication failed - user channel">
Verify your API credentials are correct and haven't expired.
</Accordion>
@@ -1,81 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Contracts
> All Polymarket smart contract addresses, audits, and security resources
All Polymarket contracts are deployed on **Polygon mainnet** (Chain ID: 137). This is the single source of truth for all contract addresses used across the platform.
***
## Core Trading Contracts
| Contract | Address |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| CTF Exchange | [`0xE111180000d2663C0091e4f400237545B87B996B`](https://polygonscan.com/address/0xE111180000d2663C0091e4f400237545B87B996B) |
| Neg Risk CTF Exchange | [`0xe2222d279d744050d28e00520010520000310F59`](https://polygonscan.com/address/0xe2222d279d744050d28e00520010520000310F59) |
| Neg Risk Adapter | [`0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296`](https://polygonscan.com/address/0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296) |
| Conditional Tokens (CTF) | [`0x4D97DCd97eC945f40cF65F87097ACe5EA0476045`](https://polygonscan.com/address/0x4D97DCd97eC945f40cF65F87097ACe5EA0476045) |
***
## Collateral Contracts
| Contract | Address |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| pUSD — CollateralToken (proxy) | [`0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB`](https://polygonscan.com/address/0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB) |
| pUSD — CollateralToken (impl) | [`0x6bBCef9f7ef3B6C592c99e0f206a0DE94Ad0925f`](https://polygonscan.com/address/0x6bBCef9f7ef3B6C592c99e0f206a0DE94Ad0925f) |
| CollateralOnramp | [`0x93070a847efEf7F70739046A929D47a521F5B8ee`](https://polygonscan.com/address/0x93070a847efEf7F70739046A929D47a521F5B8ee) |
| CollateralOfframp | [`0x2957922Eb93258b93368531d39fAcCA3B4dC5854`](https://polygonscan.com/address/0x2957922Eb93258b93368531d39fAcCA3B4dC5854) |
| PermissionedRamp | [`0xebC2459Ec962869ca4c0bd1E06368272732BCb08`](https://polygonscan.com/address/0xebC2459Ec962869ca4c0bd1E06368272732BCb08) |
| CtfCollateralAdapter | [`0xAdA100Db00Ca00073811820692005400218FcE1f`](https://polygonscan.com/address/0xAdA100Db00Ca00073811820692005400218FcE1f) |
| NegRiskCtfCollateralAdapter | [`0xadA2005600Dec949baf300f4C6120000bDB6eAab`](https://polygonscan.com/address/0xadA2005600Dec949baf300f4C6120000bDB6eAab) |
***
## Wallet Factory Contracts
| Contract | Address |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| Deposit Wallet Factory | [`0x00000000000Fb5C9ADea0298D729A0CB3823Cc07`](https://polygonscan.com/address/0x00000000000Fb5C9ADea0298D729A0CB3823Cc07) |
| Deposit Wallet Beacon | [`0x7A18EDfe055488A3128f01F563e5B479D92ffc3a`](https://polygonscan.com/address/0x7A18EDfe055488A3128f01F563e5B479D92ffc3a) |
| Gnosis Safe Factory | [`0xaacfeea03eb1561c4e67d661e40682bd20e3541b`](https://polygonscan.com/address/0xaacfeea03eb1561c4e67d661e40682bd20e3541b) |
| Polymarket Proxy Factory | [`0xaB45c5A4B0c941a2F231C04C3f49182e1A254052`](https://polygonscan.com/address/0xaB45c5A4B0c941a2F231C04C3f49182e1A254052) |
***
## Resolution Contracts
| Contract | Address |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| UMA Adapter | [`0x6A9D222616C90FcA5754cd1333cFD9b7fb6a4F74`](https://polygonscan.com/address/0x6A9D222616C90FcA5754cd1333cFD9b7fb6a4F74) |
| UMA Optimistic Oracle | [`0xCB1822859cEF82Cd2Eb4E6276C7916e692995130`](https://polygonscan.com/address/0xCB1822859cEF82Cd2Eb4E6276C7916e692995130) |
***
## Security
### Audits
CTF Exchange V2 has been audited by two independent firms:
| Auditor | Report |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Quantstamp | [CTF Exchange V2 — Quantstamp — March 2026](https://github.com/Polymarket/ctf-exchange-v2/blob/main/audits/CTF%20Exchange%20V2%20-%20Quantstamp%20-%20March%202026.pdf) |
| Cantina | [CTF Exchange V2 — Cantina — March 2026](https://github.com/Polymarket/ctf-exchange-v2/blob/main/audits/CTF%20Exchange%20V2%20-%20Cantina%20-%20March%202026.pdf) |
### Bug Bounty
Security vulnerabilities can be reported through the [Cantina bug bounty program](https://cantina.xyz/bounties/ff945ca2-2a6e-4b83-b1b6-7a0cd3b94bea).
***
## Source Code
<CardGroup cols={1}>
<Card title="CTF Exchange V2" icon="github" href="https://github.com/Polymarket/ctf-exchange-v2">
Order matching and settlement contracts
</Card>
</CardGroup>
-71
View File
@@ -1,71 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Merge Tokens
> Convert outcome token pairs back to pUSD
**Merging** is the inverse of splitting — it converts a full set of outcome tokens back into pUSD collateral. For every 1 Yes token and 1 No token you merge, you receive \$1 pUSD. The condition must already be prepared on the CTF contract (via `prepareCondition`).
```
100 Yes tokens + 100 No tokens → $100 pUSD
```
## Prerequisites
Before merging, you need:
1. **Equal amounts** of both Yes and No tokens
2. **Condition ID** of the market
3. **Sufficient gas** for the transaction
<Note>
Polymarket uses thin collateral adapter contracts for pUSD-native CTF actions.
Approve the adapter once, then route split, merge, and redeem actions through
it. For merge flows, the adapter calls the underlying CTF contract, receives
the released USDC.e collateral, wraps it into pUSD, and returns pUSD to your
wallet automatically.
</Note>
## How It Works
1. You call the adapter's merge flow with the amount and market details
2. One unit of each position in a full set is burned in return for 1 collateral unit
3. The adapter converts the released collateral into pUSD and returns pUSD to your wallet
The operation is atomic — if you don't have enough of both tokens, the transaction reverts.
## Function Parameters
<ResponseField name="collateralToken" type="IERC20">
pUSD (Polymarket USD) contract address: `0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB`
</ResponseField>
<ResponseField name="parentCollectionId" type="bytes32">
Always `0x0000...0000` (32 zero bytes) for Polymarket markets
</ResponseField>
<ResponseField name="conditionId" type="bytes32">
The market's condition ID, available from the Markets API
</ResponseField>
<ResponseField name="partition" type="uint[]">
Array of index sets: `[1, 2]` for binary markets
</ResponseField>
<ResponseField name="amount" type="uint256">
The number of full sets to merge. Also the amount of collateral to receive.
</ResponseField>
## Next Steps
<CardGroup cols={2}>
<Card title="Redeem Tokens" icon="hand-holding-dollar" href="/trading/ctf/redeem">
Exchange winning tokens for pUSD after resolution
</Card>
<Card title="CTF Overview" icon="book" href="/trading/ctf/overview">
Learn more about the Conditional Token Framework
</Card>
</CardGroup>
-140
View File
@@ -1,140 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Conditional Token Framework
> Onchain token mechanics powering Polymarket positions
All outcomes on Polymarket are tokenized using the **Conditional Token Framework (CTF)**, an open standard developed by Gnosis. Understanding CTF operations enables advanced trading strategies, market making, and direct smart contract interactions.
## What is CTF
The Conditional Token Framework creates **ERC1155 tokens** representing outcomes of prediction markets. Each binary market has two tokens:
| Token | Redeems for | Condition |
| ------- | ----------- | -------------------- |
| **Yes** | \$1.00 pUSD | Event occurs |
| **No** | \$1.00 pUSD | Event does not occur |
These tokens are always **fully collateralized** — every Yes/No pair is backed by exactly \$1.00 pUSD locked in the CTF contract.
## Core Operations
CTF provides three fundamental operations:
<CardGroup cols={3}>
<Card title="Split" icon="scissors" href="/trading/ctf/split">
Convert pUSD into Yes + No token pairs
</Card>
<Card title="Merge" icon="merge" href="/trading/ctf/merge">
Convert Yes + No pairs back to pUSD
</Card>
<Card title="Redeem" icon="hand-holding-dollar" href="/trading/ctf/redeem">
Exchange winning tokens for pUSD after resolution
</Card>
</CardGroup>
## Token Flow
<Frame>
<img src="https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/core-concepts/token-flow.png?fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=36f5a57946ac2b83136e17b6c06b358c" alt="" className="dark:hidden" width="1596" height="952" data-path="images/core-concepts/token-flow.png" />
<img src="https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/dark/core-concepts/token-flow.png?fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=69d150ea49ffa18cd7f24689342b1bec" alt="" className="hidden dark:block" width="1596" height="952" data-path="images/dark/core-concepts/token-flow.png" />
</Frame>
## Token Identifiers
Each outcome token has a unique **position ID** (also called token ID or asset ID), computed onchain in three steps.
### Step 1 - Condition ID
```
getConditionId(oracle, questionId, outcomeSlotCount)
```
| Parameter | Type | Value |
| ------------------ | --------- | ---------------------------------------------------------------- |
| `oracle` | `address` | [UMA CTF Adapter](https://github.com/Polymarket/uma-ctf-adapter) |
| `questionId` | `bytes32` | Hash of the UMA ancillary data |
| `outcomeSlotCount` | `uint` | `2` for all binary markets |
### Step 2 - Collection IDs
```
getCollectionId(parentCollectionId, conditionId, indexSet)
```
| Parameter | Type | Value |
| -------------------- | --------- | --------------------------------------------------------------- |
| `parentCollectionId` | `bytes32` | `bytes32(0)` — always zero for top-level positions |
| `conditionId` | `bytes32` | The condition ID from step 1 |
| `indexSet` | `uint` | `1` (`0b01`) for the first outcome, `2` (`0b10`) for the second |
The `indexSet` is a bitmask denoting which outcome slots belong to a collection. It must be a nonempty proper subset of the condition's outcome slots. Binary markets always have exactly two collections — one per outcome.
### Step 3 - Position IDs
```
getPositionId(collateralToken, collectionId)
```
| Parameter | Type | Value |
| ----------------- | --------- | ----------------------------------------- |
| `collateralToken` | `IERC20` | pUSD contract address on Polygon |
| `collectionId` | `bytes32` | One of the two collection IDs from step 2 |
The two resulting position IDs are the ERC1155 token IDs for the Yes and No outcomes of the market.
<Note>
You can look up token IDs directly via the Gamma API (`GET /markets` or `GET /events`
— the `tokens` array on each market contains both outcome token IDs). Computing them
manually is only necessary for direct smart contract integration.
</Note>
## Standard vs Neg Risk Markets
Polymarket has two market types with different CTF configurations:
| Feature | Standard Markets | Neg Risk Markets |
| ----------------- | ------------------- | --------------------- |
| CTF Contract | ConditionalTokens | ConditionalTokens |
| Exchange Contract | CTF Exchange | Neg Risk CTF Exchange |
| Multi-outcome | Independent markets | Linked via conversion |
| `negRisk` flag | `false` | `true` |
For neg risk markets, an additional **conversion** operation allows exchanging a No token for Yes tokens in all other outcomes. See [Negative Risk Markets](/advanced/neg-risk) for details.
## Contract Addresses
See [Contracts](/resources/contracts) for all Polymarket smart contract addresses on Polygon.
## Resources
<CardGroup cols={2}>
<Card title="CTF Source Code" icon="github" href="https://github.com/gnosis/conditional-tokens-contracts">
Gnosis Conditional Tokens smart contracts
</Card>
<Card title="Code Examples" icon="code" href="https://github.com/Polymarket/examples/tree/main/examples">
Python and TypeScript examples for onchain operations
</Card>
</CardGroup>
## Next Steps
<CardGroup cols={3}>
<Card title="Split Tokens" icon="scissors" href="/trading/ctf/split">
Create outcome token pairs from pUSD
</Card>
<Card title="Merge Tokens" icon="merge" href="/trading/ctf/merge">
Convert token pairs back to pUSD
</Card>
<Card title="Redeem Tokens" icon="hand-holding-dollar" href="/trading/ctf/redeem">
Collect winnings after resolution
</Card>
</CardGroup>
-102
View File
@@ -1,102 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Redeem Tokens
> Exchange winning tokens for pUSD after market resolution
**Redeeming** converts winning outcome tokens into pUSD after a market resolves. Each winning token is worth exactly $1.00 — the losing token is worth $0.
```
Market resolves YES:
100 Yes tokens → $100 pUSD
100 No tokens → $0
```
## When to Redeem
Redemption is only available **after a market resolves**. Once the oracle reports the outcome:
* **Winning tokens** can be redeemed for \$1.00 pUSD each
* **Losing tokens** are worth \$0 and produce no payout
<Note>
You can redeem at any time after resolution — there's no deadline. Your
winning tokens will always be redeemable.
</Note>
## How Resolution Works
1. The market's end condition is met (event occurs, date passes, etc.)
2. The UMA Adapter oracle reports the outcome via `reportPayouts()`
3. The CTF contract records the payout vector
4. Redemption becomes available for winning tokens
## Prerequisites
Before redeeming:
1. **Market must be resolved** — check the market's `resolved` status
2. **Hold winning tokens** — only the winning outcome can be redeemed
3. **Know the condition ID** — required for the redemption call
<Note>
Polymarket uses thin collateral adapter contracts for pUSD-native CTF actions.
Approve the adapter once, then route split, merge, and redeem actions through
it. On redeem, the adapter burns the ERC1155 outcome tokens through the CTF
contract, receives USDC.e collateral, wraps it into pUSD, and returns pUSD to
your wallet automatically.
</Note>
## Function Parameters
<ResponseField name="collateralToken" type="IERC20">
pUSD (Polymarket USD) contract address: `0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB`
</ResponseField>
<ResponseField name="parentCollectionId" type="bytes32">
Always `0x0000...0000` (32 zero bytes) for Polymarket markets
</ResponseField>
<ResponseField name="conditionId" type="bytes32">
The market's condition ID
</ResponseField>
<ResponseField name="indexSets" type="uint[]">
Array of index sets to redeem: `[1, 2]` redeems both outcomes (only winning
pays)
</ResponseField>
<Note>
Redemption burns your entire token balance for the condition — there is no
amount parameter.
</Note>
## Payout Mechanics
The CTF uses a **payout vector** to determine redemption values:
| Outcome | Payout Vector | Redemption |
| -------- | ------------- | ----------------- |
| Yes wins | `[1, 0]` | Yes = $1, No = $0 |
| No wins | `[0, 1]` | Yes = $0, No = $1 |
When you redeem through the adapter:
* Your token balance is multiplied by the payout
* Winning tokens are burned
* The released collateral is wrapped into pUSD and transferred to your wallet
* Losing tokens are burned as well, but produce a \$0 payout
## Next Steps
<CardGroup cols={2}>
<Card title="CTF Overview" icon="book" href="/trading/ctf/overview">
Learn more about the Conditional Token Framework
</Card>
<Card title="Resolution Process" icon="gavel" href="/concepts/resolution">
Understand how markets are resolved
</Card>
</CardGroup>
-76
View File
@@ -1,76 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Split Tokens
> Convert pUSD into outcome token pairs
**Splitting** converts pUSD collateral into a full (position) set of outcome tokens. For every \$1 pUSD you split, you receive 1 Yes token and 1 No token.
```
$100 pUSD → 100 Yes tokens + 100 No tokens
```
## Prerequisites
Before splitting, ensure you have:
1. **pUSD balance** on Polygon
2. **pUSD approval** for the CTF collateral adapter to spend your tokens
3. **Condition ID** of the market — the condition must already be prepared on the CTF contract (via `prepareCondition`)
<Note>
Polymarket uses thin collateral adapter contracts for pUSD-native CTF actions.
Approve the adapter once, then route split, merge, and redeem actions through
it. The adapter handles the CTF collateral plumbing so user-facing flows stay
in pUSD.
</Note>
<Note>
If the partition is trivial, invalid, or refers to more slots than the
condition is prepared with, the transaction will revert.
</Note>
## How It Works
1. You approve the CTF collateral adapter to spend your pUSD
2. You call the adapter's split flow with the amount and market details
3. The adapter calls the underlying CTF contract and mints both outcome tokens
The operation is atomic — if any step fails, the entire transaction reverts.
## Function Parameters
<ResponseField name="collateralToken" type="IERC20">
pUSD (Polymarket USD) contract address: `0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB`
</ResponseField>
<ResponseField name="parentCollectionId" type="bytes32">
Always `0x0000...0000` (32 zero bytes) for Polymarket markets
</ResponseField>
<ResponseField name="conditionId" type="bytes32">
The market's condition ID, available from the Markets API
</ResponseField>
<ResponseField name="partition" type="uint[]">
Array of index sets: `[1, 2]` for binary markets (Yes = 1, No = 2)
</ResponseField>
<ResponseField name="amount" type="uint256">
The amount of collateral or stake to split. Also the number of full sets to
receive.
</ResponseField>
## Next Steps
<CardGroup cols={2}>
<Card title="Merge Tokens" icon="merge" href="/trading/ctf/merge">
Convert token pairs back to pUSD
</Card>
<Card title="Trade on Orderbook" icon="chart-line" href="/trading/orders/create">
Place orders using your newly split tokens
</Card>
</CardGroup>
-554
View File
@@ -1,554 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Real-Time Data Socket
> Stream comments, crypto prices, and equity prices via WebSocket
The Polymarket Real-Time Data Socket (RTDS) is a WebSocket-based streaming service that provides real-time updates for **comments**, **crypto prices**, and **equity prices**.
<Card title="TypeScript client" icon="github" href="https://github.com/Polymarket/real-time-data-client">
Official RTDS TypeScript client (`real-time-data-client`).
</Card>
## Endpoint
```
wss://ws-live-data.polymarket.com
```
Some user-specific streams may require `gamma_auth` with your wallet address.
## Subscribing
Send a JSON message to subscribe to data streams:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "topic_name",
"type": "message_type",
"filters": "optional_filter_string",
"gamma_auth": {
"address": "wallet_address"
}
}
]
}
```
To unsubscribe, send the same structure with `"action": "unsubscribe"`.
Subscriptions can be added, removed, and modified without disconnecting. Send `PING` messages every 5 seconds to maintain the connection.
<Note>Only the subscription types documented below are supported.</Note>
## Message Structure
All messages follow this structure:
```json theme={null}
{
"topic": "string",
"type": "string",
"timestamp": "number",
"payload": "object"
}
```
| Field | Type | Description |
| ----------- | ------ | --------------------------------------------------------------------------- |
| `topic` | string | The subscription topic (e.g., `crypto_prices`, `equity_prices`, `comments`) |
| `type` | string | The message type/event (e.g., `update`, `reaction_created`) |
| `timestamp` | number | Unix timestamp in milliseconds when the message was sent |
| `payload` | object | Event-specific data object |
## Crypto Prices
Real-time cryptocurrency price data from two sources: **Binance** and **Chainlink**. No authentication required.
### Binance Source
Subscribe to all symbols:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "crypto_prices",
"type": "update"
}
]
}
```
Subscribe to specific symbols with a comma-separated filter:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "crypto_prices",
"type": "update",
"filters": "solusdt,btcusdt,ethusdt"
}
]
}
```
Symbols use lowercase concatenated format (e.g., `solusdt`, `btcusdt`).
**Solana price update:**
```json theme={null}
{
"topic": "crypto_prices",
"type": "update",
"timestamp": 1753314064237,
"payload": {
"symbol": "solusdt",
"timestamp": 1753314064213,
"value": 189.55
}
}
```
**Bitcoin price update:**
```json theme={null}
{
"topic": "crypto_prices",
"type": "update",
"timestamp": 1753314088421,
"payload": {
"symbol": "btcusdt",
"timestamp": 1753314088395,
"value": 67234.50
}
}
```
### Chainlink Source
<Tip>
**Trading 15m Crypto Markets?** Get a sponsored Chainlink API key with onboarding support from Chainlink. Fill out [this form](https://pm-ds-request.streams.chain.link/).
</Tip>
Subscribe to all symbols:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "crypto_prices_chainlink",
"type": "*",
"filters": ""
}
]
}
```
Subscribe to a specific symbol with a JSON filter:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "crypto_prices_chainlink",
"type": "*",
"filters": "{\"symbol\":\"eth/usd\"}"
}
]
}
```
Symbols use slash-separated format (e.g., `eth/usd`, `btc/usd`).
**Ethereum price update:**
```json theme={null}
{
"topic": "crypto_prices_chainlink",
"type": "update",
"timestamp": 1753314064237,
"payload": {
"symbol": "eth/usd",
"timestamp": 1753314064213,
"value": 3456.78
}
}
```
**Bitcoin price update:**
```json theme={null}
{
"topic": "crypto_prices_chainlink",
"type": "update",
"timestamp": 1753314088421,
"payload": {
"symbol": "btc/usd",
"timestamp": 1753314088395,
"value": 67234.50
}
}
```
### Price Payload Fields
| Field | Type | Description |
| ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `symbol` | string | Trading pair symbol. **Binance**: lowercase concatenated (e.g., `solusdt`, `btcusdt`). **Chainlink**: slash-separated (e.g., `eth/usd`, `btc/usd`) |
| `timestamp` | number | When the price was recorded, in Unix milliseconds |
| `value` | number | Current price value in the quote currency |
### Supported Symbols
**Binance Source** — lowercase concatenated format:
* `btcusdt` — Bitcoin to USDT
* `ethusdt` — Ethereum to USDT
* `solusdt` — Solana to USDT
* `xrpusdt` — XRP to USDT
**Chainlink Source** — slash-separated format:
* `btc/usd` — Bitcoin to USD
* `eth/usd` — Ethereum to USD
* `sol/usd` — Solana to USD
* `xrp/usd` — XRP to USD
## Equity Prices
Real-time price data for stocks, ETFs, forex pairs, precious metals, and commodities sourced from **Pyth Network**. No authentication required.
<Tip>
**Trading Equity Markets?** Get a Pyth Network data feed - first 30 days free, then \$99/month. [Subscribe here](https://buy.stripe.com/cNi8wPeiq76FgQrbsD4ZG09).
</Tip>
All asset classes stream through a single `equity_prices` topic. When you subscribe with a symbol filter, the server sends a historical snapshot (last 2 minutes of data), then continues streaming live updates.
### Subscribe
Subscribe to a specific symbol with a JSON filter:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "equity_prices",
"type": "update",
"filters": "{\"symbol\":\"AAPL\"}"
}
]
}
```
Subscribe to multiple symbols across asset classes:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{ "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"AAPL\"}" },
{ "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"EURUSD\"}" },
{ "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"XAUUSD\"}" },
{ "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"WTI\"}" }
]
}
```
Use `type: "*"` to receive all message types (live updates and snapshots):
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "equity_prices",
"type": "*",
"filters": "{\"symbol\":\"GOOGL\"}"
}
]
}
```
Filter values are case-insensitive on subscribe, but the `symbol` field in payloads is always returned lowercase.
<Tip>
**Need the price-to-beat value?** Pass the market slug to the price-to-beat endpoint:
`GET https://polymarket.com/api/equity/price-to-beat/{slug}`
Example: `https://polymarket.com/api/equity/price-to-beat/wti-up-or-down-on-april-7-2026`
</Tip>
### Live Price Update
**Apple stock update:**
```json theme={null}
{
"topic": "equity_prices",
"type": "update",
"timestamp": 1711382400000,
"payload": {
"symbol": "aapl",
"value": 198.45,
"full_accuracy_value": "198.4523",
"timestamp": 1711382400000,
"received_at": 1711382400005
}
}
```
**Gold price update (market closed):**
```json theme={null}
{
"topic": "equity_prices",
"type": "update",
"timestamp": 1711400000000,
"payload": {
"symbol": "xauusd",
"value": 2175.30,
"full_accuracy_value": "2175.3012",
"timestamp": 1711399000000,
"received_at": 1711400000002,
"is_carried_forward": true
}
}
```
### Historical Snapshot
On subscribe, the server delivers a backfill of the last 2 minutes of price data. Use the `type` field to distinguish: `"subscribe"` for the initial snapshot vs `"update"` for live ticks.
```json theme={null}
{
"topic": "equity_prices",
"type": "subscribe",
"timestamp": 1711382400000,
"payload": {
"symbol": "aapl",
"data": [
{ "timestamp": 1711382280000, "value": 198.30 },
{ "timestamp": 1711382281000, "value": 198.32 },
{ "timestamp": 1711382340000, "value": 198.41 }
]
}
}
```
### Equity Price Payload Fields
| Field | Type | Description |
| --------------------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `symbol` | string | Lowercase symbol identifier (e.g., `aapl`, `eurusd`, `xauusd`) |
| `value` | number | Spot price as a float |
| `full_accuracy_value` | string | Full-precision price as a string |
| `timestamp` | number | Price measurement timestamp in Unix milliseconds |
| `received_at` | number | When the system received the price, in Unix milliseconds. Only present when non-zero. |
| `is_carried_forward` | boolean | `true` when the market session is closed and the value is the last known price. Only present when `true`. |
### Supported Symbols
**Stocks:**
| Symbol | Name |
| ------- | -------------- |
| `AAPL` | Apple |
| `TSLA` | Tesla |
| `MSFT` | Microsoft |
| `GOOGL` | Alphabet |
| `AMZN` | Amazon |
| `META` | Meta Platforms |
| `NVDA` | NVIDIA |
| `NFLX` | Netflix |
| `PLTR` | Palantir |
| `OPEN` | Opendoor |
| `RKLB` | Rocket Lab |
| `ABNB` | Airbnb |
| `COIN` | Coinbase |
| `HOOD` | Robinhood |
**ETFs:**
| Symbol | Name |
| ------ | ------------------------------------ |
| `QQQ` | Invesco QQQ ETF |
| `SPY` | S\&P 500 ETF |
| `EWY` | iShares MSCI South Korea ETF |
| `VXX` | Barclays iPath Series B S\&P 500 VIX |
**Forex:**
| Symbol | Pair |
| -------- | ---------------------------- |
| `EURUSD` | Euro / US Dollar |
| `GBPUSD` | British Pound / US Dollar |
| `USDCAD` | US Dollar / Canadian Dollar |
| `USDJPY` | US Dollar / Japanese Yen |
| `USDKRW` | US Dollar / South Korean Won |
**Precious Metals:**
| Symbol | Name |
| -------- | ------ |
| `XAUUSD` | Gold |
| `XAGUSD` | Silver |
**Commodities** (rolling front-month futures):
| Symbol | Name |
| ------ | --------------- |
| `WTI` | Crude Oil (WTI) |
| `CC` | Cocoa |
| `NGD` | Natural Gas |
### Market Hours
When a market session is closed, the stream continues with the last known price and `is_carried_forward: true`. This lets you distinguish stale prices from live ticks. Update frequency is sub-second (up to 5 per second per feed) during market hours.
## Comments
Real-time comment events on the Polymarket platform, including new comments, replies, reactions, and removals. May require Gamma authentication for user-specific data.
### Subscribe
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "comments",
"type": "comment_created"
}
]
}
```
### Message Types
| Type | Description |
| ------------------ | ------------------------------------- |
| `comment_created` | A user creates a new comment or reply |
| `comment_removed` | A comment is removed or deleted |
| `reaction_created` | A user adds a reaction to a comment |
| `reaction_removed` | A reaction is removed from a comment |
### comment\_created
Emitted when a user posts a new comment or replies to an existing one.
```json theme={null}
{
"topic": "comments",
"type": "comment_created",
"timestamp": 1753454975808,
"payload": {
"body": "That's a good point about the definition.",
"createdAt": "2025-07-25T14:49:35.801298Z",
"id": "1763355",
"parentCommentID": "1763325",
"parentEntityID": 18396,
"parentEntityType": "Event",
"profile": {
"baseAddress": "0xce533188d53a16ed580fd5121dedf166d3482677",
"displayUsernamePublic": true,
"name": "salted.caramel",
"proxyWallet": "0x4ca749dcfa93c87e5ee23e2d21ff4422c7a4c1ee",
"pseudonym": "Adored-Disparity"
},
"reactionCount": 0,
"replyAddress": "0x0bda5d16f76cd1d3485bcc7a44bc6fa7db004cdd",
"reportCount": 0,
"userAddress": "0xce533188d53a16ed580fd5121dedf166d3482677"
}
}
```
A reply to the above comment — note `parentCommentID` references the parent:
```json theme={null}
{
"topic": "comments",
"type": "comment_created",
"timestamp": 1753454985123,
"payload": {
"body": "I agree, the resolution criteria should be clearer.",
"createdAt": "2025-07-25T14:49:45.120000Z",
"id": "1763356",
"parentCommentID": "1763355",
"parentEntityID": 18396,
"parentEntityType": "Event",
"profile": {
"baseAddress": "0x1234567890abcdef1234567890abcdef12345678",
"displayUsernamePublic": true,
"name": "trader",
"proxyWallet": "0x9876543210fedcba9876543210fedcba98765432",
"pseudonym": "Bright-Analysis"
},
"reactionCount": 0,
"replyAddress": "0x0bda5d16f76cd1d3485bcc7a44bc6fa7db004cdd",
"reportCount": 0,
"userAddress": "0x1234567890abcdef1234567890abcdef12345678"
}
}
```
### Comment Payload Fields
| Field | Type | Description |
| ------------------ | ------ | ------------------------------------------------------------------------- |
| `body` | string | The text content of the comment |
| `createdAt` | string | ISO 8601 timestamp when the comment was created |
| `id` | string | Unique identifier for this comment |
| `parentCommentID` | string | ID of the parent comment if this is a reply (null for top-level comments) |
| `parentEntityID` | number | ID of the parent entity (event, market, etc.) |
| `parentEntityType` | string | Type of parent entity (`Event`, `Market`) |
| `profile` | object | Profile information of the comment author |
| `reactionCount` | number | Current number of reactions on this comment |
| `replyAddress` | string | Polygon address for replies (may differ from userAddress) |
| `reportCount` | number | Current number of reports on this comment |
| `userAddress` | string | Polygon address of the comment author |
### Profile Object Fields
| Field | Type | Description |
| ----------------------- | ------- | ------------------------------------------ |
| `baseAddress` | string | User profile address |
| `displayUsernamePublic` | boolean | Whether the username is displayed publicly |
| `name` | string | User's display name |
| `proxyWallet` | string | Proxy wallet address used for transactions |
| `pseudonym` | string | Generated pseudonym for the user |
### Comment Hierarchy
Comments support nested threading:
* **Top-level comments**: `parentCommentID` is null or empty
* **Reply comments**: `parentCommentID` contains the ID of the parent comment
* All comments are associated with a `parentEntityID` and `parentEntityType` (`Event` or `Market`)
## Troubleshooting
<Accordion title="Connection drops unexpectedly">
Send `PING` messages every 5 seconds to keep the connection alive. Connection errors will trigger automatic reconnection attempts.
</Accordion>
<Accordion title="Not receiving messages after subscribing">
Verify your subscription message is valid JSON with the correct `action`, `topic`, and `type` fields. Invalid subscription messages may result in connection closure.
</Accordion>
<Accordion title="Authentication failures">
If subscribing to user-specific streams, ensure your `gamma_auth` object includes a valid wallet `address`. Authentication failures will prevent subscription to protected topics.
</Accordion>
-554
View File
@@ -1,554 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Real-Time Data Socket
> Stream comments, crypto prices, and equity prices via WebSocket
The Polymarket Real-Time Data Socket (RTDS) is a WebSocket-based streaming service that provides real-time updates for **comments**, **crypto prices**, and **equity prices**.
<Card title="TypeScript client" icon="github" href="https://github.com/Polymarket/real-time-data-client">
Official RTDS TypeScript client (`real-time-data-client`).
</Card>
## Endpoint
```
wss://ws-live-data.polymarket.com
```
Some user-specific streams may require `gamma_auth` with your wallet address.
## Subscribing
Send a JSON message to subscribe to data streams:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "topic_name",
"type": "message_type",
"filters": "optional_filter_string",
"gamma_auth": {
"address": "wallet_address"
}
}
]
}
```
To unsubscribe, send the same structure with `"action": "unsubscribe"`.
Subscriptions can be added, removed, and modified without disconnecting. Send `PING` messages every 5 seconds to maintain the connection.
<Note>Only the subscription types documented below are supported.</Note>
## Message Structure
All messages follow this structure:
```json theme={null}
{
"topic": "string",
"type": "string",
"timestamp": "number",
"payload": "object"
}
```
| Field | Type | Description |
| ----------- | ------ | --------------------------------------------------------------------------- |
| `topic` | string | The subscription topic (e.g., `crypto_prices`, `equity_prices`, `comments`) |
| `type` | string | The message type/event (e.g., `update`, `reaction_created`) |
| `timestamp` | number | Unix timestamp in milliseconds when the message was sent |
| `payload` | object | Event-specific data object |
## Crypto Prices
Real-time cryptocurrency price data from two sources: **Binance** and **Chainlink**. No authentication required.
### Binance Source
Subscribe to all symbols:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "crypto_prices",
"type": "update"
}
]
}
```
Subscribe to specific symbols with a comma-separated filter:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "crypto_prices",
"type": "update",
"filters": "solusdt,btcusdt,ethusdt"
}
]
}
```
Symbols use lowercase concatenated format (e.g., `solusdt`, `btcusdt`).
**Solana price update:**
```json theme={null}
{
"topic": "crypto_prices",
"type": "update",
"timestamp": 1753314064237,
"payload": {
"symbol": "solusdt",
"timestamp": 1753314064213,
"value": 189.55
}
}
```
**Bitcoin price update:**
```json theme={null}
{
"topic": "crypto_prices",
"type": "update",
"timestamp": 1753314088421,
"payload": {
"symbol": "btcusdt",
"timestamp": 1753314088395,
"value": 67234.50
}
}
```
### Chainlink Source
<Tip>
**Trading 15m Crypto Markets?** Get a sponsored Chainlink API key with onboarding support from Chainlink. Fill out [this form](https://pm-ds-request.streams.chain.link/).
</Tip>
Subscribe to all symbols:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "crypto_prices_chainlink",
"type": "*",
"filters": ""
}
]
}
```
Subscribe to a specific symbol with a JSON filter:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "crypto_prices_chainlink",
"type": "*",
"filters": "{\"symbol\":\"eth/usd\"}"
}
]
}
```
Symbols use slash-separated format (e.g., `eth/usd`, `btc/usd`).
**Ethereum price update:**
```json theme={null}
{
"topic": "crypto_prices_chainlink",
"type": "update",
"timestamp": 1753314064237,
"payload": {
"symbol": "eth/usd",
"timestamp": 1753314064213,
"value": 3456.78
}
}
```
**Bitcoin price update:**
```json theme={null}
{
"topic": "crypto_prices_chainlink",
"type": "update",
"timestamp": 1753314088421,
"payload": {
"symbol": "btc/usd",
"timestamp": 1753314088395,
"value": 67234.50
}
}
```
### Price Payload Fields
| Field | Type | Description |
| ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `symbol` | string | Trading pair symbol. **Binance**: lowercase concatenated (e.g., `solusdt`, `btcusdt`). **Chainlink**: slash-separated (e.g., `eth/usd`, `btc/usd`) |
| `timestamp` | number | When the price was recorded, in Unix milliseconds |
| `value` | number | Current price value in the quote currency |
### Supported Symbols
**Binance Source** — lowercase concatenated format:
* `btcusdt` — Bitcoin to USDT
* `ethusdt` — Ethereum to USDT
* `solusdt` — Solana to USDT
* `xrpusdt` — XRP to USDT
**Chainlink Source** — slash-separated format:
* `btc/usd` — Bitcoin to USD
* `eth/usd` — Ethereum to USD
* `sol/usd` — Solana to USD
* `xrp/usd` — XRP to USD
## Equity Prices
Real-time price data for stocks, ETFs, forex pairs, precious metals, and commodities sourced from **Pyth Network**. No authentication required.
<Tip>
**Trading Equity Markets?** Get a Pyth Network data feed - first 30 days free, then \$99/month. [Subscribe here](https://buy.stripe.com/cNi8wPeiq76FgQrbsD4ZG09).
</Tip>
All asset classes stream through a single `equity_prices` topic. When you subscribe with a symbol filter, the server sends a historical snapshot (last 2 minutes of data), then continues streaming live updates.
### Subscribe
Subscribe to a specific symbol with a JSON filter:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "equity_prices",
"type": "update",
"filters": "{\"symbol\":\"AAPL\"}"
}
]
}
```
Subscribe to multiple symbols across asset classes:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{ "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"AAPL\"}" },
{ "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"EURUSD\"}" },
{ "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"XAUUSD\"}" },
{ "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"WTI\"}" }
]
}
```
Use `type: "*"` to receive all message types (live updates and snapshots):
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "equity_prices",
"type": "*",
"filters": "{\"symbol\":\"GOOGL\"}"
}
]
}
```
Filter values are case-insensitive on subscribe, but the `symbol` field in payloads is always returned lowercase.
<Tip>
**Need the price-to-beat value?** Pass the market slug to the price-to-beat endpoint:
`GET https://polymarket.com/api/equity/price-to-beat/{slug}`
Example: `https://polymarket.com/api/equity/price-to-beat/wti-up-or-down-on-april-7-2026`
</Tip>
### Live Price Update
**Apple stock update:**
```json theme={null}
{
"topic": "equity_prices",
"type": "update",
"timestamp": 1711382400000,
"payload": {
"symbol": "aapl",
"value": 198.45,
"full_accuracy_value": "198.4523",
"timestamp": 1711382400000,
"received_at": 1711382400005
}
}
```
**Gold price update (market closed):**
```json theme={null}
{
"topic": "equity_prices",
"type": "update",
"timestamp": 1711400000000,
"payload": {
"symbol": "xauusd",
"value": 2175.30,
"full_accuracy_value": "2175.3012",
"timestamp": 1711399000000,
"received_at": 1711400000002,
"is_carried_forward": true
}
}
```
### Historical Snapshot
On subscribe, the server delivers a backfill of the last 2 minutes of price data. Use the `type` field to distinguish: `"subscribe"` for the initial snapshot vs `"update"` for live ticks.
```json theme={null}
{
"topic": "equity_prices",
"type": "subscribe",
"timestamp": 1711382400000,
"payload": {
"symbol": "aapl",
"data": [
{ "timestamp": 1711382280000, "value": 198.30 },
{ "timestamp": 1711382281000, "value": 198.32 },
{ "timestamp": 1711382340000, "value": 198.41 }
]
}
}
```
### Equity Price Payload Fields
| Field | Type | Description |
| --------------------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `symbol` | string | Lowercase symbol identifier (e.g., `aapl`, `eurusd`, `xauusd`) |
| `value` | number | Spot price as a float |
| `full_accuracy_value` | string | Full-precision price as a string |
| `timestamp` | number | Price measurement timestamp in Unix milliseconds |
| `received_at` | number | When the system received the price, in Unix milliseconds. Only present when non-zero. |
| `is_carried_forward` | boolean | `true` when the market session is closed and the value is the last known price. Only present when `true`. |
### Supported Symbols
**Stocks:**
| Symbol | Name |
| ------- | -------------- |
| `AAPL` | Apple |
| `TSLA` | Tesla |
| `MSFT` | Microsoft |
| `GOOGL` | Alphabet |
| `AMZN` | Amazon |
| `META` | Meta Platforms |
| `NVDA` | NVIDIA |
| `NFLX` | Netflix |
| `PLTR` | Palantir |
| `OPEN` | Opendoor |
| `RKLB` | Rocket Lab |
| `ABNB` | Airbnb |
| `COIN` | Coinbase |
| `HOOD` | Robinhood |
**ETFs:**
| Symbol | Name |
| ------ | ------------------------------------ |
| `QQQ` | Invesco QQQ ETF |
| `SPY` | S\&P 500 ETF |
| `EWY` | iShares MSCI South Korea ETF |
| `VXX` | Barclays iPath Series B S\&P 500 VIX |
**Forex:**
| Symbol | Pair |
| -------- | ---------------------------- |
| `EURUSD` | Euro / US Dollar |
| `GBPUSD` | British Pound / US Dollar |
| `USDCAD` | US Dollar / Canadian Dollar |
| `USDJPY` | US Dollar / Japanese Yen |
| `USDKRW` | US Dollar / South Korean Won |
**Precious Metals:**
| Symbol | Name |
| -------- | ------ |
| `XAUUSD` | Gold |
| `XAGUSD` | Silver |
**Commodities** (rolling front-month futures):
| Symbol | Name |
| ------ | --------------- |
| `WTI` | Crude Oil (WTI) |
| `CC` | Cocoa |
| `NGD` | Natural Gas |
### Market Hours
When a market session is closed, the stream continues with the last known price and `is_carried_forward: true`. This lets you distinguish stale prices from live ticks. Update frequency is sub-second (up to 5 per second per feed) during market hours.
## Comments
Real-time comment events on the Polymarket platform, including new comments, replies, reactions, and removals. May require Gamma authentication for user-specific data.
### Subscribe
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "comments",
"type": "comment_created"
}
]
}
```
### Message Types
| Type | Description |
| ------------------ | ------------------------------------- |
| `comment_created` | A user creates a new comment or reply |
| `comment_removed` | A comment is removed or deleted |
| `reaction_created` | A user adds a reaction to a comment |
| `reaction_removed` | A reaction is removed from a comment |
### comment\_created
Emitted when a user posts a new comment or replies to an existing one.
```json theme={null}
{
"topic": "comments",
"type": "comment_created",
"timestamp": 1753454975808,
"payload": {
"body": "That's a good point about the definition.",
"createdAt": "2025-07-25T14:49:35.801298Z",
"id": "1763355",
"parentCommentID": "1763325",
"parentEntityID": 18396,
"parentEntityType": "Event",
"profile": {
"baseAddress": "0xce533188d53a16ed580fd5121dedf166d3482677",
"displayUsernamePublic": true,
"name": "salted.caramel",
"proxyWallet": "0x4ca749dcfa93c87e5ee23e2d21ff4422c7a4c1ee",
"pseudonym": "Adored-Disparity"
},
"reactionCount": 0,
"replyAddress": "0x0bda5d16f76cd1d3485bcc7a44bc6fa7db004cdd",
"reportCount": 0,
"userAddress": "0xce533188d53a16ed580fd5121dedf166d3482677"
}
}
```
A reply to the above comment — note `parentCommentID` references the parent:
```json theme={null}
{
"topic": "comments",
"type": "comment_created",
"timestamp": 1753454985123,
"payload": {
"body": "I agree, the resolution criteria should be clearer.",
"createdAt": "2025-07-25T14:49:45.120000Z",
"id": "1763356",
"parentCommentID": "1763355",
"parentEntityID": 18396,
"parentEntityType": "Event",
"profile": {
"baseAddress": "0x1234567890abcdef1234567890abcdef12345678",
"displayUsernamePublic": true,
"name": "trader",
"proxyWallet": "0x9876543210fedcba9876543210fedcba98765432",
"pseudonym": "Bright-Analysis"
},
"reactionCount": 0,
"replyAddress": "0x0bda5d16f76cd1d3485bcc7a44bc6fa7db004cdd",
"reportCount": 0,
"userAddress": "0x1234567890abcdef1234567890abcdef12345678"
}
}
```
### Comment Payload Fields
| Field | Type | Description |
| ------------------ | ------ | ------------------------------------------------------------------------- |
| `body` | string | The text content of the comment |
| `createdAt` | string | ISO 8601 timestamp when the comment was created |
| `id` | string | Unique identifier for this comment |
| `parentCommentID` | string | ID of the parent comment if this is a reply (null for top-level comments) |
| `parentEntityID` | number | ID of the parent entity (event, market, etc.) |
| `parentEntityType` | string | Type of parent entity (`Event`, `Market`) |
| `profile` | object | Profile information of the comment author |
| `reactionCount` | number | Current number of reactions on this comment |
| `replyAddress` | string | Polygon address for replies (may differ from userAddress) |
| `reportCount` | number | Current number of reports on this comment |
| `userAddress` | string | Polygon address of the comment author |
### Profile Object Fields
| Field | Type | Description |
| ----------------------- | ------- | ------------------------------------------ |
| `baseAddress` | string | User profile address |
| `displayUsernamePublic` | boolean | Whether the username is displayed publicly |
| `name` | string | User's display name |
| `proxyWallet` | string | Proxy wallet address used for transactions |
| `pseudonym` | string | Generated pseudonym for the user |
### Comment Hierarchy
Comments support nested threading:
* **Top-level comments**: `parentCommentID` is null or empty
* **Reply comments**: `parentCommentID` contains the ID of the parent comment
* All comments are associated with a `parentEntityID` and `parentEntityType` (`Event` or `Market`)
## Troubleshooting
<Accordion title="Connection drops unexpectedly">
Send `PING` messages every 5 seconds to keep the connection alive. Connection errors will trigger automatic reconnection attempts.
</Accordion>
<Accordion title="Not receiving messages after subscribing">
Verify your subscription message is valid JSON with the correct `action`, `topic`, and `type` fields. Invalid subscription messages may result in connection closure.
</Accordion>
<Accordion title="Authentication failures">
If subscribing to user-specific streams, ensure your `gamma_auth` object includes a valid wallet `address`. Authentication failures will prevent subscription to protected topics.
</Accordion>
-554
View File
@@ -1,554 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Real-Time Data Socket
> Stream comments, crypto prices, and equity prices via WebSocket
The Polymarket Real-Time Data Socket (RTDS) is a WebSocket-based streaming service that provides real-time updates for **comments**, **crypto prices**, and **equity prices**.
<Card title="TypeScript client" icon="github" href="https://github.com/Polymarket/real-time-data-client">
Official RTDS TypeScript client (`real-time-data-client`).
</Card>
## Endpoint
```
wss://ws-live-data.polymarket.com
```
Some user-specific streams may require `gamma_auth` with your wallet address.
## Subscribing
Send a JSON message to subscribe to data streams:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "topic_name",
"type": "message_type",
"filters": "optional_filter_string",
"gamma_auth": {
"address": "wallet_address"
}
}
]
}
```
To unsubscribe, send the same structure with `"action": "unsubscribe"`.
Subscriptions can be added, removed, and modified without disconnecting. Send `PING` messages every 5 seconds to maintain the connection.
<Note>Only the subscription types documented below are supported.</Note>
## Message Structure
All messages follow this structure:
```json theme={null}
{
"topic": "string",
"type": "string",
"timestamp": "number",
"payload": "object"
}
```
| Field | Type | Description |
| ----------- | ------ | --------------------------------------------------------------------------- |
| `topic` | string | The subscription topic (e.g., `crypto_prices`, `equity_prices`, `comments`) |
| `type` | string | The message type/event (e.g., `update`, `reaction_created`) |
| `timestamp` | number | Unix timestamp in milliseconds when the message was sent |
| `payload` | object | Event-specific data object |
## Crypto Prices
Real-time cryptocurrency price data from two sources: **Binance** and **Chainlink**. No authentication required.
### Binance Source
Subscribe to all symbols:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "crypto_prices",
"type": "update"
}
]
}
```
Subscribe to specific symbols with a comma-separated filter:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "crypto_prices",
"type": "update",
"filters": "solusdt,btcusdt,ethusdt"
}
]
}
```
Symbols use lowercase concatenated format (e.g., `solusdt`, `btcusdt`).
**Solana price update:**
```json theme={null}
{
"topic": "crypto_prices",
"type": "update",
"timestamp": 1753314064237,
"payload": {
"symbol": "solusdt",
"timestamp": 1753314064213,
"value": 189.55
}
}
```
**Bitcoin price update:**
```json theme={null}
{
"topic": "crypto_prices",
"type": "update",
"timestamp": 1753314088421,
"payload": {
"symbol": "btcusdt",
"timestamp": 1753314088395,
"value": 67234.50
}
}
```
### Chainlink Source
<Tip>
**Trading 15m Crypto Markets?** Get a sponsored Chainlink API key with onboarding support from Chainlink. Fill out [this form](https://pm-ds-request.streams.chain.link/).
</Tip>
Subscribe to all symbols:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "crypto_prices_chainlink",
"type": "*",
"filters": ""
}
]
}
```
Subscribe to a specific symbol with a JSON filter:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "crypto_prices_chainlink",
"type": "*",
"filters": "{\"symbol\":\"eth/usd\"}"
}
]
}
```
Symbols use slash-separated format (e.g., `eth/usd`, `btc/usd`).
**Ethereum price update:**
```json theme={null}
{
"topic": "crypto_prices_chainlink",
"type": "update",
"timestamp": 1753314064237,
"payload": {
"symbol": "eth/usd",
"timestamp": 1753314064213,
"value": 3456.78
}
}
```
**Bitcoin price update:**
```json theme={null}
{
"topic": "crypto_prices_chainlink",
"type": "update",
"timestamp": 1753314088421,
"payload": {
"symbol": "btc/usd",
"timestamp": 1753314088395,
"value": 67234.50
}
}
```
### Price Payload Fields
| Field | Type | Description |
| ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `symbol` | string | Trading pair symbol. **Binance**: lowercase concatenated (e.g., `solusdt`, `btcusdt`). **Chainlink**: slash-separated (e.g., `eth/usd`, `btc/usd`) |
| `timestamp` | number | When the price was recorded, in Unix milliseconds |
| `value` | number | Current price value in the quote currency |
### Supported Symbols
**Binance Source** — lowercase concatenated format:
* `btcusdt` — Bitcoin to USDT
* `ethusdt` — Ethereum to USDT
* `solusdt` — Solana to USDT
* `xrpusdt` — XRP to USDT
**Chainlink Source** — slash-separated format:
* `btc/usd` — Bitcoin to USD
* `eth/usd` — Ethereum to USD
* `sol/usd` — Solana to USD
* `xrp/usd` — XRP to USD
## Equity Prices
Real-time price data for stocks, ETFs, forex pairs, precious metals, and commodities sourced from **Pyth Network**. No authentication required.
<Tip>
**Trading Equity Markets?** Get a Pyth Network data feed - first 30 days free, then \$99/month. [Subscribe here](https://buy.stripe.com/cNi8wPeiq76FgQrbsD4ZG09).
</Tip>
All asset classes stream through a single `equity_prices` topic. When you subscribe with a symbol filter, the server sends a historical snapshot (last 2 minutes of data), then continues streaming live updates.
### Subscribe
Subscribe to a specific symbol with a JSON filter:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "equity_prices",
"type": "update",
"filters": "{\"symbol\":\"AAPL\"}"
}
]
}
```
Subscribe to multiple symbols across asset classes:
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{ "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"AAPL\"}" },
{ "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"EURUSD\"}" },
{ "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"XAUUSD\"}" },
{ "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"WTI\"}" }
]
}
```
Use `type: "*"` to receive all message types (live updates and snapshots):
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "equity_prices",
"type": "*",
"filters": "{\"symbol\":\"GOOGL\"}"
}
]
}
```
Filter values are case-insensitive on subscribe, but the `symbol` field in payloads is always returned lowercase.
<Tip>
**Need the price-to-beat value?** Pass the market slug to the price-to-beat endpoint:
`GET https://polymarket.com/api/equity/price-to-beat/{slug}`
Example: `https://polymarket.com/api/equity/price-to-beat/wti-up-or-down-on-april-7-2026`
</Tip>
### Live Price Update
**Apple stock update:**
```json theme={null}
{
"topic": "equity_prices",
"type": "update",
"timestamp": 1711382400000,
"payload": {
"symbol": "aapl",
"value": 198.45,
"full_accuracy_value": "198.4523",
"timestamp": 1711382400000,
"received_at": 1711382400005
}
}
```
**Gold price update (market closed):**
```json theme={null}
{
"topic": "equity_prices",
"type": "update",
"timestamp": 1711400000000,
"payload": {
"symbol": "xauusd",
"value": 2175.30,
"full_accuracy_value": "2175.3012",
"timestamp": 1711399000000,
"received_at": 1711400000002,
"is_carried_forward": true
}
}
```
### Historical Snapshot
On subscribe, the server delivers a backfill of the last 2 minutes of price data. Use the `type` field to distinguish: `"subscribe"` for the initial snapshot vs `"update"` for live ticks.
```json theme={null}
{
"topic": "equity_prices",
"type": "subscribe",
"timestamp": 1711382400000,
"payload": {
"symbol": "aapl",
"data": [
{ "timestamp": 1711382280000, "value": 198.30 },
{ "timestamp": 1711382281000, "value": 198.32 },
{ "timestamp": 1711382340000, "value": 198.41 }
]
}
}
```
### Equity Price Payload Fields
| Field | Type | Description |
| --------------------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `symbol` | string | Lowercase symbol identifier (e.g., `aapl`, `eurusd`, `xauusd`) |
| `value` | number | Spot price as a float |
| `full_accuracy_value` | string | Full-precision price as a string |
| `timestamp` | number | Price measurement timestamp in Unix milliseconds |
| `received_at` | number | When the system received the price, in Unix milliseconds. Only present when non-zero. |
| `is_carried_forward` | boolean | `true` when the market session is closed and the value is the last known price. Only present when `true`. |
### Supported Symbols
**Stocks:**
| Symbol | Name |
| ------- | -------------- |
| `AAPL` | Apple |
| `TSLA` | Tesla |
| `MSFT` | Microsoft |
| `GOOGL` | Alphabet |
| `AMZN` | Amazon |
| `META` | Meta Platforms |
| `NVDA` | NVIDIA |
| `NFLX` | Netflix |
| `PLTR` | Palantir |
| `OPEN` | Opendoor |
| `RKLB` | Rocket Lab |
| `ABNB` | Airbnb |
| `COIN` | Coinbase |
| `HOOD` | Robinhood |
**ETFs:**
| Symbol | Name |
| ------ | ------------------------------------ |
| `QQQ` | Invesco QQQ ETF |
| `SPY` | S\&P 500 ETF |
| `EWY` | iShares MSCI South Korea ETF |
| `VXX` | Barclays iPath Series B S\&P 500 VIX |
**Forex:**
| Symbol | Pair |
| -------- | ---------------------------- |
| `EURUSD` | Euro / US Dollar |
| `GBPUSD` | British Pound / US Dollar |
| `USDCAD` | US Dollar / Canadian Dollar |
| `USDJPY` | US Dollar / Japanese Yen |
| `USDKRW` | US Dollar / South Korean Won |
**Precious Metals:**
| Symbol | Name |
| -------- | ------ |
| `XAUUSD` | Gold |
| `XAGUSD` | Silver |
**Commodities** (rolling front-month futures):
| Symbol | Name |
| ------ | --------------- |
| `WTI` | Crude Oil (WTI) |
| `CC` | Cocoa |
| `NGD` | Natural Gas |
### Market Hours
When a market session is closed, the stream continues with the last known price and `is_carried_forward: true`. This lets you distinguish stale prices from live ticks. Update frequency is sub-second (up to 5 per second per feed) during market hours.
## Comments
Real-time comment events on the Polymarket platform, including new comments, replies, reactions, and removals. May require Gamma authentication for user-specific data.
### Subscribe
```json theme={null}
{
"action": "subscribe",
"subscriptions": [
{
"topic": "comments",
"type": "comment_created"
}
]
}
```
### Message Types
| Type | Description |
| ------------------ | ------------------------------------- |
| `comment_created` | A user creates a new comment or reply |
| `comment_removed` | A comment is removed or deleted |
| `reaction_created` | A user adds a reaction to a comment |
| `reaction_removed` | A reaction is removed from a comment |
### comment\_created
Emitted when a user posts a new comment or replies to an existing one.
```json theme={null}
{
"topic": "comments",
"type": "comment_created",
"timestamp": 1753454975808,
"payload": {
"body": "That's a good point about the definition.",
"createdAt": "2025-07-25T14:49:35.801298Z",
"id": "1763355",
"parentCommentID": "1763325",
"parentEntityID": 18396,
"parentEntityType": "Event",
"profile": {
"baseAddress": "0xce533188d53a16ed580fd5121dedf166d3482677",
"displayUsernamePublic": true,
"name": "salted.caramel",
"proxyWallet": "0x4ca749dcfa93c87e5ee23e2d21ff4422c7a4c1ee",
"pseudonym": "Adored-Disparity"
},
"reactionCount": 0,
"replyAddress": "0x0bda5d16f76cd1d3485bcc7a44bc6fa7db004cdd",
"reportCount": 0,
"userAddress": "0xce533188d53a16ed580fd5121dedf166d3482677"
}
}
```
A reply to the above comment — note `parentCommentID` references the parent:
```json theme={null}
{
"topic": "comments",
"type": "comment_created",
"timestamp": 1753454985123,
"payload": {
"body": "I agree, the resolution criteria should be clearer.",
"createdAt": "2025-07-25T14:49:45.120000Z",
"id": "1763356",
"parentCommentID": "1763355",
"parentEntityID": 18396,
"parentEntityType": "Event",
"profile": {
"baseAddress": "0x1234567890abcdef1234567890abcdef12345678",
"displayUsernamePublic": true,
"name": "trader",
"proxyWallet": "0x9876543210fedcba9876543210fedcba98765432",
"pseudonym": "Bright-Analysis"
},
"reactionCount": 0,
"replyAddress": "0x0bda5d16f76cd1d3485bcc7a44bc6fa7db004cdd",
"reportCount": 0,
"userAddress": "0x1234567890abcdef1234567890abcdef12345678"
}
}
```
### Comment Payload Fields
| Field | Type | Description |
| ------------------ | ------ | ------------------------------------------------------------------------- |
| `body` | string | The text content of the comment |
| `createdAt` | string | ISO 8601 timestamp when the comment was created |
| `id` | string | Unique identifier for this comment |
| `parentCommentID` | string | ID of the parent comment if this is a reply (null for top-level comments) |
| `parentEntityID` | number | ID of the parent entity (event, market, etc.) |
| `parentEntityType` | string | Type of parent entity (`Event`, `Market`) |
| `profile` | object | Profile information of the comment author |
| `reactionCount` | number | Current number of reactions on this comment |
| `replyAddress` | string | Polygon address for replies (may differ from userAddress) |
| `reportCount` | number | Current number of reports on this comment |
| `userAddress` | string | Polygon address of the comment author |
### Profile Object Fields
| Field | Type | Description |
| ----------------------- | ------- | ------------------------------------------ |
| `baseAddress` | string | User profile address |
| `displayUsernamePublic` | boolean | Whether the username is displayed publicly |
| `name` | string | User's display name |
| `proxyWallet` | string | Proxy wallet address used for transactions |
| `pseudonym` | string | Generated pseudonym for the user |
### Comment Hierarchy
Comments support nested threading:
* **Top-level comments**: `parentCommentID` is null or empty
* **Reply comments**: `parentCommentID` contains the ID of the parent comment
* All comments are associated with a `parentEntityID` and `parentEntityType` (`Event` or `Market`)
## Troubleshooting
<Accordion title="Connection drops unexpectedly">
Send `PING` messages every 5 seconds to keep the connection alive. Connection errors will trigger automatic reconnection attempts.
</Accordion>
<Accordion title="Not receiving messages after subscribing">
Verify your subscription message is valid JSON with the correct `action`, `topic`, and `type` fields. Invalid subscription messages may result in connection closure.
</Accordion>
<Accordion title="Authentication failures">
If subscribing to user-specific streams, ensure your `gamma_auth` object includes a valid wallet `address`. Authentication failures will prevent subscription to protected topics.
</Accordion>
@@ -1,70 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Data Resources
> Access Polymarket on-chain activity for data & analytics
Polymarket data that lands on the blockchain, such as trades, balances, positions, and redeems, is available through various on-chain analytics platforms and blockchain data providers. Polymarket also provides its own APIs and WebSockets. See the [API Endpoints reference](/quickstart/reference/endpoints) for more information.
The purpose of this page is to serve as a public good for Polymarket builders, researches, and analysts alike.
***
## Data
### Goldsky
[Goldsky](https://docs.goldsky.com/chains/polymarket) provides real-time streaming pipelines for Polymarket on-chain activity (i.e. trades, balances, positions, etc...) into your own database/data warehouse.
Goldsky also partnered with [ClickHouse](https://clickhouse.com) to create [CryptoHouse](https://crypto.clickhouse.com), where you can query Polymarket on-chain data using SQL.
### Dune
[Dune](https://dune.com) is a blockchain analytics platform that has Polymarket on-chain activity (i.e. trades, balances, positions, etc...). Query Polymarket data using SQL, create custom dashboards, and more.
Here are a few simple queries to get started:
| Query | Description | Link |
| ------------- | --------------------------------------------- | --------------------------------------------------- |
| Volume | Notional Volume and Maker & Taker USDC Volume | [View Dune Query](https://dune.com/queries/6545441) |
| TVL | USDC locked in Polymarket smart contracts | [View Dune Query](https://dune.com/queries/6588784) |
| Open Interest | Estimated market open interest, and over time | [View Dune Query](https://dune.com/queries/6555478) |
### Allium
[Allium](https://docs.allium.so/historical-data/predictions) is a blockchain analytics platform that has Polymarket on-chain activity (i.e. trades, balances, positions, etc...). Query Polymarket data using SQL, create custom dashboards, and more.
\--
## Dashboards
Third-party blockchain analytics platforms that aggregate and visualize Polymarket data:
<CardGroup cols={4}>
<Card title="Blockworks" img="https://pbs.twimg.com/profile_images/1651677302634483712/7s2FxV2K_400x400.jpg" href="https://blockworks.com/analytics/polymarket" />
<Card title="Artemis" img="https://pbs.twimg.com/profile_images/1896982195723546624/2XeO9mPb_400x400.png" href="https://app.artemisanalytics.com/asset/polymarket?from=assets" />
<Card title="Dune" img="https://pbs.twimg.com/profile_images/1986458079248986112/qq80s3hx_400x400.jpg" href="https://dune.com/discover/content/popular?q=polymarket&resource-type=dashboards" />
<Card title="DeFiLlama" img="https://pbs.twimg.com/profile_images/1915756547705036800/rAeLzZqs_400x400.jpg" href="https://defillama.com/protocol/polymarket" />
<Card title="The Block" img="https://pbs.twimg.com/profile_images/1944749695525425152/9babG7Df_400x400.jpg" href="https://www.theblock.co/data/decentralized-finance/prediction-markets-and-betting" />
<Card title="Token Terminal" img="https://pbs.twimg.com/profile_images/1594678659222306817/SMum_RcQ_400x400.jpg" href="https://tokenterminal.com/explorer/projects/polymarket" />
<Card title="Allium" img="https://pbs.twimg.com/profile_images/1778926940407132160/UEwR3lHt_400x400.jpg" href="https://predictions.allium.so" />
</CardGroup>
### Community Dashboards
Community-created Dune dashboards of Polymarket on-chain analytics:
| Dashboard | Created By | Link |
| ------------------------------------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------- |
| Polymarket Overview | [@datadashboards](https://x.com/datadashboards) | [View Dashboard](https://dune.com/datadashboards/polymarket-overview) |
| Polymarket Volume, OI, Markets, Addresses and TVL | [@hildobby](https://x.com/hildobby) | [View Dashboard](https://dune.com/hildobby/polymarket) |
| Polymarket Historical Accuracy | [@alexmccullaaa](https://x.com/alexmccullaaa) | [View Dashboard](https://dune.com/alexmccullough/how-accurate-is-polymarket) |
| Polymarket Builders Dashboard | [@defioasis](https://x.com/defioasis) | [View Dashboard](https://dune.com/gateresearch/pmbuilders) |
-222
View File
@@ -1,222 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Builder Program
> Build applications that route orders through Polymarket
A **builder** is a person, group, or organization that routes orders from users to Polymarket. If you've created a platform that allows users to trade on Polymarket through your system, this program is for you.
## Program Benefits
<CardGroup cols={2}>
<Card title="Gasless Transactions" icon="gas-pump">
All onchain operations are gas-free through our relayer
</Card>
<Card title="Order Attribution" icon="tag">
Get credit for orders and compete for grants on the Builder Leaderboard
</Card>
</CardGroup>
### What You Get
| Benefit | Description |
| ------------------- | ------------------------------------------------------------------------------- |
| **Relayer Access** | Gas-free wallet deployment, approvals, order execution and CTF operations |
| **Volume Tracking** | All orders attributed to your builder profile |
| **Leaderboard** | Public visibility on [builders.polymarket.com](https://builders.polymarket.com) |
| **Support** | Telegram channel and engineering support (Verified+) |
<Warning>
EOA wallets do not have relayer access. Users trading directly from an EOA pay
their own gas fees.
</Warning>
## How It Works
<Steps>
<Step title="User Places Order">
User places an order through your application.
</Step>
<Step title="Attach Builder Code">
Your app adds your `builderCode` to the order struct.
</Step>
<Step title="Submit to CLOB">
Order is submitted to Polymarket's CLOB — the builder code is serialized
onchain as part of the signed order.
</Step>
<Step title="Trade Execution">
Polymarket matches the order and covers gas fees for onchain operations.
</Step>
<Step title="Volume Attribution">
Volume is credited to your builder account for every matched trade where
your code is attached.
</Step>
</Steps>
## Getting Started
<Steps>
<Step title="Create Builder Profile">
Go to
[polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder)
and copy your builder code.
</Step>
<Step title="Attach Your Builder Code">
Pass `builderCode` on every order you submit — see [Order
Attribution](/trading/orders/attribution).
</Step>
<Step title="Enable Gasless Transactions">
Use the Relayer Client for gas-free wallet deployment and onchain
operations.
</Step>
<Step title="Track Performance">
Monitor your volume on the [Builder
Leaderboard](https://builders.polymarket.com).
</Step>
</Steps>
## SDKs and Libraries
<CardGroup cols={2}>
<Card title="CLOB Client (TypeScript)" icon="github" href="https://github.com/Polymarket/clob-client-v2">
Place orders with builder attribution
</Card>
<Card title="CLOB Client (Python)" icon="github" href="https://github.com/Polymarket/py-clob-client-v2">
Place orders with builder attribution
</Card>
<Card title="Relayer Client (TypeScript)" icon="github" href="https://github.com/Polymarket/builder-relayer-client">
Gasless onchain transactions
</Card>
<Card title="Relayer Client (Python)" icon="github" href="https://github.com/Polymarket/py-builder-relayer-client">
Gasless onchain transactions
</Card>
<Card title="CLOB Client (Rust)" icon="github" href="https://github.com/Polymarket/rs-clob-client-v2">
Place orders with builder attribution
</Card>
</CardGroup>
## Examples
These open-source demo applications show how to integrate Polymarket's CLOB Client and Builder Relayer Client for gasless trading with builder order attribution.
<CardGroup cols={3}>
<Card title="Authentication" icon="user-check">
Multiple wallet providers
</Card>
<Card title="Gasless Trading" icon="gas-pump">
Deposit wallet support for new API users
</Card>
<Card title="Full Integration" icon="puzzle-piece">
Orders, positions, CTF ops
</Card>
</CardGroup>
### Deposit Wallet Integrations
New API users should use deposit wallets. Use the Builder Relayer Client to
deploy deposit wallets and execute signed wallet batches, then place CLOB
orders with `POLY_1271`.
See the [Deposit Wallet Guide](/trading/deposit-wallets) for TypeScript,
Python, Rust, and direct API integration details.
### Existing Safe Wallet Examples
Existing Safe integrations can continue using Gnosis Safe wallets:
<CardGroup cols={2}>
<Card title="wagmi + Safe" icon="wallet" href="https://github.com/Polymarket/wagmi-safe-builder-example">
MetaMask, Phantom, Rabby, and other browser wallets
</Card>
<Card title="Privy + Safe" icon="shield-check" href="https://github.com/Polymarket/privy-safe-builder-example">
Privy embedded wallets
</Card>
<Card title="Magic Link + Safe" icon="wand-magic-sparkles" href="https://github.com/Polymarket/magic-safe-builder-example">
Magic Link email/social authentication
</Card>
<Card title="Turnkey + Safe" icon="key" href="https://github.com/Polymarket/turnkey-safe-builder-example">
Turnkey embedded wallets
</Card>
</CardGroup>
### Existing Proxy Wallet Examples
For existing Magic Link users from Polymarket.com:
<CardGroup cols={1}>
<Card title="Magic Link + Proxy" icon="wand-magic-sparkles" href="https://github.com/Polymarket/magic-proxy-builder-example">
Auto-deploying proxy wallets for Polymarket.com Magic users
</Card>
</CardGroup>
### What Each Demo Covers
<Tabs>
<Tab title="Authentication">
<ul>
<li>User sign-in via wallet provider</li>
<li>User API credential derivation (L2 auth)</li>
<li>Builder config with remote signing</li>
<li>Signature types for Deposit Wallet, Safe, and Proxy wallets</li>
</ul>
</Tab>
<Tab title="Wallet Operations">
<ul>
<li>Deposit wallet deployment via Relayer</li>
<li>Batch token approvals (pUSD + outcome tokens)</li>
<li>CTF operations (split, merge, redeem)</li>
<li>Transaction monitoring</li>
</ul>
</Tab>
<Tab title="Trading">
<ul>
<li>CLOB client initialization</li>
<li>Order placement with builder attribution</li>
<li>Position and order management</li>
<li>Market discovery via Gamma API</li>
</ul>
</Tab>
</Tabs>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Get API Keys" icon="key" href="/builders/api-keys">
Create and manage your Builder API credentials.
</Card>
<Card title="Understand Tiers" icon="layer-group" href="/builders/tiers">
Learn about rate limits and how to upgrade.
</Card>
<Card title="Attribute Orders" icon="tag" href="/trading/orders/attribution">
Configure your client to credit trades to your account.
</Card>
<Card title="Gasless Guide" icon="gas-pump" href="/trading/gasless">
Set up gasless transactions for your users.
</Card>
</CardGroup>
-222
View File
@@ -1,222 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Builder Program
> Build applications that route orders through Polymarket
A **builder** is a person, group, or organization that routes orders from users to Polymarket. If you've created a platform that allows users to trade on Polymarket through your system, this program is for you.
## Program Benefits
<CardGroup cols={2}>
<Card title="Gasless Transactions" icon="gas-pump">
All onchain operations are gas-free through our relayer
</Card>
<Card title="Order Attribution" icon="tag">
Get credit for orders and compete for grants on the Builder Leaderboard
</Card>
</CardGroup>
### What You Get
| Benefit | Description |
| ------------------- | ------------------------------------------------------------------------------- |
| **Relayer Access** | Gas-free wallet deployment, approvals, order execution and CTF operations |
| **Volume Tracking** | All orders attributed to your builder profile |
| **Leaderboard** | Public visibility on [builders.polymarket.com](https://builders.polymarket.com) |
| **Support** | Telegram channel and engineering support (Verified+) |
<Warning>
EOA wallets do not have relayer access. Users trading directly from an EOA pay
their own gas fees.
</Warning>
## How It Works
<Steps>
<Step title="User Places Order">
User places an order through your application.
</Step>
<Step title="Attach Builder Code">
Your app adds your `builderCode` to the order struct.
</Step>
<Step title="Submit to CLOB">
Order is submitted to Polymarket's CLOB — the builder code is serialized
onchain as part of the signed order.
</Step>
<Step title="Trade Execution">
Polymarket matches the order and covers gas fees for onchain operations.
</Step>
<Step title="Volume Attribution">
Volume is credited to your builder account for every matched trade where
your code is attached.
</Step>
</Steps>
## Getting Started
<Steps>
<Step title="Create Builder Profile">
Go to
[polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder)
and copy your builder code.
</Step>
<Step title="Attach Your Builder Code">
Pass `builderCode` on every order you submit — see [Order
Attribution](/trading/orders/attribution).
</Step>
<Step title="Enable Gasless Transactions">
Use the Relayer Client for gas-free wallet deployment and onchain
operations.
</Step>
<Step title="Track Performance">
Monitor your volume on the [Builder
Leaderboard](https://builders.polymarket.com).
</Step>
</Steps>
## SDKs and Libraries
<CardGroup cols={2}>
<Card title="CLOB Client (TypeScript)" icon="github" href="https://github.com/Polymarket/clob-client-v2">
Place orders with builder attribution
</Card>
<Card title="CLOB Client (Python)" icon="github" href="https://github.com/Polymarket/py-clob-client-v2">
Place orders with builder attribution
</Card>
<Card title="Relayer Client (TypeScript)" icon="github" href="https://github.com/Polymarket/builder-relayer-client">
Gasless onchain transactions
</Card>
<Card title="Relayer Client (Python)" icon="github" href="https://github.com/Polymarket/py-builder-relayer-client">
Gasless onchain transactions
</Card>
<Card title="CLOB Client (Rust)" icon="github" href="https://github.com/Polymarket/rs-clob-client-v2">
Place orders with builder attribution
</Card>
</CardGroup>
## Examples
These open-source demo applications show how to integrate Polymarket's CLOB Client and Builder Relayer Client for gasless trading with builder order attribution.
<CardGroup cols={3}>
<Card title="Authentication" icon="user-check">
Multiple wallet providers
</Card>
<Card title="Gasless Trading" icon="gas-pump">
Deposit wallet support for new API users
</Card>
<Card title="Full Integration" icon="puzzle-piece">
Orders, positions, CTF ops
</Card>
</CardGroup>
### Deposit Wallet Integrations
New API users should use deposit wallets. Use the Builder Relayer Client to
deploy deposit wallets and execute signed wallet batches, then place CLOB
orders with `POLY_1271`.
See the [Deposit Wallet Guide](/trading/deposit-wallets) for TypeScript,
Python, Rust, and direct API integration details.
### Existing Safe Wallet Examples
Existing Safe integrations can continue using Gnosis Safe wallets:
<CardGroup cols={2}>
<Card title="wagmi + Safe" icon="wallet" href="https://github.com/Polymarket/wagmi-safe-builder-example">
MetaMask, Phantom, Rabby, and other browser wallets
</Card>
<Card title="Privy + Safe" icon="shield-check" href="https://github.com/Polymarket/privy-safe-builder-example">
Privy embedded wallets
</Card>
<Card title="Magic Link + Safe" icon="wand-magic-sparkles" href="https://github.com/Polymarket/magic-safe-builder-example">
Magic Link email/social authentication
</Card>
<Card title="Turnkey + Safe" icon="key" href="https://github.com/Polymarket/turnkey-safe-builder-example">
Turnkey embedded wallets
</Card>
</CardGroup>
### Existing Proxy Wallet Examples
For existing Magic Link users from Polymarket.com:
<CardGroup cols={1}>
<Card title="Magic Link + Proxy" icon="wand-magic-sparkles" href="https://github.com/Polymarket/magic-proxy-builder-example">
Auto-deploying proxy wallets for Polymarket.com Magic users
</Card>
</CardGroup>
### What Each Demo Covers
<Tabs>
<Tab title="Authentication">
<ul>
<li>User sign-in via wallet provider</li>
<li>User API credential derivation (L2 auth)</li>
<li>Builder config with remote signing</li>
<li>Signature types for Deposit Wallet, Safe, and Proxy wallets</li>
</ul>
</Tab>
<Tab title="Wallet Operations">
<ul>
<li>Deposit wallet deployment via Relayer</li>
<li>Batch token approvals (pUSD + outcome tokens)</li>
<li>CTF operations (split, merge, redeem)</li>
<li>Transaction monitoring</li>
</ul>
</Tab>
<Tab title="Trading">
<ul>
<li>CLOB client initialization</li>
<li>Order placement with builder attribution</li>
<li>Position and order management</li>
<li>Market discovery via Gamma API</li>
</ul>
</Tab>
</Tabs>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Get API Keys" icon="key" href="/builders/api-keys">
Create and manage your Builder API credentials.
</Card>
<Card title="Understand Tiers" icon="layer-group" href="/builders/tiers">
Learn about rate limits and how to upgrade.
</Card>
<Card title="Attribute Orders" icon="tag" href="/trading/orders/attribution">
Configure your client to credit trades to your account.
</Card>
<Card title="Gasless Guide" icon="gas-pump" href="/trading/gasless">
Set up gasless transactions for your users.
</Card>
</CardGroup>
-170
View File
@@ -1,170 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Tiers
> Rate limits, rewards, and how to upgrade
The Builder Program uses a tiered system to manage rate limits while rewarding high-performing integrations. Higher tiers unlock increased limits, weekly rewards, and priority support.
## Feature Definitions
| Feature | Description |
| --------------------------- | ------------------------------------------------------------------------------------------ |
| **Daily Relayer Txn Limit** | Maximum Relayer transactions per day for deposit wallet, Safe, and Proxy wallet operations |
| **API Rate Limits** | Rate limits for non-relayer endpoints (CLOB, Gamma, etc.) |
| **Gasless Trading** | Gas fees subsidized for supported smart-wallet operations |
| **Order Attribution** | Orders tracked and attributed to your Builder profile |
| **Builder Fees** | Builders who route orders can charge fees and monetize on flow |
| **Leaderboard Visibility** | Visibility on the [Builder Leaderboard](https://builders.polymarket.com/) |
| **Telegram Channel** | Private Builders channel for announcements and support |
| **Engineering Support** | Direct access to engineering team |
| **Marketing Support** | Promotion via official Polymarket social accounts |
| **Priority Access** | Early access to new features and products |
***
## Tier Comparison
| Feature | Unverified | Verified | Partner |
| --------------------------- | :--------: | :--------: | :-------: |
| **Daily Relayer Txn Limit** | 100/day | 10,000/day | Unlimited |
| **API Rate Limits** | Standard | Standard | Highest |
| **Gasless Trading\*** | Yes | Yes | Yes |
| **Order Attribution** | Yes | Yes | Yes |
| **Builder Fees** | Yes | Yes | Yes |
| **Leaderboard Visibility** | — | Yes | Yes |
| **Telegram Channel** | — | Yes | Yes |
| **Engineering Support** | — | Standard | Elevated |
| **Marketing Support** | — | Standard | Elevated |
| **Priority Access** | — | — | Yes |
***
## Unverified
<Card title="100 Relay transactions/day" icon="seedling">
The default tier for all new builders. Start immediately with no approval
required.
</Card>
**How to get started:**
1. Go to [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder)
2. Create a builder profile
3. Click **"+ Create New"** to generate API keys
4. Attach your [builder code](/trading/orders/attribution) to CLOB orders for attribution; use a Relayer API key for gasless wallet operations
**What's included:**
* Gasless trading through deposit wallets for new API users and existing Safe/Proxy wallets
* Gas subsidized on all Relayer transactions up to the daily limit
* Access to all client libraries and documentation
***
## Verified
<Card title="10,000 Relay transactions/day" icon="badge-check">
For builders who need higher throughput. Requires manual approval.
</Card>
**How to upgrade:**
Contact us at [builder@polymarket.com](mailto:builder@polymarket.com) with:
* Your Builder API Key
* Use case description
* Expected volume
* Other relevant information (links, docs, decks, etc.)
**Unlocks over Unverified:**
* 100x daily Relayer transaction limit
* Monetize with Builder fees
* Leaderboard visibility at [builders.polymarket.com](https://builders.polymarket.com)
* Private Telegram channel for announcements and support
* Weekly USDC rewards based on volume (subject to approval)
* Grants (subject to approval)
***
## Partner
<Card title="Unlimited Relay transactions/day" icon="handshake">
Enterprise tier for high-volume integrations and strategic partners.
</Card>
**Unlocks over Verified:**
* Unlimited Relayer transactions
* Highest API rate limits
* Elevated engineering support
* Elevated and coordinated marketing support
* Priority access to new features and products
***
## How to Upgrade
<Steps>
<Step title="Build and Launch">
Start with the Unverified tier and build your integration.
</Step>
<Step title="Generate Volume">
Route orders through Polymarket and demonstrate consistent usage.
</Step>
<Step title="Apply for Verification">
Email [builder@polymarket.com](mailto:builder@polymarket.com) with your
builder key and use case.
</Step>
<Step title="Get Approved">
The Polymarket team reviews applications and responds within a few business
days.
</Step>
</Steps>
## Contact
Ready to upgrade or have questions?
<Card title="builder@polymarket.com" icon="envelope" href="mailto:builder@polymarket.com">
Email us with your Builder API Key and use case details.
</Card>
## FAQ
<AccordionGroup>
<Accordion title="How do I know if I am verified">
Verification is displayed in your [Builder Profile](https://polymarket.com/settings?tab=builder) settings.
</Accordion>
<Accordion title="What happens if I exceed my daily limit">
Relayer requests beyond your daily limit will be rate-limited and return an
error. Consider upgrading to Verified or Partner tier if you're hitting
limits.
</Accordion>
<Accordion title="What if I just need more daily Relay transaction limits for my own wallet">
If you're not routing orders for other users (wallets), you can get unlimited
daily Relay transactions by obtaining a [Relayer API key](https://polymarket.com/settings?tab=api-keys).
</Accordion>
</AccordionGroup>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Get API Keys" icon="key" href="/builders/api-keys">
Create your Builder API credentials.
</Card>
<Card title="Attribute Orders" icon="tag" href="/trading/orders/attribution">
Configure your client to credit trades to your account.
</Card>
</CardGroup>
-222
View File
@@ -1,222 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Builder Program
> Build applications that route orders through Polymarket
A **builder** is a person, group, or organization that routes orders from users to Polymarket. If you've created a platform that allows users to trade on Polymarket through your system, this program is for you.
## Program Benefits
<CardGroup cols={2}>
<Card title="Gasless Transactions" icon="gas-pump">
All onchain operations are gas-free through our relayer
</Card>
<Card title="Order Attribution" icon="tag">
Get credit for orders and compete for grants on the Builder Leaderboard
</Card>
</CardGroup>
### What You Get
| Benefit | Description |
| ------------------- | ------------------------------------------------------------------------------- |
| **Relayer Access** | Gas-free wallet deployment, approvals, order execution and CTF operations |
| **Volume Tracking** | All orders attributed to your builder profile |
| **Leaderboard** | Public visibility on [builders.polymarket.com](https://builders.polymarket.com) |
| **Support** | Telegram channel and engineering support (Verified+) |
<Warning>
EOA wallets do not have relayer access. Users trading directly from an EOA pay
their own gas fees.
</Warning>
## How It Works
<Steps>
<Step title="User Places Order">
User places an order through your application.
</Step>
<Step title="Attach Builder Code">
Your app adds your `builderCode` to the order struct.
</Step>
<Step title="Submit to CLOB">
Order is submitted to Polymarket's CLOB — the builder code is serialized
onchain as part of the signed order.
</Step>
<Step title="Trade Execution">
Polymarket matches the order and covers gas fees for onchain operations.
</Step>
<Step title="Volume Attribution">
Volume is credited to your builder account for every matched trade where
your code is attached.
</Step>
</Steps>
## Getting Started
<Steps>
<Step title="Create Builder Profile">
Go to
[polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder)
and copy your builder code.
</Step>
<Step title="Attach Your Builder Code">
Pass `builderCode` on every order you submit — see [Order
Attribution](/trading/orders/attribution).
</Step>
<Step title="Enable Gasless Transactions">
Use the Relayer Client for gas-free wallet deployment and onchain
operations.
</Step>
<Step title="Track Performance">
Monitor your volume on the [Builder
Leaderboard](https://builders.polymarket.com).
</Step>
</Steps>
## SDKs and Libraries
<CardGroup cols={2}>
<Card title="CLOB Client (TypeScript)" icon="github" href="https://github.com/Polymarket/clob-client-v2">
Place orders with builder attribution
</Card>
<Card title="CLOB Client (Python)" icon="github" href="https://github.com/Polymarket/py-clob-client-v2">
Place orders with builder attribution
</Card>
<Card title="Relayer Client (TypeScript)" icon="github" href="https://github.com/Polymarket/builder-relayer-client">
Gasless onchain transactions
</Card>
<Card title="Relayer Client (Python)" icon="github" href="https://github.com/Polymarket/py-builder-relayer-client">
Gasless onchain transactions
</Card>
<Card title="CLOB Client (Rust)" icon="github" href="https://github.com/Polymarket/rs-clob-client-v2">
Place orders with builder attribution
</Card>
</CardGroup>
## Examples
These open-source demo applications show how to integrate Polymarket's CLOB Client and Builder Relayer Client for gasless trading with builder order attribution.
<CardGroup cols={3}>
<Card title="Authentication" icon="user-check">
Multiple wallet providers
</Card>
<Card title="Gasless Trading" icon="gas-pump">
Deposit wallet support for new API users
</Card>
<Card title="Full Integration" icon="puzzle-piece">
Orders, positions, CTF ops
</Card>
</CardGroup>
### Deposit Wallet Integrations
New API users should use deposit wallets. Use the Builder Relayer Client to
deploy deposit wallets and execute signed wallet batches, then place CLOB
orders with `POLY_1271`.
See the [Deposit Wallet Guide](/trading/deposit-wallets) for TypeScript,
Python, Rust, and direct API integration details.
### Existing Safe Wallet Examples
Existing Safe integrations can continue using Gnosis Safe wallets:
<CardGroup cols={2}>
<Card title="wagmi + Safe" icon="wallet" href="https://github.com/Polymarket/wagmi-safe-builder-example">
MetaMask, Phantom, Rabby, and other browser wallets
</Card>
<Card title="Privy + Safe" icon="shield-check" href="https://github.com/Polymarket/privy-safe-builder-example">
Privy embedded wallets
</Card>
<Card title="Magic Link + Safe" icon="wand-magic-sparkles" href="https://github.com/Polymarket/magic-safe-builder-example">
Magic Link email/social authentication
</Card>
<Card title="Turnkey + Safe" icon="key" href="https://github.com/Polymarket/turnkey-safe-builder-example">
Turnkey embedded wallets
</Card>
</CardGroup>
### Existing Proxy Wallet Examples
For existing Magic Link users from Polymarket.com:
<CardGroup cols={1}>
<Card title="Magic Link + Proxy" icon="wand-magic-sparkles" href="https://github.com/Polymarket/magic-proxy-builder-example">
Auto-deploying proxy wallets for Polymarket.com Magic users
</Card>
</CardGroup>
### What Each Demo Covers
<Tabs>
<Tab title="Authentication">
<ul>
<li>User sign-in via wallet provider</li>
<li>User API credential derivation (L2 auth)</li>
<li>Builder config with remote signing</li>
<li>Signature types for Deposit Wallet, Safe, and Proxy wallets</li>
</ul>
</Tab>
<Tab title="Wallet Operations">
<ul>
<li>Deposit wallet deployment via Relayer</li>
<li>Batch token approvals (pUSD + outcome tokens)</li>
<li>CTF operations (split, merge, redeem)</li>
<li>Transaction monitoring</li>
</ul>
</Tab>
<Tab title="Trading">
<ul>
<li>CLOB client initialization</li>
<li>Order placement with builder attribution</li>
<li>Position and order management</li>
<li>Market discovery via Gamma API</li>
</ul>
</Tab>
</Tabs>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Get API Keys" icon="key" href="/builders/api-keys">
Create and manage your Builder API credentials.
</Card>
<Card title="Understand Tiers" icon="layer-group" href="/builders/tiers">
Learn about rate limits and how to upgrade.
</Card>
<Card title="Attribute Orders" icon="tag" href="/trading/orders/attribution">
Configure your client to credit trades to your account.
</Card>
<Card title="Gasless Guide" icon="gas-pump" href="/trading/gasless">
Set up gasless transactions for your users.
</Card>
</CardGroup>
@@ -1,150 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Order Attribution
> Attribute orders to your builder code for volume credit and fee rewards
Order attribution credits trades to your builder account by attaching your **builder code** to every order. This enables:
* Volume tracking on the [Builder Leaderboard](https://builders.polymarket.com/)
* Fee rewards through the [Builder Program](/builders/overview)
* Performance monitoring via the Data API
***
## Builder Code
Your **builder code** is a `bytes32` identifier tied to your builder profile. Find it at [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder).
That's the only credential you need for attribution — no HMAC signing, no separate API key, no special headers.
<Note>
Builder codes are public identifiers — they appear onchain in the `builder`
field of every order you attribute. Only you control which orders include your
code, so keep it scoped to apps you own.
</Note>
***
## Attaching the Builder Code
Pass `builderCode` in the order struct on every order you submit. The SDK serializes it into the onchain order's `builder` field, and the protocol attributes every matched trade to your profile.
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient, Side, OrderType } from "@polymarket/clob-client-v2";
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer,
creds: apiCreds,
signatureType: 3,
funderAddress: depositWalletAddress,
});
const response = await client.createAndPostOrder(
{
tokenID: "0x...",
price: 0.55,
size: 100,
side: Side.BUY,
builderCode: "0xabc123...", // your builder code from polymarket.com/settings?tab=builder
},
{ tickSize: "0.01", negRisk: false },
OrderType.GTC,
);
```
```python Python theme={null}
from py_clob_client_v2 import ClobClient
from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=private_key,
creds=api_creds,
signature_type=3,
funder=deposit_wallet_address,
)
response = client.create_and_post_order(
OrderArgs(
token_id="0x...",
price=0.55,
size=100,
side=BUY,
builder_code="0xabc123...", # your builder code from polymarket.com/settings?tab=builder
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
order_type=OrderType.GTC,
)
```
</CodeGroup>
Every order placed with `builderCode` attached is credited to your builder profile — no additional configuration needed.
***
## Verifying Attribution
Query trades attributed to your builder code:
<CodeGroup>
```typescript TypeScript theme={null}
const trades = await client.getBuilderTrades();
// Filtered by market
const marketTrades = await client.getBuilderTrades({
market: "0xbd31dc8a...",
});
```
```python Python theme={null}
trades = client.get_builder_trades()
market_trades = client.get_builder_trades(
market="0xbd31dc8a..."
)
```
</CodeGroup>
Each `BuilderTrade` includes: `id`, `market`, `assetId`, `side`, `size`, `price`, `status`, `outcome`, `owner`, `maker`, `builder`, `transactionHash`, `matchTime`, `fee`, and `feeUsdc`.
***
## Troubleshooting
<AccordionGroup>
<Accordion title="Volume not appearing on the leaderboard">
<ul>
<li>Confirm your `builderCode` is correctly attached to every order</li>
<li>Check that orders are being matched, not just placed</li>
<li>Allow up to 24 hours for volume to appear on the leaderboard</li>
</ul>
</Accordion>
<Accordion title="Invalid builder code">
Verify the code matches what's shown on [your Builder
Profile](https://polymarket.com/settings?tab=builder). Builder codes are
`bytes32` hex values starting with `0x`.
</Accordion>
</AccordionGroup>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Builder Program" icon="hammer" href="/builders/overview">
Learn about the Builder Program tiers and rewards
</Card>
<Card title="Create Orders" icon="plus" href="/trading/orders/create">
Build, sign, and submit orders
</Card>
</CardGroup>
-432
View File
@@ -1,432 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Gasless Transactions
> Execute onchain operations without paying gas fees
Polymarket's **Relayer Client** enables gasless transactions for your users. Instead of requiring users to hold POL for gas, Polymarket's infrastructure pays all transaction fees. This creates a seamless experience where users only need pUSD to trade.
## How It Works
The relayer acts as a transaction sponsor:
1. Your app creates a transaction
2. The user signs it with their private key
3. Your app sends it to Polymarket's relayer
4. The relayer submits it onchain and pays the gas fee
5. The transaction executes from the user's wallet
## What Is Covered
Polymarket pays gas for all operations routed through the relayer:
| Operation | Description |
| --------------------- | ------------------------------------------------- |
| **Wallet deployment** | Deploy deposit wallets for new API users |
| **Token approvals** | Approve contracts to spend pUSD or outcome tokens |
| **CTF operations** | Split, merge, and redeem positions |
| **Transfers** | Move tokens between addresses |
## Authentication
The relayer uses **Relayer API Keys**. You can create one from [Settings > API Keys](https://polymarket.com/settings?tab=api-keys) on the Polymarket website.
<Note>
**Already have a builder signing key?** Your existing HMAC-based builder API
key keeps working with the Relayer — no need to rotate or reissue. Order
attribution is now associated with the native `builderCode` field in CLOB V2.
See [Migrating to CLOB V2](/v2-migration#builder-program) for context.
</Note>
Include these headers with your requests:
| Header | Description |
| ------------------------- | ----------------------------- |
| `RELAYER_API_KEY` | Your Relayer API key |
| `RELAYER_API_KEY_ADDRESS` | The address that owns the key |
<Info>
If you want to use the Relayer API Key directly without the SDK, see the
[Relayer API Reference](/api-reference/relayer).
</Info>
## Prerequisites
Before using the relayer, you need:
| Requirement | Source |
| ---------------------------- | ------------------------------------------------------------------- |
| Relayer API Key | [Settings > API Keys](https://polymarket.com/settings?tab=api-keys) |
| User's private key or signer | Your wallet integration |
| pUSD balance | For trading (not for gas) |
## Installation
<CodeGroup>
```bash npm theme={null}
npm install @polymarket/builder-relayer-client
```
```bash pip theme={null}
pip install py-builder-relayer-client
```
</CodeGroup>
## Client Setup
Initialize the relayer client with your Relayer API Key:
<CodeGroup>
```typescript TypeScript theme={null}
import { createWalletClient, http, Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { polygon } from "viem/chains";
import { RelayClient } from "@polymarket/builder-relayer-client";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as Hex);
const wallet = createWalletClient({
account,
chain: polygon,
transport: http(process.env.RPC_URL),
});
const client = new RelayClient({
host: "https://relayer-v2.polymarket.com/",
chain: 137,
signer: wallet,
relayerApiKey: process.env.RELAYER_API_KEY!,
relayerApiKeyAddress: process.env.RELAYER_API_KEY_ADDRESS!,
});
```
```python Python theme={null}
import os
from py_builder_relayer_client.client import RelayClient
client = RelayClient(
host="https://relayer-v2.polymarket.com",
chain=137,
signer=os.getenv("PRIVATE_KEY"),
relayer_api_key=os.environ["RELAYER_API_KEY"],
relayer_api_key_address=os.environ["RELAYER_API_KEY_ADDRESS"],
)
```
</CodeGroup>
<Warning>
Never expose your Relayer API Key in client-side code. Use environment
variables or a secrets manager.
</Warning>
## Wallet Types
Use deposit wallets for new API users. Existing Safe and Proxy users can keep
using their current wallet type and signature flow.
| Type | Deployment | Best For |
| ------------------ | ---------------------------------------- | ----------------------------------- |
| **Deposit Wallet** | Call `deployDepositWallet()` | New API users |
| **Safe** | Call `deploy()` before first transaction | Existing Safe integrations |
| **Proxy** | Auto-deploys on first transaction | Existing Polymarket.com proxy users |
<Info>
For the new deposit wallet flow, including `WALLET-CREATE`, signed `WALLET`
batches, and `POLY_1271` CLOB orders, see the [Deposit Wallet
Guide](/trading/deposit-wallets).
</Info>
<CodeGroup>
```typescript Safe Wallet (TypeScript) theme={null}
import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client";
const client = new RelayClient({
host: "https://relayer-v2.polymarket.com/",
chain: 137,
signer: wallet,
relayerApiKey: process.env.RELAYER_API_KEY!,
relayerApiKeyAddress: process.env.RELAYER_API_KEY_ADDRESS!,
txType: RelayerTxType.SAFE,
});
// Deploy before first transaction
const response = await client.deploy();
const result = await response.wait();
console.log("Safe Address:", result?.proxyAddress);
```
```python Safe Wallet (Python) theme={null}
from py_builder_relayer_client.client import RelayClient
# client initialized with relayer credentials (see Client Setup above)
# Deploy before first transaction
response = client.deploy()
result = response.wait()
print("Safe Address:", result.get("proxyAddress"))
```
```typescript Proxy Wallet (TypeScript) theme={null}
import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client";
const client = new RelayClient({
host: "https://relayer-v2.polymarket.com/",
chain: 137,
signer: wallet,
relayerApiKey: process.env.RELAYER_API_KEY!,
relayerApiKeyAddress: process.env.RELAYER_API_KEY_ADDRESS!,
txType: RelayerTxType.PROXY,
});
// No deploy needed - auto-deploys on first transaction
```
```python Proxy Wallet (Python) theme={null}
from py_builder_relayer_client.client import RelayClient
# client initialized with relayer credentials (see Client Setup above)
# No deploy needed - auto-deploys on first transaction
```
</CodeGroup>
## Executing Transactions
Use the `execute` method to send transactions through the relayer:
```typescript theme={null}
interface Transaction {
to: string; // Target contract address
data: string; // Encoded function call
value: string; // POL to send (usually "0")
}
const response = await client.execute(transactions, "Description");
const result = await response.wait();
```
### Token Approval
Approve contracts to spend tokens:
<CodeGroup>
```typescript TypeScript theme={null}
import { encodeFunctionData, maxUint256 } from "viem";
const pUSD = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB";
const CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045";
const approveTx = {
to: pUSD,
data: encodeFunctionData({
abi: [
{
name: "approve",
type: "function",
inputs: [
{ name: "spender", type: "address" },
{ name: "amount", type: "uint256" },
],
outputs: [{ type: "bool" }],
},
],
functionName: "approve",
args: [CTF, maxUint256],
}),
value: "0",
};
const response = await client.execute([approveTx], "Approve pUSD for CTF");
await response.wait();
```
```python Python theme={null}
from web3 import Web3
pUSD = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"
CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
MAX_UINT256 = 2**256 - 1
approve_tx = {
"to": pUSD,
"data": Web3().eth.contract(
address=pUSD,
abi=[{
"name": "approve",
"type": "function",
"inputs": [
{"name": "spender", "type": "address"},
{"name": "amount", "type": "uint256"}
],
"outputs": [{"type": "bool"}]
}]
).encode_abi(abi_element_identifier="approve", args=[CTF, MAX_UINT256]),
"value": "0"
}
response = client.execute([approve_tx], "Approve pUSD for CTF")
response.wait()
```
</CodeGroup>
### Redeem Positions
Exchange winning tokens for pUSD after market resolution:
<CodeGroup>
```typescript TypeScript theme={null}
import { encodeFunctionData } from "viem";
const redeemTx = {
to: CTF_ADDRESS,
data: encodeFunctionData({
abi: [
{
name: "redeemPositions",
type: "function",
inputs: [
{ name: "collateralToken", type: "address" },
{ name: "parentCollectionId", type: "bytes32" },
{ name: "conditionId", type: "bytes32" },
{ name: "indexSets", type: "uint256[]" },
],
outputs: [],
},
],
functionName: "redeemPositions",
args: [collateralToken, parentCollectionId, conditionId, indexSets],
}),
value: "0",
};
const response = await client.execute([redeemTx], "Redeem positions");
await response.wait();
```
```python Python theme={null}
CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
redeem_tx = {
"to": CTF,
"data": Web3().eth.contract(
address=CTF,
abi=[{
"name": "redeemPositions",
"type": "function",
"inputs": [
{"name": "collateralToken", "type": "address"},
{"name": "parentCollectionId", "type": "bytes32"},
{"name": "conditionId", "type": "bytes32"},
{"name": "indexSets", "type": "uint256[]"}
],
"outputs": []
}]
).encode_abi(
abi_element_identifier="redeemPositions",
args=[collateral_token, parent_collection_id, condition_id, index_sets]
),
"value": "0"
}
response = client.execute([redeem_tx], "Redeem positions")
response.wait()
```
</CodeGroup>
### Batch Transactions
Execute multiple operations atomically in a single call:
<CodeGroup>
```typescript TypeScript theme={null}
const approveTx = {
to: pUSD,
data: encodeFunctionData({
abi: erc20Abi,
functionName: "approve",
args: [CTF, maxUint256],
}),
value: "0",
};
const transferTx = {
to: pUSD,
data: encodeFunctionData({
abi: erc20Abi,
functionName: "transfer",
args: [recipientAddress, parseUnits("50", 6)],
}),
value: "0",
};
// Both execute atomically
const response = await client.execute(
[approveTx, transferTx],
"Approve and transfer",
);
await response.wait();
```
```python Python theme={null}
approve_tx = {
"to": pUSD,
"data": contract.encode_abi(
abi_element_identifier="approve",
args=[CTF, MAX_UINT256]
),
"value": "0"
}
transfer_tx = {
"to": pUSD,
"data": contract.encode_abi(
abi_element_identifier="transfer",
args=[recipient_address, 50 * 10**6]
),
"value": "0"
}
# Both execute atomically
response = client.execute([approve_tx, transfer_tx], "Approve and transfer")
response.wait()
```
</CodeGroup>
<Tip>
Batching reduces latency and ensures all transactions succeed or fail
together.
</Tip>
## Transaction States
Track transaction progress through these states:
| State | Terminal | Description |
| ----------------- | -------- | ------------------------------- |
| `STATE_NEW` | No | Transaction received by relayer |
| `STATE_EXECUTED` | No | Submitted onchain |
| `STATE_MINED` | No | Included in a block |
| `STATE_CONFIRMED` | Yes | Finalized successfully |
| `STATE_FAILED` | Yes | Failed permanently |
| `STATE_INVALID` | Yes | Rejected as invalid |
## Contract Addresses
See [Contracts](/resources/contracts) for all Polymarket smart contract addresses on Polygon.
## Resources
* [Builder Relayer Client (TypeScript)](https://github.com/Polymarket/builder-relayer-client)
* [Builder Relayer Client (Python)](https://github.com/Polymarket/py-builder-relayer-client)
## Next Steps
<CardGroup cols={2}>
<Card title="Negative Risk Markets" icon="scale-balanced" href="/advanced/neg-risk">
Learn about capital-efficient trading for multi-outcome events.
</Card>
<Card title="Positions & Tokens" icon="coins" href="/concepts/positions-tokens">
Understand token operations like split, merge, and redeem.
</Card>
</CardGroup>
@@ -1,156 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Fetching Markets
> Three strategies for discovering and querying markets
<Tip>
Both the events and markets endpoints are paginated. See
[pagination](#pagination) for details.
</Tip>
There are three main strategies for retrieving market data, each optimized for different use cases:
1. **By Slug** — Best for fetching specific individual markets or events
2. **By Tags** — Ideal for filtering markets by category or sport
3. **Via Events Endpoint** — Most efficient for retrieving all active markets
***
## Fetch by Slug
**Use case:** When you need to retrieve a specific market or event that you already know about.
Individual markets and events are best fetched using their unique slug identifier. The slug can be found directly in the Polymarket frontend URL.
### How to Extract the Slug
From any Polymarket URL, the slug is the path segment after `/event/`:
```
https://polymarket.com/event/fed-decision-in-october
Slug: fed-decision-in-october
```
### Examples
```bash theme={null}
# Fetch an event by slug (query parameter)
curl "https://gamma-api.polymarket.com/events?slug=fed-decision-in-october"
# Or use the path endpoint
curl "https://gamma-api.polymarket.com/events/slug/fed-decision-in-october"
```
```bash theme={null}
# Fetch a market by slug (query parameter)
curl "https://gamma-api.polymarket.com/markets?slug=fed-decision-in-october"
# Or use the path endpoint
curl "https://gamma-api.polymarket.com/markets/slug/fed-decision-in-october"
```
***
## Fetch by Tags
**Use case:** When you want to filter markets by category, sport, or topic.
Tags provide a way to categorize and filter markets. You can discover available tags and then use them to filter your requests.
### Discover Available Tags
**General tags:** `GET /tags` (Gamma API)
**Sports tags and metadata:** `GET /sports` (Gamma API)
The `/sports` endpoint returns metadata for sports including tag IDs, images, resolution sources, and series information.
### Filter by Tag
Once you have tag IDs, use the `tag_id` parameter in both events and markets endpoints:
```bash theme={null}
# Fetch events for a specific tag
curl "https://gamma-api.polymarket.com/events?tag_id=100381&limit=10&active=true&closed=false"
```
### Additional Tag Filtering
You can also:
* Use `related_tags=true` to include related tag markets
* Exclude specific tags with `exclude_tag_id`
```bash theme={null}
# Include related tags
curl "https://gamma-api.polymarket.com/events?tag_id=100381&related_tags=true&active=true&closed=false"
```
***
## Fetch All Active Markets
**Use case:** When you need to retrieve all available active markets, typically for broader analysis or market discovery.
The most efficient approach is to use the events endpoint with `active=true&closed=false`, as events contain their associated markets.
```bash theme={null}
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=100"
```
### Key Parameters
| Parameter | Description |
| ----------- | ---------------------------------------------------------------------------------------------------------------- |
| `order` | Field to order by (`volume_24hr`, `volume`, `liquidity`, `start_date`, `end_date`, `competitive`, `closed_time`) |
| `ascending` | Sort direction (`true` for ascending, `false` for descending). Default: `false` |
| `active` | Filter by active status (`true` for live tradable events) |
| `closed` | Filter by closed status. Default: `false` |
| `limit` | Results per page |
| `offset` | Number of results to skip for pagination |
```bash theme={null}
# Get the highest volume active events
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&order=volume_24hr&ascending=false&limit=100"
```
***
## Pagination
All list endpoints return paginated responses with `limit` and `offset` parameters:
```bash theme={null}
# Page 1: First 50 results
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=50&offset=0"
# Page 2: Next 50 results
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=50&offset=50"
# Page 3: Next 50 results
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=50&offset=100"
```
***
## Best Practices
1. **For individual markets:** Use the slug method for direct lookups
2. **For category browsing:** Use tag filtering to reduce API calls
3. **For complete market discovery:** Use the events endpoint with pagination
4. **Always include `active=true`** when fetching live markets. The `closed` parameter now defaults to `false`, so closed markets are excluded automatically — pass `closed=true` only if you need historical data
5. **Use the events endpoint** and work backwards — events contain their associated markets, reducing the number of API calls needed
***
## Next Steps
<CardGroup cols={2}>
<Card title="API Reference" icon="code" href="/api-reference/introduction">
Full endpoint documentation with parameters and response schemas.
</Card>
</CardGroup>
@@ -1,108 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Markets & Events
> Understanding the fundamental building blocks of Polymarket
Every prediction on Polymarket is structured around two core concepts: **markets** and **events**. Understanding how they relate is essential for building on the platform.
<Frame>
<img src="https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/core-concepts/event-market.png?fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=4c62bd08a405868307cdd6799b368ca5" alt="" className="dark:hidden" width="1540" height="952" data-path="images/core-concepts/event-market.png" />
<img src="https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/dark/core-concepts/event-market.png?fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=2eb5c9b0f8a2afe52bc2e717b7b796a2" alt="" className="hidden dark:block" width="1540" height="952" data-path="images/dark/core-concepts/event-market.png" />
</Frame>
## Markets
A **market** is the fundamental tradable unit on Polymarket. Each market represents a single binary question with Yes/No outcomes.
<Frame>
<img src="https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/core-concepts/event.png?fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=0c9a264aec9a22ce5a20c4cc7980806d" alt="" className="dark:hidden" width="1540" height="952" data-path="images/core-concepts/event.png" />
<img src="https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/dark/core-concepts/event.png?fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=912e41bebfe8c1a43ef53b89685ca3d2" alt="" className="hidden dark:block" width="1540" height="952" data-path="images/dark/core-concepts/event.png" />
</Frame>
Every market has:
| Identifier | Description |
| ---------------- | ------------------------------------------------------------------------ |
| **Condition ID** | Unique identifier for the market's condition in the CTF contracts |
| **Question ID** | Hash of the market question used for resolution |
| **Token IDs** | ERC1155 token IDs used for trading on the CLOB — one for Yes, one for No |
<Note>
Markets can only be traded via the CLOB if `enableOrderBook` is `true`. Some
markets may exist onchain but not be available for order book trading.
</Note>
### Market Example
A simple market might be:
> **"Will Bitcoin reach \$150,000 by December 2026?"**
This creates two outcome tokens:
* **Yes token** - Redeemable for `$1` if Bitcoin reaches `$150k`
* **No token** - Redeemable for `$1` if Bitcoin doesn't reach `$100k`
## Events
An **event** is a container that groups one or more related markets together. Events provide organizational structure and enable multi-outcome predictions.
### Single-Market Events
When an event contains just one market, it creates a simple market pair. The event and market are essentially equivalent.
```
Event: Will Bitcoin reach $100,000 by December 2024?
└── Market: Will Bitcoin reach $100,000 by December 2024? (Yes/No)
```
### Multi-Market Events
When an event contains two or more markets, it creates a grouped market pair. This enables mutually exclusive multi-outcome predictions.
```
Event: Who will win the 2024 Presidential Election?
├── Market: Donald Trump? (Yes/No)
├── Market: Joe Biden? (Yes/No)
├── Market: Kamala Harris? (Yes/No)
└── Market: Other? (Yes/No)
```
## Identifying Markets
Every market and event has a unique **slug** that appears in the Polymarket URL:
```
https://polymarket.com/event/fed-decision-in-october
└── slug: fed-decision-in-october
```
You can use slugs to fetch specific markets or events from the API:
```bash theme={null}
# Fetch event by slug
curl "https://gamma-api.polymarket.com/events?slug=fed-decision-in-october"
```
## Sports Markets
Specifically for sports markets, outstanding limit orders are **automatically cancelled** once the game begins, clearing the order book at the official start time. However, game start times can shift — if a game starts earlier than scheduled, orders may not be cleared in time. Always monitor your orders closely around game start times.
***
## Next Steps
<CardGroup cols={2}>
<Card title="Prices & Orderbook" icon="chart-line" href="/concepts/prices-orderbook">
Learn how prices are determined and how the order book works.
</Card>
<Card title="Fetching Market Data" icon="code" href="/market-data/overview">
Start querying markets and events from the API.
</Card>
</CardGroup>
@@ -1,111 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Overview
> Fetch market data with no authentication required
All market data is available through public REST endpoints. No API key, no authentication, no wallet required.
```bash theme={null}
curl "https://gamma-api.polymarket.com/events?limit=5"
```
***
## Data Model
Polymarket structures data using two organizational models. The most fundamental element is always markets—events simply provide additional organization.
<Steps>
<Step title="Event">
A top-level object representing a question (e.g., "Who will win the 2024
Presidential Election?"). Contains one or more markets.
</Step>
<Step title="Market">
A specific tradable binary outcome within an event. Maps to a pair of CLOB
token IDs, a market address, a question ID, and a condition ID.
</Step>
</Steps>
### Single-Market Events vs Multi-Market Events
| Type | Example |
| ------------------- | ---------------------------------------------------------------------------------------------- |
| Single-market event | "Will Bitcoin reach \$100k?" → 1 market (Yes/No) |
| Multi-market event | "Where will Barron Trump attend College?" → Markets for Georgetown, NYU, UPenn, Harvard, Other |
### Outcomes and Prices
Each market has `outcomes` and `outcomePrices` arrays that map 1:1. Prices represent implied probabilities:
```json theme={null}
{
"outcomes": "[\"Yes\", \"No\"]",
"outcomePrices": "[\"0.20\", \"0.80\"]"
}
// Index 0: "Yes" → 0.20 (20% probability)
// Index 1: "No" → 0.80 (80% probability)
```
<Info>Markets can be traded via the CLOB if `enableOrderBook` is `true`.</Info>
***
## Available Data
Endpoints are split across three APIs. See the [API Reference](/api-reference/introduction) for full endpoint documentation with parameters and response schemas.
### Gamma API - Events Markets and Discovery
| Endpoint | Description |
| -------------------- | ------------------------------------------- |
| `GET /events` | List events with filtering and pagination |
| `GET /events/{id}` | Get a single event by ID |
| `GET /markets` | List markets with filtering and pagination |
| `GET /markets/{id}` | Get a single market by ID |
| `GET /public-search` | Search across events, markets, and profiles |
| `GET /tags` | Ranked tags/categories |
| `GET /series` | Series (grouped events) |
| `GET /sports` | Sports metadata |
| `GET /teams` | Teams |
### CLOB API - Prices and Orderbooks
| Endpoint | Description |
| --------------------- | --------------------------------- |
| `GET /price` | Price for a single token |
| `GET /prices` | Prices for multiple tokens |
| `GET /book` | Order book for a token |
| `POST /books` | Order books for multiple tokens |
| `GET /prices-history` | Historical price data for a token |
| `GET /midpoint` | Midpoint price for a token |
| `GET /spread` | Spread for a token |
### Data API - Positions Trades and Analytics
| Endpoint | Description |
| -------------------------------------- | ---------------------------- |
| `GET /positions?user={address}` | Current positions for a user |
| `GET /closed-positions?user={address}` | Closed positions for a user |
| `GET /activity?user={address}` | Onchain activity for a user |
| `GET /value?user={address}` | Total position value |
| `GET /oi` | Open interest for a market |
| `GET /holders` | Top holders of a market |
| `GET /trades` | Trade history |
***
## Next Steps
<CardGroup cols={2}>
<Card title="Fetching Markets" icon="magnifying-glass" href="/market-data/fetching-markets">
Three strategies for discovering and querying markets.
</Card>
<Card title="API Reference" icon="code" href="/api-reference/introduction">
Full endpoint documentation with parameters and response schemas.
</Card>
</CardGroup>
-156
View File
@@ -1,156 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Fetching Markets
> Three strategies for discovering and querying markets
<Tip>
Both the events and markets endpoints are paginated. See
[pagination](#pagination) for details.
</Tip>
There are three main strategies for retrieving market data, each optimized for different use cases:
1. **By Slug** — Best for fetching specific individual markets or events
2. **By Tags** — Ideal for filtering markets by category or sport
3. **Via Events Endpoint** — Most efficient for retrieving all active markets
***
## Fetch by Slug
**Use case:** When you need to retrieve a specific market or event that you already know about.
Individual markets and events are best fetched using their unique slug identifier. The slug can be found directly in the Polymarket frontend URL.
### How to Extract the Slug
From any Polymarket URL, the slug is the path segment after `/event/`:
```
https://polymarket.com/event/fed-decision-in-october
Slug: fed-decision-in-october
```
### Examples
```bash theme={null}
# Fetch an event by slug (query parameter)
curl "https://gamma-api.polymarket.com/events?slug=fed-decision-in-october"
# Or use the path endpoint
curl "https://gamma-api.polymarket.com/events/slug/fed-decision-in-october"
```
```bash theme={null}
# Fetch a market by slug (query parameter)
curl "https://gamma-api.polymarket.com/markets?slug=fed-decision-in-october"
# Or use the path endpoint
curl "https://gamma-api.polymarket.com/markets/slug/fed-decision-in-october"
```
***
## Fetch by Tags
**Use case:** When you want to filter markets by category, sport, or topic.
Tags provide a way to categorize and filter markets. You can discover available tags and then use them to filter your requests.
### Discover Available Tags
**General tags:** `GET /tags` (Gamma API)
**Sports tags and metadata:** `GET /sports` (Gamma API)
The `/sports` endpoint returns metadata for sports including tag IDs, images, resolution sources, and series information.
### Filter by Tag
Once you have tag IDs, use the `tag_id` parameter in both events and markets endpoints:
```bash theme={null}
# Fetch events for a specific tag
curl "https://gamma-api.polymarket.com/events?tag_id=100381&limit=10&active=true&closed=false"
```
### Additional Tag Filtering
You can also:
* Use `related_tags=true` to include related tag markets
* Exclude specific tags with `exclude_tag_id`
```bash theme={null}
# Include related tags
curl "https://gamma-api.polymarket.com/events?tag_id=100381&related_tags=true&active=true&closed=false"
```
***
## Fetch All Active Markets
**Use case:** When you need to retrieve all available active markets, typically for broader analysis or market discovery.
The most efficient approach is to use the events endpoint with `active=true&closed=false`, as events contain their associated markets.
```bash theme={null}
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=100"
```
### Key Parameters
| Parameter | Description |
| ----------- | ---------------------------------------------------------------------------------------------------------------- |
| `order` | Field to order by (`volume_24hr`, `volume`, `liquidity`, `start_date`, `end_date`, `competitive`, `closed_time`) |
| `ascending` | Sort direction (`true` for ascending, `false` for descending). Default: `false` |
| `active` | Filter by active status (`true` for live tradable events) |
| `closed` | Filter by closed status. Default: `false` |
| `limit` | Results per page |
| `offset` | Number of results to skip for pagination |
```bash theme={null}
# Get the highest volume active events
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&order=volume_24hr&ascending=false&limit=100"
```
***
## Pagination
All list endpoints return paginated responses with `limit` and `offset` parameters:
```bash theme={null}
# Page 1: First 50 results
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=50&offset=0"
# Page 2: Next 50 results
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=50&offset=50"
# Page 3: Next 50 results
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=50&offset=100"
```
***
## Best Practices
1. **For individual markets:** Use the slug method for direct lookups
2. **For category browsing:** Use tag filtering to reduce API calls
3. **For complete market discovery:** Use the events endpoint with pagination
4. **Always include `active=true`** when fetching live markets. The `closed` parameter now defaults to `false`, so closed markets are excluded automatically — pass `closed=true` only if you need historical data
5. **Use the events endpoint** and work backwards — events contain their associated markets, reducing the number of API calls needed
***
## Next Steps
<CardGroup cols={2}>
<Card title="API Reference" icon="code" href="/api-reference/introduction">
Full endpoint documentation with parameters and response schemas.
</Card>
</CardGroup>
@@ -1,83 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Overview
> Market making on Polymarket
A Market Maker (MM) on Polymarket is a trader who provides liquidity to prediction markets by continuously posting bid and ask orders. By laying the spread, market makers enable other users to trade efficiently while earning the spread as compensation for the risk they take.
Market makers are essential to Polymarket's ecosystem — they provide liquidity across markets, tighten spreads for better user experience, enable price discovery through continuous quoting, and absorb trading flow from retail and institutional users.
<Note>
**Not a Market Maker?** If you're building an application that routes orders
for your users, see the [Builder Program](/builders/overview) instead.
</Note>
***
## Getting Started
<Steps>
<Step title="Complete Setup">
Deploy wallets, fund with pUSD, and set token approvals. See the [Getting
Started](/market-makers/getting-started) guide.
</Step>
<Step title="Connect to Data Feeds">
WebSocket for real-time orderbook updates, Gamma API for market metadata.
See [Market Data](/market-data/overview).
</Step>
<Step title="Start Quoting">
Post orders via the CLOB REST API. See [Trading ](/market-makers/trading).
</Step>
</Steps>
***
## Quick Reference
| Action | Tool | Documentation |
| -------------------- | -------------- | ------------------------------------------------- |
| Deposit pUSD | Bridge API | [Bridge](/trading/bridge/deposit) |
| Approve tokens | Relayer Client | [Getting Started](/market-makers/getting-started) |
| Post limit orders | CLOB REST API | [Create Orders](/trading/orders/create) |
| Monitor orderbook | WebSocket | [WebSocket](/market-data/websocket/overview) |
| Split pUSD to tokens | CTF / Relayer | [Inventory](/market-makers/inventory) |
| Merge tokens to pUSD | CTF / Relayer | [Inventory](/market-makers/inventory) |
***
## What Is in This Section
<CardGroup cols={2}>
<Card title="Getting Started" icon="gear" href="/market-makers/getting-started">
Deposits, token approvals, wallet deployment, API keys
</Card>
<Card title="Trading" icon="chart-line" href="/market-makers/trading">
Quoting best practices, strategies, and risk controls
</Card>
<Card title="Inventory Management" icon="boxes-stacked" href="/market-makers/inventory">
Split, merge, and redeem outcome tokens
</Card>
<Card title="Liquidity Rewards" icon="gift" href="/market-makers/liquidity-rewards">
Earn rewards for providing liquidity
</Card>
</CardGroup>
## Risks
<Warning>
Be careful with spread management — if your bid price is higher than your ask
price (a "negative spread" or "crossed market"), you will lose money on every
fill. Always validate your quote prices before submission.
</Warning>
## Support
For market maker onboarding and support, contact [support@polymarket.com](mailto:support@polymarket.com).
-241
View File
@@ -1,241 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Getting Started
> One-time setup for market making on Polymarket
Before you can start market making, you need to complete these one-time setup steps — deposit pUSD to Polygon, deploy a wallet, approve tokens for trading, and generate API credentials.
<Steps>
<Step title="Deposit pUSD">
Market makers need pUSD on Polygon to fund their trading operations.
| Method | Best For | Documentation |
| ----------------------- | ------------------------------------ | ---------------------------------------------------- |
| Bridge API | Automated deposits from other chains | [Bridge Deposit](/trading/bridge/deposit) |
| Direct Polygon transfer | Already have pUSD on Polygon | N/A |
| Cross-chain bridge | Large deposits from Ethereum | [Supported Assets](/trading/bridge/supported-assets) |
### Using the Bridge API
```typescript theme={null}
// Get bridge addresses for your Polymarket wallet
const deposit = await fetch("https://bridge.polymarket.com/deposit", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
address: "YOUR_POLYMARKET_WALLET_ADDRESS",
}),
});
// Returns bridge addresses for EVM, SVM, and BTC networks
const addresses = await deposit.json();
// Send USDC to the appropriate address for your source chain
```
</Step>
<Step title="Deploy a Wallet">
### EOA
Standard Ethereum wallet. You pay for all onchain transactions (approvals, splits, merges, trade execution).
### Deposit Wallet
Deposit wallets are the recommended wallet path for new API users. They are
deployed through Polymarket's relayer and use `POLY_1271` order signatures.
See the [Deposit Wallet Guide](/trading/deposit-wallets) for the
wallet creation, approval, balance sync, and order-signing flow.
### Existing Safe Wallets
Existing Gnosis Safe users can continue using their current wallet. Safe wallets
are deployed via Polymarket's relayer and support:
* **Gasless transactions** — Polymarket pays gas fees for onchain operations
* **Contract wallet** — Enables advanced features like batched transactions
For existing Safe integrations, deploy a Safe wallet using the Relayer Client:
<CodeGroup>
```typescript TypeScript theme={null}
import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client";
const client = new RelayClient({
host: "https://relayer-v2.polymarket.com/",
chain: 137,
signer,
relayerApiKey: process.env.RELAYER_API_KEY!,
relayerApiKeyAddress: process.env.RELAYER_API_KEY_ADDRESS!,
txType: RelayerTxType.SAFE,
});
// Deploy the Safe wallet
const response = await client.deploy();
const result = await response.wait();
console.log("Safe Address:", result?.proxyAddress);
```
```python Python theme={null}
from py_builder_relayer_client.client import RelayClient
# client initialized with Relayer API Key credentials (see Gasless Transactions)
# Deploy the Safe wallet
response = client.deploy()
result = response.wait()
print("Safe Address:", result.get("proxyAddress"))
```
</CodeGroup>
<Info>
See [Gasless Transactions](/trading/gasless) for full Relayer Client setup
including local and remote signing configurations.
</Info>
</Step>
<Step title="Approve Tokens">
Before trading, you must approve the exchange contracts to spend your tokens.
### Required Approvals
| Token | Spender | Purpose |
| -------------------- | --------------------- | ------------------------------ |
| pUSD | CTF Contract | Split pUSD into outcome tokens |
| CTF (outcome tokens) | CTF Exchange | Trade outcome tokens |
| CTF (outcome tokens) | Neg Risk CTF Exchange | Trade neg-risk market tokens |
### Contract Addresses
```typescript theme={null}
const ADDRESSES = {
pUSD: "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB",
CTF: "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045",
CTF_EXCHANGE: "0xE111180000d2663C0091e4f400237545B87B996B",
NEG_RISK_CTF_EXCHANGE: "0xe2222d279d744050d28e00520010520000310F59",
NEG_RISK_ADAPTER: "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296",
};
```
### Approve via Relayer Client
<CodeGroup>
```typescript TypeScript theme={null}
import { ethers } from "ethers";
import { Interface } from "ethers/lib/utils";
const erc20Interface = new Interface([
"function approve(address spender, uint256 amount) returns (bool)",
]);
// Approve pUSD for CTF contract
const approveTx = {
to: ADDRESSES.pUSD,
data: erc20Interface.encodeFunctionData("approve", [
ADDRESSES.CTF,
ethers.constants.MaxUint256,
]),
value: "0",
};
const response = await client.execute([approveTx], "Approve pUSD for CTF");
await response.wait();
```
```python Python theme={null}
from web3 import Web3
pUSD = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"
CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
MAX_UINT256 = 2**256 - 1
approve_tx = {
"to": pUSD,
"data": Web3().eth.contract(
address=pUSD,
abi=[{
"name": "approve",
"type": "function",
"inputs": [
{"name": "spender", "type": "address"},
{"name": "amount", "type": "uint256"}
],
"outputs": [{"type": "bool"}]
}]
).encode_abi(abi_element_identifier="approve", args=[CTF, MAX_UINT256]),
"value": "0"
}
response = client.execute([approve_tx], "Approve pUSD for CTF")
response.wait()
```
</CodeGroup>
</Step>
<Step title="Generate API Credentials">
To place orders and access authenticated endpoints, you need L2 API credentials derived from your wallet.
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient } from "@polymarket/clob-client-v2";
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer,
});
// Derive API credentials from your wallet
const credentials = await client.createOrDeriveApiKey();
console.log("API Key:", credentials.key);
console.log("Secret:", credentials.secret);
console.log("Passphrase:", credentials.passphrase);
```
```python Python theme={null}
from py_clob_client_v2 import ClobClient
import os
private_key = os.getenv("PRIVATE_KEY")
temp_client = ClobClient("https://clob.polymarket.com", key=private_key, chain_id=137)
credentials = temp_client.create_or_derive_api_key()
```
```rust Rust theme={null}
use std::str::FromStr;
use polymarket_client_sdk_v2::POLYGON;
use polymarket_client_sdk_v2::auth::{LocalSigner, Signer};
use polymarket_client_sdk_v2::clob::{Client, Config};
let private_key = std::env::var("POLYMARKET_PRIVATE_KEY")?;
let signer = LocalSigner::from_str(&private_key)?
.with_chain_id(Some(POLYGON));
// The Rust SDK derives credentials and initializes in one step
let client = Client::new("https://clob.polymarket.com", Config::default())?
.authentication_builder(&signer)
.authenticate()
.await?;
```
</CodeGroup>
See [Authentication](/trading/overview#authentication) for full details on signature types and REST API headers.
</Step>
</Steps>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Trading" icon="chart-line" href="/market-makers/trading">
Post limit orders and manage quotes
</Card>
<Card title="Market Data" icon="database" href="/market-data/overview">
Connect to real-time market data
</Card>
</CardGroup>
@@ -1,104 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Deposit
> Bridge assets from any supported chain to fund your Polymarket account
Polymarket uses **pUSD** (Polymarket USD) on Polygon as collateral for all trading. The Bridge API lets you deposit assets from Ethereum, Solana, Bitcoin, and other chains—they're automatically converted to pUSD on Polygon.
## How It Works
1. Request bridge addresses for your Polymarket wallet
2. Send assets to the appropriate address for your source chain
3. Assets are bridged and swapped to pUSD automatically
4. pUSD is credited to your wallet for trading
## Create Bridge Addresses
Generate unique bridge addresses linked to your Polymarket wallet. See the [Bridge API Reference](/api-reference/introduction) for full request and response schemas.
```bash theme={null}
curl -X POST https://bridge.polymarket.com/deposit \
-H "Content-Type: application/json" \
-d '{"address": "0x56687bf447db6ffa42ffe2204a05edaa20f55839"}'
```
### Address Types
| Address | Use For |
| ------- | -------------------------------------------------------- |
| `evm` | Ethereum, Arbitrum, Base, Optimism, and other EVM chains |
| `svm` | Solana |
| `btc` | Bitcoin |
| `tvm` | Tron |
<Warning>
Each address is unique to your wallet. Only send assets from supported chains
to the correct address type.
</Warning>
## Deposit Flow
<Steps>
<Step title="Get Your Bridge Address">
Call `POST /deposit` with your Polymarket wallet address to get bridge
addresses.
</Step>
<Step title="Check Supported Assets">
Verify your token is supported and meets the minimum deposit amount via
`/supported-assets`.
</Step>
<Step title="Send Assets">
Transfer tokens to the appropriate bridge address from your source chain.
</Step>
<Step title="Track Status">
Monitor your deposit progress using `/status/{address}`.
</Step>
</Steps>
## USDC vs pUSD
You can deposit either USDC (native) or USDC.e (bridged) as the source asset to your Polymarket wallet. Either way, the incoming USDC or USDC.e is wrapped into pUSD via the Collateral Onramp, and pUSD is what you hold and trade with on Polymarket.
## Large Deposits
For deposits over \$50,000 originating from a chain other than Polygon, we recommend using a third-party bridge to minimize slippage:
* [DeBridge](https://app.debridge.finance/)
* [Across](https://app.across.to/bridge)
* [Portal](https://portalbridge.com/)
Bridge directly to your Polymarket USDC (Polygon) bridge address. Polymarket is not affiliated with or responsible for any third-party bridge.
## Minimum Deposits
Each asset has a minimum deposit amount. Deposits below the minimum will not be processed. Check `/supported-assets` for current minimums.
## Deposit Recovery
If you deposited the wrong token, use this tool to recover your funds:
[recovery.polymarket.com](https://recovery.polymarket.com/)
<Warning>
Sending unsupported tokens may cause **irrecoverable loss**. Always verify
your token is listed in [Supported Assets](/trading/bridge/supported-assets)
before depositing.
</Warning>
## Next Steps
<CardGroup cols={2}>
<Card title="Supported Assets" icon="coins" href="/trading/bridge/supported-assets">
See all supported chains and tokens with minimum amounts.
</Card>
<Card title="Check Status" icon="clock" href="/trading/bridge/status">
Track your deposit progress through completion.
</Card>
</CardGroup>
-145
View File
@@ -1,145 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Negative Risk Markets
> Capital-efficient trading for multi-outcome events
**Negative risk** is a mechanism for multi-outcome events where only one outcome can win. It enables capital-efficient trading by allowing positions across all outcomes within an event to be related through a **conversion** operation.
## How It Works
In a standard multi-outcome event, each market is independent. If you want to bet against one outcome, you must buy that outcome's No tokens—but those No tokens have no relationship to the other outcomes.
Negative risk changes this. In a neg risk event:
* A **No share** in any market can be converted into **1 Yes share in every other market**
* This conversion happens through the Neg Risk Adapter contract
### Example
Consider an event: "Who will win the 2024 Presidential Election?" with three outcomes:
| Outcome | Your Position |
| ------- | ------------- |
| Trump | — |
| Harris | — |
| Other | 1 No |
With negative risk, that 1 No on "Other" can be converted into:
| Outcome | After Conversion |
| ------- | ---------------- |
| Trump | 1 Yes |
| Harris | 1 Yes |
| Other | — |
This is capital-efficient because betting against one outcome is economically equivalent to betting *for* all other outcomes.
## Identifying Neg Risk Markets
The Gamma API includes a `negRisk` boolean on events and markets:
```json theme={null}
{
"id": "123",
"title": "Who will win the 2024 Presidential Election?",
"negRisk": true,
"markets": [...]
}
```
When placing orders on neg risk markets, you must specify this in your order options:
```typescript theme={null}
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 100,
side: Side.BUY,
},
{
tickSize: "0.01",
negRisk: true, // Required for neg risk markets
},
);
```
## Contract Addresses
Neg risk markets use different contracts than standard markets:
See [Contracts](/resources/contracts) for the Neg Risk Adapter and Neg Risk CTF Exchange addresses.
## Augmented Negative Risk
Standard negative risk requires the complete set of outcomes to be known at market creation. But sometimes new outcomes emerge after trading begins (e.g., a new candidate enters a race).
**Augmented negative risk** solves this with:
| Outcome Type | Description |
| ------------------------ | ------------------------------------------------------------- |
| **Named outcomes** | Known outcomes (e.g., "Trump", "Harris") |
| **Placeholder outcomes** | Reserved slots that can be clarified later (e.g., "Person A") |
| **Explicit Other** | Catches any outcome not explicitly named |
### How Placeholders Work
1. Event launches with named outcomes + placeholders + "Other"
2. When a new outcome emerges, a placeholder is clarified via the bulletin board
3. The "Other" definition narrows as placeholders are assigned
### Trading Rules for Augmented Neg Risk
<Warning>
Only trade on **named outcomes**. Placeholder outcomes should be ignored until
they are named or until resolution occurs. The Polymarket UI does not display
unnamed outcomes.
</Warning>
* If the correct outcome at resolution is not named, the market resolves to "Other"
* The "Other" outcome's definition changes as placeholders are clarified—avoid trading it directly
### Identifying Augmented Neg Risk
An event is augmented neg risk when both flags are true:
```json theme={null}
{
"enableNegRisk": true,
"negRiskAugmented": true
}
```
<Note>
The Gamma API includes a boolean field `negRisk` on events and markets, which indicates whether the event uses negative risk. For augmented neg risk events, an additional `enableNegRisk` field is also `true`. When placing orders, the SDK option is always `negRisk: true` / `neg_risk: True` regardless of whether the market is standard or augmented neg risk.
</Note>
## Technical Details
### Conversion Mechanics
The conversion operation is atomic and happens through the Neg Risk Adapter:
1. You hold 1 No token for Outcome A
2. Call the convert function on the adapter
3. You receive 1 Yes token for every other outcome in the event
## Resources
* [Neg Risk Adapter Source Code](https://github.com/Polymarket/neg-risk-ctf-adapter)
* [Gamma API Documentation](/market-data/overview)
## Next Steps
<CardGroup cols={2}>
<Card title="Markets & Events" icon="calendar" href="/concepts/markets-events">
Understand how multi-market events are structured.
</Card>
<Card title="Positions & Tokens" icon="coins" href="/concepts/positions-tokens">
Learn about token operations like split, merge, and redeem.
</Card>
</CardGroup>
-437
View File
@@ -1,437 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Authentication
> How to authenticate requests to the CLOB API
The CLOB API uses two levels of authentication: **L1 (Private Key)** and **L2 (API Key)**. Either can be accomplished using the CLOB client or REST API.
## Public vs Authenticated
<CardGroup cols={1}>
<Card title="Public (No Auth)" icon="unlock">
The **Gamma API**, **Data API**, and CLOB read endpoints (orderbook, prices, spreads) require no authentication.
</Card>
<Card title="Authenticated (CLOB)" icon="lock">
CLOB trading endpoints (placing orders, cancellations, heartbeat) require all 5 `POLY_*` L2 HTTP headers.
</Card>
</CardGroup>
***
## Two-Level Authentication Model
The CLOB uses two levels of authentication: L1 (Private Key) and L2 (API Key). Either can be accomplished using the CLOB client or REST API
### L1 Authentication
L1 authentication uses the wallet's private key to sign an EIP-712 message used in the request header. It proves ownership and control over the private key. The private key stays in control of the user and all trading activity remains non-custodial.
**Used for:**
* Creating API credentials
* Deriving existing API credentials
* Signing and creating user's orders locally
### L2 Authentication
L2 uses API credentials (apiKey, secret, passphrase) generated from L1 authentication. These are used solely to authenticate requests made to the CLOB API. Requests are signed using HMAC-SHA256.
**Used for:**
* Cancel or get user's open orders
* Check user's balances and allowances
* Post user's signed orders
<Info>
Even with L2 authentication headers, methods that create user orders still
require the user to sign the order payload.
</Info>
***
## Getting API Credentials
Before making authenticated requests, you need to obtain API credentials using L1 authentication.
### Using the SDK
<Tabs>
<Tab title="TypeScript">
```typescript theme={null}
import { ClobClient } from "@polymarket/clob-client-v2";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const signer = createWalletClient({ account, transport: http() });
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137, // Polygon mainnet
signer,
});
// Creates new credentials or derives existing ones
const credentials = await client.createOrDeriveApiKey();
console.log(credentials);
// {
// key: "550e8400-e29b-41d4-a716-446655440000",
// secret: "base64EncodedSecretString",
// passphrase: "randomPassphraseString"
// }
```
</Tab>
<Tab title="Python">
```python theme={null}
from py_clob_client_v2 import ClobClient
import os
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137, # Polygon mainnet
key=os.getenv("PRIVATE_KEY")
)
# Creates new credentials or derives existing ones
credentials = client.create_or_derive_api_key()
print(credentials)
# {
# "apiKey": "550e8400-e29b-41d4-a716-446655440000",
# "secret": "base64EncodedSecretString",
# "passphrase": "randomPassphraseString"
# }
```
</Tab>
<Tab title="Rust">
```rust theme={null}
use std::str::FromStr;
use polymarket_client_sdk_v2::POLYGON;
use polymarket_client_sdk_v2::auth::{LocalSigner, Signer};
use polymarket_client_sdk_v2::clob::{Client, Config};
let private_key = std::env::var("POLYMARKET_PRIVATE_KEY")?;
let signer = LocalSigner::from_str(&private_key)?
.with_chain_id(Some(POLYGON));
// Creates new credentials or derives existing ones,
// then initializes the authenticated client — all in one step
let client = Client::new("https://clob.polymarket.com", Config::default())?
.authentication_builder(&signer)
.authenticate()
.await?;
let credentials = client.credentials();
println!("API Key: {}", credentials.key());
```
</Tab>
</Tabs>
<Warning>
**Never commit private keys to version control.** Always use environment
variables or secure key management systems.
</Warning>
### Using the REST API
While we highly recommend using our provided clients to handle signing and authentication, the following is for developers who choose NOT to use our [Python](https://github.com/Polymarket/py-clob-client-v2) or [TypeScript](https://github.com/Polymarket/clob-client-v2) clients.
**Create API Credentials**
```bash theme={null}
POST https://clob.polymarket.com/auth/api-key
```
**Derive API Credentials**
```bash theme={null}
GET https://clob.polymarket.com/auth/derive-api-key
```
Required L1 headers:
| Header | Description |
| ---------------- | ---------------------- |
| `POLY_ADDRESS` | Polygon signer address |
| `POLY_SIGNATURE` | CLOB EIP-712 signature |
| `POLY_TIMESTAMP` | Current UNIX timestamp |
| `POLY_NONCE` | Nonce (default: 0) |
The `POLY_SIGNATURE` is generated by signing the following EIP-712 struct:
<Accordion title="EIP-712 Signing Example">
<CodeGroup>
```typescript TypeScript theme={null}
const domain = {
name: "ClobAuthDomain",
version: "1",
chainId: chainId, // Polygon Chain ID 137
};
const types = {
ClobAuth: [
{ name: "address", type: "address" },
{ name: "timestamp", type: "string" },
{ name: "nonce", type: "uint256" },
{ name: "message", type: "string" },
],
};
const value = {
address: signingAddress, // The Signing address
timestamp: ts, // The CLOB API server timestamp
nonce: nonce, // The nonce used
message: "This message attests that I control the given wallet",
};
const sig = await signer._signTypedData(domain, types, value);
```
```python Python theme={null}
domain = {
"name": "ClobAuthDomain",
"version": "1",
"chainId": chainId, # Polygon Chain ID 137
}
types = {
"ClobAuth": [
{"name": "address", "type": "address"},
{"name": "timestamp", "type": "string"},
{"name": "nonce", "type": "uint256"},
{"name": "message", "type": "string"},
]
}
value = {
"address": signingAddress, # The signing address
"timestamp": ts, # The CLOB API server timestamp
"nonce": nonce, # The nonce used
"message": "This message attests that I control the given wallet",
}
sig = signer.sign_typed_data(domain, types, value)
```
</CodeGroup>
</Accordion>
Reference implementations:
* [TypeScript](https://github.com/Polymarket/clob-client-v2/blob/main/src/signing/eip712.ts)
* [Python](https://github.com/Polymarket/py-clob-client-v2/blob/main/py_clob_client_v2/signing/eip712.py)
Response:
```json theme={null}
{
"apiKey": "550e8400-e29b-41d4-a716-446655440000",
"secret": "base64EncodedSecretString",
"passphrase": "randomPassphraseString"
}
```
**You'll need all three values for L2 authentication.**
***
## L2 Authentication Headers
All trading endpoints require these 5 headers:
| Header | Description |
| ----------------- | ----------------------------- |
| `POLY_ADDRESS` | Polygon signer address |
| `POLY_SIGNATURE` | HMAC signature for request |
| `POLY_TIMESTAMP` | Current UNIX timestamp |
| `POLY_API_KEY` | User's API `apiKey` value |
| `POLY_PASSPHRASE` | User's API `passphrase` value |
The `POLY_SIGNATURE` for L2 is an HMAC-SHA256 signature created using the user's API credentials `secret` value. Reference implementations can be found in the [TypeScript](https://github.com/Polymarket/clob-client-v2/blob/main/src/signing/hmac.ts) and [Python](https://github.com/Polymarket/py-clob-client-v2/blob/main/py_clob_client_v2/signing/hmac.py) clients.
### CLOB Client
<Tabs>
<Tab title="TypeScript">
```typescript theme={null}
import { ClobClient, Side } from "@polymarket/clob-client-v2";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const signer = createWalletClient({ account, transport: http() });
const depositWalletAddress = process.env.DEPOSIT_WALLET_ADDRESS!;
const client = new ClobClient({
host: "https://clob.polymarket.com",
chain: 137,
signer,
creds: apiCreds, // Generated from L1 auth, API credentials enable L2 methods
signatureType: 3, // POLY_1271, explained below
funderAddress: depositWalletAddress, // deposit wallet funder
});
// Now you can trade!
const order = await client.createAndPostOrder(
{ tokenID: "123456", price: 0.65, size: 100, side: Side.BUY },
{ tickSize: "0.01", negRisk: false }
);
```
</Tab>
<Tab title="Python">
```python theme={null}
from py_clob_client_v2 import ClobClient, OrderArgs, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
import os
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=os.getenv("PRIVATE_KEY"),
creds=api_creds, # Generated from L1 auth, API credentials enable L2 methods
signature_type=3, # POLY_1271, explained below
funder=os.getenv("DEPOSIT_WALLET_ADDRESS")
)
# Now you can trade!
order = client.create_and_post_order(
OrderArgs(token_id="123456", price=0.65, size=100, side=BUY),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
)
```
</Tab>
<Tab title="Rust">
```rust theme={null}
use polymarket_client_sdk_v2::clob::types::{Side, SignatureType};
use polymarket_client_sdk_v2::types::dec;
let deposit_wallet = std::env::var("DEPOSIT_WALLET_ADDRESS")?.parse()?;
let client = Client::new("https://clob.polymarket.com", Config::default())?
.authentication_builder(&signer)
.funder(deposit_wallet)
.signature_type(SignatureType::Poly1271)
.authenticate()
.await?;
// Now you can trade!
let order = client.limit_order()
.token_id("123456".parse()?)
.price(dec!(0.65))
.size(dec!(100))
.side(Side::Buy)
.build().await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</Tab>
</Tabs>
<Info>
Even with L2 authentication headers, methods that create user orders still
require the user to sign the order payload.
</Info>
***
## Signature Types and Funder
When initializing the L2 client, you must specify your wallet **signatureType** and the **funder** address which holds the funds:
| Signature Type | Value | Description |
| -------------- | ----- | -------------------------------------------------------------------------------------------------------------------------- |
| EOA | `0` | Standard Ethereum wallet (MetaMask). Funder is the EOA address and will need POL to pay gas on transactions. |
| POLY\_PROXY | `1` | Existing Polymarket proxy wallet flow, commonly used by users who logged in via Magic Link email/Google. |
| GNOSIS\_SAFE | `2` | Existing Gnosis Safe wallet flow. Existing Safe users can continue using this type. |
| POLY\_1271 | `3` | Deposit wallet flow for new API users. The funder is the deposit wallet address and orders are validated through ERC-1271. |
<Tip>
New API users should use deposit wallets with `POLY_1271`. Existing Safe and
Proxy users are unaffected and can keep using their current funder address and
signature type. See the [Deposit Wallet Guide](/trading/deposit-wallets) for
setup details.
</Tip>
***
## Security Best Practices
<AccordionGroup>
<Accordion title="Never expose private keys">
Store private keys in environment variables or secure key management systems. Never commit them to version control.
```bash theme={null}
# .env (never commit this file)
PRIVATE_KEY=0x...
```
</Accordion>
<Accordion title="Implement request signing on the server">
Never expose your API secret in client-side code. All authenticated requests should originate from your backend.
</Accordion>
</AccordionGroup>
***
## Troubleshooting
<AccordionGroup>
<Accordion title="Error - INVALID_SIGNATURE">
Your wallet's private key is incorrect or improperly formatted.
**Solutions:**
* Verify your private key is a valid hex string (starts with "0x")
* Ensure you're using the correct key for the intended address
* Check that the key has proper permissions
</Accordion>
<Accordion title="Error - NONCE_ALREADY_USED">
The nonce you provided has already been used to create an API key.
**Solutions:**
* Use `deriveApiKey()` with the same nonce to retrieve existing credentials
* Or use a different nonce with `createApiKey()`
</Accordion>
<Accordion title="Error - Invalid Funder Address">
Your funder address is incorrect or doesn't match your wallet.
**Solution:** Check your Polymarket profile address at [polymarket.com/settings](https://polymarket.com/settings).
If it does not exist or user has never logged into Polymarket.com, deploy it first before creating L2 authentication.
</Accordion>
<Accordion title="Lost both credentials and nonce">
Unfortunately, there's no way to recover lost API credentials without the nonce. You'll need to create new credentials:
```typescript theme={null}
// Create fresh credentials with a new nonce
const newCreds = await client.createApiKey();
// Save the nonce this time!
```
</Accordion>
</AccordionGroup>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Place Your First Order" icon="plus" href="/trading/quickstart">
Learn how to create and submit orders.
</Card>
<Card title="Geographic Restrictions" icon="globe" href="/api-reference/geoblock">
Check trading availability by region.
</Card>
</CardGroup>
-151
View File
@@ -1,151 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Resolution
> How markets are resolved and winning positions redeemed
When the outcome of an event becomes known, the market is **resolved**. Resolution determines which outcome won, allowing holders of winning tokens to redeem them for \$1 each. Losing tokens become worthless.
Polymarket uses the **UMA Optimistic Oracle** for decentralized, permissionless resolution. Anyone can propose an outcome, and anyone can dispute it if they believe it's incorrect.
<Frame>
<img src="https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/core-concepts/resolution-lifecycle.png?fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=6726569af3efd6f4fda54528c8eb0d0a" alt="" className="dark:hidden" width="1722" height="952" data-path="images/core-concepts/resolution-lifecycle.png" />
<img src="https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/dark/core-concepts/resolution-lifecycle.png?fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=36e91c655f7f50b18dea3a23b44f8c23" alt="" className="hidden dark:block" width="1722" height="952" data-path="images/dark/core-concepts/resolution-lifecycle.png" />
</Frame>
## Resolution Rules
Every market has pre-defined resolution rules that specify:
* **Resolution source** — Where the outcome will be determined from (e.g., official announcements, specific websites)
* **End date** — When the market is eligible for resolution
* **Edge cases** — How ambiguous situations should be handled
<Warning>
Always read the resolution rules before trading. The market title describes
the question, but the **rules** define how it resolves.
</Warning>
<Steps>
<Step title="Proposal">
Anyone can propose a resolution by:
1. Selecting the winning outcome
2. Posting a bond (typically \$750 pUSD)
3. Submitting the proposal to the UMA Oracle
If the proposal is correct and undisputed, the proposer receives their bond back plus a reward.
<Warning>
If you propose incorrectly or too early, you lose your entire bond. Only
propose if you're confident in the outcome and understand the process.
</Warning>
</Step>
<Step title="Challenge Period">
After a proposal, there's a **2-hour challenge period** where anyone can dispute the outcome.
* **If no dispute**: The proposal is accepted and the market resolves
* **If disputed**: A new proposal round begins. If the second proposal is also disputed, the resolution escalates to UMA's DVM (Data Verification Mechanism) for a token holder vote.
There are three possible resolution flows:
1. **No dispute** — Propose then Resolve (fastest, \~2 hours)
2. **One dispute** — Propose, Challenge, second Propose, Resolve (second proposal accepted)
3. **Two disputes** — Propose, Challenge, second Propose, second Challenge, Resolve via DVM vote
</Step>
<Step title="Dispute - If Challenged">
To dispute a proposal:
1. Post a counter-bond (same amount as proposer, typically \$750)
2. The dispute triggers a new proposal round, or if already in the second round, a debate period
During the **24-48 hour debate period**, evidence can be submitted in UMA's Discord channels (`#evidence-rationale` and `#voting-discussion`).
</Step>
<Step title="UMA Vote">
After the debate period, UMA token holders vote on the correct outcome. The voting process takes approximately 48 hours.
| Outcome | Result | Bond Distribution |
| ----------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| **Proposer wins** | Original proposal accepted | Proposer gets bond back + half of disputer's bond |
| **Disputer wins** | Proposal rejected, new proposal needed | Disputer gets bond back + half of proposer's bond |
| **Too Early** | Event hasn't concluded yet | Disputer gets bond back + half of proposer's bond |
| **Unknown/50-50** | Neither outcome applicable (rare) | Market resolves 50/50 — each token redeems for \$0.50; disputer gets bond back + half of proposer's bond |
</Step>
</Steps>
## After Resolution
Once a market resolves:
* **Trading stops** — You can no longer buy or sell tokens for this market
* **Winning tokens** become redeemable for \$1.00 each
* **Losing tokens** become worthless (\$0.00)
### Redeeming Tokens
After resolution, redeem through the CTF collateral adapter to exchange winning tokens for pUSD. The adapter burns your ERC1155 outcome tokens through the CTF contract, receives the released USDC.e collateral, wraps it into pUSD, and returns pUSD to your wallet.
```
100 winning tokens → $100 pUSD
```
## Clarifications
In rare cases, unforeseen circumstances require clarification of the rules after trading begins. Polymarket may issue an **"Additional context"** update that proposers and voters should consider during resolution.
Clarifications:
* Cannot change the fundamental intent of the question
* Are published onchain via the bulletin board contract
* Should be considered by UMA voters when resolving disputes
<Tip>
If you believe a clarification is needed, request it in the [Polymarket
Discord](https://discord.com/invite/polymarket) `#market-review` channel.
</Tip>
## Resolution Timeline
| Phase | Duration |
| --------------------------- | ----------- |
| Challenge period | 2 hours |
| Debate period (if disputed) | 24-48 hours |
| UMA voting (if disputed) | \~48 hours |
**Undisputed resolution**: \~2 hours after proposal
**Disputed resolution**: 4-6 days total
## Contract Addresses
| Contract | Address | Network |
| ---------------------- | -------------------------------------------- | --------------- |
| **UmaCtfAdapter v3.0** | `0x157Ce2d672854c848c9b79C49a8Cc6cc89176a49` | Polygon Mainnet |
| **UmaCtfAdapter v2.0** | `0x6A9D222616C90FcA5754cd1333cFD9b7fb6a4F74` | Polygon Mainnet |
| **UmaCtfAdapter v1.0** | `0xCB1822859cEF82Cd2Eb4E6276C7916e692995130` | Polygon Mainnet |
## Resources
* [UMA Oracle Portal](https://oracle.uma.xyz/) — View and interact with proposals
* [UMA Documentation](https://docs.uma.xyz/) — Learn more about the Optimistic Oracle
* [Polymarket Discord](https://discord.com/invite/polymarket) — Discuss resolutions and request clarifications
* [UmaCtfAdapter Source Code](https://github.com/Polymarket/uma-ctf-adapter) — Smart contract source
* [UmaCtfAdapter Audit](https://github.com/Polymarket/uma-ctf-adapter/blob/main/audit/Polymarket_UMA_Optimistic_Oracle_Adapter_Audit.pdf) — Security audit report
## Next Steps
<CardGroup cols={2}>
<Card title="Positions & Tokens" icon="coins" href="/concepts/positions-tokens">
Learn how to redeem winning tokens after resolution.
</Card>
<Card title="Markets & Events" icon="calendar" href="/concepts/markets-events">
Understand how markets are structured.
</Card>
</CardGroup>
@@ -1,222 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Sports WebSocket
> Live sports scores and game state
The Sports WebSocket provides real-time sports results updates, including scores, periods, and game status. No authentication required.
<Warning>
This feed is provided for informational purposes only. It may be delayed,
contain errors, or omit recent events. Polymarket does not provide trading or
investment advice, and this content should not be used as the basis for any
trading decision.
</Warning>
## Endpoint
```
wss://sports-api.polymarket.com/ws
```
No subscription message required — connect and start receiving data for all active sports events.
## Heartbeat
The server sends `ping` every 5 seconds. Respond with `pong` within 10 seconds or the connection will close.
```javascript theme={null}
ws.onmessage = (event) => {
if (event.data === "ping") {
ws.send("pong");
return;
}
// Handle JSON messages...
};
```
## Message Type
Each message is a JSON object with game state fields.
### sport\_result
Emitted when:
* A match goes live
* The score changes
* The period changes (e.g., halftime, overtime)
* A match ends
* Possession changes (NFL and CFB only)
**NFL (in progress):**
```json theme={null}
{
"gameId": 19439,
"leagueAbbreviation": "nfl",
"slug": "nfl-lac-buf-2025-01-26",
"homeTeam": "LAC",
"awayTeam": "BUF",
"status": "InProgress",
"score": "3-16",
"period": "Q4",
"elapsed": "5:18",
"live": true,
"ended": false,
"turn": "lac"
}
```
**Esports — CS2 (finished):**
```json theme={null}
{
"gameId": 1317359,
"leagueAbbreviation": "cs2",
"slug": "cs2-arcred-the-glecs-2025-07-20",
"homeTeam": "ARCRED",
"awayTeam": "The glecs",
"status": "finished",
"score": "000-000|2-0|Bo3",
"period": "2/3",
"live": false,
"ended": true,
"finished_timestamp": "2025-07-20T18:30:00.000Z"
}
```
The `finished_timestamp` field is an ISO 8601 timestamp only present when `ended: true`.
The `slug` field follows the format `{league}-{team1}-{team2}-{date}` (e.g., `nfl-buf-kc-2025-01-26`).
## Period Values
| Period | Description |
| ---------------------- | --------------------------------------- |
| `1H` | First half |
| `2H` | Second half |
| `1Q`, `2Q`, `3Q`, `4Q` | Quarters (NFL, NBA) |
| `HT` | Halftime |
| `FT` | Full time (match ended in regulation) |
| `FT OT` | Full time with overtime |
| `FT NR` | Full time, no result (draw or canceled) |
| `End 1`, `End 2`, ... | End of inning (MLB) |
| `1/3`, `2/3`, `3/3` | Map number in Bo3 series (Esports) |
| `1/5`, `2/5`, ... | Map number in Bo5 series (Esports) |
## Game Status Values
Game status values vary by sport:
### NFL
| Status | Description |
| -------------- | ---------------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed in regulation |
| `F/OT` | Final after overtime |
| `Suspended` | Game suspended |
| `Postponed` | Game postponed |
| `Delayed` | Game delayed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
| `NotNecessary` | Scheduled, but not needed |
### NHL
| Status | Description |
| -------------- | ---------------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed in regulation |
| `F/OT` | Final after overtime |
| `F/SO` | Final after shootout |
| `Suspended` | Game suspended |
| `Postponed` | Game postponed |
| `Delayed` | Game delayed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
| `NotNecessary` | Scheduled, but not needed |
### MLB
| Status | Description |
| -------------- | ------------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed |
| `Suspended` | Game suspended |
| `Delayed` | Game delayed |
| `Postponed` | Game postponed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
| `NotNecessary` | Scheduled, but not needed |
### NBA and CBB
| Status | Description |
| -------------- | ------------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed |
| `F/OT` | Final after overtime |
| `Suspended` | Game suspended |
| `Postponed` | Game postponed |
| `Delayed` | Game delayed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
| `NotNecessary` | Scheduled, but not needed |
### CFB
| Status | Description |
| ------------ | ---------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed |
| `F/OT` | Final after overtime |
| `Suspended` | Game suspended |
| `Postponed` | Game postponed |
| `Delayed` | Game delayed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
### Soccer
| Status | Description |
| ----------------- | ------------------------------------ |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Break` | Halftime or other break |
| `Suspended` | Game suspended |
| `PenaltyShootout` | Penalty shootout in progress |
| `Final` | Game completed |
| `Awarded` | Result awarded due to ruling/forfeit |
| `Postponed` | Game postponed |
| `Canceled` | Game canceled |
### Esports
| Status | Description |
| ------------- | ----------------------- |
| `not_started` | Match not yet started |
| `running` | Match currently playing |
| `finished` | Match completed |
| `postponed` | Match postponed |
| `canceled` | Match canceled |
### Tennis
| Status | Description |
| ------------ | ----------------------- |
| `scheduled` | Match not yet started |
| `inprogress` | Match currently playing |
| `suspended` | Match suspended |
| `finished` | Match completed |
| `postponed` | Match postponed |
| `cancelled` | Match canceled |
@@ -1,222 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Sports WebSocket
> Live sports scores and game state
The Sports WebSocket provides real-time sports results updates, including scores, periods, and game status. No authentication required.
<Warning>
This feed is provided for informational purposes only. It may be delayed,
contain errors, or omit recent events. Polymarket does not provide trading or
investment advice, and this content should not be used as the basis for any
trading decision.
</Warning>
## Endpoint
```
wss://sports-api.polymarket.com/ws
```
No subscription message required — connect and start receiving data for all active sports events.
## Heartbeat
The server sends `ping` every 5 seconds. Respond with `pong` within 10 seconds or the connection will close.
```javascript theme={null}
ws.onmessage = (event) => {
if (event.data === "ping") {
ws.send("pong");
return;
}
// Handle JSON messages...
};
```
## Message Type
Each message is a JSON object with game state fields.
### sport\_result
Emitted when:
* A match goes live
* The score changes
* The period changes (e.g., halftime, overtime)
* A match ends
* Possession changes (NFL and CFB only)
**NFL (in progress):**
```json theme={null}
{
"gameId": 19439,
"leagueAbbreviation": "nfl",
"slug": "nfl-lac-buf-2025-01-26",
"homeTeam": "LAC",
"awayTeam": "BUF",
"status": "InProgress",
"score": "3-16",
"period": "Q4",
"elapsed": "5:18",
"live": true,
"ended": false,
"turn": "lac"
}
```
**Esports — CS2 (finished):**
```json theme={null}
{
"gameId": 1317359,
"leagueAbbreviation": "cs2",
"slug": "cs2-arcred-the-glecs-2025-07-20",
"homeTeam": "ARCRED",
"awayTeam": "The glecs",
"status": "finished",
"score": "000-000|2-0|Bo3",
"period": "2/3",
"live": false,
"ended": true,
"finished_timestamp": "2025-07-20T18:30:00.000Z"
}
```
The `finished_timestamp` field is an ISO 8601 timestamp only present when `ended: true`.
The `slug` field follows the format `{league}-{team1}-{team2}-{date}` (e.g., `nfl-buf-kc-2025-01-26`).
## Period Values
| Period | Description |
| ---------------------- | --------------------------------------- |
| `1H` | First half |
| `2H` | Second half |
| `1Q`, `2Q`, `3Q`, `4Q` | Quarters (NFL, NBA) |
| `HT` | Halftime |
| `FT` | Full time (match ended in regulation) |
| `FT OT` | Full time with overtime |
| `FT NR` | Full time, no result (draw or canceled) |
| `End 1`, `End 2`, ... | End of inning (MLB) |
| `1/3`, `2/3`, `3/3` | Map number in Bo3 series (Esports) |
| `1/5`, `2/5`, ... | Map number in Bo5 series (Esports) |
## Game Status Values
Game status values vary by sport:
### NFL
| Status | Description |
| -------------- | ---------------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed in regulation |
| `F/OT` | Final after overtime |
| `Suspended` | Game suspended |
| `Postponed` | Game postponed |
| `Delayed` | Game delayed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
| `NotNecessary` | Scheduled, but not needed |
### NHL
| Status | Description |
| -------------- | ---------------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed in regulation |
| `F/OT` | Final after overtime |
| `F/SO` | Final after shootout |
| `Suspended` | Game suspended |
| `Postponed` | Game postponed |
| `Delayed` | Game delayed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
| `NotNecessary` | Scheduled, but not needed |
### MLB
| Status | Description |
| -------------- | ------------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed |
| `Suspended` | Game suspended |
| `Delayed` | Game delayed |
| `Postponed` | Game postponed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
| `NotNecessary` | Scheduled, but not needed |
### NBA and CBB
| Status | Description |
| -------------- | ------------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed |
| `F/OT` | Final after overtime |
| `Suspended` | Game suspended |
| `Postponed` | Game postponed |
| `Delayed` | Game delayed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
| `NotNecessary` | Scheduled, but not needed |
### CFB
| Status | Description |
| ------------ | ---------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed |
| `F/OT` | Final after overtime |
| `Suspended` | Game suspended |
| `Postponed` | Game postponed |
| `Delayed` | Game delayed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
### Soccer
| Status | Description |
| ----------------- | ------------------------------------ |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Break` | Halftime or other break |
| `Suspended` | Game suspended |
| `PenaltyShootout` | Penalty shootout in progress |
| `Final` | Game completed |
| `Awarded` | Result awarded due to ruling/forfeit |
| `Postponed` | Game postponed |
| `Canceled` | Game canceled |
### Esports
| Status | Description |
| ------------- | ----------------------- |
| `not_started` | Match not yet started |
| `running` | Match currently playing |
| `finished` | Match completed |
| `postponed` | Match postponed |
| `canceled` | Match canceled |
### Tennis
| Status | Description |
| ------------ | ----------------------- |
| `scheduled` | Match not yet started |
| `inprogress` | Match currently playing |
| `suspended` | Match suspended |
| `finished` | Match completed |
| `postponed` | Match postponed |
| `cancelled` | Match canceled |
@@ -1,222 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Sports WebSocket
> Live sports scores and game state
The Sports WebSocket provides real-time sports results updates, including scores, periods, and game status. No authentication required.
<Warning>
This feed is provided for informational purposes only. It may be delayed,
contain errors, or omit recent events. Polymarket does not provide trading or
investment advice, and this content should not be used as the basis for any
trading decision.
</Warning>
## Endpoint
```
wss://sports-api.polymarket.com/ws
```
No subscription message required — connect and start receiving data for all active sports events.
## Heartbeat
The server sends `ping` every 5 seconds. Respond with `pong` within 10 seconds or the connection will close.
```javascript theme={null}
ws.onmessage = (event) => {
if (event.data === "ping") {
ws.send("pong");
return;
}
// Handle JSON messages...
};
```
## Message Type
Each message is a JSON object with game state fields.
### sport\_result
Emitted when:
* A match goes live
* The score changes
* The period changes (e.g., halftime, overtime)
* A match ends
* Possession changes (NFL and CFB only)
**NFL (in progress):**
```json theme={null}
{
"gameId": 19439,
"leagueAbbreviation": "nfl",
"slug": "nfl-lac-buf-2025-01-26",
"homeTeam": "LAC",
"awayTeam": "BUF",
"status": "InProgress",
"score": "3-16",
"period": "Q4",
"elapsed": "5:18",
"live": true,
"ended": false,
"turn": "lac"
}
```
**Esports — CS2 (finished):**
```json theme={null}
{
"gameId": 1317359,
"leagueAbbreviation": "cs2",
"slug": "cs2-arcred-the-glecs-2025-07-20",
"homeTeam": "ARCRED",
"awayTeam": "The glecs",
"status": "finished",
"score": "000-000|2-0|Bo3",
"period": "2/3",
"live": false,
"ended": true,
"finished_timestamp": "2025-07-20T18:30:00.000Z"
}
```
The `finished_timestamp` field is an ISO 8601 timestamp only present when `ended: true`.
The `slug` field follows the format `{league}-{team1}-{team2}-{date}` (e.g., `nfl-buf-kc-2025-01-26`).
## Period Values
| Period | Description |
| ---------------------- | --------------------------------------- |
| `1H` | First half |
| `2H` | Second half |
| `1Q`, `2Q`, `3Q`, `4Q` | Quarters (NFL, NBA) |
| `HT` | Halftime |
| `FT` | Full time (match ended in regulation) |
| `FT OT` | Full time with overtime |
| `FT NR` | Full time, no result (draw or canceled) |
| `End 1`, `End 2`, ... | End of inning (MLB) |
| `1/3`, `2/3`, `3/3` | Map number in Bo3 series (Esports) |
| `1/5`, `2/5`, ... | Map number in Bo5 series (Esports) |
## Game Status Values
Game status values vary by sport:
### NFL
| Status | Description |
| -------------- | ---------------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed in regulation |
| `F/OT` | Final after overtime |
| `Suspended` | Game suspended |
| `Postponed` | Game postponed |
| `Delayed` | Game delayed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
| `NotNecessary` | Scheduled, but not needed |
### NHL
| Status | Description |
| -------------- | ---------------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed in regulation |
| `F/OT` | Final after overtime |
| `F/SO` | Final after shootout |
| `Suspended` | Game suspended |
| `Postponed` | Game postponed |
| `Delayed` | Game delayed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
| `NotNecessary` | Scheduled, but not needed |
### MLB
| Status | Description |
| -------------- | ------------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed |
| `Suspended` | Game suspended |
| `Delayed` | Game delayed |
| `Postponed` | Game postponed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
| `NotNecessary` | Scheduled, but not needed |
### NBA and CBB
| Status | Description |
| -------------- | ------------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed |
| `F/OT` | Final after overtime |
| `Suspended` | Game suspended |
| `Postponed` | Game postponed |
| `Delayed` | Game delayed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
| `NotNecessary` | Scheduled, but not needed |
### CFB
| Status | Description |
| ------------ | ---------------------- |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Final` | Game completed |
| `F/OT` | Final after overtime |
| `Suspended` | Game suspended |
| `Postponed` | Game postponed |
| `Delayed` | Game delayed |
| `Canceled` | Game canceled |
| `Forfeit` | Game forfeited |
### Soccer
| Status | Description |
| ----------------- | ------------------------------------ |
| `Scheduled` | Game not yet started |
| `InProgress` | Game currently playing |
| `Break` | Halftime or other break |
| `Suspended` | Game suspended |
| `PenaltyShootout` | Penalty shootout in progress |
| `Final` | Game completed |
| `Awarded` | Result awarded due to ruling/forfeit |
| `Postponed` | Game postponed |
| `Canceled` | Game canceled |
### Esports
| Status | Description |
| ------------- | ----------------------- |
| `not_started` | Match not yet started |
| `running` | Match currently playing |
| `finished` | Match completed |
| `postponed` | Match postponed |
| `canceled` | Match canceled |
### Tennis
| Status | Description |
| ------------ | ----------------------- |
| `scheduled` | Match not yet started |
| `inprogress` | Match currently playing |
| `suspended` | Match suspended |
| `finished` | Match completed |
| `postponed` | Match postponed |
| `cancelled` | Match canceled |
+1 -1
View File
@@ -1 +1 @@
null
null
+1 -1
View File
@@ -1 +1 @@
null
null
+14 -199
View File
@@ -16,16 +16,6 @@ The program is designed to:
* Encourage trading activity
* Discourage blatantly exploitative behaviors
<Info>
This program is heavily inspired by [dYdX's liquidity provider
rewards](https://www.dydx.foundation/blog/liquidity-provider-rewards). The
methodology is essentially a copy of dYdX's approach with adjustments for
binary contract markets — distinct books, no staking mechanic, a modified
order utility-relative depth function, and reward amounts isolated per market.
</Info>
***
<Note>
The minimum reward payout is **\$1**; amounts below this will not be paid.
</Note>
@@ -155,202 +145,27 @@ Q<sub>no</sub> is calculated every minute using random sampling.
***
## April 2026 — Liquidity Incentive Program
## World Cup 2026 — Liquidity Incentive Program
Polymarket is distributing over **\$5M** in liquidity incentives for April 2026 across sports and esports markets. The reward pool is split into **Pre** (pre-game) and **Live** (in-play) periods per game. Rewards are distributed pro-rata across all eligible markets within each game.
Polymarket is distributing liquidity incentives for World Cup 2026 markets from June 11 through July 19, 2026. Rewards are split into **Pre** (pre-game) and **Live** (in-play) periods per game.
<Note>
This covers April 2026 sports markets. Additional categories will be added soon.
The values below are configured reward caps. Actual payouts depend on eligible
quoting and the reward methodology above.
</Note>
### Soccer — Top 5 Leagues + UEFA
### Stage Pools
Every game in these leagues has liquidity rewards split across pre-game and live periods.
| League | Pre \$/Game | Live \$/Game | Total \$/Game |
| ----------------------- | ----------- | ------------ | ------------- |
| English Premier League | \$2,800 | \$7,200 | \$10,000 |
| La Liga | \$900 | \$2,400 | \$3,300 |
| Serie A | \$900 | \$2,400 | \$3,300 |
| Bundesliga | \$850 | \$2,150 | \$3,000 |
| Ligue 1 | \$600 | \$1,500 | \$2,100 |
| Champions League (QFs) | \$6,750 | \$17,250 | \$24,000 |
| Europa League (QFs) | \$1,350 | \$3,400 | \$4,750 |
| Conference League (QFs) | \$400 | \$1,100 | \$1,500 |
### Soccer — Americas
| League | Pre \$/Game | Live \$/Game | Total \$/Game |
| -------------------------- | ----------- | ------------ | ------------- |
| MLS | \$450 | \$1,200 | \$1,650 |
| Liga MX | \$450 | \$1,200 | \$1,650 |
| Copa Libertadores (Groups) | \$750 | \$1,900 | \$2,650 |
| Copa Sudamericana (Groups) | \$225 | \$575 | \$800 |
| Argentine Primera Division | \$150 | \$400 | \$550 |
| Brasileirao Serie A | \$150 | \$400 | \$550 |
| Colombian Primera A | \$100 | \$200 | \$300 |
| Chilean Primera Division | \$75 | \$175 | \$250 |
| Peruvian Primera Division | \$75 | \$175 | \$250 |
| Bolivian Primera | \$25 | \$50 | \$75 |
| Brasileirao Serie B | \$25 | \$50 | \$75 |
### Soccer — Other Europe
| League | Pre \$/Game | Live \$/Game | Total \$/Game |
| ------------------------ | ----------- | ------------ | ------------- |
| Turkish Super Lig | \$550 | \$1,450 | \$2,000 |
| Eredivisie | \$250 | \$650 | \$900 |
| Liga Portugal | \$200 | \$550 | \$750 |
| EFL Championship | \$150 | \$350 | \$500 |
| Russian Premier League | \$100 | \$275 | \$375 |
| Danish Superliga | \$75 | \$150 | \$225 |
| Czech First League | \$25 | \$75 | \$100 |
| Romanian Liga I | \$25 | \$75 | \$100 |
| Ukrainian Premier League | \$25 | \$75 | \$100 |
### Soccer — Asia / Middle East / Africa
| League | Pre \$/Game | Live \$/Game | Total \$/Game |
| ----------------------- | ----------- | ------------ | ------------- |
| Saudi Pro League | \$450 | \$1,200 | \$1,650 |
| J1 League (Japan) | \$300 | \$800 | \$1,100 |
| K League 1 (Korea) | \$200 | \$550 | \$750 |
| Chinese Super League | \$100 | \$250 | \$350 |
| A-League (Australia) | \$100 | \$250 | \$350 |
| Indian Super League | \$75 | \$175 | \$250 |
| J2 League (Japan) | \$25 | \$75 | \$100 |
| Egyptian Premier League | \$25 | \$75 | \$100 |
| Moroccan League | \$25 | \$75 | \$100 |
| Norwegian Eliteserien | \$25 | \$75 | \$100 |
### Soccer — Domestic Cups
| League | Pre \$/Game | Live \$/Game | Total \$/Game |
| ----------------------------- | ----------- | ------------ | ------------- |
| FA Cup (Semi-Finals) | \$850 | \$2,000 | \$2,850 |
| DFB-Pokal (Semi-Finals) | \$450 | \$950 | \$1,400 |
| Coppa Italia (Semi-Finals) | \$450 | \$950 | \$1,400 |
| Coupe de France (Semi-Finals) | \$275 | \$675 | \$950 |
### Esports — CS2
| Tier | Pre \$/Game | Live \$/Game | Total \$/Game |
| ----------------------------------- | ----------- | ------------ | ------------- |
| A Tier (ESL Pro League, BLAST) | \$1,550 | \$3,950 | \$5,500 |
| B Tier (RMRs, Large Regional) | \$1,550 | \$3,950 | \$5,500 |
| C Tier (Small Regional, Qualifiers) | \$150 | \$350 | \$500 |
### Esports — League of Legends
| Tier | Pre \$/Game | Live \$/Game | Total \$/Game |
| ------------------------------- | ----------- | ------------ | ------------- |
| A Tier (LCK, LPL, LEC Playoffs) | \$1,550 | \$3,950 | \$5,500 |
| B Tier (LCS, Other Regional) | \$1,550 | \$3,950 | \$5,500 |
| C Tier (ERLs, National Leagues) | \$150 | \$350 | \$500 |
### Esports — Dota 2
| Tier | Pre \$/Game | Live \$/Game | Total \$/Game |
| -------------------------- | ----------- | ------------ | ------------- |
| A/B Tier (DPC, Qualifiers) | \$1,000 | \$2,500 | \$3,500 |
| C Tier (Regional) | \$150 | \$350 | \$500 |
### Esports — Valorant
| Tier | Pre \$/Game | Live \$/Game | Total \$/Game |
| Stage | Pre \$/Game | Live \$/Game | Total \$/Game |
| --------------------- | ----------- | ------------ | ------------- |
| A/B Tier (VCT Stages) | \$1,000 | \$2,500 | \$3,500 |
| C Tier (Regional) | \$150 | \$350 | \$500 |
### Esports — Other Titles
| Game | Pre \$/Game | Live \$/Game | Total \$/Game |
| ------------------------- | ----------- | ------------ | ------------- |
| Call of Duty (CDL) | \$50 | \$100 | \$150 |
| Rocket League (RLCS) | \$50 | \$100 | \$150 |
| Mobile Legends: Bang Bang | \$50 | \$100 | \$150 |
| Honor of Kings | \$50 | \$100 | \$150 |
### Basketball
| League | Pre \$/Game | Live \$/Game | Total \$/Game |
| ------------------------------------- | ----------- | ------------ | ------------- |
| NBA (Reg Season + Play-In + Playoffs) | \$2,150 | \$5,550 | \$7,700 |
| EuroLeague (Playoffs) | \$150 | \$350 | \$500 |
| ACB Spain | \$75 | \$200 | \$275 |
| Lega Basket Serie A (Italy) | \$75 | \$200 | \$275 |
| Basketball Champions League | \$75 | \$200 | \$275 |
| CBA (China) | \$50 | \$150 | \$200 |
| LNB Pro A (France) | \$50 | \$150 | \$200 |
| KBL (Korea) | \$25 | \$50 | \$75 |
| NBL (Australia) | \$25 | \$50 | \$75 |
| B.League (Japan) | \$25 | \$50 | \$75 |
| BBL (Germany) | \$25 | \$50 | \$75 |
| ABA League | \$25 | \$50 | \$75 |
| BSL (Turkey) | \$25 | \$50 | \$75 |
| Greek A1 | \$25 | \$50 | \$75 |
| LNB Argentina | \$0 | \$25 | \$25 |
| VTB United League | \$0 | \$25 | \$25 |
### Baseball
| League | Pre \$/Game | Live \$/Game | Total \$/Game |
| ----------- | ----------- | ------------ | ------------- |
| MLB | \$465 | \$1,185 | \$1,650 |
| KBO (Korea) | \$75 | \$225 | \$300 |
### Hockey
| League | Pre \$/Game | Live \$/Game | Total \$/Game |
| --------------------------- | ----------- | ------------ | ------------- |
| NHL (Reg Season + Playoffs) | \$400 | \$1,100 | \$1,500 |
| KHL (Playoffs) | \$75 | \$200 | \$275 |
| SHL (Playoffs) | \$25 | \$150 | \$175 |
| AHL | \$0 | \$25 | \$25 |
| Czech Extraliga (Playoffs) | \$0 | \$25 | \$25 |
| DEL Germany (Playoffs) | \$0 | \$25 | \$25 |
### Tennis
| Tour | Pre \$/Game | Live \$/Game | Total \$/Game |
| -------- | ----------- | ------------ | ------------- |
| ATP Tour | \$450 | \$1,000 | \$1,450 |
| WTA Tour | \$300 | \$750 | \$1,050 |
### UFC / MMA
| Event Type | Pre \$/Game | Live \$/Game | Total \$/Game |
| ------------- | ----------- | ------------ | ------------- |
| UFC Main Card | \$1,200 | \$3,050 | \$4,250 |
| UFC Prelims | \$250 | \$700 | \$950 |
### Cricket
| League | Pre \$/Game | Live \$/Game | Total \$/Game |
| ---------------------------- | ----------- | ------------ | ------------- |
| IPL (Indian Premier League) | \$1,250 | \$3,250 | \$4,500 |
| ICC ODI Internationals | \$0 | \$50 | \$50 |
| ICC T20 Internationals | \$0 | \$50 | \$50 |
| Other Cricket Internationals | \$0 | \$25 | \$25 |
| Test Cricket | \$0 | \$25 | \$25 |
### Rugby
| League | Pre \$/Game | Live \$/Game | Total \$/Game |
| ---------------------------- | ----------- | ------------ | ------------- |
| Top 14 (France) | \$75 | \$175 | \$250 |
| Premiership Rugby (England) | \$75 | \$175 | \$250 |
| Super Rugby Pacific | \$75 | \$175 | \$250 |
| United Rugby Championship | \$50 | \$125 | \$175 |
| European Champions Cup (QFs) | \$100 | \$300 | \$400 |
### Other
| Event | Pre \$/Game | Live \$/Game | Total \$/Game |
| ---------------- | ----------- | ------------ | ------------- |
| WTT Table Tennis | \$0 | \$25 | \$25 |
| Chess | \$25 | \$75 | \$100 |
| PLL Lacrosse | \$25 | \$75 | \$100 |
| Group Stage | \$2,139 | \$3,971 | \$6,110 |
| Group Stage — Marquee | \$3,754 | \$6,971 | \$10,725 |
| Round of 32 | \$4,778 | \$8,872 | \$13,650 |
| Round of 16 | \$6,370 | \$11,830 | \$18,200 |
| Quarterfinals | \$9,442 | \$17,533 | \$26,975 |
| Semifinals | \$13,423 | \$24,927 | \$38,350 |
| Third Place | \$5,460 | \$10,140 | \$15,600 |
| Final | \$18,200 | \$33,800 | \$52,000 |
***
+7 -7
View File
@@ -4,9 +4,9 @@
# Maker Rebates Program
> Earn daily USDC rebates by providing liquidity on Polymarket
> Earn daily pUSD rebates by providing liquidity on Polymarket
Polymarket charges taker fees across multiple market categories. Fees are determined by the protocol at match time and fund a **Maker Rebates** program that pays daily USDC rebates to liquidity providers.
Polymarket charges taker fees across multiple market categories. Fees are determined by the protocol at match time and fund a **Maker Rebates** program that pays daily pUSD rebates to liquidity providers.
***
@@ -18,7 +18,7 @@ Deeper liquidity means tighter spreads, lower price impact, more reliable fills,
## How Maker Rebates Work
* **Paid daily in USDC:** Rebates are calculated and distributed every day.
* **Paid daily in pUSD:** Rebates are calculated and distributed every day.
* **Performance-based:** You earn based on the share of liquidity you provided that actually got taken.
### Eligibility
@@ -27,7 +27,7 @@ Place orders that add liquidity to the book and get filled (i.e., your liquidity
### Payment
Rebates are paid daily in USDC, directly to your wallet. A minimum accrued rebate of **\$1 USDC** is required for a payout.
Rebates are paid daily in pUSD, directly to your wallet. A minimum accrued rebate of **\$1 pUSD** is required for a payout.
***
@@ -95,7 +95,7 @@ Totals are calculated per market, so you only compete with other makers in the s
## Taker Fee Structure
Taker fees are calculated in USDC and vary based on the share price. The fee amount in USDC is symmetric around 50% probability — a trade at 30¢ incurs the same dollar fee as a trade at 70¢.
Taker fees are calculated in pUSD and vary based on the share price. The fee amount in pUSD is symmetric around 50% probability — a trade at 30¢ incurs the same dollar fee as a trade at 70¢.
<Frame>
<div className="p-3 bg-white rounded-xl">
@@ -109,7 +109,7 @@ For detailed fee tables for each market category, see the [Fees](/trading/fees)
### Fee Precision
Fees are rounded to 5 decimal places. The smallest fee charged is 0.00001 USDC. Anything smaller rounds to zero, so very small trades near the extremes may incur no fee at all.
Fees are rounded to 5 decimal places. The smallest fee charged is 0.00001 pUSD. Anything smaller rounds to zero, so very small trades near the extremes may incur no fee at all.
***
@@ -132,7 +132,7 @@ The following market categories have taker fees enabled and are eligible for mak
liquidity is taken by another trader).
</Accordion>
<Accordion title="When are rebates paid">Daily, in USDC. You must accrue at least \$1 in rebates before a payout is issued.</Accordion>
<Accordion title="When are rebates paid">Daily, in pUSD. You must accrue at least \$1 in rebates before a payout is issued.</Accordion>
<Accordion title="How are rebates calculated">
Rebates are proportional to your share of executed maker liquidity in each
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-217
View File
@@ -1,217 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Geographic Restrictions
> Check geographic restrictions before placing orders on the Polymarket API
Polymarket restricts order placement from certain geographic locations due to regulatory requirements and compliance with international sanctions. Before placing orders, builders should verify the location.
<Warning>
Orders submitted from blocked regions will be rejected. Implement geoblock
checks in your application to provide users with appropriate feedback before
they attempt to trade.
</Warning>
***
## Geoblock Endpoint
Check the geographic eligibility of the requesting IP address:
```bash theme={null}
GET https://polymarket.com/api/geoblock
```
<Note>This endpoint is on `polymarket.com`, not the API servers.</Note>
### Response
```json theme={null}
{
"blocked": true,
"ip": "203.0.113.42",
"country": "US",
"region": "NY"
}
```
| Field | Type | Description |
| --------- | ------- | ----------------------------------------------- |
| `blocked` | boolean | Whether the user is blocked from placing orders |
| `ip` | string | Detected IP address |
| `country` | string | ISO 3166-1 alpha-2 country code |
| `region` | string | Region/state code |
***
## Blocked Countries
The following countries are restricted from placing orders on Polymarket. Countries marked as **close-only** can close existing positions but cannot open new ones. Countries marked as **frontend UI restricted** are blocked only on the Polymarket frontend; the API itself is not restricted:
| Country Code | Country Name | Status |
| ------------ | ------------------------------------ | ---------------------- |
| AU | Australia | Blocked |
| BE | Belgium | Blocked |
| BY | Belarus | Blocked |
| BI | Burundi | Blocked |
| CF | Central African Republic | Blocked |
| CD | Congo (Kinshasa) | Blocked |
| CU | Cuba | Blocked |
| DE | Germany | Blocked |
| ET | Ethiopia | Blocked |
| FR | France | Blocked |
| GB | United Kingdom | Blocked |
| IR | Iran | Blocked |
| IQ | Iraq | Blocked |
| IT | Italy | Blocked |
| JP | Japan | Frontend UI restricted |
| KP | North Korea | Blocked |
| LB | Lebanon | Blocked |
| LY | Libya | Blocked |
| MM | Myanmar | Blocked |
| NI | Nicaragua | Blocked |
| NL | Netherlands | Blocked |
| PL | Poland | Close-only |
| RU | Russia | Blocked |
| SG | Singapore | Close-only |
| SO | Somalia | Blocked |
| SS | South Sudan | Blocked |
| SD | Sudan | Blocked |
| SY | Syria | Blocked |
| TH | Thailand | Close-only |
| TW | Taiwan | Close-only |
| UM | United States Minor Outlying Islands | Blocked |
| US | United States | Blocked |
| VE | Venezuela | Blocked |
| YE | Yemen | Blocked |
| ZW | Zimbabwe | Blocked |
***
## Blocked Regions
In addition to fully blocked countries, the following specific regions within otherwise accessible countries are also restricted:
| Country | Region | Region Code |
| ------------ | ------- | ----------- |
| Canada (CA) | Ontario | ON |
| Ukraine (UA) | Crimea | 43 |
| Ukraine (UA) | Donetsk | 14 |
| Ukraine (UA) | Luhansk | 09 |
***
## Blocking Logic
The geoblocking system includes:
1. **OFAC-Sanctioned Countries**: Countries sanctioned by the U.S. Office of Foreign Assets Control (OFAC)
2. **Additional Regulatory Restrictions**: Countries added for specific regulatory compliance reasons
***
## Server Infrastructure
* **Primary Servers**: eu-west-2
* **Closest Non-Georestricted Region**: eu-west-1
<Tip>
**Direct co-location available.** Users who complete the [KYC/KYB
form](https://docs.google.com/forms/d/e/1FAIpQLSfY-3Dl3yxq8HKFjFad8YzKZmm0k3Gdg29HD6gL-K-AmI6KXw/viewform) can get access to co-locate
directly in `eu-west-2` for the lowest possible latency to Polymarket's
primary servers.
</Tip>
***
## Usage Examples
<Tabs>
<Tab title="TypeScript">
```typescript theme={null}
interface GeoblockResponse {
blocked: boolean;
ip: string;
country: string;
region: string;
}
async function checkGeoblock(): Promise<GeoblockResponse> {
const response = await fetch("https://polymarket.com/api/geoblock");
return response.json();
}
// Usage
const geo = await checkGeoblock();
if (geo.blocked) {
console.log(`Trading not available in ${geo.country}`);
} else {
console.log("Trading available");
}
```
</Tab>
<Tab title="Python">
```python theme={null}
import requests
def check_geoblock() -> dict:
response = requests.get("https://polymarket.com/api/geoblock")
return response.json()
# Usage
geo = check_geoblock()
if geo["blocked"]:
print(f"Trading not available in {geo['country']}")
else:
print("Trading available")
```
</Tab>
<Tab title="Rust">
```rust theme={null}
use polymarket_client_sdk_v2::clob::{Client, Config};
let client = Client::new("https://clob.polymarket.com", Config::default())?;
let geo = client.check_geoblock().await?;
if geo.blocked {
println!("Trading not available in {}", geo.country);
} else {
println!("Trading available");
}
```
</Tab>
</Tabs>
***
## Why These Restrictions
Geographic restrictions are implemented to ensure compliance with:
* International sanctions and embargoes
* Local financial regulations
* Gambling and prediction market laws
* Anti-money laundering (AML) requirements
* Know Your Customer (KYC) regulations
If you believe you are incorrectly restricted or have questions about geographic availability, please contact [Polymarket Support](https://polymarket.com/support).
***
## Next Steps
<CardGroup cols={2}>
<Card title="Authentication" icon="key" href="/api-reference/authentication">
Learn how to authenticate trading requests.
</Card>
<Card title="Place Orders" icon="plus" href="/trading/quickstart">
Start placing orders (from eligible regions).
</Card>
</CardGroup>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,104 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Deposit
> Bridge assets from any supported chain to fund your Polymarket account
Polymarket uses **pUSD** (Polymarket USD) on Polygon as collateral for all trading. The Bridge API lets you deposit assets from Ethereum, Solana, Bitcoin, and other chains—they're automatically converted to pUSD on Polygon.
## How It Works
1. Request bridge addresses for your Polymarket wallet
2. Send assets to the appropriate address for your source chain
3. Assets are bridged and swapped to pUSD automatically
4. pUSD is credited to your wallet for trading
## Create Bridge Addresses
Generate unique bridge addresses linked to your Polymarket wallet. See the [Bridge API Reference](/api-reference/introduction) for full request and response schemas.
```bash theme={null}
curl -X POST https://bridge.polymarket.com/deposit \
-H "Content-Type: application/json" \
-d '{"address": "0x56687bf447db6ffa42ffe2204a05edaa20f55839"}'
```
### Address Types
| Address | Use For |
| ------- | -------------------------------------------------------- |
| `evm` | Ethereum, Arbitrum, Base, Optimism, and other EVM chains |
| `svm` | Solana |
| `btc` | Bitcoin |
| `tvm` | Tron |
<Warning>
Each address is unique to your wallet. Only send assets from supported chains
to the correct address type.
</Warning>
## Deposit Flow
<Steps>
<Step title="Get Your Bridge Address">
Call `POST /deposit` with your Polymarket wallet address to get bridge
addresses.
</Step>
<Step title="Check Supported Assets">
Verify your token is supported and meets the minimum deposit amount via
`/supported-assets`.
</Step>
<Step title="Send Assets">
Transfer tokens to the appropriate bridge address from your source chain.
</Step>
<Step title="Track Status">
Monitor your deposit progress using `/status/{address}`.
</Step>
</Steps>
## USDC vs pUSD
You can deposit either USDC (native) or USDC.e (bridged) as the source asset to your Polymarket wallet. Either way, the incoming USDC or USDC.e is wrapped into pUSD via the Collateral Onramp, and pUSD is what you hold and trade with on Polymarket.
## Large Deposits
For deposits over \$50,000 originating from a chain other than Polygon, we recommend using a third-party bridge to minimize slippage:
* [DeBridge](https://app.debridge.finance/)
* [Across](https://app.across.to/bridge)
* [Portal](https://portalbridge.com/)
Bridge directly to your Polymarket USDC (Polygon) bridge address. Polymarket is not affiliated with or responsible for any third-party bridge.
## Minimum Deposits
Each asset has a minimum deposit amount. Deposits below the minimum will not be processed. Check `/supported-assets` for current minimums.
## Deposit Recovery
If you deposited the wrong token, use this tool to recover your funds:
[recovery.polymarket.com](https://recovery.polymarket.com/)
<Warning>
Sending unsupported tokens may cause **irrecoverable loss**. Always verify
your token is listed in [Supported Assets](/trading/bridge/supported-assets)
before depositing.
</Warning>
## Next Steps
<CardGroup cols={2}>
<Card title="Supported Assets" icon="coins" href="/trading/bridge/supported-assets">
See all supported chains and tokens with minimum amounts.
</Card>
<Card title="Check Status" icon="clock" href="/trading/bridge/status">
Track your deposit progress through completion.
</Card>
</CardGroup>
File diff suppressed because one or more lines are too long
@@ -1,62 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Supported Assets
> Chains and tokens supported for deposits to Polymarket
The Bridge API supports deposits from multiple chains and tokens. All deposits are automatically converted to **pUSD on Polygon**, which is used as collateral for trading on Polymarket.
## Get Supported Assets
Retrieve the full list of supported chains and tokens with their minimum deposit amounts.
```bash theme={null}
curl https://bridge.polymarket.com/supported-assets
```
## Supported Chains
The bridge supports deposits from these blockchain networks:
| Chain | Address Type | Min Deposit | Example Tokens |
| --------------- | ------------ | ----------- | ------------------------------------------- |
| Ethereum | EVM | \$7 | ETH, USDC, USDT, WBTC, DAI, LINK, UNI, AAVE |
| Polygon | EVM | \$2 | POL, USDC, USDT, DAI, WETH, SAND |
| Arbitrum | EVM | \$2 | ETH, ARB, USDC, USDT, DAI, WBTC, USDe |
| Base | EVM | \$2 | ETH, USDC, USDT, DAI, cbBTC, AERO, USDS |
| Optimism | EVM | \$2 | ETH, OP, USDC, USDT, DAI, USDe |
| BNB Smart Chain | EVM | \$2 | BNB, USDC, USDT, DAI, ETH, BTCB, BUSD |
| Solana | SVM | \$2 | SOL, USDC, USDT, USDe, TRUMP |
| Bitcoin | BTC | \$9 | BTC |
| Tron | TVM | \$9 | USDT |
| HyperEVM | EVM | \$2 | HYPE, USDC, USDe, stHYPE, UBTC, UETH |
| Abstract | EVM | \$2 | ETH, USDC, USDT |
| Monad | EVM | \$2 | MON, USDC, USDT |
| Ethereal | EVM | \$2 | USDe, WUSDe |
| Katana | EVM | \$2 | AUSD |
| Lighter | EVM | \$2 | USDC |
<Note>
Supported assets change over time. Always call `/supported-assets` for the
current list before initiating a deposit.
</Note>
## Minimum Amounts
Each asset has a `minCheckoutUsd` value—the minimum deposit amount in USD equivalent. Deposits below this threshold may fail to process.
Most L2 chains (Polygon, Arbitrum, Base, Optimism) have low minimums of $2, while Ethereum deposits require $7 minimum. Bitcoin and Tron have \$9 minimums due to higher bridging costs.
## Next Steps
<CardGroup cols={2}>
<Card title="Create Deposit" icon="arrow-right-to-bracket" href="/trading/bridge/deposit">
Generate bridge addresses for your wallet.
</Card>
<Card title="Check Status" icon="clock" href="/trading/bridge/status">
Track your deposit progress.
</Card>
</CardGroup>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,699 +0,0 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Create Order
> Build, sign, and submit orders
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
<Info>
The SDK handles EIP-712 signing and submission for you. If you prefer the REST
API directly, see [Authentication](/api-reference/authentication) for
constructing the required headers and the [API
Reference](/api-reference/introduction) for full endpoint documentation
including the raw order object fields and request/response schemas.
</Info>
***
## Order Types
| Type | Behavior | Use Case |
| ------- | -------------------------------------------------------------------- | ------------------------------- |
| **GTC** | Good-Til-Cancelled — rests on the book until filled or cancelled | Default for limit orders |
| **GTD** | Good-Til-Date — active until a specified expiration time | Auto-expire before known events |
| **FOK** | Fill-Or-Kill — must fill immediately and entirely, or cancel | All-or-nothing market orders |
| **FAK** | Fill-And-Kill — fills what's available immediately, cancels the rest | Partial-fill market orders |
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
* **BUY**: specify the dollar amount you want to spend
* **SELL**: specify the number of shares you want to sell
***
## Limit Orders
The simplest way to place a limit order — create, sign, and submit in one call:
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient, Side, OrderType } from "@polymarket/clob-client-v2";
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{
tickSize: "0.01",
negRisk: false,
},
OrderType.GTC,
);
console.log("Order ID:", response.orderID);
console.log("Status:", response.status);
```
```python Python theme={null}
from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
response = client.create_and_post_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
order_type=OrderType.GTC
)
print("Order ID:", response["orderID"])
print("Status:", response["status"])
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::Side;
use polymarket_client_sdk_v2::types::dec;
let token_id = "TOKEN_ID".parse()?;
let order = client
.limit_order()
.token_id(token_id)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
println!("Order ID: {}", response.order_id);
println!("Status: {:?}", response.status);
```
</CodeGroup>
### Two-Step Sign Then Submit
For more control, you can separate signing from submission. This is useful for batch orders or custom submission logic:
<CodeGroup>
```typescript TypeScript theme={null}
// Step 1: Create and sign locally
const signedOrder = await client.createOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{ tickSize: "0.01", negRisk: false },
);
// Step 2: Submit to the CLOB
const response = await client.postOrder(signedOrder, OrderType.GTC);
```
```python Python theme={null}
# Step 1: Create and sign locally
signed_order = client.create_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False)
)
# Step 2: Submit to the CLOB
response = client.post_order(signed_order, OrderType.GTC)
```
```rust Rust theme={null}
// Step 1: Create order (auto-fetches tick size, neg risk, fee rate)
let order = client
.limit_order()
.token_id("TOKEN_ID".parse()?)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.build()
.await?;
// Step 2: Sign and submit separately
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
***
## GTD Orders
GTD orders auto-expire at a specified time. Useful for quoting around known events.
<CodeGroup>
```typescript TypeScript theme={null}
// Expire in 1 hour (+ 60s security threshold buffer)
const expiration = Math.floor(Date.now() / 1000) + 60 + 3600;
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
expiration,
},
{ tickSize: "0.01", negRisk: false },
OrderType.GTD,
);
```
```python Python theme={null}
import time
# Expire in 1 hour (+ 60s security threshold buffer)
expiration = int(time.time()) + 60 + 3600
response = client.create_and_post_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
expiration=expiration,
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
order_type=OrderType.GTD
)
```
```rust Rust theme={null}
use chrono::{TimeDelta, Utc};
use polymarket_client_sdk_v2::clob::types::OrderType;
let order = client
.limit_order()
.token_id("TOKEN_ID".parse()?)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.order_type(OrderType::GTD)
.expiration(Utc::now() + TimeDelta::hours(1))
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
<Note>
There is a security threshold of one minute on GTD expiration. To set an
effective lifetime of N seconds, use `now + 60 + N`. For example, for a
30-second effective lifetime, set the expiration to `now + 60 + 30`.
</Note>
***
## Market Orders
Market orders execute immediately against resting liquidity using FOK or FAK types:
<CodeGroup>
```typescript TypeScript theme={null}
import { Side, OrderType } from "@polymarket/clob-client-v2";
// FOK BUY: spend exactly $100 or cancel entirely
const buyOrder = await client.createMarketOrder(
{
tokenID: "TOKEN_ID",
side: Side.BUY,
amount: 100, // dollar amount
price: 0.5, // worst-price limit (slippage protection)
},
{ tickSize: "0.01", negRisk: false },
);
await client.postOrder(buyOrder, OrderType.FOK);
// FOK SELL: sell exactly 200 shares or cancel entirely
const sellOrder = await client.createMarketOrder(
{
tokenID: "TOKEN_ID",
side: Side.SELL,
amount: 200, // number of shares
price: 0.45, // worst-price limit (slippage protection)
},
{ tickSize: "0.01", negRisk: false },
);
await client.postOrder(sellOrder, OrderType.FOK);
```
```python Python theme={null}
from py_clob_client_v2.order_builder.constants import BUY, SELL
from py_clob_client_v2 import MarketOrderArgs, OrderType, PartialCreateOrderOptions
# FOK BUY: spend exactly $100 or cancel entirely
buy_order = client.create_market_order(
order_args=MarketOrderArgs(
token_id="TOKEN_ID",
side=BUY,
amount=100, # dollar amount
price=0.50, # worst-price limit (slippage protection)
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
)
client.post_order(buy_order, OrderType.FOK)
# FOK SELL: sell exactly 200 shares or cancel entirely
sell_order = client.create_market_order(
order_args=MarketOrderArgs(
token_id="TOKEN_ID",
side=SELL,
amount=200, # number of shares
price=0.45, # worst-price limit (slippage protection)
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
)
client.post_order(sell_order, OrderType.FOK)
```
```rust Rust theme={null}
use polymarket_client_sdk_v2::clob::types::{Amount, OrderType, Side};
let token_id = "TOKEN_ID".parse()?;
// FOK BUY: spend exactly $100 or cancel entirely
let buy = client
.market_order()
.token_id(token_id)
.amount(Amount::usdc(dec!(100))?)
.price(dec!(0.50)) // worst-price limit (slippage protection)
.side(Side::Buy)
.order_type(OrderType::FOK)
.build()
.await?;
let signed = client.sign(&signer, buy).await?;
client.post_order(signed).await?;
// FOK SELL: sell exactly 200 shares or cancel entirely
let sell = client
.market_order()
.token_id(token_id)
.amount(Amount::shares(dec!(200))?)
.price(dec!(0.45)) // worst-price limit (slippage protection)
.side(Side::Sell)
.order_type(OrderType::FOK)
.build()
.await?;
let signed = client.sign(&signer, sell).await?;
client.post_order(signed).await?;
```
</CodeGroup>
* **FOK** — fill entirely or cancel the whole order
* **FAK** — fill what's available, cancel the rest
The `price` field on market orders acts as a **worst-price limit** (slippage protection), not a target execution price.
### One-Step Market Order
For convenience, `createAndPostMarketOrder` handles creation, signing, and submission in one call:
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.createAndPostMarketOrder(
{
tokenID: "TOKEN_ID",
side: Side.BUY,
amount: 100,
price: 0.5,
},
{ tickSize: "0.01", negRisk: false },
OrderType.FOK,
);
```
```python Python theme={null}
from py_clob_client_v2 import MarketOrderArgs, OrderType, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY
response = client.create_and_post_market_order(
order_args=MarketOrderArgs(
token_id="TOKEN_ID",
side=BUY,
amount=100,
price=0.50,
),
options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
order_type=OrderType.FOK,
)
```
```rust Rust theme={null}
let order = client
.market_order()
.token_id("TOKEN_ID".parse()?)
.amount(Amount::usdc(dec!(100))?)
.price(dec!(0.50))
.side(Side::Buy)
.order_type(OrderType::FOK)
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
***
## Post-Only Orders
Post-only orders guarantee you're always the maker. If the order would match immediately (cross the spread), it's rejected instead of executed.
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.postOrder(signedOrder, OrderType.GTC, true);
```
```python Python theme={null}
response = client.post_order(signed_order, OrderType.GTC, post_only=True)
```
```rust Rust theme={null}
let order = client
.limit_order()
.token_id("TOKEN_ID".parse()?)
.price(dec!(0.50))
.size(dec!(10))
.side(Side::Buy)
.post_only(true)
.build()
.await?;
let signed = client.sign(&signer, order).await?;
let response = client.post_order(signed).await?;
```
</CodeGroup>
* Only works with **GTC** and **GTD** order types
* Rejected if combined with FOK or FAK
***
## Batch Orders
Place up to **15 orders** in a single request:
<CodeGroup>
```typescript TypeScript theme={null}
import { OrderType, Side, PostOrdersArgs } from "@polymarket/clob-client-v2";
const orders: PostOrdersArgs[] = [
{
order: await client.createOrder(
{
tokenID: "TOKEN_ID",
price: 0.48,
side: Side.BUY,
size: 500,
},
{ tickSize: "0.01", negRisk: false },
),
orderType: OrderType.GTC,
},
{
order: await client.createOrder(
{
tokenID: "TOKEN_ID",
price: 0.52,
side: Side.SELL,
size: 500,
},
{ tickSize: "0.01", negRisk: false },
),
orderType: OrderType.GTC,
},
];
const response = await client.postOrders(orders);
```
```python Python theme={null}
from py_clob_client_v2 import OrderArgs, OrderType, PostOrdersV2Args, PartialCreateOrderOptions
from py_clob_client_v2.order_builder.constants import BUY, SELL
response = client.post_orders([
PostOrdersV2Args(
order=client.create_order(OrderArgs(
price=0.48,
size=500,
side=BUY,
token_id="TOKEN_ID",
), options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False)),
orderType=OrderType.GTC,
),
PostOrdersV2Args(
order=client.create_order(OrderArgs(
price=0.52,
size=500,
side=SELL,
token_id="TOKEN_ID",
), options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False)),
orderType=OrderType.GTC,
),
])
```
```rust Rust theme={null}
let token_id = "TOKEN_ID".parse()?;
let bid = client
.limit_order()
.token_id(token_id)
.price(dec!(0.48))
.size(dec!(500))
.side(Side::Buy)
.build()
.await?;
let ask = client
.limit_order()
.token_id(token_id)
.price(dec!(0.52))
.size(dec!(500))
.side(Side::Sell)
.build()
.await?;
let signed_bid = client.sign(&signer, bid).await?;
let signed_ask = client.sign(&signer, ask).await?;
let response = client.post_orders(vec![signed_bid, signed_ask]).await?;
```
</CodeGroup>
***
## Order Options
Every order requires two market-specific options: `tickSize` and `negRisk`. For
details on signature types (`0` = EOA, `1` = POLY\_PROXY, `2` = GNOSIS\_SAFE,
`3` = POLY\_1271 deposit wallet), see
[Authentication](/api-reference/authentication#signature-types-and-funder).
### Tick Sizes
Your order price must conform to the market's tick size, or the order is rejected.
| Tick Size | Precision | Example Prices |
| --------- | ---------- | ---------------------- |
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
<CodeGroup>
```typescript TypeScript theme={null}
const tickSize = await client.getTickSize("TOKEN_ID");
```
```python Python theme={null}
tick_size = client.get_tick_size("TOKEN_ID")
```
```rust Rust theme={null}
let token_id = "TOKEN_ID".parse()?;
let tick_size = client.tick_size(token_id).await?;
```
</CodeGroup>
### Negative Risk
Multi-outcome events (3+ outcomes) use the Neg Risk CTF Exchange. Pass `negRisk: true` for these markets.
<CodeGroup>
```typescript TypeScript theme={null}
const isNegRisk = await client.getNegRisk("TOKEN_ID");
```
```python Python theme={null}
is_neg_risk = client.get_neg_risk("TOKEN_ID")
```
```rust Rust theme={null}
let token_id = "TOKEN_ID".parse()?;
let is_neg_risk = client.neg_risk(token_id).await?;
```
</CodeGroup>
<Tip>
Both values are also available on the market object: `minimum_tick_size` and
`neg_risk`. In Rust, the order builder auto-fetches both — you don't need to
look them up manually.
</Tip>
***
## Prerequisites
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
* **BUY orders**: pUSD allowance >= spending amount
* **SELL orders**: conditional token allowance >= selling amount
Order size is limited by your available balance minus amounts reserved by existing open orders:
$$
\text{maxOrderSize} = \text{balance} - \sum(\text{openOrderSize} - \text{filledAmount})
$$
<Warning>
Orders are continuously monitored for validity — balances and allowances are
tracked in real time. Any maker caught intentionally abusing these checks will
be blacklisted.
</Warning>
### Sports Markets
Sports markets have additional behaviors:
* Outstanding limit orders are **automatically cancelled** once the game begins, clearing the entire order book at the official start time
* Marketable orders have a **1-second placement delay** before matching
* Game start times can shift — monitor your orders closely, as they may not be cleared if the start time changes unexpectedly
***
## Response
A successful order placement returns:
```json theme={null}
{
"success": true,
"errorMsg": "",
"orderID": "0xabc123...",
"takingAmount": "",
"makingAmount": "",
"status": "live",
"transactionsHashes": [],
"tradeIDs": []
}
```
### Statuses
| Status | Description |
| ----------- | ------------------------------------------------------------- |
| `live` | Order resting on the book |
| `matched` | Order matched immediately with a resting order |
| `delayed` | Marketable order accepted into an asynchronous matching delay |
| `unmatched` | Marketable but failed to delay — placement still successful |
<Note>
Selected crypto and finance up/down markets apply a 250 ms taker delay to
marketable orders. To check a specific market, call `GET
https://clob.polymarket.com/clob-markets/{condition_id}` or SDK
`getClobMarketInfo(conditionID)` and look for `itode: true`. The API waits for
this short hold and returns the final order result, so these orders usually
return `matched`, `live`, or `unmatched` rather than `delayed`. Orders cannot
be canceled while they are pending in the delay window.
</Note>
### Error Messages
| Error | Description |
| ---------------------------------- | ----------------------------------------------- |
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
| `INVALID_ORDER_MIN_SIZE` | Order size below the minimum threshold |
| `INVALID_ORDER_DUPLICATED` | Identical order already placed |
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Insufficient balance or allowance |
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only used with FOK/FAK |
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
| `INVALID_ORDER_ERROR` | System error inserting the order |
| `EXECUTION_ERROR` | System error executing the trade |
| `ORDER_DELAYED` | Order match delayed due to market conditions |
| `DELAYING_ORDER_ERROR` | System error while delaying the order |
| `MARKET_NOT_READY` | Market not yet accepting orders |
***
## Heartbeat
The heartbeat endpoint maintains session liveness. If a valid heartbeat is not received within **10 seconds** (with a 5-second buffer), **all open orders are cancelled**.
<CodeGroup>
```typescript TypeScript theme={null}
let heartbeatId = "";
setInterval(async () => {
const resp = await client.postHeartbeat(heartbeatId);
heartbeatId = resp.heartbeat_id;
}, 5000);
```
```python Python theme={null}
import time
heartbeat_id = ""
while True:
resp = client.post_heartbeat(heartbeat_id)
heartbeat_id = resp["heartbeat_id"]
time.sleep(5)
```
```rust Rust theme={null}
// With the `heartbeats` feature, the Rust SDK can auto-send heartbeats
// in a background task — no manual loop needed:
Client::start_heartbeats(&mut client)?;
// ... your trading logic ...
client.stop_heartbeats().await?;
// Or send manually:
let resp = client.post_heartbeat(None).await?; // None for first call
let resp = client.post_heartbeat(Some(resp.heartbeat_id)).await?;
```
</CodeGroup>
* Include the most recent `heartbeat_id` in each request. Use an empty string for the first request.
* If you send an expired ID, the server responds with `400` and the correct ID. Update and retry.
***
## Next Steps
<CardGroup cols={2}>
<Card title="Cancel Orders" icon="xmark" href="/trading/orders/cancel">
Cancel single, multiple, or all open orders
</Card>
<Card title="Order Attribution" icon="tag" href="/trading/orders/attribution">
Attribute orders to your builder account for volume credit
</Card>
</CardGroup>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More