diff --git a/TARGET.md b/TARGET.md index 85f1df1..979d659 100644 --- a/TARGET.md +++ b/TARGET.md @@ -3,6 +3,7 @@ These URLs will be scraped and organized into the repository. ## Quickstart +https://docs.polymarket.com/quickstart.md https://docs.polymarket.com/quickstart/overview.md https://docs.polymarket.com/quickstart/fetching-data.md https://docs.polymarket.com/quickstart/first-order.md @@ -11,23 +12,31 @@ https://docs.polymarket.com/quickstart/introduction/rate-limits.md https://docs.polymarket.com/quickstart/reference/endpoints.md ## Market Makers +https://docs.polymarket.com/market-makers/overview.md +https://docs.polymarket.com/market-makers/getting-started.md +https://docs.polymarket.com/market-makers/trading.md +https://docs.polymarket.com/market-makers/liquidity-rewards.md +https://docs.polymarket.com/market-makers/maker-rebates.md +https://docs.polymarket.com/market-makers/inventory.md https://docs.polymarket.com/developers/market-makers/introduction.md https://docs.polymarket.com/developers/market-makers/setup.md -https://docs.polymarket.com/developers/market-makers/trading.md -https://docs.polymarket.com/developers/market-makers/liquidity-rewards.md -https://docs.polymarket.com/developers/market-makers/maker-rebates-program.md https://docs.polymarket.com/developers/market-makers/data-feeds.md -https://docs.polymarket.com/developers/market-makers/inventory.md ## Polymarket Builders Program +https://docs.polymarket.com/builders/overview.md +https://docs.polymarket.com/builders/tiers.md +https://docs.polymarket.com/builders/api-keys.md https://docs.polymarket.com/developers/builders/builder-intro.md https://docs.polymarket.com/developers/builders/builder-tiers.md https://docs.polymarket.com/developers/builders/builder-profile.md https://docs.polymarket.com/developers/builders/order-attribution.md https://docs.polymarket.com/developers/builders/relayer-client.md https://docs.polymarket.com/developers/builders/blockchain-data-resources.md +https://docs.polymarket.com/developers/builders/examples.md ## Central Limit Order Book (CLOB) +https://docs.polymarket.com/trading/overview.md +https://docs.polymarket.com/trading/quickstart.md https://docs.polymarket.com/developers/CLOB/introduction.md https://docs.polymarket.com/developers/CLOB/status.md https://docs.polymarket.com/developers/CLOB/quickstart.md @@ -39,11 +48,40 @@ https://docs.polymarket.com/developers/CLOB/clients/methods-l1.md https://docs.polymarket.com/developers/CLOB/clients/methods-l2.md https://docs.polymarket.com/developers/CLOB/clients/methods-builder.md +## API Reference - Market Data +https://docs.polymarket.com/api-reference/introduction.md +https://docs.polymarket.com/api-reference/authentication.md +https://docs.polymarket.com/api-reference/rate-limits.md +https://docs.polymarket.com/api-reference/geoblock.md +https://docs.polymarket.com/api-reference/clients-sdks.md + +## API Reference - Market Data (Data API) +https://docs.polymarket.com/market-data/overview.md +https://docs.polymarket.com/market-data/fetching-markets.md +https://docs.polymarket.com/api-reference/market-data/get-order-book.md +https://docs.polymarket.com/api-reference/market-data/get-order-books-request-body.md +https://docs.polymarket.com/api-reference/market-data/get-market-price.md +https://docs.polymarket.com/api-reference/market-data/get-market-prices-query-parameters.md +https://docs.polymarket.com/api-reference/market-data/get-market-prices-request-body.md +https://docs.polymarket.com/api-reference/market-data/get-midpoint-price.md +https://docs.polymarket.com/api-reference/market-data/get-midpoint-prices-query-parameters.md +https://docs.polymarket.com/api-reference/market-data/get-midpoint-prices-request-body.md +https://docs.polymarket.com/api-reference/market-data/get-spread.md +https://docs.polymarket.com/api-reference/market-data/get-spreads.md +https://docs.polymarket.com/api-reference/market-data/get-last-trade-price.md +https://docs.polymarket.com/api-reference/market-data/get-last-trade-prices-query-parameters.md +https://docs.polymarket.com/api-reference/market-data/get-last-trade-prices-request-body.md +https://docs.polymarket.com/api-reference/market-data/get-fee-rate.md +https://docs.polymarket.com/api-reference/market-data/get-fee-rate-by-path-parameter.md +https://docs.polymarket.com/api-reference/market-data/get-tick-size.md +https://docs.polymarket.com/api-reference/market-data/get-tick-size-by-path-parameter.md +https://docs.polymarket.com/api-reference/data/get-server-time.md + ## API Reference - Orderbook https://docs.polymarket.com/api-reference/orderbook/get-order-book-summary.md https://docs.polymarket.com/api-reference/orderbook/get-multiple-order-books-summaries-by-request.md -## API Reference - Pricing +## API Reference - Pricing (Legacy) https://docs.polymarket.com/api-reference/pricing/get-market-price.md https://docs.polymarket.com/api-reference/pricing/get-multiple-market-prices.md https://docs.polymarket.com/api-reference/pricing/get-multiple-market-prices-by-request.md @@ -53,6 +91,20 @@ https://docs.polymarket.com/api-reference/pricing/get-price-history-for-a-traded ## API Reference - Spreads https://docs.polymarket.com/api-reference/spreads/get-bid-ask-spreads.md +## API Reference - Trade (CLOB) +https://docs.polymarket.com/api-reference/trade/post-a-new-order.md +https://docs.polymarket.com/api-reference/trade/post-multiple-orders.md +https://docs.polymarket.com/api-reference/trade/get-single-order-by-id.md +https://docs.polymarket.com/api-reference/trade/get-user-orders.md +https://docs.polymarket.com/api-reference/trade/get-trades.md +https://docs.polymarket.com/api-reference/trade/cancel-single-order.md +https://docs.polymarket.com/api-reference/trade/cancel-multiple-orders.md +https://docs.polymarket.com/api-reference/trade/cancel-all-orders.md +https://docs.polymarket.com/api-reference/trade/cancel-orders-for-a-market.md +https://docs.polymarket.com/api-reference/trade/get-order-scoring-status.md +https://docs.polymarket.com/api-reference/trade/send-heartbeat.md +https://docs.polymarket.com/api-reference/trade/get-builder-trades.md + ## Historical Timeseries Data https://docs.polymarket.com/developers/CLOB/timeseries.md @@ -65,24 +117,35 @@ https://docs.polymarket.com/developers/CLOB/orders/get-active-order.md https://docs.polymarket.com/developers/CLOB/orders/check-scoring.md https://docs.polymarket.com/developers/CLOB/orders/cancel-orders.md https://docs.polymarket.com/developers/CLOB/orders/onchain-order-info.md +https://docs.polymarket.com/trading/orders/overview.md +https://docs.polymarket.com/trading/orders/create.md +https://docs.polymarket.com/trading/orders/cancel.md +https://docs.polymarket.com/trading/orders/attribution.md ## Trades https://docs.polymarket.com/developers/CLOB/trades/trades-overview.md https://docs.polymarket.com/developers/CLOB/trades/trades.md ## Websocket +https://docs.polymarket.com/market-data/websocket/overview.md +https://docs.polymarket.com/market-data/websocket/market-channel.md https://docs.polymarket.com/developers/CLOB/websocket/wss-overview.md https://docs.polymarket.com/quickstart/websocket/WSS-Quickstart.md https://docs.polymarket.com/developers/CLOB/websocket/wss-auth.md https://docs.polymarket.com/developers/CLOB/websocket/user-channel.md https://docs.polymarket.com/developers/CLOB/websocket/market-channel.md +https://docs.polymarket.com/api-reference/wss/market.md +https://docs.polymarket.com/api-reference/wss/user.md ## Sports Websocket https://docs.polymarket.com/developers/sports-websocket/overview.md https://docs.polymarket.com/developers/sports-websocket/message-format.md https://docs.polymarket.com/developers/sports-websocket/quickstart.md +https://docs.polymarket.com/market-data/websocket/sports.md +https://docs.polymarket.com/api-reference/wss/sports.md ## Real Time Data Stream +https://docs.polymarket.com/market-data/websocket/rtds.md https://docs.polymarket.com/developers/RTDS/RTDS-overview.md https://docs.polymarket.com/developers/RTDS/RTDS-crypto-prices.md https://docs.polymarket.com/developers/RTDS/RTDS-comments.md @@ -120,6 +183,10 @@ https://docs.polymarket.com/api-reference/markets/list-markets.md https://docs.polymarket.com/api-reference/markets/get-market-by-id.md https://docs.polymarket.com/api-reference/markets/get-market-tags-by-id.md https://docs.polymarket.com/api-reference/markets/get-market-by-slug.md +https://docs.polymarket.com/api-reference/markets/get-prices-history.md +https://docs.polymarket.com/api-reference/markets/get-sampling-markets.md +https://docs.polymarket.com/api-reference/markets/get-simplified-markets.md +https://docs.polymarket.com/api-reference/markets/get-sampling-simplified-markets.md ## API Reference - Series https://docs.polymarket.com/api-reference/series/list-series.md @@ -153,12 +220,14 @@ https://docs.polymarket.com/api-reference/core/get-top-holders-for-markets.md https://docs.polymarket.com/api-reference/core/get-total-value-of-a-users-positions.md https://docs.polymarket.com/api-reference/core/get-closed-positions-for-a-user.md https://docs.polymarket.com/api-reference/core/get-trader-leaderboard-rankings.md +https://docs.polymarket.com/api-reference/core/get-positions-for-a-market.md ## API Reference - Builders https://docs.polymarket.com/api-reference/builders/get-aggregated-builder-leaderboard.md https://docs.polymarket.com/api-reference/builders/get-daily-builder-volume-time-series.md ## Bridge & Swap - Overview +https://docs.polymarket.com/trading/bridge/overview.md https://docs.polymarket.com/developers/misc-endpoints/bridge-overview.md ## API Reference - Bridge @@ -167,14 +236,24 @@ https://docs.polymarket.com/api-reference/bridge/get-a-quote.md https://docs.polymarket.com/api-reference/bridge/create-deposit-addresses.md https://docs.polymarket.com/api-reference/bridge/create-withdrawal-addresses.md https://docs.polymarket.com/api-reference/bridge/get-transaction-status.md +https://docs.polymarket.com/trading/bridge/deposit.md +https://docs.polymarket.com/trading/bridge/quote.md +https://docs.polymarket.com/trading/bridge/status.md +https://docs.polymarket.com/trading/bridge/supported-assets.md +https://docs.polymarket.com/trading/bridge/withdraw.md ## Subgraph +https://docs.polymarket.com/market-data/subgraph.md https://docs.polymarket.com/developers/subgraph/overview.md ## Resolution https://docs.polymarket.com/developers/resolution/UMA.md ## Conditional Token Frameworks (CTF) +https://docs.polymarket.com/trading/ctf/overview.md +https://docs.polymarket.com/trading/ctf/split.md +https://docs.polymarket.com/trading/ctf/merge.md +https://docs.polymarket.com/trading/ctf/redeem.md https://docs.polymarket.com/developers/CTF/overview.md https://docs.polymarket.com/developers/CTF/split.md https://docs.polymarket.com/developers/CTF/merge.md @@ -185,6 +264,7 @@ https://docs.polymarket.com/developers/CTF/deployment-resources.md https://docs.polymarket.com/developers/proxy-wallet.md ## Negative Risk +https://docs.polymarket.com/advanced/neg-risk.md https://docs.polymarket.com/developers/neg-risk/overview.md ## Changelog @@ -236,8 +316,26 @@ https://docs.polymarket.com/polymarket-learn/trading/market-orders.md https://docs.polymarket.com/polymarket-learn/trading/no-limits.md https://docs.polymarket.com/polymarket-learn/trading/using-the-orderbook.md -## Missing from API Reference - Core -https://docs.polymarket.com/api-reference/core/get-positions-for-a-market.md +## Polymarket 101 +https://docs.polymarket.com/polymarket-101.md -## Missing from Builders -https://docs.polymarket.com/developers/builders/examples.md +## Concepts +https://docs.polymarket.com/concepts/markets-events.md +https://docs.polymarket.com/concepts/order-lifecycle.md +https://docs.polymarket.com/concepts/positions-tokens.md +https://docs.polymarket.com/concepts/prices-orderbook.md +https://docs.polymarket.com/concepts/resolution.md + +## Trading +https://docs.polymarket.com/trading/fees.md +https://docs.polymarket.com/trading/gasless.md +https://docs.polymarket.com/trading/orderbook.md +https://docs.polymarket.com/trading/clients/public.md +https://docs.polymarket.com/trading/clients/l1.md +https://docs.polymarket.com/trading/clients/l2.md +https://docs.polymarket.com/trading/clients/builder.md + +## Index & Resources +https://docs.polymarket.com/index.md +https://docs.polymarket.com/resources/contract-addresses.md +https://docs.polymarket.com/resources/error-codes.md diff --git a/docs/advanced/neg-risk.md b/docs/advanced/neg-risk.md new file mode 100644 index 0000000..84f9ac7 --- /dev/null +++ b/docs/advanced/neg-risk.md @@ -0,0 +1,145 @@ +> ## 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 [Contract Addresses](/resources/contract-addresses) 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 + + + 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. + + +* 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 +} +``` + + + 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. + + +## 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 + + + + Understand how multi-market events are structured. + + + + Learn about token operations like split, merge, and redeem. + + diff --git a/docs/api-reference/authentication.md b/docs/api-reference/authentication.md new file mode 100644 index 0000000..80dd436 --- /dev/null +++ b/docs/api-reference/authentication.md @@ -0,0 +1,377 @@ +> ## 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 + + + + The **Gamma API**, **Data API**, and CLOB read endpoints (orderbook, prices, spreads) require no authentication. + + + + CLOB trading endpoints (placing orders, cancellations, heartbeat) require all 5 `POLY_*` L2 HTTP headers. + + + +*** + +## 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 (Private Key) + +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 (API Credentials) + +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 + + + Even with L2 authentication headers, methods that create user orders still + require the user to sign the order payload. + + +*** + +## Getting API Credentials + +Before making authenticated requests, you need to obtain API credentials using L1 authentication. + +### Using the SDK (Recommended) + + + + ```typescript theme={null} + import { ClobClient } from "@polymarket/clob-client"; + import { Wallet } from "ethers"; // v5.8.0 + + const client = new ClobClient( + "https://clob.polymarket.com", + 137, // Polygon mainnet + new Wallet(process.env.PRIVATE_KEY) + ); + + // Creates new credentials or derives existing ones + const credentials = await client.createOrDeriveApiKey(); + + console.log(credentials); + // { + // apiKey: "550e8400-e29b-41d4-a716-446655440000", + // secret: "base64EncodedSecretString", + // passphrase: "randomPassphraseString" + // } + ``` + + + + ```python theme={null} + from py_clob_client.client import ClobClient + import os + + client = ClobClient( + host="https://clob.polymarket.com", + chain_id=137, # Polygon mainnet + key=os.getenv("PRIVATE_KEY") + ) + + # Creates new credentials or derives existing ones + credentials = client.create_or_derive_api_creds() + + print(credentials) + # { + # "apiKey": "550e8400-e29b-41d4-a716-446655440000", + # "secret": "base64EncodedSecretString", + # "passphrase": "randomPassphraseString" + # } + ``` + + + + + **Never commit private keys to version control.** Always use environment + variables or secure key management systems. + + +### 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) or [TypeScript](https://github.com/Polymarket/clob-client) 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: + + + + ```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) + ``` + + + +Reference implementations: + +* [TypeScript](https://github.com/Polymarket/clob-client/blob/main/src/signing/eip712.ts) +* [Python](https://github.com/Polymarket/py-clob-client/blob/main/py_clob_client/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/blob/main/src/signing/hmac.ts) and [Python](https://github.com/Polymarket/py-clob-client/blob/main/py_clob_client/signing/hmac.py) clients. + +### CLOB Client (L2) + + + + ```typescript theme={null} + import { ClobClient } from "@polymarket/clob-client"; + import { Wallet } from "ethers"; // v5.8.0 + + const client = new ClobClient( + "https://clob.polymarket.com", + 137, + new Wallet(process.env.PRIVATE_KEY), + apiCreds, // Generated from L1 auth, API credentials enable L2 methods + 1, // signatureType explained below + funderAddress // funder explained below + ); + + // Now you can trade! + const order = await client.createAndPostOrder( + { tokenID: "123456", price: 0.65, size: 100, side: "BUY" }, + { tickSize: "0.01", negRisk: false } + ); + ``` + + + + ```python theme={null} + from py_clob_client.client import ClobClient + 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=1, # signatureType explained below + funder=os.getenv("FUNDER_ADDRESS") # funder explained below + ) + + # Now you can trade! + order = client.create_and_post_order( + {"token_id": "123456", "price": 0.65, "size": 100, "side": "BUY"}, + {"tick_size": "0.01", "neg_risk": False} + ) + ``` + + + + + Even with L2 authentication headers, methods that create user orders still + require the user to sign the order payload. + + +*** + +## 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` | A custom proxy wallet only used with users who logged in via Magic Link email/Google. Using this requires the user to have exported their PK from Polymarket.com and imported into your app. | +| GNOSIS\_SAFE | `2` | Gnosis Safe multisig proxy wallet (most common). Use this for any new or returning user who does not fit the other 2 types. | + + + The wallet address displayed to the user on Polymarket.com is the proxy wallet + and should be used as the funder. These can be deterministically derived or + you can deploy them on behalf of the user. These proxy wallets are + automatically deployed for the user on their first login to Polymarket.com. + + +*** + +## Security Best Practices + + + + 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... + ``` + + + + Never expose your API secret in client-side code. All authenticated requests should originate from your backend. + + + +*** + +## Troubleshooting + + + + 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 + + + + 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()` + + + + 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. + + + + 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! + ``` + + + +*** + +## Next Steps + + + + Learn how to create and submit orders. + + + + Check trading availability by region. + + diff --git a/docs/api-reference/bridge/create-deposit-addresses.md b/docs/api-reference/bridge/create-deposit-addresses.md index 35caf3f..45338fc 100644 --- a/docs/api-reference/bridge/create-deposit-addresses.md +++ b/docs/api-reference/bridge/create-deposit-addresses.md @@ -4,35 +4,16 @@ # Create deposit addresses -> Generate unique deposit addresses for depositing assets to your Polymarket wallet. - -**How it works:** -1. Submit your Polymarket wallet address -2. Receive deposit addresses for each blockchain type (EVM, Solana, Bitcoin) -3. Send assets from any supported chain to the appropriate deposit address -4. Assets are automatically bridged and swapped to USDC.e on Polygon -5. USDC.e is credited to your Polymarket wallet for trading - -**Supported Assets:** -Use `/supported-assets` to see all available chains and tokens you can deposit from. - - ## OpenAPI -````yaml api-reference/bridge-api-openapi.yaml post /deposit +````yaml api-spec/bridge-openapi.yaml post /deposit openapi: 3.0.3 info: title: Polymarket Bridge API version: 1.0.0 - description: > - HTTP API for Polymarket bridge and swap operations. - - - Polymarket uses USDC.e (Bridged USDC) on Polygon as collateral for all - trading activities. This API enables users to bridge assets from various - chains and swap them to USDC.e on Polygon for seamless trading. + description: HTTP API for Polymarket bridge and swap operations. servers: - url: https://bridge.polymarket.com description: Polymarket Bridge API @@ -46,30 +27,6 @@ paths: tags: - Bridge summary: Create deposit addresses - description: > - Generate unique deposit addresses for depositing assets to your - Polymarket wallet. - - - **How it works:** - - 1. Submit your Polymarket wallet address - - 2. Receive deposit addresses for each blockchain type (EVM, Solana, - Bitcoin) - - 3. Send assets from any supported chain to the appropriate deposit - address - - 4. Assets are automatically bridged and swapped to USDC.e on Polygon - - 5. USDC.e is credited to your Polymarket wallet for trading - - - **Supported Assets:** - - Use `/supported-assets` to see all available chains and tokens you can - deposit from. requestBody: required: true content: @@ -149,4 +106,4 @@ components: pattern: ^0x[a-fA-F0-9]{40}$ example: '0x56687bf447db6ffa42ffe2204a05edaa20f55839' -```` \ No newline at end of file +```` diff --git a/docs/api-reference/bridge/create-withdrawal-addresses.md b/docs/api-reference/bridge/create-withdrawal-addresses.md index 5c571df..0bae592 100644 --- a/docs/api-reference/bridge/create-withdrawal-addresses.md +++ b/docs/api-reference/bridge/create-withdrawal-addresses.md @@ -4,39 +4,16 @@ # Create withdrawal addresses -> Generate unique deposit addresses for withdrawing USDC.e from your Polymarket wallet to any supported chain and token. - - -**⚠️ Important:** Do not pre-generate withdrawal addresses. Only generate them when you are ready to execute the withdrawal. Each address is configured for a specific destination. - - -**How it works:** -1. Specify your Polymarket wallet address, destination chain, token, and recipient address -2. Receive deposit addresses for each blockchain type (EVM, Solana, Bitcoin) -3. Send USDC.e from your Polymarket wallet to the appropriate deposit address -4. Funds are automatically bridged and swapped to your desired token -5. Funds arrive at your destination wallet - -**Supported Destinations:** -Use `/supported-assets` to see all available chains and tokens you can withdraw to. - - ## OpenAPI -````yaml api-reference/bridge-api-openapi.yaml post /withdraw +````yaml api-spec/bridge-openapi.yaml post /withdraw openapi: 3.0.3 info: title: Polymarket Bridge API version: 1.0.0 - description: > - HTTP API for Polymarket bridge and swap operations. - - - Polymarket uses USDC.e (Bridged USDC) on Polygon as collateral for all - trading activities. This API enables users to bridge assets from various - chains and swap them to USDC.e on Polygon for seamless trading. + description: HTTP API for Polymarket bridge and swap operations. servers: - url: https://bridge.polymarket.com description: Polymarket Bridge API @@ -50,40 +27,6 @@ paths: tags: - Bridge summary: Create withdrawal addresses - description: > - Generate unique deposit addresses for withdrawing USDC.e from your - Polymarket wallet to any supported chain and token. - - - - - **⚠️ Important:** Do not pre-generate withdrawal addresses. Only - generate them when you are ready to execute the withdrawal. Each address - is configured for a specific destination. - - - - - **How it works:** - - 1. Specify your Polymarket wallet address, destination chain, token, and - recipient address - - 2. Receive deposit addresses for each blockchain type (EVM, Solana, - Bitcoin) - - 3. Send USDC.e from your Polymarket wallet to the appropriate deposit - address - - 4. Funds are automatically bridged and swapped to your desired token - - 5. Funds arrive at your destination wallet - - - **Supported Destinations:** - - Use `/supported-assets` to see all available chains and tokens you can - withdraw to. requestBody: required: true content: @@ -189,4 +132,4 @@ components: pattern: ^0x[a-fA-F0-9]{40}$ example: '0x56687bf447db6ffa42ffe2204a05edaa20f55839' -```` \ No newline at end of file +```` diff --git a/docs/api-reference/bridge/get-a-quote.md b/docs/api-reference/bridge/get-a-quote.md index 9695c0f..29a3494 100644 --- a/docs/api-reference/bridge/get-a-quote.md +++ b/docs/api-reference/bridge/get-a-quote.md @@ -4,34 +4,16 @@ # Get a quote -> Get an estimated quote for a deposit or withdrawal, including output amounts, checkout time, and a detailed fee breakdown. - -**Use Cases:** -- Preview fees and estimated output before executing a deposit or withdrawal -- Compare costs across different token/chain combinations -- Get the `quoteId` to reference this specific quote - -**Notes:** -- Quotes are estimates and actual amounts may vary slightly due to market conditions -- See `/supported-assets` for a list of all supported chains and tokens - - ## OpenAPI -````yaml api-reference/bridge-api-openapi.yaml post /quote +````yaml api-spec/bridge-openapi.yaml post /quote openapi: 3.0.3 info: title: Polymarket Bridge API version: 1.0.0 - description: > - HTTP API for Polymarket bridge and swap operations. - - - Polymarket uses USDC.e (Bridged USDC) on Polygon as collateral for all - trading activities. This API enables users to bridge assets from various - chains and swap them to USDC.e on Polygon for seamless trading. + description: HTTP API for Polymarket bridge and swap operations. servers: - url: https://bridge.polymarket.com description: Polymarket Bridge API @@ -45,27 +27,6 @@ paths: tags: - Bridge summary: Get a quote - description: > - Get an estimated quote for a deposit or withdrawal, including output - amounts, checkout time, and a detailed fee breakdown. - - - **Use Cases:** - - - Preview fees and estimated output before executing a deposit or - withdrawal - - - Compare costs across different token/chain combinations - - - Get the `quoteId` to reference this specific quote - - - **Notes:** - - - Quotes are estimates and actual amounts may vary slightly due to - market conditions - - - See `/supported-assets` for a list of all supported chains and tokens requestBody: required: true content: @@ -260,4 +221,4 @@ components: description: Impact cost of the transaction example: 0 -```` \ No newline at end of file +```` diff --git a/docs/api-reference/bridge/get-supported-assets.md b/docs/api-reference/bridge/get-supported-assets.md index 771a23b..8615548 100644 --- a/docs/api-reference/bridge/get-supported-assets.md +++ b/docs/api-reference/bridge/get-supported-assets.md @@ -4,31 +4,16 @@ # Get supported assets -> Retrieve all supported chains and tokens for deposits and withdrawals. - -**USDC.e on Polygon:** -Polymarket uses USDC.e (Bridged USDC from Ethereum) on Polygon as the native collateral for all markets. When you deposit assets from other chains, they are automatically bridged and swapped to USDC.e on Polygon. When you withdraw, your USDC.e is bridged and swapped to your desired token on the destination chain. - -**Minimum Amounts:** -Each asset has a `minCheckoutUsd` field indicating the minimum amount required in USD. Make sure your deposit or withdrawal meets this minimum to avoid transaction failures. - - ## OpenAPI -````yaml api-reference/bridge-api-openapi.yaml get /supported-assets +````yaml api-spec/bridge-openapi.yaml get /supported-assets openapi: 3.0.3 info: title: Polymarket Bridge API version: 1.0.0 - description: > - HTTP API for Polymarket bridge and swap operations. - - - Polymarket uses USDC.e (Bridged USDC) on Polygon as collateral for all - trading activities. This API enables users to bridge assets from various - chains and swap them to USDC.e on Polygon for seamless trading. + description: HTTP API for Polymarket bridge and swap operations. servers: - url: https://bridge.polymarket.com description: Polymarket Bridge API @@ -42,24 +27,6 @@ paths: tags: - Bridge summary: Get supported assets - description: > - Retrieve all supported chains and tokens for deposits and withdrawals. - - - **USDC.e on Polygon:** - - Polymarket uses USDC.e (Bridged USDC from Ethereum) on Polygon as the - native collateral for all markets. When you deposit assets from other - chains, they are automatically bridged and swapped to USDC.e on Polygon. - When you withdraw, your USDC.e is bridged and swapped to your desired - token on the destination chain. - - - **Minimum Amounts:** - - Each asset has a `minCheckoutUsd` field indicating the minimum amount - required in USD. Make sure your deposit or withdrawal meets this minimum - to avoid transaction failures. responses: '200': description: Successfully retrieved supported assets @@ -129,4 +96,4 @@ components: description: Token decimals example: 6 -```` \ No newline at end of file +```` diff --git a/docs/api-reference/bridge/get-transaction-status.md b/docs/api-reference/bridge/get-transaction-status.md index 4553aac..8063bda 100644 --- a/docs/api-reference/bridge/get-transaction-status.md +++ b/docs/api-reference/bridge/get-transaction-status.md @@ -4,41 +4,16 @@ # Get transaction status -> Get the transaction status for all deposits and withdrawals associated with a given address. - -**Usage:** -- Use the deposit address returned from the `/deposit` or `/withdraw` endpoint (EVM, SVM, or BTC address) -- Poll this endpoint to track the progress of your deposits and withdrawals - -**Status Values:** -- `DEPOSIT_DETECTED`: Funds detected but not yet processing -- `PROCESSING`: Transaction is being routed and swapped -- `ORIGIN_TX_CONFIRMED`: Origin transaction has been confirmed on source chain -- `SUBMITTED`: Transaction has been submitted to destination chain -- `COMPLETED`: Transaction completed successfully -- `FAILED`: Transaction encountered an error and did not complete - -**Notes:** -- Transactions typically complete within a few minutes, but may take longer depending on network conditions -- An empty transactions array means no transactions have been made to this address yet - - ## OpenAPI -````yaml api-reference/bridge-api-openapi.yaml get /status/{address} +````yaml api-spec/bridge-openapi.yaml get /status/{address} openapi: 3.0.3 info: title: Polymarket Bridge API version: 1.0.0 - description: > - HTTP API for Polymarket bridge and swap operations. - - - Polymarket uses USDC.e (Bridged USDC) on Polygon as collateral for all - trading activities. This API enables users to bridge assets from various - chains and swap them to USDC.e on Polygon for seamless trading. + description: HTTP API for Polymarket bridge and swap operations. servers: - url: https://bridge.polymarket.com description: Polymarket Bridge API @@ -52,43 +27,6 @@ paths: tags: - Bridge summary: Get transaction status - description: > - Get the transaction status for all deposits and withdrawals associated - with a given address. - - - **Usage:** - - - Use the deposit address returned from the `/deposit` or `/withdraw` - endpoint (EVM, SVM, or BTC address) - - - Poll this endpoint to track the progress of your deposits and - withdrawals - - - **Status Values:** - - - `DEPOSIT_DETECTED`: Funds detected but not yet processing - - - `PROCESSING`: Transaction is being routed and swapped - - - `ORIGIN_TX_CONFIRMED`: Origin transaction has been confirmed on source - chain - - - `SUBMITTED`: Transaction has been submitted to destination chain - - - `COMPLETED`: Transaction completed successfully - - - `FAILED`: Transaction encountered an error and did not complete - - - **Notes:** - - - Transactions typically complete within a few minutes, but may take - longer depending on network conditions - - - An empty transactions array means no transactions have been made to - this address yet parameters: - name: address in: path @@ -209,4 +147,4 @@ components: when status is DEPOSIT_DETECTED) example: 1757531217339 -```` \ No newline at end of file +```` diff --git a/docs/api-reference/builders/get-aggregated-builder-leaderboard.md b/docs/api-reference/builders/get-aggregated-builder-leaderboard.md index dadb5f2..6df43c8 100644 --- a/docs/api-reference/builders/get-aggregated-builder-leaderboard.md +++ b/docs/api-reference/builders/get-aggregated-builder-leaderboard.md @@ -4,13 +4,11 @@ # Get aggregated builder leaderboard -> Returns aggregated builder rankings with one entry per builder showing total for the specified time period. Supports pagination. - ## OpenAPI -````yaml api-reference/data-api-openapi.yaml get /v1/builders/leaderboard +````yaml api-spec/data-openapi.yaml get /v1/builders/leaderboard openapi: 3.0.3 info: title: Polymarket Data API @@ -34,9 +32,6 @@ paths: tags: - Builders summary: Get aggregated builder leaderboard - description: >- - Returns aggregated builder rankings with one entry per builder showing - total for the specified time period. Supports pagination. parameters: - in: query name: timePeriod @@ -118,4 +113,4 @@ components: required: - error -```` \ No newline at end of file +```` diff --git a/docs/api-reference/builders/get-daily-builder-volume-time-series.md b/docs/api-reference/builders/get-daily-builder-volume-time-series.md index b851413..74f76cd 100644 --- a/docs/api-reference/builders/get-daily-builder-volume-time-series.md +++ b/docs/api-reference/builders/get-daily-builder-volume-time-series.md @@ -4,13 +4,11 @@ # Get daily builder volume time-series -> Returns daily time-series volume data with multiple entries per builder (one per day), each including a `dt` timestamp. No pagination. - ## OpenAPI -````yaml api-reference/data-api-openapi.yaml get /v1/builders/volume +````yaml api-spec/data-openapi.yaml get /v1/builders/volume openapi: 3.0.3 info: title: Polymarket Data API @@ -34,9 +32,6 @@ paths: tags: - Builders summary: Get daily builder volume time-series - description: >- - Returns daily time-series volume data with multiple entries per builder - (one per day), each including a `dt` timestamp. No pagination. parameters: - in: query name: timePeriod @@ -107,4 +102,4 @@ components: required: - error -```` \ No newline at end of file +```` diff --git a/docs/api-reference/clients-sdks.md b/docs/api-reference/clients-sdks.md new file mode 100644 index 0000000..a5fdb47 --- /dev/null +++ b/docs/api-reference/clients-sdks.md @@ -0,0 +1,97 @@ +> ## 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 + + + ```bash TypeScript theme={null} + npm install @polymarket/clob-client ethers@5 + ``` + + ```bash Python theme={null} + pip install py-clob-client + ``` + + ```bash Rust theme={null} + cargo add polymarket-client-sdk + ``` + + +## Quick Example + + + ```typescript TypeScript theme={null} + import { ClobClient } from "@polymarket/clob-client"; + + const client = new ClobClient( + "https://clob.polymarket.com", + 137, + signer, + apiCreds, + ); + + const markets = await client.getMarkets(); + ``` + + ```python Python theme={null} + from py_clob_client.client import ClobClient + + client = ClobClient( + "https://clob.polymarket.com", + key=private_key, + chain_id=137, + creds=api_creds, + ) + + markets = client.get_markets() + ``` + + +## Source Code + +| Language | Package | Repository | +| ---------- | ------------------------- | ------------------------------------------------------------------------------------ | +| TypeScript | `@polymarket/clob-client` | [github.com/Polymarket/clob-client](https://github.com/Polymarket/clob-client) | +| Python | `py-clob-client` | [github.com/Polymarket/py-clob-client](https://github.com/Polymarket/py-clob-client) | +| Rust | `polymarket-client-sdk` | [github.com/Polymarket/rs-clob-client](https://github.com/Polymarket/rs-clob-client) | + +Each repository includes working examples in the `/examples` directory. + +## Builder SDKs + +If you're building an app through the [Builder Program](/builders/overview), additional signing SDKs are available: + +| Language | Package | Repository | +| ---------- | --------------------------------- | ---------------------------------------------------------------------------------------------------- | +| TypeScript | `@polymarket/builder-signing-sdk` | [github.com/Polymarket/builder-signing-sdk](https://github.com/Polymarket/builder-signing-sdk) | +| Python | `py_builder_signing_sdk` | [github.com/Polymarket/py-builder-signing-sdk](https://github.com/Polymarket/py-builder-signing-sdk) | + +See [Order Attribution](/trading/orders/attribution) for usage details. + +## Relayer SDK + +For [gasless transactions](/trading/gasless) using proxy wallets, the relayer client handles submitting transactions through Polymarket's relayer: + +| 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 + + + + Set up your client and place your first order. + + + + Understand L1/L2 auth and API credentials. + + diff --git a/docs/api-reference/comments/get-comments-by-comment-id.md b/docs/api-reference/comments/get-comments-by-comment-id.md index c9d4f39..0c54dba 100644 --- a/docs/api-reference/comments/get-comments-by-comment-id.md +++ b/docs/api-reference/comments/get-comments-by-comment-id.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /comments/{id} +````yaml api-spec/gamma-openapi.yaml get /comments/{id} openapi: 3.0.3 info: title: Markets API @@ -209,4 +209,4 @@ components: type: string nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/comments/get-comments-by-user-address.md b/docs/api-reference/comments/get-comments-by-user-address.md index 6c2d374..02988fc 100644 --- a/docs/api-reference/comments/get-comments-by-user-address.md +++ b/docs/api-reference/comments/get-comments-by-user-address.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /comments/user_address/{user_address} +````yaml api-spec/gamma-openapi.yaml get /comments/user_address/{user_address} openapi: 3.0.3 info: title: Markets API @@ -234,4 +234,4 @@ components: type: string nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/comments/list-comments.md b/docs/api-reference/comments/list-comments.md index a728fe0..a677177 100644 --- a/docs/api-reference/comments/list-comments.md +++ b/docs/api-reference/comments/list-comments.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /comments +````yaml api-spec/gamma-openapi.yaml get /comments openapi: 3.0.3 info: title: Markets API @@ -248,4 +248,4 @@ components: type: string nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/core/get-closed-positions-for-a-user.md b/docs/api-reference/core/get-closed-positions-for-a-user.md index d584cd1..9276a82 100644 --- a/docs/api-reference/core/get-closed-positions-for-a-user.md +++ b/docs/api-reference/core/get-closed-positions-for-a-user.md @@ -4,13 +4,11 @@ # Get closed positions for a user -> Fetches closed positions for a user(address) - ## OpenAPI -````yaml api-reference/data-api-openapi.yaml get /closed-positions +````yaml api-spec/data-openapi.yaml get /closed-positions openapi: 3.0.3 info: title: Polymarket Data API @@ -34,7 +32,6 @@ paths: tags: - Core summary: Get closed positions for a user - description: Fetches closed positions for a user(address) parameters: - in: query name: user @@ -194,4 +191,4 @@ components: required: - error -```` \ No newline at end of file +```` diff --git a/docs/api-reference/core/get-current-positions-for-a-user.md b/docs/api-reference/core/get-current-positions-for-a-user.md index 3f381e9..4d26310 100644 --- a/docs/api-reference/core/get-current-positions-for-a-user.md +++ b/docs/api-reference/core/get-current-positions-for-a-user.md @@ -4,13 +4,11 @@ # Get current positions for a user -> Returns positions filtered by user and optional filters. - ## OpenAPI -````yaml api-reference/data-api-openapi.yaml get /positions +````yaml api-spec/data-openapi.yaml get /positions openapi: 3.0.3 info: title: Polymarket Data API @@ -34,7 +32,6 @@ paths: tags: - Core summary: Get current positions for a user - description: Returns positions filtered by user and optional filters. parameters: - in: query name: user @@ -221,4 +218,4 @@ components: required: - error -```` \ No newline at end of file +```` diff --git a/docs/api-reference/core/get-positions-for-a-market.md b/docs/api-reference/core/get-positions-for-a-market.md index 1592016..3c164c5 100644 --- a/docs/api-reference/core/get-positions-for-a-market.md +++ b/docs/api-reference/core/get-positions-for-a-market.md @@ -4,14 +4,11 @@ # Get positions for a market -> Returns positions for a given market (condition_id), grouped by outcome token, with profile data, PnL breakdown, and current pricing. - - ## OpenAPI -````yaml api-reference/data-api-openapi.yaml get /v1/market-positions +````yaml api-spec/data-openapi.yaml get /v1/market-positions openapi: 3.0.3 info: title: Polymarket Data API @@ -35,9 +32,6 @@ paths: tags: - Core summary: Get positions for a market - description: > - Returns positions for a given market (condition_id), grouped by outcome - token, with profile data, PnL breakdown, and current pricing. parameters: - in: query name: market @@ -196,4 +190,4 @@ components: outcomeIndex: type: integer -```` \ No newline at end of file +```` diff --git a/docs/api-reference/core/get-top-holders-for-markets.md b/docs/api-reference/core/get-top-holders-for-markets.md index b2dfb9d..b646ed8 100644 --- a/docs/api-reference/core/get-top-holders-for-markets.md +++ b/docs/api-reference/core/get-top-holders-for-markets.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/data-api-openapi.yaml get /holders +````yaml api-spec/data-openapi.yaml get /holders openapi: 3.0.3 info: title: Polymarket Data API @@ -137,4 +137,4 @@ components: pattern: ^0x[a-fA-F0-9]{40}$ example: '0x56687bf447db6ffa42ffe2204a05edaa20f55839' -```` \ No newline at end of file +```` diff --git a/docs/api-reference/core/get-total-value-of-a-users-positions.md b/docs/api-reference/core/get-total-value-of-a-users-positions.md index 9871f16..d51e115 100644 --- a/docs/api-reference/core/get-total-value-of-a-users-positions.md +++ b/docs/api-reference/core/get-total-value-of-a-users-positions.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/data-api-openapi.yaml get /value +````yaml api-spec/data-openapi.yaml get /value openapi: 3.0.3 info: title: Polymarket Data API @@ -94,4 +94,4 @@ components: required: - error -```` \ No newline at end of file +```` diff --git a/docs/api-reference/core/get-trader-leaderboard-rankings.md b/docs/api-reference/core/get-trader-leaderboard-rankings.md index ac40001..ef3451a 100644 --- a/docs/api-reference/core/get-trader-leaderboard-rankings.md +++ b/docs/api-reference/core/get-trader-leaderboard-rankings.md @@ -4,13 +4,11 @@ # Get trader leaderboard rankings -> Returns trader leaderboard rankings filtered by category, time period, and ordering. - ## OpenAPI -````yaml api-reference/data-api-openapi.yaml get /v1/leaderboard +````yaml api-spec/data-openapi.yaml get /v1/leaderboard openapi: 3.0.3 info: title: Polymarket Data API @@ -34,9 +32,6 @@ paths: tags: - Core summary: Get trader leaderboard rankings - description: >- - Returns trader leaderboard rankings filtered by category, time period, - and ordering. parameters: - in: query name: category @@ -163,4 +158,4 @@ components: required: - error -```` \ No newline at end of file +```` diff --git a/docs/api-reference/core/get-trades-for-a-user-or-markets.md b/docs/api-reference/core/get-trades-for-a-user-or-markets.md index 4d42608..5b8050d 100644 --- a/docs/api-reference/core/get-trades-for-a-user-or-markets.md +++ b/docs/api-reference/core/get-trades-for-a-user-or-markets.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/data-api-openapi.yaml get /trades +````yaml api-spec/data-openapi.yaml get /trades openapi: 3.0.3 info: title: Polymarket Data API @@ -190,4 +190,4 @@ components: required: - error -```` \ No newline at end of file +```` diff --git a/docs/api-reference/core/get-user-activity.md b/docs/api-reference/core/get-user-activity.md index 22f68de..ec8fcd1 100644 --- a/docs/api-reference/core/get-user-activity.md +++ b/docs/api-reference/core/get-user-activity.md @@ -4,13 +4,11 @@ # Get user activity -> Returns on-chain activity for a user. - ## OpenAPI -````yaml api-reference/data-api-openapi.yaml get /activity +````yaml api-spec/data-openapi.yaml get /activity openapi: 3.0.3 info: title: Polymarket Data API @@ -34,7 +32,6 @@ paths: tags: - Core summary: Get user activity - description: Returns on-chain activity for a user. parameters: - in: query name: limit @@ -230,4 +227,4 @@ components: required: - error -```` \ No newline at end of file +```` diff --git a/docs/api-reference/data-api-status/data-api-health-check.md b/docs/api-reference/data-api-status/data-api-health-check.md index a5b7747..19765bd 100644 --- a/docs/api-reference/data-api-status/data-api-health-check.md +++ b/docs/api-reference/data-api-status/data-api-health-check.md @@ -1,52 +1 @@ -> ## 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 API Health check - - - -## OpenAPI - -````yaml api-reference/data-api-openapi.yaml get / -openapi: 3.0.3 -info: - title: Polymarket Data API - version: 1.0.0 - description: > - HTTP API for Polymarket data. This specification documents all public - routes. -servers: - - url: https://data-api.polymarket.com - description: Relative server (same host) -security: [] -tags: - - name: Data API Status - description: Data API health check - - name: Core - - name: Builders - - name: Misc -paths: - /: - get: - tags: - - Data API Status - summary: Data API Health check - operationId: getDataApiHealth - responses: - '200': - description: OK - content: - application/json: - schema: - $ref: '#/components/schemas/HealthResponse' -components: - schemas: - HealthResponse: - type: object - properties: - data: - type: string - example: OK - -```` \ No newline at end of file +null diff --git a/docs/api-reference/data/get-server-time.md b/docs/api-reference/data/get-server-time.md new file mode 100644 index 0000000..6cb9c49 --- /dev/null +++ b/docs/api-reference/data/get-server-time.md @@ -0,0 +1,79 @@ +> ## 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 server time + +> Returns the current Unix timestamp of the server. +This can be used to synchronize client time with server time. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /time +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 +paths: + /time: + get: + tags: + - Data + summary: Get server time + description: | + Returns the current Unix timestamp of the server. + This can be used to synchronize client time with server time. + operationId: getTime + responses: + '200': + description: Successfully retrieved server time + content: + application/json: + schema: + type: integer + format: int64 + description: Unix timestamp (seconds since epoch) + example: 1234567890 + '400': + description: Bad request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + security: [] +components: + schemas: + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/events/get-event-by-id.md b/docs/api-reference/events/get-event-by-id.md index 5344f5e..6439a40 100644 --- a/docs/api-reference/events/get-event-by-id.md +++ b/docs/api-reference/events/get-event-by-id.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /events/{id} +````yaml api-spec/gamma-openapi.yaml get /events/{id} openapi: 3.0.3 info: title: Markets API @@ -1190,4 +1190,4 @@ components: type: string nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/events/get-event-by-slug.md b/docs/api-reference/events/get-event-by-slug.md index ec5909c..c5086f8 100644 --- a/docs/api-reference/events/get-event-by-slug.md +++ b/docs/api-reference/events/get-event-by-slug.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /events/slug/{slug} +````yaml api-spec/gamma-openapi.yaml get /events/slug/{slug} openapi: 3.0.3 info: title: Markets API @@ -1190,4 +1190,4 @@ components: type: string nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/events/get-event-tags.md b/docs/api-reference/events/get-event-tags.md index d9a1254..97ce97b 100644 --- a/docs/api-reference/events/get-event-tags.md +++ b/docs/api-reference/events/get-event-tags.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /events/{id}/tags +````yaml api-spec/gamma-openapi.yaml get /events/{id}/tags openapi: 3.0.3 info: title: Markets API @@ -105,4 +105,4 @@ components: type: boolean nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/events/list-events.md b/docs/api-reference/events/list-events.md index 4c39d01..ae022a2 100644 --- a/docs/api-reference/events/list-events.md +++ b/docs/api-reference/events/list-events.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /events +````yaml api-spec/gamma-openapi.yaml get /events openapi: 3.0.3 info: title: Markets API @@ -1300,4 +1300,4 @@ components: type: string nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/gamma-status/gamma-api-health-check.md b/docs/api-reference/gamma-status/gamma-api-health-check.md index c8b1aa3..19765bd 100644 --- a/docs/api-reference/gamma-status/gamma-api-health-check.md +++ b/docs/api-reference/gamma-status/gamma-api-health-check.md @@ -1,56 +1 @@ -> ## 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. - -# Gamma API Health check - - - -## OpenAPI - -````yaml api-reference/gamma-openapi.json get /status -openapi: 3.0.3 -info: - title: Markets API - version: 1.0.0 - description: REST API specification for public endpoints used by the Markets service. -servers: - - url: https://gamma-api.polymarket.com - description: Polymarket Gamma API Production Server -security: [] -tags: - - name: Gamma Status - description: Gamma API status and health check - - name: Sports - description: Sports-related endpoints including teams and game data - - name: Tags - description: Tag management and related tag operations - - name: Events - description: Event management and event-related operations - - name: Markets - description: Market data and market-related operations - - name: Comments - description: Comment system and user interactions - - name: Series - description: Series management and related operations - - name: Profiles - description: User profile management - - name: Search - description: Search functionality across different entity types -paths: - /status: - get: - tags: - - Gamma Status - summary: Gamma API Health check - operationId: getGammaStatus - responses: - '200': - description: OK - content: - text/plain: - schema: - type: string - example: OK - -```` \ No newline at end of file +null diff --git a/docs/api-reference/geoblock.md b/docs/api-reference/geoblock.md new file mode 100644 index 0000000..24690aa --- /dev/null +++ b/docs/api-reference/geoblock.md @@ -0,0 +1,193 @@ +> ## 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. + + + 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. + + +*** + +## Geoblock Endpoint + +Check the geographic eligibility of the requesting IP address: + +```bash theme={null} +GET https://polymarket.com/api/geoblock +``` + +This endpoint is on `polymarket.com`, not the API servers. + +### 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: + +| 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 | +| KP | North Korea | Blocked | +| LB | Lebanon | Blocked | +| LY | Libya | Blocked | +| MM | Myanmar | Blocked | +| NI | Nicaragua | 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 + +*** + +## Usage Examples + + + + ```typescript theme={null} + interface GeoblockResponse { + blocked: boolean; + ip: string; + country: string; + region: string; + } + + async function checkGeoblock(): Promise { + 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"); + } + ``` + + + + ```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") + ``` + + + +*** + +## 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 + + + + Learn how to authenticate trading requests. + + + + Start placing orders (from eligible regions). + + diff --git a/docs/api-reference/introduction.md b/docs/api-reference/introduction.md new file mode 100644 index 0000000..003f8c4 --- /dev/null +++ b/docs/api-reference/introduction.md @@ -0,0 +1,59 @@ +> ## 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. + +# Introduction + +> Overview of the Polymarket APIs + +The Polymarket API provides programmatic access to the world's largest prediction market. The platform is served by three separate APIs, each handling a different domain. + +*** + +## APIs + + + + **`https://gamma-api.polymarket.com`** + + Markets, events, tags, series, comments, sports, search, and public profiles. This is the primary API for discovering and browsing market data. + + + + **`https://data-api.polymarket.com`** + + User positions, trades, activity, holder data, open interest, leaderboards, and builder analytics. + + + + **`https://clob.polymarket.com`** + + Orderbook data, pricing, midpoints, spreads, and price history. Also handles order placement, cancellation, and other trading operations. Trading endpoints require [authentication](/api-reference/authentication). + + + + + A separate **Bridge API** (`https://bridge.polymarket.com`) handles deposits and withdrawals. Bridges are not handled by Polymarket, it is a proxy of fun.xyz service. + + +*** + +## Authentication + +The Gamma API and Data API are fully public — no authentication required. + +The CLOB API has both public endpoints (orderbook, prices) and authenticated endpoints (order management). See [Authentication](/api-reference/authentication) for details. + +*** + +## Next Steps + + + + Learn how to authenticate requests for trading endpoints. + + + + Official TypeScript, Python, and Rust libraries. + + diff --git a/docs/api-reference/market-data/get-fee-rate-by-path-parameter.md b/docs/api-reference/market-data/get-fee-rate-by-path-parameter.md new file mode 100644 index 0000000..62742bc --- /dev/null +++ b/docs/api-reference/market-data/get-fee-rate-by-path-parameter.md @@ -0,0 +1,113 @@ +> ## 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 fee rate by path parameter + +> Retrieves the base fee rate for a specific token ID using the token ID as a path parameter. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /fee-rate/{token_id} +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 +paths: + /fee-rate/{token_id}: + get: + tags: + - Market Data + summary: Get fee rate by path parameter + description: > + Retrieves the base fee rate for a specific token ID using the token ID + as a path parameter. + operationId: getFeeRateByPath + parameters: + - name: token_id + in: path + description: Token ID (asset ID) + required: true + schema: + type: string + example: 0xabc123def456... + responses: + '200': + description: Successfully retrieved fee rate + content: + application/json: + schema: + $ref: '#/components/schemas/FeeRate' + example: + base_fee: 30 + '400': + description: Bad request - Invalid token id + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid token id + '404': + description: Not found - Fee rate not found for market + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: fee rate not found for market + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + security: [] +components: + schemas: + FeeRate: + type: object + required: + - base_fee + properties: + base_fee: + type: integer + format: int64 + description: Base fee in basis points + example: 30 + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/market-data/get-fee-rate.md b/docs/api-reference/market-data/get-fee-rate.md new file mode 100644 index 0000000..dfd4fe7 --- /dev/null +++ b/docs/api-reference/market-data/get-fee-rate.md @@ -0,0 +1,116 @@ +> ## 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 fee rate + +> Retrieves the base fee rate for a specific token ID. +The fee rate can be provided either as a query parameter or as a path parameter. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /fee-rate +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 +paths: + /fee-rate: + get: + tags: + - Market Data + summary: Get fee rate + description: > + Retrieves the base fee rate for a specific token ID. + + The fee rate can be provided either as a query parameter or as a path + parameter. + operationId: getFeeRate + parameters: + - name: token_id + in: query + description: Token ID (asset ID) + required: false + schema: + type: string + example: 0xabc123def456... + responses: + '200': + description: Successfully retrieved fee rate + content: + application/json: + schema: + $ref: '#/components/schemas/FeeRate' + example: + base_fee: 30 + '400': + description: Bad request - Invalid token id + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid token id + '404': + description: Not found - Fee rate not found for market + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: fee rate not found for market + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + security: [] +components: + schemas: + FeeRate: + type: object + required: + - base_fee + properties: + base_fee: + type: integer + format: int64 + description: Base fee in basis points + example: 30 + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/market-data/get-last-trade-price.md b/docs/api-reference/market-data/get-last-trade-price.md new file mode 100644 index 0000000..d85bcbf --- /dev/null +++ b/docs/api-reference/market-data/get-last-trade-price.md @@ -0,0 +1,112 @@ +> ## 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 last trade price + +> Retrieves the last trade price and side for a specific token ID. +Returns default values of "0.5" for price and empty string for side if no trades found. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /last-trade-price +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 +paths: + /last-trade-price: + get: + tags: + - Market Data + summary: Get last trade price + description: > + Retrieves the last trade price and side for a specific token ID. + + Returns default values of "0.5" for price and empty string for side if + no trades found. + operationId: getLastTradePrice + parameters: + - name: token_id + in: query + description: Token ID (asset ID) + required: true + schema: + type: string + example: 0xabc123def456... + responses: + '200': + description: Successfully retrieved last trade price + content: + application/json: + schema: + type: object + required: + - price + - side + properties: + price: + type: string + description: Last trade price + example: '0.45' + side: + type: string + description: Last trade side (BUY or SELL) + enum: + - BUY + - SELL + - '' + example: BUY + '400': + description: Bad request - Invalid token id + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid token id + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + security: [] +components: + schemas: + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/market-data/get-last-trade-prices-query-parameters.md b/docs/api-reference/market-data/get-last-trade-prices-query-parameters.md new file mode 100644 index 0000000..abde495 --- /dev/null +++ b/docs/api-reference/market-data/get-last-trade-prices-query-parameters.md @@ -0,0 +1,132 @@ +> ## 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 last trade prices (query parameters) + +> Retrieves last trade prices for multiple token IDs using query parameters. +Maximum 500 token IDs can be requested per call. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /last-trades-prices +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 +paths: + /last-trades-prices: + get: + tags: + - Market Data + summary: Get last trade prices (query parameters) + description: > + Retrieves last trade prices for multiple token IDs using query + parameters. + + Maximum 500 token IDs can be requested per call. + operationId: getLastTradesPricesGet + parameters: + - name: token_ids + in: query + description: Comma-separated list of token IDs (max 500) + required: true + schema: + type: string + example: 0xabc123...,0xdef456... + responses: + '200': + description: Successfully retrieved last trade prices + content: + application/json: + schema: + type: array + items: + type: object + required: + - token_id + - price + - side + properties: + token_id: + type: string + description: Token ID (asset ID) + example: 0xabc123def456... + price: + type: string + description: Last trade price + example: '0.45' + side: + type: string + description: Last trade side (BUY or SELL) + enum: + - BUY + - SELL + example: BUY + example: + - token_id: 0xabc123def456... + price: '0.45' + side: BUY + - token_id: 0xdef456abc123... + price: '0.52' + side: SELL + '400': + description: Bad request - Invalid payload or exceeds limit + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + invalid_payload: + summary: Invalid payload + value: + error: Invalid payload + exceeds_limit: + summary: Payload exceeds limit + value: + error: Payload exceeds the limit + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + security: [] +components: + schemas: + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/market-data/get-last-trade-prices-request-body.md b/docs/api-reference/market-data/get-last-trade-prices-request-body.md new file mode 100644 index 0000000..9046722 --- /dev/null +++ b/docs/api-reference/market-data/get-last-trade-prices-request-body.md @@ -0,0 +1,149 @@ +> ## 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 last trade prices (request body) + +> Retrieves last trade prices for multiple token IDs using a request body. +Maximum 500 token IDs can be requested per call. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml post /last-trades-prices +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 +paths: + /last-trades-prices: + post: + tags: + - Market Data + summary: Get last trade prices (request body) + description: | + Retrieves last trade prices for multiple token IDs using a request body. + Maximum 500 token IDs can be requested per call. + operationId: getLastTradesPricesPost + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/BookRequest' + example: + - token_id: 0xabc123def456... + - token_id: 0xdef456abc123... + responses: + '200': + description: Successfully retrieved last trade prices + content: + application/json: + schema: + type: array + items: + type: object + required: + - token_id + - price + - side + properties: + token_id: + type: string + description: Token ID (asset ID) + example: 0xabc123def456... + price: + type: string + description: Last trade price + example: '0.45' + side: + type: string + description: Last trade side (BUY or SELL) + enum: + - BUY + - SELL + example: BUY + example: + - token_id: 0xabc123def456... + price: '0.45' + side: BUY + - token_id: 0xdef456abc123... + price: '0.52' + side: SELL + '400': + description: Bad request - Invalid payload or exceeds limit + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + invalid_payload: + summary: Invalid payload + value: + error: Invalid payload + exceeds_limit: + summary: Payload exceeds limit + value: + error: Payload exceeds the limit + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + security: [] +components: + schemas: + BookRequest: + type: object + required: + - token_id + properties: + token_id: + type: string + description: Token ID (asset ID) + example: 0xabc123def456... + side: + type: string + description: Order side (optional, not used for midpoint calculation) + enum: + - BUY + - SELL + example: BUY + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/market-data/get-market-price.md b/docs/api-reference/market-data/get-market-price.md new file mode 100644 index 0000000..f7d576d --- /dev/null +++ b/docs/api-reference/market-data/get-market-price.md @@ -0,0 +1,131 @@ +> ## 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 market price + +> Retrieves the best market price for a specific token ID and side (bid or ask). +Returns the best bid price for BUY side or best ask price for SELL side. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /price +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 +paths: + /price: + get: + tags: + - Market Data + summary: Get market price + description: > + Retrieves the best market price for a specific token ID and side (bid or + ask). + + Returns the best bid price for BUY side or best ask price for SELL side. + operationId: getPrice + parameters: + - name: token_id + in: query + description: Token ID (asset ID) + required: true + schema: + type: string + example: 0xabc123def456... + - name: side + in: query + description: Order side + required: true + schema: + type: string + enum: + - BUY + - SELL + example: BUY + responses: + '200': + description: Successfully retrieved market price + content: + application/json: + schema: + type: object + required: + - price + properties: + price: + type: number + format: double + description: Market price as a decimal number + example: 0.45 + example: + price: 0.45 + '400': + description: Bad request - Invalid token id or side + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + invalid_token_id: + summary: Invalid token id + value: + error: Invalid token id + invalid_side: + summary: Invalid side + value: + error: Invalid side + '404': + description: Not found - No orderbook exists for the requested token id + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: No orderbook exists for the requested token id + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + security: [] +components: + schemas: + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/market-data/get-market-prices-query-parameters.md b/docs/api-reference/market-data/get-market-prices-query-parameters.md new file mode 100644 index 0000000..50c67a8 --- /dev/null +++ b/docs/api-reference/market-data/get-market-prices-query-parameters.md @@ -0,0 +1,128 @@ +> ## 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 market prices (query parameters) + +> Retrieves market prices for multiple token IDs and sides using query parameters. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /prices +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 +paths: + /prices: + get: + tags: + - Market Data + summary: Get market prices (query parameters) + description: > + Retrieves market prices for multiple token IDs and sides using query + parameters. + operationId: getPricesGet + parameters: + - name: token_ids + in: query + description: Comma-separated list of token IDs + required: true + schema: + type: string + example: 0xabc123...,0xdef456... + - name: sides + in: query + description: >- + Comma-separated list of sides (BUY or SELL) corresponding to token + IDs + required: true + schema: + type: string + example: BUY,SELL + responses: + '200': + description: Successfully retrieved market prices + content: + application/json: + schema: + type: object + additionalProperties: + type: object + additionalProperties: + type: number + format: double + description: Map of token ID to map of side to price + example: + 0xabc123def456...: + BUY: 0.45 + 0xdef456abc123...: + SELL: 0.52 + '400': + description: Bad request - Invalid payload or side + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + invalid_payload: + summary: Invalid payload + value: + error: Invalid payload + invalid_side: + summary: Invalid side + value: + error: Invalid side + '404': + description: Not found - No orderbook exists for the requested token id + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: No orderbook exists for the requested token id + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + security: [] +components: + schemas: + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/market-data/get-market-prices-request-body.md b/docs/api-reference/market-data/get-market-prices-request-body.md new file mode 100644 index 0000000..c8d3da6 --- /dev/null +++ b/docs/api-reference/market-data/get-market-prices-request-body.md @@ -0,0 +1,143 @@ +> ## 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 market prices (request body) + +> Retrieves market prices for multiple token IDs and sides using a request body. +Each request must include both token_id and side. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml post /prices +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 +paths: + /prices: + post: + tags: + - Market Data + summary: Get market prices (request body) + description: > + Retrieves market prices for multiple token IDs and sides using a request + body. + + Each request must include both token_id and side. + operationId: getPricesPost + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/BookRequest' + example: + - token_id: 0xabc123def456... + side: BUY + - token_id: 0xdef456abc123... + side: SELL + responses: + '200': + description: Successfully retrieved market prices + content: + application/json: + schema: + type: object + additionalProperties: + type: object + additionalProperties: + type: number + format: double + description: Map of token ID to map of side to price + example: + 0xabc123def456...: + BUY: 0.45 + 0xdef456abc123...: + SELL: 0.52 + '400': + description: Bad request - Invalid payload or side + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + invalid_payload: + summary: Invalid payload + value: + error: Invalid payload + invalid_side: + summary: Invalid side + value: + error: Invalid side + '404': + description: Not found - No orderbook exists for the requested token id + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: No orderbook exists for the requested token id + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + security: [] +components: + schemas: + BookRequest: + type: object + required: + - token_id + properties: + token_id: + type: string + description: Token ID (asset ID) + example: 0xabc123def456... + side: + type: string + description: Order side (optional, not used for midpoint calculation) + enum: + - BUY + - SELL + example: BUY + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/market-data/get-midpoint-price.md b/docs/api-reference/market-data/get-midpoint-price.md new file mode 100644 index 0000000..19765bd --- /dev/null +++ b/docs/api-reference/market-data/get-midpoint-price.md @@ -0,0 +1 @@ +null diff --git a/docs/api-reference/market-data/get-midpoint-prices-query-parameters.md b/docs/api-reference/market-data/get-midpoint-prices-query-parameters.md new file mode 100644 index 0000000..7307cb7 --- /dev/null +++ b/docs/api-reference/market-data/get-midpoint-prices-query-parameters.md @@ -0,0 +1,102 @@ +> ## 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 midpoint prices (query parameters) + +> Retrieves midpoint prices for multiple token IDs using query parameters. +The midpoint is calculated as the average of the best bid and best ask prices. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /midpoints +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 +paths: + /midpoints: + get: + tags: + - Market Data + summary: Get midpoint prices (query parameters) + description: > + Retrieves midpoint prices for multiple token IDs using query parameters. + + The midpoint is calculated as the average of the best bid and best ask + prices. + operationId: getMidpointsGet + parameters: + - name: token_ids + in: query + description: Comma-separated list of token IDs + required: true + schema: + type: string + example: 0xabc123...,0xdef456... + responses: + '200': + description: Successfully retrieved midpoint prices + content: + application/json: + schema: + type: object + additionalProperties: + type: string + description: Map of token ID to midpoint price + example: + 0xabc123def456...: '0.45' + 0xdef456abc123...: '0.52' + '400': + description: Bad request - Invalid payload + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid payload + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: error getting the mid price + security: [] +components: + schemas: + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/market-data/get-midpoint-prices-request-body.md b/docs/api-reference/market-data/get-midpoint-prices-request-body.md new file mode 100644 index 0000000..1b3bf72 --- /dev/null +++ b/docs/api-reference/market-data/get-midpoint-prices-request-body.md @@ -0,0 +1,121 @@ +> ## 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 midpoint prices (request body) + +> Retrieves midpoint prices for multiple token IDs using a request body. +The midpoint is calculated as the average of the best bid and best ask prices. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml post /midpoints +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 +paths: + /midpoints: + post: + tags: + - Market Data + summary: Get midpoint prices (request body) + description: > + Retrieves midpoint prices for multiple token IDs using a request body. + + The midpoint is calculated as the average of the best bid and best ask + prices. + operationId: getMidpointsPost + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/BookRequest' + example: + - token_id: 0xabc123def456... + - token_id: 0xdef456abc123... + responses: + '200': + description: Successfully retrieved midpoint prices + content: + application/json: + schema: + type: object + additionalProperties: + type: string + description: Map of token ID to midpoint price + example: + 0xabc123def456...: '0.45' + 0xdef456abc123...: '0.52' + '400': + description: Bad request - Invalid payload + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid payload + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: error getting the mid price + security: [] +components: + schemas: + BookRequest: + type: object + required: + - token_id + properties: + token_id: + type: string + description: Token ID (asset ID) + example: 0xabc123def456... + side: + type: string + description: Order side (optional, not used for midpoint calculation) + enum: + - BUY + - SELL + example: BUY + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/market-data/get-order-book.md b/docs/api-reference/market-data/get-order-book.md new file mode 100644 index 0000000..49553cc --- /dev/null +++ b/docs/api-reference/market-data/get-order-book.md @@ -0,0 +1,191 @@ +> ## 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 order book + +> Retrieves the order book summary for a specific token ID. +Includes bids, asks, market details, and last trade price. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /book +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 +paths: + /book: + get: + tags: + - Market Data + summary: Get order book + description: | + Retrieves the order book summary for a specific token ID. + Includes bids, asks, market details, and last trade price. + operationId: getBook + parameters: + - name: token_id + in: query + description: Token ID (asset ID) + required: true + schema: + type: string + example: 0xabc123def456... + responses: + '200': + description: Successfully retrieved order book + content: + application/json: + schema: + $ref: '#/components/schemas/OrderBookSummary' + example: + market: '0x1234567890123456789012345678901234567890' + asset_id: 0xabc123def456... + timestamp: '1234567890' + hash: a1b2c3d4e5f6... + bids: + - price: '0.45' + size: '100' + - price: '0.44' + size: '200' + asks: + - price: '0.46' + size: '150' + - price: '0.47' + size: '250' + min_order_size: '1' + tick_size: '0.01' + neg_risk: false + last_trade_price: '0.45' + '400': + description: Bad request - Invalid token id + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid token id + '404': + description: Not found - No orderbook exists for the requested token id + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: No orderbook exists for the requested token id + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: error getting the orderbook + security: [] +components: + schemas: + OrderBookSummary: + type: object + required: + - market + - asset_id + - timestamp + - hash + - bids + - asks + - min_order_size + - tick_size + - neg_risk + - last_trade_price + properties: + market: + type: string + description: Market condition ID + example: '0x1234567890123456789012345678901234567890' + asset_id: + type: string + description: Token ID (asset ID) + example: 0xabc123def456... + timestamp: + type: string + description: Timestamp of the order book snapshot + example: '1234567890' + hash: + type: string + description: Hash of the order book summary + example: a1b2c3d4e5f6... + bids: + type: array + description: List of bid orders (sorted by price descending) + items: + $ref: '#/components/schemas/OrderSummary' + asks: + type: array + description: List of ask orders (sorted by price ascending) + items: + $ref: '#/components/schemas/OrderSummary' + min_order_size: + type: string + description: Minimum order size + example: '1' + tick_size: + type: string + description: Minimum price increment (tick size) + example: '0.01' + neg_risk: + type: boolean + description: Whether negative risk is enabled for this market + example: false + last_trade_price: + type: string + description: Last trade price + example: '0.45' + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + OrderSummary: + type: object + required: + - price + - size + properties: + price: + type: string + description: Order price + example: '0.45' + size: + type: string + description: Order size + example: '100' + +```` diff --git a/docs/api-reference/market-data/get-order-books-request-body.md b/docs/api-reference/market-data/get-order-books-request-body.md new file mode 100644 index 0000000..611b22a --- /dev/null +++ b/docs/api-reference/market-data/get-order-books-request-body.md @@ -0,0 +1,191 @@ +> ## 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 order books (request body) + +> Retrieves order book summaries for multiple token IDs using a request body. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml post /books +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 +paths: + /books: + post: + tags: + - Market Data + summary: Get order books (request body) + description: > + Retrieves order book summaries for multiple token IDs using a request + body. + operationId: getBooksPost + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/BookRequest' + example: + - token_id: 0xabc123def456... + - token_id: 0xdef456abc123... + responses: + '200': + description: Successfully retrieved order books + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/OrderBookSummary' + example: + - market: '0x1234567890123456789012345678901234567890' + asset_id: 0xabc123def456... + timestamp: '1234567890' + hash: a1b2c3d4e5f6... + bids: + - price: '0.45' + size: '100' + asks: + - price: '0.46' + size: '150' + min_order_size: '1' + tick_size: '0.01' + neg_risk: false + last_trade_price: '0.45' + '400': + description: Bad request - Invalid payload + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid payload + security: [] +components: + schemas: + BookRequest: + type: object + required: + - token_id + properties: + token_id: + type: string + description: Token ID (asset ID) + example: 0xabc123def456... + side: + type: string + description: Order side (optional, not used for midpoint calculation) + enum: + - BUY + - SELL + example: BUY + OrderBookSummary: + type: object + required: + - market + - asset_id + - timestamp + - hash + - bids + - asks + - min_order_size + - tick_size + - neg_risk + - last_trade_price + properties: + market: + type: string + description: Market condition ID + example: '0x1234567890123456789012345678901234567890' + asset_id: + type: string + description: Token ID (asset ID) + example: 0xabc123def456... + timestamp: + type: string + description: Timestamp of the order book snapshot + example: '1234567890' + hash: + type: string + description: Hash of the order book summary + example: a1b2c3d4e5f6... + bids: + type: array + description: List of bid orders (sorted by price descending) + items: + $ref: '#/components/schemas/OrderSummary' + asks: + type: array + description: List of ask orders (sorted by price ascending) + items: + $ref: '#/components/schemas/OrderSummary' + min_order_size: + type: string + description: Minimum order size + example: '1' + tick_size: + type: string + description: Minimum price increment (tick size) + example: '0.01' + neg_risk: + type: boolean + description: Whether negative risk is enabled for this market + example: false + last_trade_price: + type: string + description: Last trade price + example: '0.45' + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + OrderSummary: + type: object + required: + - price + - size + properties: + price: + type: string + description: Order price + example: '0.45' + size: + type: string + description: Order size + example: '100' + +```` diff --git a/docs/api-reference/market-data/get-spread.md b/docs/api-reference/market-data/get-spread.md new file mode 100644 index 0000000..c764a34 --- /dev/null +++ b/docs/api-reference/market-data/get-spread.md @@ -0,0 +1,101 @@ +> ## 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 spread + +> Retrieves the spread for a specific token ID. +The spread is the difference between the best ask and best bid prices. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /spread +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 +paths: + /spread: + get: + tags: + - Market Data + summary: Get spread + description: | + Retrieves the spread for a specific token ID. + The spread is the difference between the best ask and best bid prices. + operationId: getSpread + parameters: + - name: token_id + in: query + description: Token ID (asset ID) + required: true + schema: + type: string + example: 0xabc123def456... + responses: + '200': + description: Successfully retrieved spread + content: + application/json: + schema: + type: object + required: + - spread + properties: + spread: + type: string + description: Spread as a string + example: '0.02' + '400': + description: Bad request - Invalid token id + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid token id + '404': + description: Not found - No orderbook exists for the requested token id + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: No orderbook exists for the requested token id + security: [] +components: + schemas: + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/market-data/get-spreads.md b/docs/api-reference/market-data/get-spreads.md new file mode 100644 index 0000000..7739be0 --- /dev/null +++ b/docs/api-reference/market-data/get-spreads.md @@ -0,0 +1,119 @@ +> ## 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 spreads + +> Retrieves spreads for multiple token IDs. +The spread is the difference between the best ask and best bid prices. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml post /spreads +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 +paths: + /spreads: + post: + tags: + - Market Data + summary: Get spreads + description: | + Retrieves spreads for multiple token IDs. + The spread is the difference between the best ask and best bid prices. + operationId: getSpreads + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/BookRequest' + example: + - token_id: 0xabc123def456... + - token_id: 0xdef456abc123... + responses: + '200': + description: Successfully retrieved spreads + content: + application/json: + schema: + type: object + additionalProperties: + type: string + description: Map of token ID to spread + example: + 0xabc123def456...: '0.02' + 0xdef456abc123...: '0.015' + '400': + description: Bad request - Invalid payload + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid payload + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: error getting the spread + security: [] +components: + schemas: + BookRequest: + type: object + required: + - token_id + properties: + token_id: + type: string + description: Token ID (asset ID) + example: 0xabc123def456... + side: + type: string + description: Order side (optional, not used for midpoint calculation) + enum: + - BUY + - SELL + example: BUY + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/market-data/get-tick-size-by-path-parameter.md b/docs/api-reference/market-data/get-tick-size-by-path-parameter.md new file mode 100644 index 0000000..1c4c5df --- /dev/null +++ b/docs/api-reference/market-data/get-tick-size-by-path-parameter.md @@ -0,0 +1,113 @@ +> ## 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 tick size by path parameter + +> Retrieves the minimum tick size (price increment) for a specific token ID using the token ID as a path parameter. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /tick-size/{token_id} +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 +paths: + /tick-size/{token_id}: + get: + tags: + - Market Data + summary: Get tick size by path parameter + description: > + Retrieves the minimum tick size (price increment) for a specific token + ID using the token ID as a path parameter. + operationId: getTickSizeByPath + parameters: + - name: token_id + in: path + description: Token ID (asset ID) + required: true + schema: + type: string + example: 0xabc123def456... + responses: + '200': + description: Successfully retrieved tick size + content: + application/json: + schema: + $ref: '#/components/schemas/TickSize' + example: + minimum_tick_size: 0.01 + '400': + description: Bad request - Invalid token id + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid token id + '404': + description: Not found - Market not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: market not found + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + security: [] +components: + schemas: + TickSize: + type: object + required: + - minimum_tick_size + properties: + minimum_tick_size: + type: number + format: double + description: Minimum tick size (price increment) + example: 0.01 + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/market-data/get-tick-size.md b/docs/api-reference/market-data/get-tick-size.md new file mode 100644 index 0000000..c893938 --- /dev/null +++ b/docs/api-reference/market-data/get-tick-size.md @@ -0,0 +1,117 @@ +> ## 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 tick size + +> Retrieves the minimum tick size (price increment) for a specific token ID. +The tick size can be provided either as a query parameter or as a path parameter. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /tick-size +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 +paths: + /tick-size: + get: + tags: + - Market Data + summary: Get tick size + description: > + Retrieves the minimum tick size (price increment) for a specific token + ID. + + The tick size can be provided either as a query parameter or as a path + parameter. + operationId: getTickSize + parameters: + - name: token_id + in: query + description: Token ID (asset ID) + required: false + schema: + type: string + example: 0xabc123def456... + responses: + '200': + description: Successfully retrieved tick size + content: + application/json: + schema: + $ref: '#/components/schemas/TickSize' + example: + minimum_tick_size: 0.01 + '400': + description: Bad request - Invalid token id + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid token id + '404': + description: Not found - Market not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: market not found + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + security: [] +components: + schemas: + TickSize: + type: object + required: + - minimum_tick_size + properties: + minimum_tick_size: + type: number + format: double + description: Minimum tick size (price increment) + example: 0.01 + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + +```` diff --git a/docs/api-reference/markets/get-market-by-id.md b/docs/api-reference/markets/get-market-by-id.md index 05ac2e0..2ce21f4 100644 --- a/docs/api-reference/markets/get-market-by-id.md +++ b/docs/api-reference/markets/get-market-by-id.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /markets/{id} +````yaml api-spec/gamma-openapi.yaml get /markets/{id} openapi: 3.0.3 info: title: Markets API @@ -1186,4 +1186,4 @@ components: type: string nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/markets/get-market-by-slug.md b/docs/api-reference/markets/get-market-by-slug.md index fd0c39e..0b0c661 100644 --- a/docs/api-reference/markets/get-market-by-slug.md +++ b/docs/api-reference/markets/get-market-by-slug.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /markets/slug/{slug} +````yaml api-spec/gamma-openapi.yaml get /markets/slug/{slug} openapi: 3.0.3 info: title: Markets API @@ -1186,4 +1186,4 @@ components: type: string nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/markets/get-market-tags-by-id.md b/docs/api-reference/markets/get-market-tags-by-id.md index 83e5606..f55385d 100644 --- a/docs/api-reference/markets/get-market-tags-by-id.md +++ b/docs/api-reference/markets/get-market-tags-by-id.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /markets/{id}/tags +````yaml api-spec/gamma-openapi.yaml get /markets/{id}/tags openapi: 3.0.3 info: title: Markets API @@ -105,4 +105,4 @@ components: type: boolean nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/markets/get-prices-history.md b/docs/api-reference/markets/get-prices-history.md new file mode 100644 index 0000000..de671aa --- /dev/null +++ b/docs/api-reference/markets/get-prices-history.md @@ -0,0 +1,135 @@ +> ## 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 +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 + MarketPrice: + type: object + properties: + t: + type: integer + format: uint32 + p: + type: number + format: float + +```` diff --git a/docs/api-reference/markets/get-sampling-markets.md b/docs/api-reference/markets/get-sampling-markets.md new file mode 100644 index 0000000..d6329b2 --- /dev/null +++ b/docs/api-reference/markets/get-sampling-markets.md @@ -0,0 +1,181 @@ +> ## 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 sampling markets + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /sampling-markets +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 +paths: + /sampling-markets: + get: + tags: + - Markets + summary: Get sampling markets + operationId: getSamplingMarkets + parameters: + - name: next_cursor + in: query + required: false + schema: + type: string + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedMarkets' + '400': + description: Invalid request + '500': + description: Internal server error + security: [] +components: + schemas: + PaginatedMarkets: + type: object + properties: + limit: + type: integer + next_cursor: + type: string + count: + type: integer + data: + type: array + items: + $ref: '#/components/schemas/Market' + Market: + type: object + properties: + enable_order_book: + type: boolean + active: + type: boolean + closed: + type: boolean + archived: + type: boolean + accepting_orders: + type: boolean + accepting_order_timestamp: + type: string + format: date-time + minimum_order_size: + type: number + format: double + minimum_tick_size: + type: number + format: double + condition_id: + type: string + question_id: + type: string + question: + type: string + description: + type: string + market_slug: + type: string + end_date_iso: + type: string + format: date-time + game_start_time: + type: string + format: date-time + seconds_delay: + type: integer + fpmm: + type: string + maker_base_fee: + type: integer + format: int64 + taker_base_fee: + type: integer + format: int64 + notifications_enabled: + type: boolean + neg_risk: + type: boolean + neg_risk_market_id: + type: string + neg_risk_request_id: + type: string + icon: + type: string + image: + type: string + rewards: + $ref: '#/components/schemas/Rewards' + is_50_50_outcome: + type: boolean + tokens: + type: array + items: + $ref: '#/components/schemas/Token' + tags: + type: array + items: + type: string + Rewards: + type: object + properties: + rates: + type: array + items: + type: object + properties: + asset_address: + type: string + rewards_daily_rate: + type: number + format: double + min_size: + type: number + format: double + max_spread: + type: number + format: double + Token: + type: object + properties: + token_id: + type: string + outcome: + type: string + price: + type: number + format: double + winner: + type: boolean + +```` diff --git a/docs/api-reference/markets/get-sampling-simplified-markets.md b/docs/api-reference/markets/get-sampling-simplified-markets.md new file mode 100644 index 0000000..a29c04d --- /dev/null +++ b/docs/api-reference/markets/get-sampling-simplified-markets.md @@ -0,0 +1,128 @@ +> ## 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 sampling simplified markets + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /sampling-simplified-markets +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 +paths: + /sampling-simplified-markets: + get: + tags: + - Markets + summary: Get sampling simplified markets + operationId: getSamplingSimplifiedMarkets + parameters: + - name: next_cursor + in: query + required: false + schema: + type: string + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedSimplifiedMarkets' + '400': + description: Invalid request + '500': + description: Internal server error + security: [] +components: + schemas: + PaginatedSimplifiedMarkets: + type: object + properties: + limit: + type: integer + next_cursor: + type: string + count: + type: integer + data: + type: array + items: + $ref: '#/components/schemas/SimplifiedMarket' + SimplifiedMarket: + type: object + properties: + condition_id: + type: string + rewards: + $ref: '#/components/schemas/Rewards' + tokens: + type: array + items: + $ref: '#/components/schemas/Token' + active: + type: boolean + closed: + type: boolean + archived: + type: boolean + accepting_orders: + type: boolean + Rewards: + type: object + properties: + rates: + type: array + items: + type: object + properties: + asset_address: + type: string + rewards_daily_rate: + type: number + format: double + min_size: + type: number + format: double + max_spread: + type: number + format: double + Token: + type: object + properties: + token_id: + type: string + outcome: + type: string + price: + type: number + format: double + winner: + type: boolean + +```` diff --git a/docs/api-reference/markets/get-simplified-markets.md b/docs/api-reference/markets/get-simplified-markets.md new file mode 100644 index 0000000..a93e047 --- /dev/null +++ b/docs/api-reference/markets/get-simplified-markets.md @@ -0,0 +1,128 @@ +> ## 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 simplified markets + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /simplified-markets +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 +paths: + /simplified-markets: + get: + tags: + - Markets + summary: Get simplified markets + operationId: getSimplifiedMarkets + parameters: + - name: next_cursor + in: query + required: false + schema: + type: string + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: '#/components/schemas/PaginatedSimplifiedMarkets' + '400': + description: Invalid request + '500': + description: Internal server error + security: [] +components: + schemas: + PaginatedSimplifiedMarkets: + type: object + properties: + limit: + type: integer + next_cursor: + type: string + count: + type: integer + data: + type: array + items: + $ref: '#/components/schemas/SimplifiedMarket' + SimplifiedMarket: + type: object + properties: + condition_id: + type: string + rewards: + $ref: '#/components/schemas/Rewards' + tokens: + type: array + items: + $ref: '#/components/schemas/Token' + active: + type: boolean + closed: + type: boolean + archived: + type: boolean + accepting_orders: + type: boolean + Rewards: + type: object + properties: + rates: + type: array + items: + type: object + properties: + asset_address: + type: string + rewards_daily_rate: + type: number + format: double + min_size: + type: number + format: double + max_spread: + type: number + format: double + Token: + type: object + properties: + token_id: + type: string + outcome: + type: string + price: + type: number + format: double + winner: + type: boolean + +```` diff --git a/docs/api-reference/markets/list-markets.md b/docs/api-reference/markets/list-markets.md index 96e92ed..7e3fb18 100644 --- a/docs/api-reference/markets/list-markets.md +++ b/docs/api-reference/markets/list-markets.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /markets +````yaml api-spec/gamma-openapi.yaml get /markets openapi: 3.0.3 info: title: Markets API @@ -1312,4 +1312,4 @@ components: type: string nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/misc/download-an-accounting-snapshot-zip-of-csvs.md b/docs/api-reference/misc/download-an-accounting-snapshot-zip-of-csvs.md index 545dfb8..44ad65a 100644 --- a/docs/api-reference/misc/download-an-accounting-snapshot-zip-of-csvs.md +++ b/docs/api-reference/misc/download-an-accounting-snapshot-zip-of-csvs.md @@ -4,46 +4,11 @@ # Download an accounting snapshot (ZIP of CSVs) -> Public endpoint (no auth) that returns an `application/zip` containing two CSV files generated from the same snapshot time. - -**ZIP contents** - -1) `positions.csv` (0+ rows) -- Columns (in order): - - `conditionId` (string): market condition id - - `asset` (string): outcome token id (uniquely identifies the position within a market) - - `size` (number): tokens, 6 decimals - - `curPrice` (number): per-token price/value in USDC, 6 decimals - - `valuationTime` (string): RFC3339 UTC timestamp - -2) `equity.csv` (0 or 1 row) -- Columns (in order): - - `cashBalance` (number): onchain USDC `balanceOf(user)` using Polygon USDC `0x2791bca1f2de4661ed88a30c99a7a9449aa84174`, 6 decimals - - `positionsValue` (number): \(\sum(\text{size} \times \text{curPrice})\) across `positions.csv`, 6 decimals - - `equity` (number): `cashBalance + positionsValue`, 6 decimals - - `valuationTime` (string): RFC3339 UTC timestamp (same snapshot time as `positions.csv`) - -**Example `positions.csv`** - -```csv -conditionId,asset,size,curPrice,valuationTime -0xd007d71fd17b0913b9d7ff198f617caa96a9e4aab1bed7d6f9abd76bb17dd507,65396714035221124737265515219989336303267439172398528294132309725835127126381,90548.087076,0.064500,2026-01-21T18:30:00Z -0x96f6fb6567b5938fc3c2e75f9829d7287340b9581a9c4817b8bc0aff82e1c45f,10057237541929696185971116542487795282113077727880089878027691009747516185940,45666.487374,0.495000,2026-01-21T18:30:00Z -``` - -**Example `equity.csv`** - -```csv -cashBalance,positionsValue,equity,valuationTime -125000.000000,28481009.037705,28606009.037705,2026-01-21T18:30:00Z -``` - - ## OpenAPI -````yaml api-reference/data-api-openapi.yaml get /v1/accounting/snapshot +````yaml api-spec/data-openapi.yaml get /v1/accounting/snapshot openapi: 3.0.3 info: title: Polymarket Data API @@ -67,55 +32,6 @@ paths: tags: - Misc summary: Download an accounting snapshot (ZIP of CSVs) - description: > - Public endpoint (no auth) that returns an `application/zip` containing - two CSV files generated from the same snapshot time. - - - **ZIP contents** - - - 1) `positions.csv` (0+ rows) - - - Columns (in order): - - `conditionId` (string): market condition id - - `asset` (string): outcome token id (uniquely identifies the position within a market) - - `size` (number): tokens, 6 decimals - - `curPrice` (number): per-token price/value in USDC, 6 decimals - - `valuationTime` (string): RFC3339 UTC timestamp - - 2) `equity.csv` (0 or 1 row) - - - Columns (in order): - - `cashBalance` (number): onchain USDC `balanceOf(user)` using Polygon USDC `0x2791bca1f2de4661ed88a30c99a7a9449aa84174`, 6 decimals - - `positionsValue` (number): \(\sum(\text{size} \times \text{curPrice})\) across `positions.csv`, 6 decimals - - `equity` (number): `cashBalance + positionsValue`, 6 decimals - - `valuationTime` (string): RFC3339 UTC timestamp (same snapshot time as `positions.csv`) - - **Example `positions.csv`** - - - ```csv - - conditionId,asset,size,curPrice,valuationTime - - 0xd007d71fd17b0913b9d7ff198f617caa96a9e4aab1bed7d6f9abd76bb17dd507,65396714035221124737265515219989336303267439172398528294132309725835127126381,90548.087076,0.064500,2026-01-21T18:30:00Z - - 0x96f6fb6567b5938fc3c2e75f9829d7287340b9581a9c4817b8bc0aff82e1c45f,10057237541929696185971116542487795282113077727880089878027691009747516185940,45666.487374,0.495000,2026-01-21T18:30:00Z - - ``` - - - **Example `equity.csv`** - - - ```csv - - cashBalance,positionsValue,equity,valuationTime - - 125000.000000,28481009.037705,28606009.037705,2026-01-21T18:30:00Z - - ``` parameters: - in: query name: user @@ -158,4 +74,4 @@ components: required: - error -```` \ No newline at end of file +```` diff --git a/docs/api-reference/misc/get-live-volume-for-an-event.md b/docs/api-reference/misc/get-live-volume-for-an-event.md index fa44eaf..6839791 100644 --- a/docs/api-reference/misc/get-live-volume-for-an-event.md +++ b/docs/api-reference/misc/get-live-volume-for-an-event.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/data-api-openapi.yaml get /live-volume +````yaml api-spec/data-openapi.yaml get /live-volume openapi: 3.0.3 info: title: Polymarket Data API @@ -91,4 +91,4 @@ components: pattern: ^0x[a-fA-F0-9]{64}$ example: '0xdd22472e552920b8438158ea7238bfadfa4f736aa4cee91a6b86c39ead110917' -```` \ No newline at end of file +```` diff --git a/docs/api-reference/misc/get-open-interest.md b/docs/api-reference/misc/get-open-interest.md index b4d84f1..974ce09 100644 --- a/docs/api-reference/misc/get-open-interest.md +++ b/docs/api-reference/misc/get-open-interest.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/data-api-openapi.yaml get /oi +````yaml api-spec/data-openapi.yaml get /oi openapi: 3.0.3 info: title: Polymarket Data API @@ -84,4 +84,4 @@ components: required: - error -```` \ No newline at end of file +```` diff --git a/docs/api-reference/misc/get-total-markets-a-user-has-traded.md b/docs/api-reference/misc/get-total-markets-a-user-has-traded.md index 5191e79..1a64750 100644 --- a/docs/api-reference/misc/get-total-markets-a-user-has-traded.md +++ b/docs/api-reference/misc/get-total-markets-a-user-has-traded.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/data-api-openapi.yaml get /traded +````yaml api-spec/data-openapi.yaml get /traded openapi: 3.0.3 info: title: Polymarket Data API @@ -85,4 +85,4 @@ components: required: - error -```` \ No newline at end of file +```` diff --git a/docs/api-reference/orderbook/get-multiple-order-books-summaries-by-request.md b/docs/api-reference/orderbook/get-multiple-order-books-summaries-by-request.md index 2f6b6f5..19765bd 100644 --- a/docs/api-reference/orderbook/get-multiple-order-books-summaries-by-request.md +++ b/docs/api-reference/orderbook/get-multiple-order-books-summaries-by-request.md @@ -1,177 +1 @@ -> ## 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 multiple order books summaries by request - -> Retrieves order book summaries for specified tokens via POST request - - - -## OpenAPI - -````yaml api-reference/clob-subset-openapi.yaml post /books -openapi: 3.0.3 -info: - title: CLOB (Central Limit Order Book) API - description: >- - API for interacting with the Central Limit Order Book system, providing - orderbook data, prices, midpoints, and spreads - version: 1.0.0 - contact: - name: CLOB API Team - license: - name: MIT -servers: - - url: https://clob.polymarket.com/ - description: Production server -security: [] -tags: - - name: Orderbook - description: Order book related operations - - name: Pricing - description: Price and midpoint operations - - name: Spreads - description: Spread calculation operations -paths: - /books: - post: - tags: - - Orderbook - summary: Get multiple order books summaries by request - description: Retrieves order book summaries for specified tokens via POST request - requestBody: - required: true - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/BookRequest' - maxItems: 500 - example: - - token_id: '1234567890' - - token_id: '0987654321' - responses: - '200': - description: Successful response - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/OrderBookSummary' - '400': - description: Bad request - Invalid payload or exceeds limit - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - examples: - invalid_payload: - value: - error: Invalid payload - exceeds_limit: - value: - error: Payload exceeds the limit - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' -components: - schemas: - BookRequest: - type: object - required: - - token_id - properties: - token_id: - type: string - description: The unique identifier for the token - example: '1234567890' - side: - type: string - enum: - - BUY - - SELL - description: Optional side parameter for certain operations - example: BUY - OrderBookSummary: - type: object - required: - - market - - asset_id - - timestamp - - hash - - bids - - asks - - min_order_size - - tick_size - - neg_risk - properties: - market: - type: string - description: Market identifier - example: '0x1b6f76e5b8587ee896c35847e12d11e75290a8c3934c5952e8a9d6e4c6f03cfa' - asset_id: - type: string - description: Asset identifier - example: '1234567890' - timestamp: - type: string - format: date-time - description: Timestamp of the order book snapshot - example: '2023-10-01T12:00:00Z' - hash: - type: string - description: Hash of the order book state - example: 0xabc123def456... - bids: - type: array - items: - $ref: '#/components/schemas/OrderLevel' - description: Array of bid levels - asks: - type: array - items: - $ref: '#/components/schemas/OrderLevel' - description: Array of ask levels - min_order_size: - type: string - description: Minimum order size for this market - example: '0.001' - tick_size: - type: string - description: Minimum price increment - example: '0.01' - neg_risk: - type: boolean - description: Whether negative risk is enabled - example: false - Error: - type: object - required: - - error - properties: - error: - type: string - description: Error message describing what went wrong - example: Invalid token id - OrderLevel: - type: object - required: - - price - - size - properties: - price: - type: string - description: Price level (as string to maintain precision) - example: '1800.50' - size: - type: string - description: Total size at this price level - example: '10.5' - -```` \ No newline at end of file +null diff --git a/docs/api-reference/orderbook/get-order-book-summary.md b/docs/api-reference/orderbook/get-order-book-summary.md index 0cccdf7..19765bd 100644 --- a/docs/api-reference/orderbook/get-order-book-summary.md +++ b/docs/api-reference/orderbook/get-order-book-summary.md @@ -1,160 +1 @@ -> ## 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 order book summary - -> Retrieves the order book summary for a specific token - - - -## OpenAPI - -````yaml api-reference/clob-subset-openapi.yaml get /book -openapi: 3.0.3 -info: - title: CLOB (Central Limit Order Book) API - description: >- - API for interacting with the Central Limit Order Book system, providing - orderbook data, prices, midpoints, and spreads - version: 1.0.0 - contact: - name: CLOB API Team - license: - name: MIT -servers: - - url: https://clob.polymarket.com/ - description: Production server -security: [] -tags: - - name: Orderbook - description: Order book related operations - - name: Pricing - description: Price and midpoint operations - - name: Spreads - description: Spread calculation operations -paths: - /book: - get: - tags: - - Orderbook - summary: Get order book summary - description: Retrieves the order book summary for a specific token - parameters: - - name: token_id - in: query - required: true - schema: - type: string - description: The unique identifier for the token - example: '1234567890' - responses: - '200': - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/OrderBookSummary' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - example: - error: Invalid token id - '404': - description: Order book not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - example: - error: No orderbook exists for the requested token id - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - example: - error: error getting the orderbook -components: - schemas: - OrderBookSummary: - type: object - required: - - market - - asset_id - - timestamp - - hash - - bids - - asks - - min_order_size - - tick_size - - neg_risk - properties: - market: - type: string - description: Market identifier - example: '0x1b6f76e5b8587ee896c35847e12d11e75290a8c3934c5952e8a9d6e4c6f03cfa' - asset_id: - type: string - description: Asset identifier - example: '1234567890' - timestamp: - type: string - format: date-time - description: Timestamp of the order book snapshot - example: '2023-10-01T12:00:00Z' - hash: - type: string - description: Hash of the order book state - example: 0xabc123def456... - bids: - type: array - items: - $ref: '#/components/schemas/OrderLevel' - description: Array of bid levels - asks: - type: array - items: - $ref: '#/components/schemas/OrderLevel' - description: Array of ask levels - min_order_size: - type: string - description: Minimum order size for this market - example: '0.001' - tick_size: - type: string - description: Minimum price increment - example: '0.01' - neg_risk: - type: boolean - description: Whether negative risk is enabled - example: false - Error: - type: object - required: - - error - properties: - error: - type: string - description: Error message describing what went wrong - example: Invalid token id - OrderLevel: - type: object - required: - - price - - size - properties: - price: - type: string - description: Price level (as string to maintain precision) - example: '1800.50' - size: - type: string - description: Total size at this price level - example: '10.5' - -```` \ No newline at end of file +null diff --git a/docs/api-reference/pricing/get-market-price.md b/docs/api-reference/pricing/get-market-price.md index e37b7fc..19765bd 100644 --- a/docs/api-reference/pricing/get-market-price.md +++ b/docs/api-reference/pricing/get-market-price.md @@ -1,116 +1 @@ -> ## 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 market price - -> Retrieves the market price for a specific token and side - - - -## OpenAPI - -````yaml api-reference/clob-subset-openapi.yaml get /price -openapi: 3.0.3 -info: - title: CLOB (Central Limit Order Book) API - description: >- - API for interacting with the Central Limit Order Book system, providing - orderbook data, prices, midpoints, and spreads - version: 1.0.0 - contact: - name: CLOB API Team - license: - name: MIT -servers: - - url: https://clob.polymarket.com/ - description: Production server -security: [] -tags: - - name: Orderbook - description: Order book related operations - - name: Pricing - description: Price and midpoint operations - - name: Spreads - description: Spread calculation operations -paths: - /price: - get: - tags: - - Pricing - summary: Get market price - description: Retrieves the market price for a specific token and side - parameters: - - name: token_id - in: query - required: true - schema: - type: string - description: The unique identifier for the token - example: '1234567890' - - name: side - in: query - required: true - schema: - type: string - enum: - - BUY - - SELL - description: The side of the market (BUY or SELL) - example: BUY - responses: - '200': - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/PriceResponse' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - examples: - invalid_token: - value: - error: Invalid token id - invalid_side: - value: - error: Invalid side - '404': - description: Order book not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - example: - error: No orderbook exists for the requested token id - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' -components: - schemas: - PriceResponse: - type: object - required: - - price - properties: - price: - type: string - description: The market price (as string to maintain precision) - example: '1800.50' - Error: - type: object - required: - - error - properties: - error: - type: string - description: Error message describing what went wrong - example: Invalid token id - -```` \ No newline at end of file +null diff --git a/docs/api-reference/pricing/get-midpoint-price.md b/docs/api-reference/pricing/get-midpoint-price.md index 770e51e..19765bd 100644 --- a/docs/api-reference/pricing/get-midpoint-price.md +++ b/docs/api-reference/pricing/get-midpoint-price.md @@ -1,101 +1 @@ -> ## 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 midpoint price - -> Retrieves the midpoint price for a specific token - - - -## OpenAPI - -````yaml api-reference/clob-subset-openapi.yaml get /midpoint -openapi: 3.0.3 -info: - title: CLOB (Central Limit Order Book) API - description: >- - API for interacting with the Central Limit Order Book system, providing - orderbook data, prices, midpoints, and spreads - version: 1.0.0 - contact: - name: CLOB API Team - license: - name: MIT -servers: - - url: https://clob.polymarket.com/ - description: Production server -security: [] -tags: - - name: Orderbook - description: Order book related operations - - name: Pricing - description: Price and midpoint operations - - name: Spreads - description: Spread calculation operations -paths: - /midpoint: - get: - tags: - - Pricing - summary: Get midpoint price - description: Retrieves the midpoint price for a specific token - parameters: - - name: token_id - in: query - required: true - schema: - type: string - description: The unique identifier for the token - example: '1234567890' - responses: - '200': - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/MidpointResponse' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - example: - error: Invalid token id - '404': - description: Order book not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - example: - error: No orderbook exists for the requested token id - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' -components: - schemas: - MidpointResponse: - type: object - required: - - mid - properties: - mid: - type: string - description: The midpoint price (as string to maintain precision) - example: '1800.75' - Error: - type: object - required: - - error - properties: - error: - type: string - description: Error message describing what went wrong - example: Invalid token id - -```` \ No newline at end of file +null diff --git a/docs/api-reference/pricing/get-multiple-market-prices-by-request.md b/docs/api-reference/pricing/get-multiple-market-prices-by-request.md index 03830a1..19765bd 100644 --- a/docs/api-reference/pricing/get-multiple-market-prices-by-request.md +++ b/docs/api-reference/pricing/get-multiple-market-prices-by-request.md @@ -1,137 +1 @@ -> ## 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 multiple market prices by request - -> Retrieves market prices for specified tokens and sides via POST request - - - -## OpenAPI - -````yaml api-reference/clob-subset-openapi.yaml post /prices -openapi: 3.0.3 -info: - title: CLOB (Central Limit Order Book) API - description: >- - API for interacting with the Central Limit Order Book system, providing - orderbook data, prices, midpoints, and spreads - version: 1.0.0 - contact: - name: CLOB API Team - license: - name: MIT -servers: - - url: https://clob.polymarket.com/ - description: Production server -security: [] -tags: - - name: Orderbook - description: Order book related operations - - name: Pricing - description: Price and midpoint operations - - name: Spreads - description: Spread calculation operations -paths: - /prices: - post: - tags: - - Pricing - summary: Get multiple market prices by request - description: Retrieves market prices for specified tokens and sides via POST request - requestBody: - required: true - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/PriceRequest' - maxItems: 500 - example: - - token_id: '1234567890' - side: BUY - - token_id: '0987654321' - side: SELL - responses: - '200': - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/PricesResponse' - '400': - description: Bad request - Invalid payload, exceeds limit, or invalid side - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - examples: - invalid_payload: - value: - error: Invalid payload - exceeds_limit: - value: - error: Payload exceeds the limit - invalid_side: - value: - error: Invalid side - '404': - description: Order book not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - example: - error: No orderbook exists for the requested token id - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' -components: - schemas: - PriceRequest: - type: object - required: - - token_id - - side - properties: - token_id: - type: string - description: The unique identifier for the token - example: '1234567890' - side: - type: string - enum: - - BUY - - SELL - description: The side of the market (BUY or SELL) - example: BUY - PricesResponse: - type: object - additionalProperties: - type: object - additionalProperties: - type: string - description: Map of token_id to side to price - example: - '1234567890': - BUY: '1800.50' - SELL: '1801.00' - '0987654321': - BUY: '50.25' - SELL: '50.30' - Error: - type: object - required: - - error - properties: - error: - type: string - description: Error message describing what went wrong - example: Invalid token id - -```` \ No newline at end of file +null diff --git a/docs/api-reference/pricing/get-multiple-market-prices.md b/docs/api-reference/pricing/get-multiple-market-prices.md index eed3351..19765bd 100644 --- a/docs/api-reference/pricing/get-multiple-market-prices.md +++ b/docs/api-reference/pricing/get-multiple-market-prices.md @@ -1,88 +1 @@ -> ## 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 multiple market prices - -> Retrieves market prices for multiple tokens and sides - - - -## OpenAPI - -````yaml api-reference/clob-subset-openapi.yaml get /prices -openapi: 3.0.3 -info: - title: CLOB (Central Limit Order Book) API - description: >- - API for interacting with the Central Limit Order Book system, providing - orderbook data, prices, midpoints, and spreads - version: 1.0.0 - contact: - name: CLOB API Team - license: - name: MIT -servers: - - url: https://clob.polymarket.com/ - description: Production server -security: [] -tags: - - name: Orderbook - description: Order book related operations - - name: Pricing - description: Price and midpoint operations - - name: Spreads - description: Spread calculation operations -paths: - /prices: - get: - tags: - - Pricing - summary: Get multiple market prices - description: Retrieves market prices for multiple tokens and sides - responses: - '200': - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/PricesResponse' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' -components: - schemas: - PricesResponse: - type: object - additionalProperties: - type: object - additionalProperties: - type: string - description: Map of token_id to side to price - example: - '1234567890': - BUY: '1800.50' - SELL: '1801.00' - '0987654321': - BUY: '50.25' - SELL: '50.30' - Error: - type: object - required: - - error - properties: - error: - type: string - description: Error message describing what went wrong - example: Invalid token id - -```` \ No newline at end of file +null diff --git a/docs/api-reference/pricing/get-price-history-for-a-traded-token.md b/docs/api-reference/pricing/get-price-history-for-a-traded-token.md index b4b9f64..19765bd 100644 --- a/docs/api-reference/pricing/get-price-history-for-a-traded-token.md +++ b/docs/api-reference/pricing/get-price-history-for-a-traded-token.md @@ -1,146 +1 @@ -> ## 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 price history for a traded token - -> Fetches historical price data for a specified market token - - - -## OpenAPI - -````yaml api-reference/clob-subset-openapi.yaml get /prices-history -openapi: 3.0.3 -info: - title: CLOB (Central Limit Order Book) API - description: >- - API for interacting with the Central Limit Order Book system, providing - orderbook data, prices, midpoints, and spreads - version: 1.0.0 - contact: - name: CLOB API Team - license: - name: MIT -servers: - - url: https://clob.polymarket.com/ - description: Production server -security: [] -tags: - - name: Orderbook - description: Order book related operations - - name: Pricing - description: Price and midpoint operations - - name: Spreads - description: Spread calculation operations -paths: - /prices-history: - get: - tags: - - Pricing - summary: Get price history for a traded token - description: Fetches historical price data for a specified market token - parameters: - - name: market - in: query - required: true - schema: - type: string - description: The CLOB token ID for which to fetch price history - example: '1234567890' - - name: startTs - in: query - required: false - schema: - type: number - description: The start time, a Unix timestamp in UTC - example: 1697875200 - - name: endTs - in: query - required: false - schema: - type: number - description: The end time, a Unix timestamp in UTC - example: 1697961600 - - name: interval - in: query - required: false - schema: - type: string - enum: - - 1m - - 1w - - 1d - - 6h - - 1h - - max - description: >- - A string representing a duration ending at the current time. - Mutually exclusive with startTs and endTs - example: 1d - - name: fidelity - in: query - required: false - schema: - type: number - description: The resolution of the data, in minutes - example: 60 - responses: - '200': - description: A list of timestamp/price pairs - content: - application/json: - schema: - $ref: '#/components/schemas/PriceHistoryResponse' - '400': - description: Bad request - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '404': - description: Market not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' -components: - schemas: - PriceHistoryResponse: - type: object - required: - - history - properties: - history: - type: array - items: - type: object - required: - - t - - p - properties: - t: - type: number - description: UTC timestamp - example: 1697875200 - p: - type: number - description: Price - example: 1800.75 - Error: - type: object - required: - - error - properties: - error: - type: string - description: Error message describing what went wrong - example: Invalid token id - -```` \ No newline at end of file +null diff --git a/docs/api-reference/profiles/get-public-profile-by-wallet-address.md b/docs/api-reference/profiles/get-public-profile-by-wallet-address.md index 1bea77b..46a8d7b 100644 --- a/docs/api-reference/profiles/get-public-profile-by-wallet-address.md +++ b/docs/api-reference/profiles/get-public-profile-by-wallet-address.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /public-profile +````yaml api-spec/gamma-openapi.yaml get /public-profile openapi: 3.0.3 info: title: Markets API @@ -151,4 +151,4 @@ components: type: boolean description: Whether the user is a moderator -```` \ No newline at end of file +```` diff --git a/docs/api-reference/rate-limits.md b/docs/api-reference/rate-limits.md new file mode 100644 index 0000000..2d99713 --- /dev/null +++ b/docs/api-reference/rate-limits.md @@ -0,0 +1,126 @@ +> ## 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. + +# Rate Limits + +> API rate limits for all Polymarket endpoints + +All API rate limits are enforced using Cloudflare's throttling system. When you exceed the limit for any endpoint, requests are throttled (delayed/queued) rather than immediately rejected. Limits reset on sliding time windows. + +*** + +## General + +| Endpoint | Limit | +| --------------------- | ---------------- | +| General rate limiting | 15,000 req / 10s | +| Health check (`/ok`) | 100 req / 10s | + +*** + +## Gamma API + +Base URL: `https://gamma-api.polymarket.com` + +| Endpoint | Limit | +| ------------------------------ | --------------- | +| General | 4,000 req / 10s | +| `/events` | 500 req / 10s | +| `/markets` | 300 req / 10s | +| `/markets` + `/events` listing | 900 req / 10s | +| `/comments` | 200 req / 10s | +| `/tags` | 200 req / 10s | +| `/public-search` | 350 req / 10s | + +*** + +## Data API + +Base URL: `https://data-api.polymarket.com` + +| Endpoint | Limit | +| -------------------- | --------------- | +| General | 1,000 req / 10s | +| `/trades` | 200 req / 10s | +| `/positions` | 150 req / 10s | +| `/closed-positions` | 150 req / 10s | +| Health check (`/ok`) | 100 req / 10s | + +*** + +## CLOB API + +Base URL: `https://clob.polymarket.com` + +### General + +| Endpoint | Limit | +| -------------------------- | --------------- | +| General | 9,000 req / 10s | +| `GET` balance allowance | 200 req / 10s | +| `UPDATE` balance allowance | 50 req / 10s | + +### Market Data + +| Endpoint | Limit | +| ----------------- | --------------- | +| `/book` | 1,500 req / 10s | +| `/books` | 500 req / 10s | +| `/price` | 1,500 req / 10s | +| `/prices` | 500 req / 10s | +| `/midpoint` | 1,500 req / 10s | +| `/midpoints` | 500 req / 10s | +| `/prices-history` | 1,000 req / 10s | +| Market tick size | 200 req / 10s | + +### Ledger + +| Endpoint | Limit | +| ------------------------------------------------ | ------------- | +| `/trades`, `/orders`, `/notifications`, `/order` | 900 req / 10s | +| `/data/orders` | 500 req / 10s | +| `/data/trades` | 500 req / 10s | +| `/notifications` | 125 req / 10s | + +### Authentication + +| Endpoint | Limit | +| ----------------- | ------------- | +| API key endpoints | 100 req / 10s | + +### Trading + +Trading endpoints have both **burst** limits (short spikes allowed) and **sustained** limits (longer-term average). + +| Endpoint | Burst Limit | Sustained Limit | +| ------------------------------ | --------------- | ------------------- | +| `POST /order` | 3,500 req / 10s | 36,000 req / 10 min | +| `DELETE /order` | 3,000 req / 10s | 30,000 req / 10 min | +| `POST /orders` | 1,000 req / 10s | 15,000 req / 10 min | +| `DELETE /orders` | 1,000 req / 10s | 15,000 req / 10 min | +| `DELETE /cancel-all` | 250 req / 10s | 6,000 req / 10 min | +| `DELETE /cancel-market-orders` | 1,000 req / 10s | 1,500 req / 10 min | + +*** + +## Other + +| Endpoint | Limit | +| ----------------- | -------------- | +| Relayer `/submit` | 25 req / 1 min | +| User PNL API | 200 req / 10s | + +*** + +## Next Steps + + + + Learn how to authenticate trading requests. + + + + Official TypeScript, Python, and Rust libraries. + + diff --git a/docs/api-reference/search/search-markets-events-and-profiles.md b/docs/api-reference/search/search-markets-events-and-profiles.md index 8c95504..1cf53d6 100644 --- a/docs/api-reference/search/search-markets-events-and-profiles.md +++ b/docs/api-reference/search/search-markets-events-and-profiles.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /public-search +````yaml api-spec/gamma-openapi.yaml get /public-search openapi: 3.0.3 info: title: Markets API @@ -1344,4 +1344,4 @@ components: type: string nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/series/get-series-by-id.md b/docs/api-reference/series/get-series-by-id.md index 2992d16..da02162 100644 --- a/docs/api-reference/series/get-series-by-id.md +++ b/docs/api-reference/series/get-series-by-id.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /series/{id} +````yaml api-spec/gamma-openapi.yaml get /series/{id} openapi: 3.0.3 info: title: Markets API @@ -1186,4 +1186,4 @@ components: type: string nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/series/list-series.md b/docs/api-reference/series/list-series.md index f75a6ab..42e2dc5 100644 --- a/docs/api-reference/series/list-series.md +++ b/docs/api-reference/series/list-series.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /series +````yaml api-spec/gamma-openapi.yaml get /series openapi: 3.0.3 info: title: Markets API @@ -1232,4 +1232,4 @@ components: type: string nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/sports/get-sports-metadata-information.md b/docs/api-reference/sports/get-sports-metadata-information.md index 02b5662..3f3bc42 100644 --- a/docs/api-reference/sports/get-sports-metadata-information.md +++ b/docs/api-reference/sports/get-sports-metadata-information.md @@ -4,13 +4,11 @@ # Get sports metadata information -> Retrieves metadata for various sports including images, resolution sources, ordering preferences, tags, and series information. This endpoint provides comprehensive sport configuration data used throughout the platform. - ## OpenAPI -````yaml api-reference/gamma-openapi.json get /sports +````yaml api-spec/gamma-openapi.yaml get /sports openapi: 3.0.3 info: title: Markets API @@ -45,11 +43,6 @@ paths: tags: - Sports summary: Get sports metadata information - description: >- - Retrieves metadata for various sports including images, resolution - sources, ordering preferences, tags, and series information. This - endpoint provides comprehensive sport configuration data used throughout - the platform. operationId: getSportsMetadata responses: '200': @@ -94,4 +87,4 @@ components: Series identifier linking the sport to a specific tournament or season series -```` \ No newline at end of file +```` diff --git a/docs/api-reference/sports/get-valid-sports-market-types.md b/docs/api-reference/sports/get-valid-sports-market-types.md index 046a397..db8f727 100644 --- a/docs/api-reference/sports/get-valid-sports-market-types.md +++ b/docs/api-reference/sports/get-valid-sports-market-types.md @@ -4,13 +4,11 @@ # Get valid sports market types -> Get a list of all valid sports market types available on the platform. Use these values when filtering markets by the sportsMarketTypes parameter. - ## OpenAPI -````yaml api-reference/gamma-openapi.json get /sports/market-types +````yaml api-spec/gamma-openapi.yaml get /sports/market-types openapi: 3.0.3 info: title: Markets API @@ -45,10 +43,6 @@ paths: tags: - Sports summary: Get valid sports market types - description: >- - Get a list of all valid sports market types available on the platform. - Use these values when filtering markets by the sportsMarketTypes - parameter. operationId: getSportsMarketTypes responses: '200': @@ -68,4 +62,4 @@ components: items: type: string -```` \ No newline at end of file +```` diff --git a/docs/api-reference/sports/list-teams.md b/docs/api-reference/sports/list-teams.md index 5b3ee9d..efe7d45 100644 --- a/docs/api-reference/sports/list-teams.md +++ b/docs/api-reference/sports/list-teams.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /teams +````yaml api-spec/gamma-openapi.yaml get /teams openapi: 3.0.3 info: title: Markets API @@ -134,4 +134,4 @@ components: format: date-time nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/spreads/get-bid-ask-spreads.md b/docs/api-reference/spreads/get-bid-ask-spreads.md index e72f2be..19765bd 100644 --- a/docs/api-reference/spreads/get-bid-ask-spreads.md +++ b/docs/api-reference/spreads/get-bid-ask-spreads.md @@ -1,119 +1 @@ -> ## 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 bid-ask spreads - -> Retrieves bid-ask spreads for multiple tokens - - - -## OpenAPI - -````yaml api-reference/clob-subset-openapi.yaml post /spreads -openapi: 3.0.3 -info: - title: CLOB (Central Limit Order Book) API - description: >- - API for interacting with the Central Limit Order Book system, providing - orderbook data, prices, midpoints, and spreads - version: 1.0.0 - contact: - name: CLOB API Team - license: - name: MIT -servers: - - url: https://clob.polymarket.com/ - description: Production server -security: [] -tags: - - name: Orderbook - description: Order book related operations - - name: Pricing - description: Price and midpoint operations - - name: Spreads - description: Spread calculation operations -paths: - /spreads: - post: - tags: - - Spreads - summary: Get bid-ask spreads - description: Retrieves bid-ask spreads for multiple tokens - requestBody: - required: true - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/BookRequest' - maxItems: 500 - example: - - token_id: '1234567890' - - token_id: '0987654321' - responses: - '200': - description: Successful response - content: - application/json: - schema: - $ref: '#/components/schemas/SpreadsResponse' - '400': - description: Bad request - Invalid payload or exceeds limit - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - examples: - invalid_payload: - value: - error: Invalid payload - exceeds_limit: - value: - error: Payload exceeds the limit - '500': - description: Internal server error - content: - application/json: - schema: - $ref: '#/components/schemas/Error' - example: - error: error getting the spread -components: - schemas: - BookRequest: - type: object - required: - - token_id - properties: - token_id: - type: string - description: The unique identifier for the token - example: '1234567890' - side: - type: string - enum: - - BUY - - SELL - description: Optional side parameter for certain operations - example: BUY - SpreadsResponse: - type: object - additionalProperties: - type: string - description: Map of token_id to spread value - example: - '1234567890': '0.50' - '0987654321': '0.05' - Error: - type: object - required: - - error - properties: - error: - type: string - description: Error message describing what went wrong - example: Invalid token id - -```` \ No newline at end of file +null diff --git a/docs/api-reference/tags/get-related-tags-relationships-by-tag-id.md b/docs/api-reference/tags/get-related-tags-relationships-by-tag-id.md index 5cb3782..346cf9b 100644 --- a/docs/api-reference/tags/get-related-tags-relationships-by-tag-id.md +++ b/docs/api-reference/tags/get-related-tags-relationships-by-tag-id.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /tags/{id}/related-tags +````yaml api-spec/gamma-openapi.yaml get /tags/{id}/related-tags openapi: 3.0.3 info: title: Markets API @@ -91,4 +91,4 @@ components: type: integer nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/tags/get-related-tags-relationships-by-tag-slug.md b/docs/api-reference/tags/get-related-tags-relationships-by-tag-slug.md index 5a1a0b0..9ccd8c4 100644 --- a/docs/api-reference/tags/get-related-tags-relationships-by-tag-slug.md +++ b/docs/api-reference/tags/get-related-tags-relationships-by-tag-slug.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /tags/slug/{slug}/related-tags +````yaml api-spec/gamma-openapi.yaml get /tags/slug/{slug}/related-tags openapi: 3.0.3 info: title: Markets API @@ -91,4 +91,4 @@ components: type: integer nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/tags/get-tag-by-id.md b/docs/api-reference/tags/get-tag-by-id.md index 77b620d..158c370 100644 --- a/docs/api-reference/tags/get-tag-by-id.md +++ b/docs/api-reference/tags/get-tag-by-id.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /tags/{id} +````yaml api-spec/gamma-openapi.yaml get /tags/{id} openapi: 3.0.3 info: title: Markets API @@ -106,4 +106,4 @@ components: type: boolean nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/tags/get-tag-by-slug.md b/docs/api-reference/tags/get-tag-by-slug.md index 6e122b9..9b97824 100644 --- a/docs/api-reference/tags/get-tag-by-slug.md +++ b/docs/api-reference/tags/get-tag-by-slug.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /tags/slug/{slug} +````yaml api-spec/gamma-openapi.yaml get /tags/slug/{slug} openapi: 3.0.3 info: title: Markets API @@ -106,4 +106,4 @@ components: type: boolean nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/tags/get-tags-related-to-a-tag-id.md b/docs/api-reference/tags/get-tags-related-to-a-tag-id.md index 9a33922..b13877a 100644 --- a/docs/api-reference/tags/get-tags-related-to-a-tag-id.md +++ b/docs/api-reference/tags/get-tags-related-to-a-tag-id.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /tags/{id}/related-tags/tags +````yaml api-spec/gamma-openapi.yaml get /tags/{id}/related-tags/tags openapi: 3.0.3 info: title: Markets API @@ -114,4 +114,4 @@ components: type: boolean nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/tags/get-tags-related-to-a-tag-slug.md b/docs/api-reference/tags/get-tags-related-to-a-tag-slug.md index c93774d..702e7fa 100644 --- a/docs/api-reference/tags/get-tags-related-to-a-tag-slug.md +++ b/docs/api-reference/tags/get-tags-related-to-a-tag-slug.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /tags/slug/{slug}/related-tags/tags +````yaml api-spec/gamma-openapi.yaml get /tags/slug/{slug}/related-tags/tags openapi: 3.0.3 info: title: Markets API @@ -114,4 +114,4 @@ components: type: boolean nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/tags/list-tags.md b/docs/api-reference/tags/list-tags.md index e6baf73..69e5fae 100644 --- a/docs/api-reference/tags/list-tags.md +++ b/docs/api-reference/tags/list-tags.md @@ -8,7 +8,7 @@ ## OpenAPI -````yaml api-reference/gamma-openapi.json get /tags +````yaml api-spec/gamma-openapi.yaml get /tags openapi: 3.0.3 info: title: Markets API @@ -130,4 +130,4 @@ components: type: boolean nullable: true -```` \ No newline at end of file +```` diff --git a/docs/api-reference/trade/cancel-all-orders.md b/docs/api-reference/trade/cancel-all-orders.md new file mode 100644 index 0000000..fe5f8e8 --- /dev/null +++ b/docs/api-reference/trade/cancel-all-orders.md @@ -0,0 +1,168 @@ +> ## 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 all orders + +> Cancels all open orders for the authenticated user. Works even in cancel-only mode. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml delete /cancel-all +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 +paths: + /cancel-all: + delete: + tags: + - Trade + summary: Cancel all orders + description: > + Cancels all open orders for the authenticated user. Works even in + cancel-only mode. + operationId: cancelAllOrders + responses: + '200': + description: Cancellation results for all orders + content: + application/json: + schema: + $ref: '#/components/schemas/CancelOrdersResponse' + examples: + canceled: + summary: All orders canceled + value: + canceled: + - '0xabcdef1234567890abcdef1234567890abcdef12' + - '0xfedcba0987654321fedcba0987654321fedcba09' + not_canceled: {} + mixed: + summary: Some orders canceled, some not + value: + canceled: + - '0xabcdef1234567890abcdef1234567890abcdef12' + not_canceled: + '0xfedcba0987654321fedcba0987654321fedcba09': Order already matched + no_orders: + summary: No orders to cancel + value: + canceled: [] + not_canceled: {} + '401': + description: Unauthorized - Invalid API key or authentication failed + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid API key + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + '503': + description: >- + Service unavailable - Trading disabled (cancels still work in + cancel-only mode) + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: >- + Trading is currently disabled. Check polymarket.com for + updates + security: + - polyApiKey: [] + polyAddress: [] + polySignature: [] + polyPassphrase: [] + polyTimestamp: [] +components: + schemas: + CancelOrdersResponse: + type: object + required: + - canceled + - not_canceled + properties: + canceled: + type: array + description: Array of order IDs that were successfully canceled + items: + type: string + example: + - '0xabcdef1234567890abcdef1234567890abcdef12' + not_canceled: + type: object + description: Map of order IDs that could not be canceled with error messages + additionalProperties: + type: string + example: + '0xabcdef1234567890abcdef1234567890abcdef12': Order not found or already canceled + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + securitySchemes: + polyApiKey: + type: apiKey + in: header + name: POLY_API_KEY + description: Your API key + polyAddress: + type: apiKey + in: header + name: POLY_ADDRESS + description: Ethereum address associated with the API key + polySignature: + type: apiKey + in: header + name: POLY_SIGNATURE + description: HMAC signature of the request + polyPassphrase: + type: apiKey + in: header + name: POLY_PASSPHRASE + description: API key passphrase + polyTimestamp: + type: apiKey + in: header + name: POLY_TIMESTAMP + description: Unix timestamp of the request + +```` diff --git a/docs/api-reference/trade/cancel-multiple-orders.md b/docs/api-reference/trade/cancel-multiple-orders.md new file mode 100644 index 0000000..dc37ff7 --- /dev/null +++ b/docs/api-reference/trade/cancel-multiple-orders.md @@ -0,0 +1,208 @@ +> ## 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 multiple orders + +> Cancels multiple orders by their IDs. Maximum 3000 orders per request. +Duplicate order IDs in the request are automatically ignored. +Works even in cancel-only mode. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml delete /orders +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 +paths: + /orders: + delete: + tags: + - Trade + summary: Cancel multiple orders + description: | + Cancels multiple orders by their IDs. Maximum 3000 orders per request. + Duplicate order IDs in the request are automatically ignored. + Works even in cancel-only mode. + operationId: cancelOrders + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + type: string + maxItems: 3000 + example: + - '0xabcdef1234567890abcdef1234567890abcdef12' + - '0xfedcba0987654321fedcba0987654321fedcba09' + - '0x1234567890abcdef1234567890abcdef12345678' + responses: + '200': + description: Cancellation results for all orders + content: + application/json: + schema: + $ref: '#/components/schemas/CancelOrdersResponse' + examples: + all_canceled: + summary: All orders canceled + value: + canceled: + - '0xabcdef1234567890abcdef1234567890abcdef12' + - '0xfedcba0987654321fedcba0987654321fedcba09' + - '0x1234567890abcdef1234567890abcdef12345678' + not_canceled: {} + mixed: + summary: Some orders canceled, some not + value: + canceled: + - '0xabcdef1234567890abcdef1234567890abcdef12' + - '0xfedcba0987654321fedcba0987654321fedcba09' + not_canceled: + '0x1234567890abcdef1234567890abcdef12345678': Order already matched + partial: + summary: Partial cancellation + value: + canceled: + - '0xabcdef1234567890abcdef1234567890abcdef12' + not_canceled: + '0xfedcba0987654321fedcba0987654321fedcba09': Order not found + '0x1234567890abcdef1234567890abcdef12345678': Order already canceled + '400': + description: Bad request - Invalid order IDs or payload + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + invalid_order_id: + summary: Invalid order ID + value: + error: Invalid orderID + invalid_payload: + summary: Invalid payload + value: + error: Invalid order payload + too_many_orders: + summary: Too many orders + value: + error: 'Too many orders in payload, max allowed: 3000' + '401': + description: Unauthorized - Invalid API key or authentication failed + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid API key + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + '503': + description: >- + Service unavailable - Trading disabled (cancels still work in + cancel-only mode) + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: >- + Trading is currently disabled. Check polymarket.com for + updates + security: + - polyApiKey: [] + polyAddress: [] + polySignature: [] + polyPassphrase: [] + polyTimestamp: [] +components: + schemas: + CancelOrdersResponse: + type: object + required: + - canceled + - not_canceled + properties: + canceled: + type: array + description: Array of order IDs that were successfully canceled + items: + type: string + example: + - '0xabcdef1234567890abcdef1234567890abcdef12' + not_canceled: + type: object + description: Map of order IDs that could not be canceled with error messages + additionalProperties: + type: string + example: + '0xabcdef1234567890abcdef1234567890abcdef12': Order not found or already canceled + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + securitySchemes: + polyApiKey: + type: apiKey + in: header + name: POLY_API_KEY + description: Your API key + polyAddress: + type: apiKey + in: header + name: POLY_ADDRESS + description: Ethereum address associated with the API key + polySignature: + type: apiKey + in: header + name: POLY_SIGNATURE + description: HMAC signature of the request + polyPassphrase: + type: apiKey + in: header + name: POLY_PASSPHRASE + description: API key passphrase + polyTimestamp: + type: apiKey + in: header + name: POLY_TIMESTAMP + description: Unix timestamp of the request + +```` diff --git a/docs/api-reference/trade/cancel-orders-for-a-market.md b/docs/api-reference/trade/cancel-orders-for-a-market.md new file mode 100644 index 0000000..e4ffa00 --- /dev/null +++ b/docs/api-reference/trade/cancel-orders-for-a-market.md @@ -0,0 +1,203 @@ +> ## 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 orders for a market + +> Cancels all open orders for the authenticated user in a specific market (condition) and asset. +Works even in cancel-only mode. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml delete /cancel-market-orders +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 +paths: + /cancel-market-orders: + delete: + tags: + - Trade + summary: Cancel orders for a market + description: > + Cancels all open orders for the authenticated user in a specific market + (condition) and asset. + + Works even in cancel-only mode. + operationId: cancelMarketOrders + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/OrderMarketCancelParams' + example: + market: >- + 0x0000000000000000000000000000000000000000000000000000000000000001 + asset_id: 0xabc123def456... + responses: + '200': + description: Cancellation results for market orders + content: + application/json: + schema: + $ref: '#/components/schemas/CancelOrdersResponse' + examples: + canceled: + summary: All market orders canceled + value: + canceled: + - '0xabcdef1234567890abcdef1234567890abcdef12' + - '0xfedcba0987654321fedcba0987654321fedcba09' + not_canceled: {} + mixed: + summary: Some orders canceled, some not + value: + canceled: + - '0xabcdef1234567890abcdef1234567890abcdef12' + not_canceled: + '0xfedcba0987654321fedcba0987654321fedcba09': Order already matched + no_orders: + summary: No orders found for this market + value: + canceled: [] + not_canceled: {} + '400': + description: Bad request - Invalid payload + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid order payload + '401': + description: Unauthorized - Invalid API key or authentication failed + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid API key + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + '503': + description: >- + Service unavailable - Trading disabled (cancels still work in + cancel-only mode) + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: >- + Trading is currently disabled. Check polymarket.com for + updates + security: + - polyApiKey: [] + polyAddress: [] + polySignature: [] + polyPassphrase: [] + polyTimestamp: [] +components: + schemas: + OrderMarketCancelParams: + type: object + required: + - market + - asset_id + properties: + market: + type: string + description: Market (condition ID) + example: '0x0000000000000000000000000000000000000000000000000000000000000001' + asset_id: + type: string + description: Asset ID (token ID) + example: 0xabc123def456... + CancelOrdersResponse: + type: object + required: + - canceled + - not_canceled + properties: + canceled: + type: array + description: Array of order IDs that were successfully canceled + items: + type: string + example: + - '0xabcdef1234567890abcdef1234567890abcdef12' + not_canceled: + type: object + description: Map of order IDs that could not be canceled with error messages + additionalProperties: + type: string + example: + '0xabcdef1234567890abcdef1234567890abcdef12': Order not found or already canceled + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + securitySchemes: + polyApiKey: + type: apiKey + in: header + name: POLY_API_KEY + description: Your API key + polyAddress: + type: apiKey + in: header + name: POLY_ADDRESS + description: Ethereum address associated with the API key + polySignature: + type: apiKey + in: header + name: POLY_SIGNATURE + description: HMAC signature of the request + polyPassphrase: + type: apiKey + in: header + name: POLY_PASSPHRASE + description: API key passphrase + polyTimestamp: + type: apiKey + in: header + name: POLY_TIMESTAMP + description: Unix timestamp of the request + +```` diff --git a/docs/api-reference/trade/cancel-single-order.md b/docs/api-reference/trade/cancel-single-order.md new file mode 100644 index 0000000..8b8c10f --- /dev/null +++ b/docs/api-reference/trade/cancel-single-order.md @@ -0,0 +1,192 @@ +> ## 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 single order + +> Cancels a single order by its ID. Works even in cancel-only mode. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml delete /order +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 +paths: + /order: + delete: + tags: + - Trade + summary: Cancel single order + description: | + Cancels a single order by its ID. Works even in cancel-only mode. + operationId: cancelOrder + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CancelOrderPayload' + example: + orderID: '0xabcdef1234567890abcdef1234567890abcdef12' + responses: + '200': + description: Order cancellation result + content: + application/json: + schema: + $ref: '#/components/schemas/CancelOrdersResponse' + examples: + canceled: + summary: Order successfully canceled + value: + canceled: + - '0xabcdef1234567890abcdef1234567890abcdef12' + not_canceled: {} + not_canceled: + summary: Order could not be canceled + value: + canceled: [] + not_canceled: + '0xabcdef1234567890abcdef1234567890abcdef12': Order not found or already canceled + '400': + description: Bad request - Invalid order ID or payload + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + invalid_order_id: + summary: Invalid order ID + value: + error: Invalid orderID + invalid_payload: + summary: Invalid payload + value: + error: Invalid order payload + '401': + description: Unauthorized - Invalid API key or authentication failed + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid API key + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + '503': + description: >- + Service unavailable - Trading disabled (cancels still work in + cancel-only mode) + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: >- + Trading is currently disabled. Check polymarket.com for + updates + security: + - polyApiKey: [] + polyAddress: [] + polySignature: [] + polyPassphrase: [] + polyTimestamp: [] +components: + schemas: + CancelOrderPayload: + type: object + required: + - orderID + properties: + orderID: + type: string + description: Order ID (order hash) to cancel + example: '0xabcdef1234567890abcdef1234567890abcdef12' + CancelOrdersResponse: + type: object + required: + - canceled + - not_canceled + properties: + canceled: + type: array + description: Array of order IDs that were successfully canceled + items: + type: string + example: + - '0xabcdef1234567890abcdef1234567890abcdef12' + not_canceled: + type: object + description: Map of order IDs that could not be canceled with error messages + additionalProperties: + type: string + example: + '0xabcdef1234567890abcdef1234567890abcdef12': Order not found or already canceled + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + securitySchemes: + polyApiKey: + type: apiKey + in: header + name: POLY_API_KEY + description: Your API key + polyAddress: + type: apiKey + in: header + name: POLY_ADDRESS + description: Ethereum address associated with the API key + polySignature: + type: apiKey + in: header + name: POLY_SIGNATURE + description: HMAC signature of the request + polyPassphrase: + type: apiKey + in: header + name: POLY_PASSPHRASE + description: API key passphrase + polyTimestamp: + type: apiKey + in: header + name: POLY_TIMESTAMP + description: Unix timestamp of the request + +```` diff --git a/docs/api-reference/trade/get-builder-trades.md b/docs/api-reference/trade/get-builder-trades.md new file mode 100644 index 0000000..095cc1e --- /dev/null +++ b/docs/api-reference/trade/get-builder-trades.md @@ -0,0 +1,364 @@ +> ## 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 builder trades + +> Retrieves originated trades for a given builder. +Builders can only see their own originated trades. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /builder/trades +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 +paths: + /builder/trades: + get: + tags: + - Trade + summary: Get builder trades + description: | + Retrieves originated trades for a given builder. + Builders can only see their own originated trades. + operationId: getBuilderTrades + parameters: + - name: id + in: query + description: Trade ID to filter by specific trade + required: false + schema: + type: string + example: trade-123 + - name: builder + in: query + description: >- + Builder identifier (automatically set from authenticated builder, or + can be specified with admin token) + required: false + schema: + type: string + example: 0199bfa0-f4c1-7a98-9c2b-b29cc6d39e10 + - name: market + in: query + description: Market (condition ID) to filter trades + required: false + schema: + type: string + pattern: ^0x[a-fA-F0-9]{64}$ + example: '0x0000000000000000000000000000000000000000000000000000000000000001' + - name: asset_id + in: query + description: Asset ID (token ID) to filter trades + required: false + schema: + type: string + example: >- + 15871154585880608648532107628464183779895785213830018178010423617714102767076 + - name: before + in: query + description: Filter trades before this Unix timestamp + required: false + schema: + type: string + pattern: ^\d+$ + example: '1700000000' + - name: after + in: query + description: Filter trades after this Unix timestamp + required: false + schema: + type: string + pattern: ^\d+$ + example: '1600000000' + - name: next_cursor + in: query + description: Cursor for pagination (base64 encoded offset) + required: false + schema: + type: string + example: MA== + responses: + '200': + description: Successfully retrieved builder trades + content: + application/json: + schema: + $ref: '#/components/schemas/BuilderTradesResponse' + examples: + example: + summary: Builder trades response + value: + limit: 300 + next_cursor: MzAw + count: 2 + data: + - id: trade-123 + tradeType: TAKER + takerOrderHash: '0xabcdef1234567890abcdef1234567890abcdef12' + builder: 0199bfa0-f4c1-7a98-9c2b-b29cc6d39e10 + market: >- + 0x0000000000000000000000000000000000000000000000000000000000000001 + assetId: >- + 15871154585880608648532107628464183779895785213830018178010423617714102767076 + side: BUY + size: '100000000' + sizeUsdc: '50000000' + price: '0.5' + status: TRADE_STATUS_CONFIRMED + outcome: 'YES' + outcomeIndex: 0 + owner: f4f247b7-4ac7-ff29-a152-04fda0a8755a + maker: '0x1234567890123456789012345678901234567890' + transactionHash: >- + 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef + matchTime: '1700000000' + bucketIndex: 0 + fee: '300000' + feeUsdc: '150000' + createdAt: '2024-01-01T00:00:00Z' + updatedAt: '2024-01-01T00:00:00Z' + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: invalid builder trade params + '401': + description: Unauthorized - Invalid builder API key or authentication failed + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid API key + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: could not fetch builder trades + security: + - polyBuilderApiKey: [] + polyBuilderPassphrase: [] + polyBuilderSignature: [] + polyBuilderTimestamp: [] +components: + schemas: + BuilderTradesResponse: + type: object + description: Paginated builder trades response + required: + - limit + - next_cursor + - count + - data + properties: + limit: + type: integer + description: Maximum number of items per page + example: 300 + next_cursor: + type: string + description: >- + Cursor for next page (base64 encoded offset). "LTE=" indicates no + more pages + example: MzAw + count: + type: integer + description: Number of items in current response + example: 2 + data: + type: array + description: Array of builder trades + items: + $ref: '#/components/schemas/BuilderTrade' + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + BuilderTrade: + type: object + description: Builder trade information + required: + - id + - tradeType + - takerOrderHash + - builder + - market + - assetId + - side + - size + - sizeUsdc + - price + - status + - outcome + - outcomeIndex + - owner + - maker + - transactionHash + - matchTime + - bucketIndex + - fee + - feeUsdc + properties: + id: + type: string + description: Trade ID + example: trade-123 + tradeType: + type: string + description: Trade type + example: TAKER + takerOrderHash: + type: string + description: Taker order hash + example: '0xabcdef1234567890abcdef1234567890abcdef12' + builder: + type: string + description: Builder identifier + example: 0199bfa0-f4c1-7a98-9c2b-b29cc6d39e10 + market: + type: string + description: Market (condition ID) + pattern: ^0x[a-fA-F0-9]{64}$ + example: '0x0000000000000000000000000000000000000000000000000000000000000001' + assetId: + type: string + description: Asset ID (token ID) + example: >- + 15871154585880608648532107628464183779895785213830018178010423617714102767076 + side: + type: string + description: Trade side + enum: + - BUY + - SELL + example: BUY + size: + type: string + description: Trade size + example: '100000000' + sizeUsdc: + type: string + description: Trade size in USDC + example: '50000000' + price: + type: string + description: Trade price + example: '0.5' + status: + type: string + description: Trade status + example: TRADE_STATUS_CONFIRMED + outcome: + type: string + description: Market outcome + example: 'YES' + outcomeIndex: + type: integer + description: Outcome index + example: 0 + owner: + type: string + description: Owner UUID + example: f4f247b7-4ac7-ff29-a152-04fda0a8755a + maker: + type: string + description: Maker address + pattern: ^0x[a-fA-F0-9]{40}$ + example: '0x1234567890123456789012345678901234567890' + transactionHash: + type: string + description: Transaction hash + pattern: ^0x[a-fA-F0-9]{64}$ + example: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' + matchTime: + type: string + description: Match time (Unix timestamp) + example: '1700000000' + bucketIndex: + type: integer + description: Bucket index + example: 0 + fee: + type: string + description: Fee amount + example: '300000' + feeUsdc: + type: string + description: Fee amount in USDC + example: '150000' + err_msg: + type: + - string + - 'null' + description: Error message (if any) + example: null + createdAt: + type: string + format: date-time + description: Creation timestamp + example: '2024-01-01T00:00:00Z' + updatedAt: + type: string + format: date-time + description: Last update timestamp + example: '2024-01-01T00:00:00Z' + securitySchemes: + polyBuilderApiKey: + type: apiKey + in: header + name: POLY_BUILDER_API_KEY + description: Builder API key for authentication + polyBuilderPassphrase: + type: apiKey + in: header + name: POLY_BUILDER_PASSPHRASE + description: Passphrase for builder authentication + polyBuilderSignature: + type: apiKey + in: header + name: POLY_BUILDER_SIGNATURE + description: HMAC signature for builder authentication + polyBuilderTimestamp: + type: apiKey + in: header + name: POLY_BUILDER_TIMESTAMP + description: Unix timestamp for builder authentication + +```` diff --git a/docs/api-reference/trade/get-order-scoring-status.md b/docs/api-reference/trade/get-order-scoring-status.md new file mode 100644 index 0000000..c7f97ac --- /dev/null +++ b/docs/api-reference/trade/get-order-scoring-status.md @@ -0,0 +1,186 @@ +> ## 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 order scoring status + +> Checks if a specific order is currently scoring for rewards. + +An order is considered "scoring" if it meets all the criteria for earning maker rewards: +- The order is live on a rewards-eligible market +- The order meets the minimum size requirements +- The order is within the valid spread range +- The order has been live for the required duration + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /order-scoring +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 +paths: + /order-scoring: + get: + tags: + - Trade + summary: Get order scoring status + description: > + Checks if a specific order is currently scoring for rewards. + + + An order is considered "scoring" if it meets all the criteria for + earning maker rewards: + + - The order is live on a rewards-eligible market + + - The order meets the minimum size requirements + + - The order is within the valid spread range + + - The order has been live for the required duration + operationId: getOrderScoring + parameters: + - name: order_id + in: query + description: The order ID (order hash) to check scoring status for + required: true + schema: + type: string + example: '0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890' + responses: + '200': + description: Successfully retrieved order scoring status + content: + application/json: + schema: + $ref: '#/components/schemas/OrderScoringResponse' + examples: + scoring: + summary: Order is scoring + value: + scoring: true + not_scoring: + summary: Order is not scoring + value: + scoring: false + '400': + description: Bad request - Invalid order ID + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid order_id + '401': + description: Unauthorized - Invalid API key or order doesn't belong to user + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid API key + '404': + description: Market not found for the order + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: market not found + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + '503': + description: Service unavailable - Trading disabled + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: >- + Trading is currently disabled. Check polymarket.com for + updates + security: + - polyApiKey: [] + polyAddress: [] + polySignature: [] + polyPassphrase: [] + polyTimestamp: [] +components: + schemas: + OrderScoringResponse: + type: object + description: Response indicating whether an order is currently scoring for rewards + required: + - scoring + properties: + scoring: + type: boolean + description: Whether the order is currently scoring for maker rewards + example: true + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + securitySchemes: + polyApiKey: + type: apiKey + in: header + name: POLY_API_KEY + description: Your API key + polyAddress: + type: apiKey + in: header + name: POLY_ADDRESS + description: Ethereum address associated with the API key + polySignature: + type: apiKey + in: header + name: POLY_SIGNATURE + description: HMAC signature of the request + polyPassphrase: + type: apiKey + in: header + name: POLY_PASSPHRASE + description: API key passphrase + polyTimestamp: + type: apiKey + in: header + name: POLY_TIMESTAMP + description: Unix timestamp of the request + +```` diff --git a/docs/api-reference/trade/get-single-order-by-id.md b/docs/api-reference/trade/get-single-order-by-id.md new file mode 100644 index 0000000..f1221eb --- /dev/null +++ b/docs/api-reference/trade/get-single-order-by-id.md @@ -0,0 +1,251 @@ +> ## 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 single order by ID + +> Retrieves a specific order by its ID (order hash) for the authenticated user. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /order/{orderID} +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 +paths: + /order/{orderID}: + get: + tags: + - Trade + summary: Get single order by ID + description: > + Retrieves a specific order by its ID (order hash) for the authenticated + user. + operationId: getOrder + parameters: + - name: orderID + in: path + description: Order ID (order hash) + required: true + schema: + type: string + example: '0x0000000000000000000000000000000000000000000000000000000000000001' + responses: + '200': + description: Successfully retrieved order + content: + application/json: + schema: + $ref: '#/components/schemas/OpenOrder' + example: + id: '0xabcdef1234567890abcdef1234567890abcdef12' + status: ORDER_STATUS_LIVE + owner: f4f247b7-4ac7-ff29-a152-04fda0a8755a + maker_address: '0x1234567890123456789012345678901234567890' + market: >- + 0x0000000000000000000000000000000000000000000000000000000000000001 + asset_id: 0xabc123def456... + side: BUY + original_size: '100000000' + size_matched: '0' + price: '0.5' + outcome: 'YES' + expiration: '1735689600' + order_type: GTC + associate_trades: [] + created_at: 1700000000 + '400': + description: Bad request - Invalid order ID + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid orderID + '401': + description: Unauthorized - Invalid API key or authentication failed + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid API key + '404': + description: Order not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Order not found + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + security: + - polyApiKey: [] + polyAddress: [] + polySignature: [] + polyPassphrase: [] + polyTimestamp: [] +components: + schemas: + OpenOrder: + type: object + required: + - id + - status + - owner + - maker_address + - market + - asset_id + - side + - original_size + - size_matched + - price + - expiration + - order_type + - created_at + - outcome + properties: + id: + type: string + description: Order ID (order hash) + example: '0xabcdef1234567890abcdef1234567890abcdef12' + status: + type: string + description: Order status + enum: + - ORDER_STATUS_LIVE + - ORDER_STATUS_INVALID + - ORDER_STATUS_CANCELED_MARKET_RESOLVED + - ORDER_STATUS_CANCELED + - ORDER_STATUS_MATCHED + owner: + type: string + description: UUID of the order owner + example: f4f247b7-4ac7-ff29-a152-04fda0a8755a + maker_address: + type: string + description: Ethereum address of the maker + example: '0x1234567890123456789012345678901234567890' + market: + type: string + description: Market (condition ID) + example: '0x0000000000000000000000000000000000000000000000000000000000000001' + asset_id: + type: string + description: Asset ID (token ID) + example: 0xabc123def456... + side: + type: string + description: Order side + enum: + - BUY + - SELL + example: BUY + original_size: + type: string + description: Original order size in fixed-math with 6 decimals + example: '100000000' + size_matched: + type: string + description: Size that has been matched in fixed-math with 6 decimals + example: '0' + price: + type: string + description: Order price + example: '0.5' + outcome: + type: string + description: Market outcome (YES/NO) + example: 'YES' + expiration: + type: string + description: Unix timestamp when the order expires + example: '1735689600' + order_type: + type: string + description: Order type + enum: + - GTC + - FOK + - GTD + - FAK + example: GTC + associate_trades: + type: array + description: Array of associated trade IDs + items: + type: string + example: + - trade-123 + created_at: + type: integer + description: Unix timestamp when the order was created + example: 1700000000 + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + securitySchemes: + polyApiKey: + type: apiKey + in: header + name: POLY_API_KEY + description: Your API key + polyAddress: + type: apiKey + in: header + name: POLY_ADDRESS + description: Ethereum address associated with the API key + polySignature: + type: apiKey + in: header + name: POLY_SIGNATURE + description: HMAC signature of the request + polyPassphrase: + type: apiKey + in: header + name: POLY_PASSPHRASE + description: API key passphrase + polyTimestamp: + type: apiKey + in: header + name: POLY_TIMESTAMP + description: Unix timestamp of the request + +```` diff --git a/docs/api-reference/trade/get-trades.md b/docs/api-reference/trade/get-trades.md new file mode 100644 index 0000000..e2d3ca8 --- /dev/null +++ b/docs/api-reference/trade/get-trades.md @@ -0,0 +1,387 @@ +> ## 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 trades + +> Retrieves trades for the authenticated user. Returns paginated results. +Requires readonly or level 2 API key authentication. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /trades +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 +paths: + /trades: + get: + tags: + - Trade + summary: Get trades + description: | + Retrieves trades for the authenticated user. Returns paginated results. + Requires readonly or level 2 API key authentication. + operationId: getTrades + parameters: + - name: id + in: query + description: Trade ID to filter by specific trade + required: false + schema: + type: string + example: trade-123 + - name: maker_address + in: query + description: Maker address to filter trades + required: true + schema: + type: string + pattern: ^0x[a-fA-F0-9]{40}$ + example: '0x1234567890123456789012345678901234567890' + - name: market + in: query + description: Market (condition ID) to filter trades + required: false + schema: + type: string + pattern: ^0x[a-fA-F0-9]{64}$ + example: '0x0000000000000000000000000000000000000000000000000000000000000001' + - name: asset_id + in: query + description: Asset ID (token ID) to filter trades + required: false + schema: + type: string + example: >- + 15871154585880608648532107628464183779895785213830018178010423617714102767076 + - name: before + in: query + description: Filter trades before this Unix timestamp + required: false + schema: + type: string + pattern: ^\d+$ + example: '1700000000' + - name: after + in: query + description: Filter trades after this Unix timestamp + required: false + schema: + type: string + pattern: ^\d+$ + example: '1600000000' + - name: next_cursor + in: query + description: Cursor for pagination (base64 encoded offset) + required: false + schema: + type: string + example: MA== + responses: + '200': + description: Successfully retrieved trades + content: + application/json: + schema: + $ref: '#/components/schemas/TradesResponse' + examples: + example: + summary: User trades response + value: + limit: 100 + next_cursor: MTAw + count: 2 + data: + - id: trade-123 + taker_order_id: '0xabcdef1234567890abcdef1234567890abcdef12' + market: >- + 0x0000000000000000000000000000000000000000000000000000000000000001 + asset_id: >- + 15871154585880608648532107628464183779895785213830018178010423617714102767076 + side: BUY + size: '100000000' + fee_rate_bps: '30' + price: '0.5' + status: TRADE_STATUS_CONFIRMED + match_time: '1700000000' + last_update: '1700000000' + outcome: 'YES' + bucket_index: 0 + owner: f4f247b7-4ac7-ff29-a152-04fda0a8755a + maker_address: '0x1234567890123456789012345678901234567890' + transaction_hash: >- + 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef + trader_side: TAKER + maker_orders: [] + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid trade params payload + '401': + description: Unauthorized - Invalid API key or authentication failed + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid API key + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + security: + - polyApiKey: [] + polyAddress: [] + polySignature: [] + polyPassphrase: [] + polyTimestamp: [] +components: + schemas: + TradesResponse: + type: object + description: Paginated trades response + required: + - limit + - next_cursor + - count + - data + properties: + limit: + type: integer + description: Maximum number of items per page + example: 100 + next_cursor: + type: string + description: >- + Cursor for next page (base64 encoded offset). "LTE=" indicates no + more pages + example: MTAw + count: + type: integer + description: Number of items in current response + example: 2 + data: + type: array + description: Array of trades + items: + $ref: '#/components/schemas/Trade' + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + Trade: + type: object + description: Trade information + required: + - id + - taker_order_id + - market + - asset_id + - side + - size + - price + - status + - match_time + - last_update + - outcome + - bucket_index + - owner + - maker_address + - trader_side + properties: + id: + type: string + description: Trade ID + example: trade-123 + taker_order_id: + type: string + description: Taker order ID (hash) + example: '0xabcdef1234567890abcdef1234567890abcdef12' + market: + type: string + description: Market (condition ID) + pattern: ^0x[a-fA-F0-9]{64}$ + example: '0x0000000000000000000000000000000000000000000000000000000000000001' + asset_id: + type: string + description: Asset ID (token ID) + example: >- + 15871154585880608648532107628464183779895785213830018178010423617714102767076 + side: + type: string + description: Trade side + enum: + - BUY + - SELL + example: BUY + size: + type: string + description: Trade size + example: '100000000' + fee_rate_bps: + type: string + description: Fee rate in basis points + example: '30' + price: + type: string + description: Trade price + example: '0.5' + status: + type: string + description: Trade status + enum: + - TRADE_STATUS_CONFIRMED + - TRADE_STATUS_FAILED + - TRADE_STATUS_RETRYING + - TRADE_STATUS_MATCHED + - TRADE_STATUS_MINED + example: TRADE_STATUS_CONFIRMED + match_time: + type: string + description: Match time (Unix timestamp) + example: '1700000000' + match_time_nano: + type: string + description: Match time in nanoseconds + example: '1700000000000000000' + last_update: + type: string + description: Last update time (Unix timestamp) + example: '1700000000' + outcome: + type: string + description: Market outcome + example: 'YES' + bucket_index: + type: integer + description: Bucket index + example: 0 + owner: + type: string + description: Owner UUID + example: f4f247b7-4ac7-ff29-a152-04fda0a8755a + maker_address: + type: string + description: Maker address + pattern: ^0x[a-fA-F0-9]{40}$ + example: '0x1234567890123456789012345678901234567890' + transaction_hash: + type: string + description: Transaction hash + pattern: ^0x[a-fA-F0-9]{64}$ + example: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef' + err_msg: + type: + - string + - 'null' + description: Error message (if any) + example: null + maker_orders: + type: array + description: Array of maker orders associated with this trade + items: + type: object + properties: + order_id: + type: string + description: Order ID (hash) + owner: + type: string + description: Owner UUID + maker_address: + type: string + description: Maker address + matched_amount: + type: string + description: Matched amount + price: + type: string + description: Price + fee_rate_bps: + type: string + description: Fee rate in basis points + asset_id: + type: string + description: Asset ID + outcome: + type: string + description: Outcome + side: + type: string + enum: + - BUY + - SELL + example: [] + trader_side: + type: string + description: Trader side (TAKER or MAKER) + enum: + - TAKER + - MAKER + example: TAKER + securitySchemes: + polyApiKey: + type: apiKey + in: header + name: POLY_API_KEY + description: Your API key + polyAddress: + type: apiKey + in: header + name: POLY_ADDRESS + description: Ethereum address associated with the API key + polySignature: + type: apiKey + in: header + name: POLY_SIGNATURE + description: HMAC signature of the request + polyPassphrase: + type: apiKey + in: header + name: POLY_PASSPHRASE + description: API key passphrase + polyTimestamp: + type: apiKey + in: header + name: POLY_TIMESTAMP + description: Unix timestamp of the request + +```` diff --git a/docs/api-reference/trade/get-user-orders.md b/docs/api-reference/trade/get-user-orders.md new file mode 100644 index 0000000..e35b31f --- /dev/null +++ b/docs/api-reference/trade/get-user-orders.md @@ -0,0 +1,315 @@ +> ## 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 user orders + +> Retrieves open orders for the authenticated user. Returns paginated results. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml get /orders +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 +paths: + /orders: + get: + tags: + - Trade + summary: Get user orders + description: > + Retrieves open orders for the authenticated user. Returns paginated + results. + operationId: getOrders + parameters: + - name: id + in: query + description: Order ID (hash) to filter by specific order + required: false + schema: + type: string + example: '0xabcdef1234567890abcdef1234567890abcdef12' + - name: market + in: query + description: Market (condition ID) to filter orders + required: false + schema: + type: string + example: '0x0000000000000000000000000000000000000000000000000000000000000001' + - name: asset_id + in: query + description: Asset ID (token ID) to filter orders + required: false + schema: + type: string + example: 0xabc123def456... + - name: next_cursor + in: query + description: Cursor for pagination (base64 encoded offset) + required: false + schema: + type: string + example: MA== + responses: + '200': + description: Successfully retrieved orders + content: + application/json: + schema: + $ref: '#/components/schemas/OrdersResponse' + examples: + example: + summary: User orders response + value: + limit: 100 + next_cursor: MTAw + count: 2 + data: + - id: '0xabcdef1234567890abcdef1234567890abcdef12' + status: ORDER_STATUS_LIVE + owner: f4f247b7-4ac7-ff29-a152-04fda0a8755a + maker_address: '0x1234567890123456789012345678901234567890' + market: >- + 0x0000000000000000000000000000000000000000000000000000000000000001 + asset_id: 0xabc123def456... + side: BUY + original_size: '100000000' + size_matched: '0' + price: '0.5' + outcome: 'YES' + expiration: '1735689600' + order_type: GTC + associate_trades: [] + created_at: 1700000000 + - id: '0xfedcba0987654321fedcba0987654321fedcba09' + status: ORDER_STATUS_LIVE + owner: f4f247b7-4ac7-ff29-a152-04fda0a8755a + maker_address: '0x1234567890123456789012345678901234567890' + market: >- + 0x0000000000000000000000000000000000000000000000000000000000000002 + asset_id: 0xdef456abc789... + side: SELL + original_size: '200000000' + size_matched: '50000000' + price: '0.75' + outcome: 'NO' + expiration: '1735689600' + order_type: GTC + associate_trades: + - trade-123 + created_at: 1700000001 + '400': + description: Bad request - Invalid parameters + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: invalid order params payload + '401': + description: Unauthorized - Invalid API key or authentication failed + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid API key + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + security: + - polyApiKey: [] + polyAddress: [] + polySignature: [] + polyPassphrase: [] + polyTimestamp: [] +components: + schemas: + OrdersResponse: + type: object + required: + - limit + - next_cursor + - count + - data + properties: + limit: + type: integer + description: Maximum number of results per page + example: 100 + next_cursor: + type: string + description: >- + Cursor for pagination (base64 encoded offset). Empty if no more + results. + example: MTAw + count: + type: integer + description: Number of orders in this response + example: 2 + data: + type: array + description: Array of open orders + items: + $ref: '#/components/schemas/OpenOrder' + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + OpenOrder: + type: object + required: + - id + - status + - owner + - maker_address + - market + - asset_id + - side + - original_size + - size_matched + - price + - expiration + - order_type + - created_at + - outcome + properties: + id: + type: string + description: Order ID (order hash) + example: '0xabcdef1234567890abcdef1234567890abcdef12' + status: + type: string + description: Order status + enum: + - ORDER_STATUS_LIVE + - ORDER_STATUS_INVALID + - ORDER_STATUS_CANCELED_MARKET_RESOLVED + - ORDER_STATUS_CANCELED + - ORDER_STATUS_MATCHED + owner: + type: string + description: UUID of the order owner + example: f4f247b7-4ac7-ff29-a152-04fda0a8755a + maker_address: + type: string + description: Ethereum address of the maker + example: '0x1234567890123456789012345678901234567890' + market: + type: string + description: Market (condition ID) + example: '0x0000000000000000000000000000000000000000000000000000000000000001' + asset_id: + type: string + description: Asset ID (token ID) + example: 0xabc123def456... + side: + type: string + description: Order side + enum: + - BUY + - SELL + example: BUY + original_size: + type: string + description: Original order size in fixed-math with 6 decimals + example: '100000000' + size_matched: + type: string + description: Size that has been matched in fixed-math with 6 decimals + example: '0' + price: + type: string + description: Order price + example: '0.5' + outcome: + type: string + description: Market outcome (YES/NO) + example: 'YES' + expiration: + type: string + description: Unix timestamp when the order expires + example: '1735689600' + order_type: + type: string + description: Order type + enum: + - GTC + - FOK + - GTD + - FAK + example: GTC + associate_trades: + type: array + description: Array of associated trade IDs + items: + type: string + example: + - trade-123 + created_at: + type: integer + description: Unix timestamp when the order was created + example: 1700000000 + securitySchemes: + polyApiKey: + type: apiKey + in: header + name: POLY_API_KEY + description: Your API key + polyAddress: + type: apiKey + in: header + name: POLY_ADDRESS + description: Ethereum address associated with the API key + polySignature: + type: apiKey + in: header + name: POLY_SIGNATURE + description: HMAC signature of the request + polyPassphrase: + type: apiKey + in: header + name: POLY_PASSPHRASE + description: API key passphrase + polyTimestamp: + type: apiKey + in: header + name: POLY_TIMESTAMP + description: Unix timestamp of the request + +```` diff --git a/docs/api-reference/trade/post-a-new-order.md b/docs/api-reference/trade/post-a-new-order.md new file mode 100644 index 0000000..2bf2d9e --- /dev/null +++ b/docs/api-reference/trade/post-a-new-order.md @@ -0,0 +1,376 @@ +> ## 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. + +# Post a new order + +> Creates a new order in the order book + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml post /order +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 +paths: + /order: + post: + tags: + - Trade + summary: Post a new order + description: | + Creates a new order in the order book + operationId: postOrder + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SendOrder' + examples: + example: + summary: Send order example + value: + order: + maker: '0x1234567890123456789012345678901234567890' + signer: '0x1234567890123456789012345678901234567890' + taker: '0x0000000000000000000000000000000000000000' + tokenId: 0xabc123def456... + makerAmount: '100000000' + takerAmount: '200000000' + side: BUY + expiration: '1735689600' + nonce: '0' + feeRateBps: '30' + signature: 0x1234abcd... + salt: 1234567890 + signatureType: 0 + owner: f4f247b7-4ac7-ff29-a152-04fda0a8755a + orderType: GTC + deferExec: false + responses: + '200': + description: Order successfully processed + content: + application/json: + schema: + $ref: '#/components/schemas/SendOrderResponse' + examples: + live_order: + summary: Order placed on book + value: + success: true + orderID: '0xabcdef1234567890abcdef1234567890abcdef12' + status: live + makingAmount: '100000000' + takingAmount: '200000000' + errorMsg: '' + matched_order: + summary: Order immediately matched + value: + success: true + orderID: '0xabcdef1234567890abcdef1234567890abcdef12' + status: matched + makingAmount: '100000000' + takingAmount: '200000000' + transactionsHashes: + - '0x1234567890abcdef1234567890abcdef12345678' + tradeIDs: + - trade-123 + errorMsg: '' + delayed_order: + summary: Order delayed + value: + success: true + orderID: '0xabcdef1234567890abcdef1234567890abcdef12' + status: delayed + makingAmount: '100000000' + takingAmount: '200000000' + errorMsg: '' + '400': + description: Bad request - Invalid order payload or validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + invalid_payload: + summary: Invalid order payload + value: + error: Invalid order payload + owner_mismatch: + summary: Owner mismatch + value: + error: the order owner has to be the owner of the API KEY + signer_mismatch: + summary: Signer mismatch + value: + error: >- + the order signer address has to be the address of the API + KEY + banned_address: + summary: Banned address + value: + error: '''0x1234...'' address banned' + closed_only_mode: + summary: Closed only mode violation + value: + error: '''0x1234...'' address in closed only mode' + invalid_order: + summary: Invalid order details + value: + error: >- + order 0xabc... is invalid. Price (100) breaks minimum tick + size rule: 0.1 + '401': + description: Unauthorized - Invalid API key or authentication failed + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid API key + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: could not insert order + '503': + description: Service unavailable - Trading disabled or cancel-only mode + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + trading_disabled: + summary: Trading disabled + value: + error: >- + Trading is currently disabled. Check polymarket.com for + updates + cancel_only: + summary: Cancel-only mode + value: + error: >- + Trading is currently cancel-only. New orders are not + accepted, but cancels are allowed. + security: + - polyApiKey: [] + polyAddress: [] + polySignature: [] + polyPassphrase: [] + polyTimestamp: [] +components: + schemas: + SendOrder: + type: object + required: + - order + - owner + properties: + order: + $ref: '#/components/schemas/Order' + owner: + type: string + description: UUID of the API key owner + example: f4f247b7-4ac7-ff29-a152-04fda0a8755a + orderType: + type: string + description: Time in force + enum: + - GTC + - FOK + - GTD + - FAK + default: GTC + deferExec: + type: boolean + description: Whether to defer execution + default: false + SendOrderResponse: + type: object + required: + - success + - orderID + - status + properties: + success: + type: boolean + description: Whether the order was successfully processed + example: true + orderID: + type: string + description: Unique identifier for the order (order hash) + example: '0xabcdef1234567890abcdef1234567890abcdef12' + status: + type: string + description: Status of the order after processing + enum: + - live + - matched + - delayed + makingAmount: + type: string + description: Amount the maker is providing in fixed-math with 6 decimals + example: '100000000' + takingAmount: + type: string + description: Amount the taker is providing in fixed-math with 6 decimals + example: '200000000' + transactionsHashes: + type: array + description: Array of transaction hashes (present when status is 'matched') + items: + type: string + example: + - '0x1234567890abcdef1234567890abcdef12345678' + tradeIDs: + type: array + description: Array of trade IDs (present when status is 'matched') + items: + type: string + errorMsg: + type: string + description: Error message (empty on success) + example: '' + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + Order: + type: object + required: + - maker + - signer + - taker + - tokenId + - makerAmount + - takerAmount + - side + - expiration + - nonce + - feeRateBps + - signature + - salt + - signatureType + properties: + maker: + type: string + description: >- + Ethereum address of the maker (In the default case, this is your + proxy address) + example: '0x1234567890123456789012345678901234567890' + signer: + type: string + description: Ethereum address of the signer + example: '0x1234567890123456789012345678901234567890' + taker: + type: string + description: Ethereum address of the taker (0x0 for open orders) + example: '0x0000000000000000000000000000000000000000' + tokenId: + type: string + description: Token ID (asset ID) for the order + example: 0xabc123def456... + makerAmount: + type: string + description: Amount the maker is providing in fixed-math with 6 decimals + example: '100000000' + takerAmount: + type: string + description: Amount the taker is providing in fixed-math with 6 decimals + example: '200000000' + side: + type: string + description: Order side + enum: + - BUY + - SELL + example: BUY + expiration: + type: string + description: Unix timestamp when the order expires + example: '1735689600' + nonce: + type: string + description: Order nonce + example: '0' + feeRateBps: + type: string + description: Fee rate in basis points + example: '30' + signature: + type: string + description: Cryptographic signature of the order + example: 0x1234abcd... + salt: + type: integer + description: Random salt for order uniqueness + example: 1234567890 + signatureType: + type: integer + description: Type of signature (0 = EOA, 1 = POLY_PROXY, 2 = POLY_GNOSIS_SAFE) + enum: + - 0 + - 1 + - 2 + securitySchemes: + polyApiKey: + type: apiKey + in: header + name: POLY_API_KEY + description: Your API key + polyAddress: + type: apiKey + in: header + name: POLY_ADDRESS + description: Ethereum address associated with the API key + polySignature: + type: apiKey + in: header + name: POLY_SIGNATURE + description: HMAC signature of the request + polyPassphrase: + type: apiKey + in: header + name: POLY_PASSPHRASE + description: API key passphrase + polyTimestamp: + type: apiKey + in: header + name: POLY_TIMESTAMP + description: Unix timestamp of the request + +```` diff --git a/docs/api-reference/trade/post-multiple-orders.md b/docs/api-reference/trade/post-multiple-orders.md new file mode 100644 index 0000000..7f6668d --- /dev/null +++ b/docs/api-reference/trade/post-multiple-orders.md @@ -0,0 +1,398 @@ +> ## 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. + +# Post multiple orders + +> Creates multiple new orders in the order book. Orders are processed in parallel. +Maximum 15 orders per request. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml post /orders +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 +paths: + /orders: + post: + tags: + - Trade + summary: Post multiple orders + description: > + Creates multiple new orders in the order book. Orders are processed in + parallel. + + Maximum 15 orders per request. + operationId: postOrders + requestBody: + required: true + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/SendOrder' + maxItems: 15 + examples: + example: + summary: Send multiple orders example + value: + - order: + maker: '0x1234567890123456789012345678901234567890' + signer: '0x1234567890123456789012345678901234567890' + taker: '0x0000000000000000000000000000000000000000' + tokenId: 0xabc123def456... + makerAmount: '100000000' + takerAmount: '200000000' + side: BUY + expiration: '1735689600' + nonce: '0' + feeRateBps: '30' + signature: 0x1234abcd... + salt: 1234567890 + signatureType: 0 + owner: f4f247b7-4ac7-ff29-a152-04fda0a8755a + orderType: GTC + deferExec: false + - order: + maker: '0x1234567890123456789012345678901234567890' + signer: '0x1234567890123456789012345678901234567890' + taker: '0x0000000000000000000000000000000000000000' + tokenId: 0xdef456abc789... + makerAmount: '200000000' + takerAmount: '100000000' + side: SELL + expiration: '1735689600' + nonce: '0' + feeRateBps: '30' + signature: 0x5678efgh... + salt: 1234567891 + signatureType: 0 + owner: f4f247b7-4ac7-ff29-a152-04fda0a8755a + orderType: GTC + deferExec: false + responses: + '200': + description: >- + Orders successfully processed. Returns an array of order responses, + one for each order in the request. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/SendOrderResponse' + examples: + mixed_results: + summary: Mixed order results + value: + - success: true + orderID: '0xabcdef1234567890abcdef1234567890abcdef12' + status: live + makingAmount: '100000000' + takingAmount: '200000000' + errorMsg: '' + - success: true + orderID: '0xfedcba0987654321fedcba0987654321fedcba09' + status: matched + makingAmount: '200000000' + takingAmount: '100000000' + transactionsHashes: + - '0x1234567890abcdef1234567890abcdef12345678' + tradeIDs: + - trade-123 + errorMsg: '' + - success: false + orderID: '' + status: delayed + errorMsg: 'Rate limit exceeded for tokenId: 0xdef456abc789...' + '400': + description: Bad request - Invalid order payload or validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + invalid_payload: + summary: Invalid order payload + value: + error: Invalid order payload + empty_payload: + summary: Empty orders array + value: + error: Invalid order payload + too_many_orders: + summary: Too many orders + value: + error: 'Too many orders in payload: 20, max allowed: 15' + owner_mismatch: + summary: Owner mismatch + value: + error: the order owner has to be the owner of the API KEY + signer_mismatch: + summary: Signer mismatch + value: + error: >- + the order signer address has to be the address of the API + KEY + banned_address: + summary: Banned address + value: + error: '''0x1234...'' address banned' + closed_only_mode: + summary: Closed only mode violation + value: + error: '''0x1234...'' address in closed only mode' + '401': + description: Unauthorized - Invalid API key or authentication failed + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid API key + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: could not insert order + '503': + description: Service unavailable - Trading disabled or cancel-only mode + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + examples: + trading_disabled: + summary: Trading disabled + value: + error: >- + Trading is currently disabled. Check polymarket.com for + updates + cancel_only: + summary: Cancel-only mode + value: + error: >- + Trading is currently cancel-only. New orders are not + accepted, but cancels are allowed. + security: + - polyApiKey: [] + polyAddress: [] + polySignature: [] + polyPassphrase: [] + polyTimestamp: [] +components: + schemas: + SendOrder: + type: object + required: + - order + - owner + properties: + order: + $ref: '#/components/schemas/Order' + owner: + type: string + description: UUID of the API key owner + example: f4f247b7-4ac7-ff29-a152-04fda0a8755a + orderType: + type: string + description: Time in force + enum: + - GTC + - FOK + - GTD + - FAK + default: GTC + deferExec: + type: boolean + description: Whether to defer execution + default: false + SendOrderResponse: + type: object + required: + - success + - orderID + - status + properties: + success: + type: boolean + description: Whether the order was successfully processed + example: true + orderID: + type: string + description: Unique identifier for the order (order hash) + example: '0xabcdef1234567890abcdef1234567890abcdef12' + status: + type: string + description: Status of the order after processing + enum: + - live + - matched + - delayed + makingAmount: + type: string + description: Amount the maker is providing in fixed-math with 6 decimals + example: '100000000' + takingAmount: + type: string + description: Amount the taker is providing in fixed-math with 6 decimals + example: '200000000' + transactionsHashes: + type: array + description: Array of transaction hashes (present when status is 'matched') + items: + type: string + example: + - '0x1234567890abcdef1234567890abcdef12345678' + tradeIDs: + type: array + description: Array of trade IDs (present when status is 'matched') + items: + type: string + errorMsg: + type: string + description: Error message (empty on success) + example: '' + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + Order: + type: object + required: + - maker + - signer + - taker + - tokenId + - makerAmount + - takerAmount + - side + - expiration + - nonce + - feeRateBps + - signature + - salt + - signatureType + properties: + maker: + type: string + description: >- + Ethereum address of the maker (In the default case, this is your + proxy address) + example: '0x1234567890123456789012345678901234567890' + signer: + type: string + description: Ethereum address of the signer + example: '0x1234567890123456789012345678901234567890' + taker: + type: string + description: Ethereum address of the taker (0x0 for open orders) + example: '0x0000000000000000000000000000000000000000' + tokenId: + type: string + description: Token ID (asset ID) for the order + example: 0xabc123def456... + makerAmount: + type: string + description: Amount the maker is providing in fixed-math with 6 decimals + example: '100000000' + takerAmount: + type: string + description: Amount the taker is providing in fixed-math with 6 decimals + example: '200000000' + side: + type: string + description: Order side + enum: + - BUY + - SELL + example: BUY + expiration: + type: string + description: Unix timestamp when the order expires + example: '1735689600' + nonce: + type: string + description: Order nonce + example: '0' + feeRateBps: + type: string + description: Fee rate in basis points + example: '30' + signature: + type: string + description: Cryptographic signature of the order + example: 0x1234abcd... + salt: + type: integer + description: Random salt for order uniqueness + example: 1234567890 + signatureType: + type: integer + description: Type of signature (0 = EOA, 1 = POLY_PROXY, 2 = POLY_GNOSIS_SAFE) + enum: + - 0 + - 1 + - 2 + securitySchemes: + polyApiKey: + type: apiKey + in: header + name: POLY_API_KEY + description: Your API key + polyAddress: + type: apiKey + in: header + name: POLY_ADDRESS + description: Ethereum address associated with the API key + polySignature: + type: apiKey + in: header + name: POLY_SIGNATURE + description: HMAC signature of the request + polyPassphrase: + type: apiKey + in: header + name: POLY_PASSPHRASE + description: API key passphrase + polyTimestamp: + type: apiKey + in: header + name: POLY_TIMESTAMP + description: Unix timestamp of the request + +```` diff --git a/docs/api-reference/trade/send-heartbeat.md b/docs/api-reference/trade/send-heartbeat.md new file mode 100644 index 0000000..477ad53 --- /dev/null +++ b/docs/api-reference/trade/send-heartbeat.md @@ -0,0 +1,138 @@ +> ## 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. + +# Send heartbeat + +> Sends a heartbeat signal to maintain active session status. +If heartbeats are not sent regularly, all open orders for the user will be automatically canceled. +This is useful for automated trading systems that need to ensure orders are canceled +if the system becomes unresponsive. + + + + +## OpenAPI + +````yaml api-spec/clob-openapi.yaml post /heartbeats +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 +paths: + /heartbeats: + post: + tags: + - Trade + summary: Send heartbeat + description: > + Sends a heartbeat signal to maintain active session status. + + If heartbeats are not sent regularly, all open orders for the user will + be automatically canceled. + + This is useful for automated trading systems that need to ensure orders + are canceled + + if the system becomes unresponsive. + operationId: sendHeartbeat + responses: + '200': + description: Heartbeat acknowledged + content: + application/json: + schema: + $ref: '#/components/schemas/HeartbeatResponse' + example: + status: ok + '401': + description: Unauthorized - Invalid API key or authentication failed + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Invalid API key + '500': + description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + example: + error: Internal server error + security: + - polyApiKey: [] + polyAddress: [] + polySignature: [] + polyPassphrase: [] + polyTimestamp: [] +components: + schemas: + HeartbeatResponse: + type: object + description: Response for heartbeat request + required: + - status + properties: + status: + type: string + description: Status of the heartbeat acknowledgment + example: ok + ErrorResponse: + type: object + required: + - error + properties: + error: + type: string + description: Error message + securitySchemes: + polyApiKey: + type: apiKey + in: header + name: POLY_API_KEY + description: Your API key + polyAddress: + type: apiKey + in: header + name: POLY_ADDRESS + description: Ethereum address associated with the API key + polySignature: + type: apiKey + in: header + name: POLY_SIGNATURE + description: HMAC signature of the request + polyPassphrase: + type: apiKey + in: header + name: POLY_PASSPHRASE + description: API key passphrase + polyTimestamp: + type: apiKey + in: header + name: POLY_TIMESTAMP + description: Unix timestamp of the request + +```` diff --git a/docs/api-reference/wss/market.md b/docs/api-reference/wss/market.md new file mode 100644 index 0000000..8cd7d8e --- /dev/null +++ b/docs/api-reference/wss/market.md @@ -0,0 +1,7 @@ +> ## 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 + +> Public WebSocket for real-time orderbook, price, and market lifecycle updates. diff --git a/docs/api-reference/wss/sports.md b/docs/api-reference/wss/sports.md new file mode 100644 index 0000000..b3c52b7 --- /dev/null +++ b/docs/api-reference/wss/sports.md @@ -0,0 +1,7 @@ +> ## 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 Channel + +> Public WebSocket for real-time sports match results. diff --git a/docs/api-reference/wss/user.md b/docs/api-reference/wss/user.md new file mode 100644 index 0000000..ace49f8 --- /dev/null +++ b/docs/api-reference/wss/user.md @@ -0,0 +1,7 @@ +> ## 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 WebSocket for real-time order and trade updates. diff --git a/docs/builders/api-keys.md b/docs/builders/api-keys.md new file mode 100644 index 0000000..662c87d --- /dev/null +++ b/docs/builders/api-keys.md @@ -0,0 +1,147 @@ +> ## 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. + +# API Keys + +> Create and manage your Builder API credentials + +Builder API keys authenticate your application with Polymarket's relayer and enable order attribution. You'll need these credentials to access gasless transactions and track volume. + +## Accessing Your Builder Profile + + + + Go to + [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder) + + + Click your profile image → Select "Builders" + + +## Creating API Keys + +In the **Builder Keys** section of your profile: + +1. Click **"+ Create New"** to generate a new API key +2. **Copy all three values immediately** — the secret and passphrase are only shown once +3. Store them securely in your secrets manager or environment variables + +Each API key includes three components: + +| Component | Description | Example | +| ------------ | ------------------------------------------ | ----------------------- | +| `key` | Public identifier for your builder account | `abc123-def456-...` | +| `secret` | Secret key for signing requests | `base64-encoded-secret` | +| `passphrase` | Additional authentication value | `your-passphrase` | + + + The `secret` and `passphrase` are only displayed once when created. If you + lose them, you'll need to generate a new key. + + +## Managing Keys + +Create separate keys for different environments: + +| Environment | Purpose | +| ----------- | ----------------------------- | +| Development | Testing and local development | +| Staging | Pre-production testing | +| Production | Live trading | + +## Profile Settings + +Your builder profile includes customizable settings: + +| Setting | Description | +| ------------------- | ----------------------------------------------------------------------- | +| **Profile Picture** | Displayed on the [Builder Leaderboard](https://builders.polymarket.com) | +| **Builder Name** | Public name shown on the leaderboard | +| **Builder Address** | Your unique builder identifier (read-only) | +| **Current Tier** | Your rate limit tier: Unverified, Verified, or Partner | + +## Environment Variables + +Store your credentials as environment variables: + + + + ```bash .env theme={null} + POLY_BUILDER_API_KEY=your-api-key + POLY_BUILDER_SECRET=your-secret + POLY_BUILDER_PASSPHRASE=your-passphrase + ``` + + + + ```typescript theme={null} + import { BuilderApiKeyCreds } from "@polymarket/builder-signing-sdk"; + + const builderCreds: BuilderApiKeyCreds = { + key: process.env.POLY_BUILDER_API_KEY!, + secret: process.env.POLY_BUILDER_SECRET!, + passphrase: process.env.POLY_BUILDER_PASSPHRASE!, + }; + ``` + + + + ```python theme={null} + import os + from py_builder_signing_sdk import BuilderApiKeyCreds + + builder_creds = BuilderApiKeyCreds( + key=os.environ["POLY_BUILDER_API_KEY"], + secret=os.environ["POLY_BUILDER_SECRET"], + passphrase=os.environ["POLY_BUILDER_PASSPHRASE"], + ) + ``` + + + +## Security Best Practices + +| Practice | Description | +| ----------------------------- | --------------------------------------------------------- | +| **Never commit credentials** | Use `.gitignore` to exclude `.env` files | +| **Use environment variables** | Load credentials from env vars, not hardcoded strings | +| **Use a secrets manager** | AWS Secrets Manager, HashiCorp Vault, etc. for production | +| **Separate environments** | Use different keys for dev, staging, and production | +| **Monitor usage** | Check the leaderboard for unexpected volume changes | + + + **Never expose Builder API credentials in client-side code.** Your secret and + passphrase must stay on your server. + + +## Troubleshooting + + + + **Cause:** You've exceeded your tier's daily transaction limit. + + **Solution:** + + * Wait until the daily limit resets + * [Contact Polymarket](/builders/tiers#contact) to upgrade your tier + + + + **Cause:** The secret and passphrase are only shown once when created. + + **Solution:** Create a new API key. You cannot recover the original values. + + + +## Next Steps + + + + Configure your client to credit trades to your account. + + + + Learn about rate limits and how to upgrade. + + diff --git a/docs/builders/overview.md b/docs/builders/overview.md new file mode 100644 index 0000000..7a76bba --- /dev/null +++ b/docs/builders/overview.md @@ -0,0 +1,218 @@ +> ## 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 + + + + All onchain operations are gas-free through our relayer + + + + Get credit for orders and compete for grants on the Builder Leaderboard + + + + + Earn a share of fees on orders you route + + +### 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 | +| **Weekly Rewards** | USDC rewards program based on volume (Verified+) | +| **Leaderboard** | Public visibility on [builders.polymarket.com](https://builders.polymarket.com) | +| **Support** | Telegram channel and engineering support (Verified+) | + + + EOA wallets do not have relayer access. Users trading directly from an EOA pay + their own gas fees. + + +## How It Works + + + + User places an order through your application. + + + + Your app signs the request with Builder API credentials. + + + + Order is submitted to Polymarket's CLOB with attribution headers. + + + + Polymarket matches the order and covers gas fees for onchain operations. + + + + Volume is credited to your builder account. + + + +## Getting Started + + + + Go to + [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder) + and generate your API keys. + + + + Set up your CLOB client to include builder authentication headers with every + order. + + + + Use the Relayer Client for gas-free wallet deployment and onchain + operations. + + + + Monitor your volume on the [Builder + Leaderboard](https://builders.polymarket.com). + + + +## SDKs & Libraries + + + + Place orders with builder attribution + + + + Place orders with builder attribution + + + + Gasless onchain transactions + + + + Gasless onchain transactions + + + + Place orders with builder attribution + + + + Sign builder authentication headers + + + + Sign builder authentication headers + + + +## 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. + + + + Multiple wallet providers + + + + Safe & Proxy wallet support + + + + Orders, positions, CTF ops + + + +### Safe Wallet Examples + +Deploy Gnosis Safe wallets for your users: + + + + MetaMask, Phantom, Rabby, and other browser wallets + + + + Privy embedded wallets + + + + Magic Link email/social authentication + + + + Turnkey embedded wallets + + + +### Proxy Wallet Examples + +For existing Magic Link users from Polymarket.com: + + + + Auto-deploying proxy wallets for Polymarket.com Magic users + + + +### What Each Demo Covers + + + + * User sign-in via wallet provider + * User API credential derivation (L2 auth) + * Builder config with remote signing + * Signature types for Safe vs Proxy wallets + + + + * Safe wallet deployment via Relayer + * Batch token approvals (USDC.e + outcome tokens) + * CTF operations (split, merge, redeem) + * Transaction monitoring + + + + * CLOB client initialization + * Order placement with builder attribution + * Position and order management + * Market discovery via Gamma API + + + +*** + +## Next Steps + + + + Create and manage your Builder API credentials. + + + + Learn about rate limits and how to upgrade. + + + + Configure your client to credit trades to your account. + + + + Set up gasless transactions for your users. + + diff --git a/docs/builders/tiers.md b/docs/builders/tiers.md new file mode 100644 index 0000000..c713cff --- /dev/null +++ b/docs/builders/tiers.md @@ -0,0 +1,184 @@ +> ## 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, revenue sharing, and priority support. + +## Feature Definitions + +| Feature | Description | +| --------------------------- | -------------------------------------------------------------------------- | +| **Daily Relayer Txn Limit** | Maximum Relayer transactions per day for Safe/Proxy wallet operations | +| **API Rate Limits** | Rate limits for non-relayer endpoints (CLOB, Gamma, etc.) | +| **Subsidized Transactions** | Gas fees subsidized for Relayer and CLOB operations via Safe/Proxy wallets | +| **Order Attribution** | Orders tracked and attributed to your Builder profile | +| **RevShare Protocol** | Infrastructure allowing Builders to charge fees | +| **Leaderboard Visibility** | Visibility on the [Builder Leaderboard](https://builders.polymarket.com/) | +| **Weekly Rewards** | Weekly USDC rewards program for visible builders based on volume | +| **Grants** | Builder grants subject to approval, awarded based on innovation and impact | +| **Telegram Channel** | Private Builders channel for announcements and support | +| **Badge** | Verified Builder affiliate badge on your Builder profile | +| **Engineering Support** | Direct access to engineering team | +| **Marketing Support** | Promotion via official Polymarket social accounts | +| **Weekly Reward Boosts** | Multiplier on the weekly USDC rewards program for visible builders | +| **Priority Access** | Early access to new features and products | + +*** + +## Tier Comparison + +| Feature | Unverified | Verified | Partner | +| --------------------------- | :-----------------: | :-----------------: | :-----------------: | +| **Daily Relayer Txn Limit** | 100/day | 3,000/day | Unlimited | +| **API Rate Limits** | Standard | Standard | Highest | +| **Subsidized Transactions** | Yes | Yes | Yes | +| **Order Attribution** | Yes | Yes | Yes | +| **RevShare Protocol** | — | Yes | Yes | +| **Leaderboard Visibility** | — | Yes | Yes | +| **Weekly Rewards** | — | Yes | Yes | +| **Grants** | Subject to approval | Subject to approval | Subject to approval | +| **Telegram Channel** | — | Yes | Yes | +| **Badge** | — | Yes | Yes | +| **Engineering Support** | — | Standard | Elevated | +| **Marketing Support** | — | Standard | Elevated | +| **Weekly Reward Boosts** | — | — | Yes | +| **Priority Access** | — | — | Yes | + +*** + +## Unverified + + + The default tier for all new builders. Start immediately with no approval + required. + + +**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. Implement [builder signing](/trading/orders/attribution) — required for Relayer access and CLOB order attribution + +**What's included:** + +* Gasless trading on all CLOB orders through Safe/Proxy wallets +* Gas subsidized on all Relayer transactions up to daily limit (through Safe/Proxy wallets) +* Order attribution to your builder profile +* Access to all client libraries and documentation + +*** + +## Verified + + + For builders who need higher throughput. Requires manual approval. + + +**How to upgrade:** + +Contact us with: + +* Your Builder API Key +* Use case description +* Expected volume +* Links to your app, docs, or X profile + +**Unlocks over Unverified:** + +* 30x daily Relayer transaction limit +* RevShare Protocol access +* Leaderboard visibility at [builders.polymarket.com](https://builders.polymarket.com) +* Weekly USDC rewards based on volume +* Private Telegram channel for announcements and support +* Verified affiliate badge and promotion from [@PolymarketBuild](https://x.com/PolymarketBuild) +* Grants (subject to approval) + +*** + +## Partner + + + Enterprise tier for high-volume integrations and strategic partners. + + +**How to apply:** + +Reach out to [builder@polymarket.com](mailto:builder@polymarket.com) to discuss partnership opportunities. + +**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 +* Multiplier on the Weekly Rewards Program + +*** + +## How to Upgrade + + + + Start with the Unverified tier and build your integration. + + + + Route orders through Polymarket and demonstrate consistent usage. + + + + Email [builder@polymarket.com](mailto:builder@polymarket.com) with your + builder key and use case. + + + + The Polymarket team reviews applications and responds within a few business + days. + + + +## Contact + +Ready to upgrade or have questions? + + + Email us with your Builder API Key and use case details. + + +## FAQ + + + + Verification is displayed in your [Builder Profile](https://polymarket.com/settings?tab=builder) settings. + + + + 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. + + + + For special events or product launches, contact [builder@polymarket.com](mailto:builder@polymarket.com). + + + +*** + +## Next Steps + + + + Create your Builder API credentials. + + + + Configure your client to credit trades to your account. + + diff --git a/docs/changelog/changelog.md b/docs/changelog/changelog.md index 75947d5..2125e71 100644 --- a/docs/changelog/changelog.md +++ b/docs/changelog/changelog.md @@ -14,7 +14,7 @@ * **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](/polymarket-learn/trading/maker-rebates-program) and [Developer Guide](/developers/market-makers/maker-rebates-program) updated with sports fee tables and parameters. + * **Updated documentation**: [Maker Rebates Program](/market-makers/maker-rebates) updated with sports fee tables and parameters. @@ -50,12 +50,12 @@ * **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 [RTDS Overview](/developers/RTDS/RTDS-overview). + For complete documentation, see [Market Data](/market-data/overview). * 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 [migration guide](/developers/CLOB/websocket/market-channel-migration-guide) for details. + * Please see the [Market Channel](/market-data/websocket/market-channel) for details. @@ -65,28 +65,28 @@ - * The batch orders limit has been increased from from 5 -> 15. Read more about the batch orders functionality [here](/developers/CLOB/orders/create-order-batch). + * The batch orders limit has been increased from 5 -> 15. Read more about the batch orders functionality [here](/trading/orders/create). * We’re 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 allowed order size. + * description: Minimum price increment. * `neg_risk` * type: boolean * description: Boolean indicating whether the market is neg\_risk. * `tick_size` * type: string - * description: Minimum allowed order size. + * description: Minimum price increment. - * We’re 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, we’ve included sample code demonstrating how to use it. Please see [Place Multiple Orders (Batching)](/developers/CLOB/orders/create-order-batch) for more details. + * We’re 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, we’ve included sample code demonstrating how to use it. Please see [Create Orders](/trading/orders/create) for more details. - * 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 [Get Trades](/developers/CLOB/trades/trades) page. + * 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. @@ -97,7 +97,7 @@ - We’re 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 Kil(FOK) orders, but with a key difference: + We’re 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. @@ -110,7 +110,7 @@ * 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 rateed + * 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 diff --git a/docs/concepts/markets-events.md b/docs/concepts/markets-events.md new file mode 100644 index 0000000..1a2fedd --- /dev/null +++ b/docs/concepts/markets-events.md @@ -0,0 +1,108 @@ +> ## 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. + + + + + + + +## Markets + +A **market** is the fundamental tradable unit on Polymarket. Each market represents a single binary question with Yes/No outcomes. + + + + + + + +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 | + + + 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. + + +### 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 + + + + Learn how prices are determined and how the order book works. + + + + Start querying markets and events from the API. + + diff --git a/docs/concepts/order-lifecycle.md b/docs/concepts/order-lifecycle.md new file mode 100644 index 0000000..d918391 --- /dev/null +++ b/docs/concepts/order-lifecycle.md @@ -0,0 +1,157 @@ +> ## 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 Lifecycle + +> Understanding how orders flow from creation to settlement + +Every trade on Polymarket follows a specific lifecycle. Orders are created offchain, matched by an operator, and settled onchain through smart contracts. This hybrid approach combines the speed of centralized matching with the security of blockchain settlement. + + + + + + + +## How Orders Work + +All orders on Polymarket are **limit orders**. A limit order specifies the price you're willing to pay (or accept) and the quantity you want to trade. + + + "Market orders" are simply limit orders with a price set to execute + immediately against the best available resting orders. + + +Orders are **EIP712-signed messages**. When you place an order, you sign a structured message with your private key. This signature authorizes the Exchange contract to execute the trade on your behalf—without ever taking custody of your funds. + +## Order Types + +| Type | Behavior | Use Case | +| ------- | ------------------------------------------------------------- | ------------------------ | +| **GTC** | Good Till Cancelled — rests on book until filled or cancelled | Standard limit orders | +| **GTD** | Good Till Date — auto-expires at specified time | Time-limited orders | +| **FOK** | Fill Or Kill — fill entirely or cancel immediately | All-or-nothing execution | +| **FAK** | Fill And Kill — fill what's available, cancel the rest | Partial fills acceptable | + +### Post-Only Orders + +Post-only orders will only rest on the book. If a post-only order would match immediately (cross the spread), it's rejected instead of executed. This guarantees you're always the maker, never the taker. + + + + Your client creates an order object containing: + + * Token ID (which outcome you're trading) + * Side (buy or sell) + * Price and size + * Expiration time + * Nonce (for replay protection) + + You sign this order with your private key, creating an EIP712 signature. + + + + The signed order is submitted to the Central Limit Order Book (CLOB) operator. The operator validates: + + * Signature is valid + * You have sufficient balance + * You have set the required allowances + * Price meets minimum tick size requirements + + + + **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 not marketable**, it rests on the book waiting for a counterparty. It remains open until: + + * Another order matches against it + * You cancel it + * It expires (GTD orders only) + + + + When orders match, the operator submits the trade to the blockchain. The Exchange contract: + + * Verifies both signatures + * Transfers tokens from seller to buyer + * Transfers USDC.e from buyer to seller + + Settlement is **atomic**—either the entire trade succeeds or nothing happens. + + + + The trade achieves finality on Polygon. Your token balances update and the trade appears in your history. + + + +## Order Statuses + +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 3-second matching delay (sports markets) | +| `unmatched` | Marketable order placed on the book after the delay expired without a match | + +## Trade Statuses + +After matching, trades progress through these statuses: + +| Status | Terminal | Description | +| ----------- | -------- | ------------------------------------------------------ | +| `MATCHED` | No | Trade matched, sent to executor for onchain submission | +| `MINED` | No | Transaction mined into the blockchain | +| `CONFIRMED` | Yes | Trade achieved finality, successful | +| `RETRYING` | No | Transaction failed, being retried | +| `FAILED` | Yes | Trade failed permanently | + +## Maker vs Taker + +| Role | Description | When | +| --------- | ------------------------------- | ----------------------------------------------------- | +| **Maker** | Adds liquidity to the book | Your order rests and is later matched | +| **Taker** | Removes liquidity from the book | Your order matches immediately against resting orders | + +Price improvement always benefits the taker. If you place a buy order at `$0.55` and it matches against a resting sell at `$0.52`, you pay `$0.52`. + +## Cancellation + +You can cancel orders at any time before they're matched: + +* **Via API** — Cancel through the CLOB API (instant) +* **Onchain** — Cancel directly on the Exchange contract (fallback if API is unavailable) + +Partial fills cannot be cancelled—only the unfilled portion of an order can be cancelled. + +## Requirements + +Before placing orders, ensure: + +| Requirement | Description | +| ------------------- | -------------------------------------------------- | +| **Balance** | Sufficient USDC.e (for buys) or tokens (for sells) | +| **Allowance** | Approve the Exchange contract to spend your assets | +| **API Credentials** | Valid API key for authenticated endpoints | + + + Order size is limited by your available balance minus any amounts reserved by existing open orders. + + $$ + \text{maxOrderSize} = \text{balance} - \sum(\text{openOrderSize} - \text{filledAmount}) + $$ + + +## Next Steps + + + + Learn how markets are resolved and winning tokens redeemed. + + + + Start placing orders with our step-by-step guide. + + diff --git a/docs/concepts/positions-tokens.md b/docs/concepts/positions-tokens.md new file mode 100644 index 0000000..3183d8d --- /dev/null +++ b/docs/concepts/positions-tokens.md @@ -0,0 +1,116 @@ +> ## 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. + +# Positions & Tokens + +> Understanding outcome tokens and how positions work on Polymarket + +Every prediction on Polymarket is represented by **outcome tokens**. When you trade, you're buying and selling these tokens. Your **position** is simply your balance of tokens for a given market. + + + + + + + +## Outcome Tokens + +Each market has exactly two outcome tokens: + +| Token | Redeems for | If... | +| ------- | ----------- | ------------------------ | +| **Yes** | \$1.00 | The event occurs | +| **No** | \$1.00 | The event does not occur | + +Tokens are **ERC1155** assets on Polygon, using the [Gnosis Conditional Token Framework](https://github.com/gnosis/conditional-tokens-contracts/) (CTF). This means they're fully onchain and function as standard ERC1155 tokens. + + + Outcome tokens are always fully backed. Every Yes/No pair in existence is + backed by exactly `$1` of USDC.e collateral locked in the CTF contract. + + +### Split + +Convert USDC.e into outcome tokens. Splitting \$1 creates 1 Yes token and 1 No token. + +``` +$100 USDC.e → 100 Yes tokens + 100 No tokens +``` + +Use this when you want to: + +* Create inventory for market making +* Obtain both sides of a market + +### Trade + +Buy or sell tokens on the order book. This is how most users acquire positions. + +* **Buy Yes** at `$0.60` → Pay `$0.60`, receive 1 Yes token +* **Sell Yes** at `$0.60` → Give up 1 Yes token, receive `$0.60` + +You can sell your position at any time before resolution. + +### Merge + +Convert a complete set of tokens back into USDC.e. Merging requires equal amounts of Yes and No tokens. + +``` +100 Yes tokens + 100 No tokens → $100 USDC.e +``` + +Use this when you want to: + +* Exit a position without trading +* Convert accumulated tokens back to collateral + +### Redeem + +After a market resolves, exchange winning tokens for USDC.e. + +| Outcome | Yes tokens | No tokens | +| ------------------- | -------------- | -------------- | +| Event occurs | Worth \$1 each | Worth \$0 | +| Event doesn't occur | Worth \$0 | Worth \$1 each | + +``` +100 winning tokens → $100 USDC.e +``` + +### Position Value + +The value of your position depends on the current market price: + +``` +Position value = Token balance × Current price +``` + +If you hold 100 Yes tokens and Yes is trading at \$0.75: + +``` +Position value = 100 × $0.75 = $75 +``` + +## Profit & Loss + +Your profit depends on how the market resolves compared to your entry price. + +### Example: Buying Yes at \$0.40 + +| Scenario | Outcome | Return | Profit | +| ------------------- | -------- | ------ | ------------------------- | +| Event occurs | Yes wins | \$1.00 | +\$0.60 per token (150%) | +| Event doesn't occur | No wins | \$0.00 | -\$0.40 per token (-100%) | + +### Holding Rewards + +Polymarket pays a **4.00% annualized** Holding Reward based on your total position value in eligible markets. Your total position value is randomly sampled once each hour, and the reward is distributed daily. The rate is variable and subject to change at Polymarket's discretion. + +### Example: Selling before resolution + +You can lock in profits or cut losses by selling before the market resolves: + +* Bought Yes at `$0.40` +* Price rises to `$0.70` +* Sell at `$0.70` → Profit of `$0.30` per token (75%) diff --git a/docs/concepts/prices-orderbook.md b/docs/concepts/prices-orderbook.md new file mode 100644 index 0000000..059ccd0 --- /dev/null +++ b/docs/concepts/prices-orderbook.md @@ -0,0 +1,116 @@ +> ## 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. + +# Prices & Orderbook + +> How prices work and how the order book enables peer-to-peer trading + +Polymarket uses a **Central Limit Order Book (CLOB)** for trading. Prices aren't set by Polymarket—they emerge from supply and demand as users trade with each other. + + + + + + + +## Prices = Probabilities + +Every share on Polymarket is priced between `$0.00` and `$1.00`. The price directly represents the market's belief in the probability of that outcome. + +| Price | Implied Probability | +| ------ | ------------------- | +| \$0.25 | 25% chance | +| \$0.50 | 50% chance | +| \$0.75 | 75% chance | + + + The displayed price is the **midpoint** of the bid-ask spread. If the spread + is wider than \$0.10, the last traded price is shown instead. + + +### Example + +If the best bid for "Yes" is `$0.34` and the best ask is `$0.40`: + +``` +Displayed price = ($0.34 + $0.40) / 2 = $0.37 (37% probability) +``` + +You won't necessarily trade at `$0.37`—you'll pay the ask (`$0.40`) when buying or receive the bid (`$0.34`) when selling. + +## The Order Book + +The order book is a list of all open buy and sell orders for a market. It has two sides: + +| Side | Description | +| ---- | ----------------------------------------------------------- | +| Bids | Buy orders—the highest prices traders are willing to pay | +| Asks | Sell orders—the lowest prices traders are willing to accept | + +The **spread** is the gap between the highest bid and lowest ask. Tighter spreads mean more liquid markets. + +## Order Types + +### Market Orders + +Execute immediately at the best available price. Use when you want instant execution and are willing to pay the spread. + +* **Buying**: You pay the lowest ask price +* **Selling**: You receive the highest bid price + +### Limit Orders + +Execute only at your specified price or better. Use when you want price control and are willing to wait. + +* Your order sits in the book until someone trades against it +* Orders can **partially fill** as different traders match portions of your order +* You can cancel unfilled orders at any time + + + All orders on Polymarket are technically limit orders. A "market order" is + simply a limit order priced to execute immediately against resting orders. + + +## How Trades Work + +Polymarket's CLOB is **hybrid-decentralized**: + +1. **Offchain matching** — An operator matches compatible orders +2. **Onchain settlement** — Matched trades settle via smart contracts + + + + + + + +This design gives you the speed of centralized matching with the security of onchain settlement. You always maintain custody of your funds. + +## Price Discovery + +When a new market launches, there's no initial price. The first price emerges when: + +1. Someone places a limit order to buy Yes at a price (e.g., `$0.60`) +2. Someone places a limit order to buy No at the complementary price (e.g., `$0.40`) +3. Since `$0.60` + `$0.40` = `$1.00`, the orders match + +When matched, `$1.00` is converted into 1 Yes token and 1 No token, each going to their respective buyers. + +## Next Steps + + + Polymarket's orderbook has **no trading size limits** — it matches willing + buyers and sellers of any amount. However, large orders may move the price + significantly. Always check orderbook depth before trading in size. + + + + + Learn about outcome tokens and how positions work. + + + + Understand what happens from order placement to settlement. + + diff --git a/docs/concepts/resolution.md b/docs/concepts/resolution.md new file mode 100644 index 0000000..3fef454 --- /dev/null +++ b/docs/concepts/resolution.md @@ -0,0 +1,151 @@ +> ## 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. + + + + + + + +## 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 + + + Always read the resolution rules before trading. The market title describes + the question, but the **rules** define how it resolves. + + + + + Anyone can propose a resolution by: + + 1. Selecting the winning outcome + 2. Posting a bond (typically \$750 USDC.e) + 3. Submitting the proposal to the UMA Oracle + + If the proposal is correct and undisputed, the proposer receives their bond back plus a reward. + + + 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. + + + + + 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 + + + + 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`). + + + + 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 | + + + +## 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, call the `redeemPositions` function on the CTF contract to exchange winning tokens for USDC.e. The contract burns your tokens and returns the corresponding collateral. + +``` +100 winning tokens → $100 USDC.e +``` + +## 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 + + + If you believe a clarification is needed, request it in the [Polymarket + Discord](https://discord.com/invite/polymarket) `#market-review` channel. + + +## 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 + + + + Learn how to redeem winning tokens after resolution. + + + + Understand how markets are structured. + + diff --git a/docs/developers/CLOB/authentication.md b/docs/developers/CLOB/authentication.md index 65ed29d..80dd436 100644 --- a/docs/developers/CLOB/authentication.md +++ b/docs/developers/CLOB/authentication.md @@ -4,43 +4,60 @@ # Authentication -> Understanding authentication using Polymarket's CLOB +> How to authenticate requests to the CLOB API -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. Authentication is not -required to access client public methods and public endpoints. +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. -## Authentication Levels +## Public vs Authenticated - - - Use the private key of the user’s account to sign messages + + + The **Gamma API**, **Data API**, and CLOB read endpoints (orderbook, prices, spreads) require no authentication. - - Use API credentials (key, secret, passphrase) to authenticate requests to the CLOB + + CLOB trading endpoints (placing orders, cancellations, heartbeat) require all 5 `POLY_*` L2 HTTP headers. *** -## L1 Authentication +## Two-Level Authentication Model -### What is L1? +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 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. +### L1 Authentication (Private Key) -### What This Enables +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. -Access to L1 methods that create or derive L2 authentication headers. +**Used for:** -* Create user API credentials -* Derive existing user API credentials -* Sign/create user's orders locally +* Creating API credentials +* Deriving existing API credentials +* Signing and creating user's orders locally -### CLOB Client +### L2 Authentication (API Credentials) + +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 + + + Even with L2 authentication headers, methods that create user orders still + require the user to sign the order payload. + + +*** + +## Getting API Credentials + +Before making authenticated requests, you need to obtain API credentials using L1 authentication. + +### Using the SDK (Recommended) @@ -48,26 +65,21 @@ Access to L1 methods that create or derive L2 authentication headers. import { ClobClient } from "@polymarket/clob-client"; import { Wallet } from "ethers"; // v5.8.0 - const HOST = "https://clob.polymarket.com"; - const CHAIN_ID = 137; // Polygon mainnet - const signer = new Wallet(process.env.PRIVATE_KEY); - const client = new ClobClient( - HOST, - CHAIN_ID, - signer // Signer enables L1 methods + "https://clob.polymarket.com", + 137, // Polygon mainnet + new Wallet(process.env.PRIVATE_KEY) ); - // Gets API key, or else creates - const apiCreds = await client.createOrDeriveApiKey(); + // Creates new credentials or derives existing ones + const credentials = await client.createOrDeriveApiKey(); - /* - apiCreds = { - "apiKey": "550e8400-e29b-41d4-a716-446655440000", - "secret": "base64EncodedSecretString", - "passphrase": "randomPassphraseString" - } - */ + console.log(credentials); + // { + // apiKey: "550e8400-e29b-41d4-a716-446655440000", + // secret: "base64EncodedSecretString", + // passphrase: "randomPassphraseString" + // } ``` @@ -76,20 +88,17 @@ Access to L1 methods that create or derive L2 authentication headers. from py_clob_client.client import ClobClient import os - host = "https://clob.polymarket.com" - chain_id = 137 # Polygon mainnet - private_key = os.getenv("PRIVATE_KEY") - client = ClobClient( - host=host, - chain_id=chaind_id, - key=private_key # Signer enables L1 methods + host="https://clob.polymarket.com", + chain_id=137, # Polygon mainnet + key=os.getenv("PRIVATE_KEY") ) - # Gets API key, or else creates - api_creds = await client.create_or_derive_api_key() + # Creates new credentials or derives existing ones + credentials = client.create_or_derive_api_creds() - # api_creds = { + print(credentials) + # { # "apiKey": "550e8400-e29b-41d4-a716-446655440000", # "secret": "base64EncodedSecretString", # "passphrase": "randomPassphraseString" @@ -103,29 +112,36 @@ Access to L1 methods that create or derive L2 authentication headers. variables or secure key management systems. -*** +### Using the REST API -### 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) or [TypeScript](https://github.com/Polymarket/clob-client) clients. -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) or -[TypeScript](https://github.com/Polymarket/clob-client) clients. +**Create API Credentials** -When making direct REST API calls with L1 authentication, include these headers: +```bash theme={null} +POST https://clob.polymarket.com/auth/api-key +``` -| Header | Required? | Description | -| ---------------- | --------- | ---------------------- | -| `POLY_ADDRESS` | yes | Polygon signer address | -| `POLY_SIGNATURE` | yes | CLOB EIP 712 signature | -| `POLY_TIMESTAMP` | yes | Current UNIX timestamp | -| `POLY_NONCE` | yes | Nonce. Default 0 | +**Derive API Credentials** -The `POLY_SIGNATURE` is generated by signing the following EIP-712 struct. +```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: - ```typescript Typescript theme={null} + ```typescript TypeScript theme={null} const domain = { name: "ClobAuthDomain", version: "1", @@ -174,7 +190,7 @@ The `POLY_SIGNATURE` is generated by signing the following EIP-712 struct. "message": "This message attests that I control the given wallet", } - sig = await signer._signTypedData(domain, types, value) + sig = signer.sign_typed_data(domain, types, value) ``` @@ -184,25 +200,7 @@ Reference implementations: * [TypeScript](https://github.com/Polymarket/clob-client/blob/main/src/signing/eip712.ts) * [Python](https://github.com/Polymarket/py-clob-client/blob/main/py_clob_client/signing/eip712.py) -*** - -**Create API Credentials** - -Create new API credentials for user. - -```bash theme={null} -POST {clob-endpoint}/auth/api-key -``` - -**Derive API Credentials** - -Derive API credentials for user. - -```bash theme={null} -GET {clob-endpoint}/auth/derive-api-key -``` - -**Response** +Response: ```json theme={null} { @@ -216,25 +214,21 @@ GET {clob-endpoint}/auth/derive-api-key *** -## L2 Authentication +## L2 Authentication Headers -### What is L2? +All trading endpoints require these 5 headers: -The next level of authentication is called L2, and it consists of the -user's 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. +| 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 | -### What This Enables +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/blob/main/src/signing/hmac.ts) and [Python](https://github.com/Polymarket/py-clob-client/blob/main/py_clob_client/signing/hmac.py) clients. -Access to L2 methods such as posting signed/created orders, viewing open -orders, cancelling open orders, getting trades - -* Cancel or get user's open orders -* Check user's balances and allowances -* Post user's signed orders - -### CLOB Client +### CLOB Client (L2) @@ -242,20 +236,16 @@ orders, cancelling open orders, getting trades import { ClobClient } from "@polymarket/clob-client"; import { Wallet } from "ethers"; // v5.8.0 - const HOST = "https://clob.polymarket.com"; - const CHAIN_ID = 137; // Polygon mainnet - const signer = new Wallet(process.env.PRIVATE_KEY); - const client = new ClobClient( - HOST, - CHAIN_ID, - signer, + "https://clob.polymarket.com", + 137, + new Wallet(process.env.PRIVATE_KEY), apiCreds, // Generated from L1 auth, API credentials enable L2 methods 1, // signatureType explained below - FUNDER // funder explained below + funderAddress // funder explained below ); - // Now you can trade!* + // Now you can trade! const order = await client.createAndPostOrder( { tokenID: "123456", price: 0.65, size: 100, side: "BUY" }, { tickSize: "0.01", negRisk: false } @@ -268,10 +258,6 @@ orders, cancelling open orders, getting trades from py_clob_client.client import ClobClient import os - host = "https://clob.polymarket.com" - chain_id = 137 # Polygon mainnet - private_key = os.getenv("PRIVATE_KEY") - client = ClobClient( host="https://clob.polymarket.com", chain_id=137, @@ -281,8 +267,8 @@ orders, cancelling open orders, getting trades funder=os.getenv("FUNDER_ADDRESS") # funder explained below ) - # Now you can trade!* - order = await client.create_and_post_order( + # Now you can trade! + order = client.create_and_post_order( {"token_id": "123456", "price": 0.65, "size": 100, "side": "BUY"}, {"tick_size": "0.01", "neg_risk": False} ) @@ -291,59 +277,57 @@ orders, cancelling open orders, getting trades - Even with L2 authentication headers, methods that create user orders still require the user to sign the order payload. + Even with L2 authentication headers, methods that create user orders still + require the user to sign the order payload. *** -### 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) or -[TypeScript](https://github.com/Polymarket/clob-client) clients. - -When making direct REST API calls with L2 authentication, include these headers: - -| Header | Required? | Description | -| ----------------- | --------- | ----------------------------- | -| `POLY_ADDRESS` | yes | Polygon signer address | -| `POLY_SIGNATURE` | yes | HMAC signature for request | -| `POLY_TIMESTAMP` | yes | Current UNIX timestamp | -| `POLY_API_KEY` | yes | User's API `apiKey` value | -| `POLY_PASSPHRASE` | yes | 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/blob/main/src/signing/hmac.ts) -and [Python](https://github.com/Polymarket/py-clob-client/blob/main/py_clob_client/signing/hmac.py) clients. - -*** - ## 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 | A custom proxy wallet only used with users who logged in via Magic Link email/Google. Using this requires the user to have exported their PK from Polymarket.com and imported into your app. | -| GNOSIS\_SAFE | 2 | Gnosis Safe multisig proxy wallet (most common). Use this for any new or returning user who does not fit the other 2 types. | +| EOA | `0` | Standard Ethereum wallet (MetaMask). Funder is the EOA address and will need POL to pay gas on transactions. | +| POLY\_PROXY | `1` | A custom proxy wallet only used with users who logged in via Magic Link email/Google. Using this requires the user to have exported their PK from Polymarket.com and imported into your app. | +| GNOSIS\_SAFE | `2` | Gnosis Safe multisig proxy wallet (most common). Use this for any new or returning user who does not fit the other 2 types. | - The wallet addresses displayed to the user on Polymarket.com is the proxy wallet and should be used as the funder. - These can be deterministically derived or you can deploy them on behalf of the user. - These proxy wallets are automatically deployed for the user on their first login to Polymarket.com. + The wallet address displayed to the user on Polymarket.com is the proxy wallet + and should be used as the funder. These can be deterministically derived or + you can deploy them on behalf of the user. These proxy wallets are + automatically deployed for the user on their first login to Polymarket.com. *** +## Security Best Practices + + + + 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... + ``` + + + + Never expose your API secret in client-side code. All authenticated requests should originate from your backend. + + + +*** + ## Troubleshooting Your wallet's private key is incorrect or improperly formatted. - **Solution:** + **Solutions:** * Verify your private key is a valid hex string (starts with "0x") * Ensure you're using the correct key for the intended address @@ -353,7 +337,7 @@ When initializing the L2 client, you must specify your wallet **signatureType** The nonce you provided has already been used to create an API key. - **Solution:** + **Solutions:** * Use `deriveApiKey()` with the same nonce to retrieve existing credentials * Or use a different nonce with `createApiKey()` @@ -367,13 +351,6 @@ When initializing the L2 client, you must specify your wallet **signatureType** If it does not exist or user has never logged into Polymarket.com, deploy it first before creating L2 authentication. - - ```typescript theme={null} - // Use deriveApiKey with the original nonce - const recovered = await client.deriveApiKey(originalNonce); - ``` - - Unfortunately, there's no way to recover lost API credentials without the nonce. You'll need to create new credentials: @@ -387,22 +364,14 @@ When initializing the L2 client, you must specify your wallet **signatureType** *** -## See Client Methods +## Next Steps - - Access market data, orderbooks, and prices. + + Learn how to create and submit orders. - - Private key authentication to create or derive API keys (L2 headers). - - - - Manage and close orders. Creating orders requires signer. - - - - Builder-specific operations for those in the Builders Program. + + Check trading availability by region. diff --git a/docs/developers/CLOB/clients/methods-builder.md b/docs/developers/CLOB/clients/methods-builder.md index 1994c9d..85a209a 100644 --- a/docs/developers/CLOB/clients/methods-builder.md +++ b/docs/developers/CLOB/clients/methods-builder.md @@ -8,9 +8,7 @@ ## Client Initialization -Builder methods require the client to initialize with a separate authentication setup using -builder configs acquired from [Polymarket.com](https://polymarket.com/settings?tab=builder) -and the `@polymarket/builder-signing-sdk` package. +Builder methods require the client to initialize with a separate builder config using credentials acquired from [Polymarket.com](https://polymarket.com/settings?tab=builder) and the `@polymarket/builder-signing-sdk` package. @@ -31,7 +29,7 @@ and the `@polymarket/builder-signing-sdk` package. "https://clob.polymarket.com", 137, signer, - apiCreds, // The user's API credentials generated from L1 authentication + apiCreds, // User's API credentials from L1 authentication signatureType, funderAddress, undefined, @@ -57,7 +55,7 @@ and the `@polymarket/builder-signing-sdk` package. host="https://clob.polymarket.com", chain_id=137, key=os.getenv("PRIVATE_KEY"), - creds=creds, # The user's API credentials generated from L1 authentication + creds=creds, # User's API credentials from L1 authentication signature_type=signature_type, funder=funder, builder_config=builder_config @@ -73,14 +71,14 @@ and the `@polymarket/builder-signing-sdk` package. import { BuilderConfig } from "@polymarket/builder-signing-sdk"; const builderConfig = new BuilderConfig({ - remoteBuilderConfig: {url: "http://localhost:3000/sign"} + remoteBuilderConfig: { url: "http://localhost:3000/sign" } }); const clobClient = new ClobClient( "https://clob.polymarket.com", 137, signer, - apiCreds, // The user's API credentials generated from L1 authentication + apiCreds, // User's API credentials from L1 authentication signatureType, funder, undefined, @@ -89,7 +87,7 @@ and the `@polymarket/builder-signing-sdk` package. ); ``` - ```typescript Python theme={null} + ```python Python theme={null} from py_clob_client.client import ClobClient from py_builder_signing_sdk.config import BuilderConfig, RemoteBuilderConfig import os @@ -104,7 +102,7 @@ and the `@polymarket/builder-signing-sdk` package. host="https://clob.polymarket.com", chain_id=137, key=os.getenv("PRIVATE_KEY"), - creds=creds, # The user's API credentials generated from L1 authentication + creds=creds, # User's API credentials from L1 authentication signature_type=signature_type, funder=funder, builder_config=builder_config @@ -115,7 +113,7 @@ and the `@polymarket/builder-signing-sdk` package. - [More information on builder signing](/developers/builders/order-attribution) + See [Order Attribution](/trading/orders/attribution) for more information on builder signing. *** @@ -126,8 +124,7 @@ and the `@polymarket/builder-signing-sdk` package. ### getBuilderTrades() -Retrieves all trades attributed to your builder account. -This method allows builders to track which trades were routed through your platform. +Retrieves all trades attributed to your builder account. Use this to track which trades were routed through your platform. ```typescript Signature theme={null} async getBuilderTrades( @@ -135,81 +132,176 @@ async getBuilderTrades( ): Promise ``` -```typescript Params theme={null} -interface TradeParams { - id?: string; - maker_address?: string; - market?: string; - asset_id?: string; - before?: string; - after?: string; -} -``` +**Params (`TradeParams`)** -```typescript Response theme={null} -interface BuilderTradesPaginatedResponse { - trades: BuilderTrade[]; - next_cursor: string; - limit: number; - count: number; -} + + Optional. Filter trades by trade ID. + -interface BuilderTrade { - id: string; - tradeType: string; - takerOrderHash: string; - builder: string; - market: string; - assetId: string; - side: string; - size: string; - sizeUsdc: string; - price: string; - status: string; - outcome: string; - outcomeIndex: number; - owner: string; - maker: string; - transactionHash: string; - matchTime: string; - bucketIndex: number; - fee: string; - feeUsdc: string; - err_msg?: string | null; - createdAt: string | null; - updatedAt: string | null; -} -``` + + Optional. Filter trades by maker address. + + + + Optional. Filter trades by market condition ID. + + + + Optional. Filter trades by asset (token) ID. + + + + Optional. Return trades created before this cursor value. + + + + Optional. Return trades created after this cursor value. + + +**Response (`BuilderTradesPaginatedResponse`)** + + + Array of trades attributed to the builder account. + + + + Cursor string for fetching the next page of results. + + + + Maximum number of trades returned per page. + + + + Total number of trades returned in this response. + + +**`BuilderTrade` fields** + + + Unique identifier for the trade. + + + + Type of the trade. + + + + Hash of the taker order associated with this trade. + + + + Address of the builder who attributed this trade. + + + + Condition ID of the market this trade belongs to. + + + + Token ID of the asset traded. + + + + Side of the trade (e.g. BUY or SELL). + + + + Size of the trade in shares. + + + + Size of the trade denominated in USDC. + + + + Price at which the trade was executed. + + + + Current status of the trade. + + + + Outcome label associated with the traded asset. + + + + Index of the outcome within the market. + + + + Address of the order owner (taker). + + + + Address of the maker in the trade. + + + + On-chain transaction hash for the trade. + + + + Timestamp when the trade was matched. + + + + Bucket index used for trade grouping. + + + + Fee charged for the trade in shares. + + + + Fee charged for the trade denominated in USDC. + + + + Optional. Error message if the trade encountered an issue, otherwise null. + + + + Timestamp when the trade record was created, or null if unavailable. + + + + Timestamp when the trade record was last updated, or null if unavailable. + *** ### revokeBuilderApiKey() -Revokes the builder API key used to authenticate the current request. -After revocation, the key can no longer be used to make builder-authenticated requests. +Revokes the builder API key used to authenticate the current request. After revocation, the key can no longer be used for builder-authenticated requests. ```typescript Signature theme={null} async revokeBuilderApiKey(): Promise ``` + + Response from the revocation request. + + *** ## See Also - - Learn the benefits, how to implement, and more. + + Learn about the Builders Program and its benefits. - - Attribute orders to you, and pre-requisite to using the Relayer Client. + + Attribute orders to your builder account. - - The relayer executes other gasless transactions for your users, on your app. + + Place and manage orders with API credentials. - - Complete Next.js examples integrated with embedded wallets (Privy, Magic, Turnkey, wagmi) + + Execute onchain operations without paying gas. diff --git a/docs/developers/CLOB/clients/methods-l1.md b/docs/developers/CLOB/clients/methods-l1.md index f3fe9fc..3b3a6a8 100644 --- a/docs/developers/CLOB/clients/methods-l1.md +++ b/docs/developers/CLOB/clients/methods-l1.md @@ -43,13 +43,13 @@ L1 methods require the client to initialize with a signer. ) # Ready to create user API credentials - api_key = await client.create_api_key() + api_key = client.create_api_key() ``` - **Security:** Never commit private keys to version control. Always use environment variables or secure key management systems. + Never commit private keys to version control. Always use environment variables or a secure key management system. *** @@ -60,68 +60,75 @@ L1 methods require the client to initialize with a signer. ### createApiKey() -Creates a new API key (L2 credentials) for the wallet signer. This generates a new set of credentials that can be used for L2 authenticated requests. -Each wallet can only have one active API key at a time. Creating a new key invalidates the previous one. +Creates a new API key (L2 credentials) for the wallet signer. Each wallet can only have one active API key at a time — creating a new key invalidates the previous one. ```typescript Signature theme={null} async createApiKey(nonce?: number): Promise ``` -```typescript Params theme={null} -`nonce` (optional): Custom nonce for deterministic key generation. If not provided, a default derivation is used. -``` + + Optional custom nonce for deterministic key generation. Optional. + -```typescript Response theme={null} -interface ApiKeyCreds { - apiKey: string; - secret: string; - passphrase: string; -} -``` + + The generated API key string. + + + + The secret associated with the API key. + + + + The passphrase associated with the API key. + *** ### deriveApiKey() -Derives an existing API key (L2 credentials) using a specific nonce. If you've already created API credentials with a particular nonce, this method will return the same credentials again. +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 ``` -```typescript Params theme={null} -`nonce` (optional): Custom nonce for deterministic key generation. If not provided, a default derivation is used. -``` + + The nonce used when originally creating the key. Optional. + -```typescript Response theme={null} -interface ApiKeyCreds { - apiKey: string; - secret: string; - passphrase: string; -} -``` + + The derived API key string. + + + + The secret associated with the API key. + + + + The passphrase associated with the API key. + *** ### createOrDeriveApiKey() -Convenience method that attempts to derive an API key with the default nonce, or creates a new one if it doesn't exist. This is the recommended method for initial setup if you're unsure if credentials already exist. +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 ``` -```typescript Params theme={null} -`nonce` (optional): Custom nonce for deterministic key generation. If not provided, a default derivation is used. -``` + + The API key string, either derived or newly created. + -```typescript Response theme={null} -interface ApiKeyCreds { - apiKey: string; - secret: string; - passphrase: string; -} -``` + + The secret associated with the API key. + + + + The passphrase associated with the API key. + *** @@ -129,9 +136,7 @@ interface ApiKeyCreds { ### 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 order submission logic. -Place order via L2 methods postOrder or postOrders. +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( @@ -140,49 +145,103 @@ async createOrder( ): Promise ``` -```typescript Params theme={null} -interface UserOrder { - tokenID: string; - price: number; - size: number; - side: Side; - feeRateBps?: number; - nonce?: number; - expiration?: number; - taker?: string; -} + + The token ID of the market outcome to trade. + -interface CreateOrderOptions { - tickSize: TickSize; - negRisk?: boolean; -} -``` + + The limit price for the order. + -```typescript Response theme={null} -interface SignedOrder { - salt: string; - maker: string; - signer: string; - taker: string; - tokenId: string; - makerAmount: string; - takerAmount: string; - side: number; // 0 = BUY, 1 = SELL - expiration: string; - nonce: string; - feeRateBps: string; - signatureType: number; - signature: string; -} -``` + + The size (number of shares) for the order. + + + + The side of the order (buy or sell). + + + + Optional fee rate in basis points. Optional. + + + + Optional nonce for the order. Optional. + + + + Optional expiration timestamp for the order. Optional. + + + + Optional taker address for the order. Optional. + + + + The tick size used for order validation (CreateOrderOptions). + + + + Optional flag for negative risk markets (CreateOrderOptions). Optional. + + + + A random salt value for the signed order. + + + + The maker's address. + + + + The signer's address. + + + + The taker's address in the signed order. + + + + The token ID in the signed order. + + + + The maker amount as a string. + + + + The taker amount as a string. + + + + The side of the order as a number (0 = BUY, 1 = SELL). + + + + The expiration timestamp as a string. + + + + The nonce as a string. + + + + The fee rate in basis points as a string. + + + + The type identifier for the signature scheme used. + + + + The cryptographic signature of the order. + *** ### createMarketOrder() -Create and sign a market order locally without posting it to the CLOB. -Use this when you want to sign orders in advance or implement custom order submission logic. -Place orders via L2 methods postOrder or postOrders. +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( @@ -191,36 +250,89 @@ async createMarketOrder( ): Promise ``` -```typescript Params theme={null} -interface UserMarketOrder { - tokenID: string; - amount: number; // BUY: dollar amount, SELL: number of shares - side: Side; - price?: number; // Optional price limit - feeRateBps?: number; - nonce?: number; - taker?: string; - orderType?: OrderType.FOK | OrderType.FAK; -} -``` + + The token ID of the market outcome to trade. + -```typescript Response theme={null} -interface SignedOrder { - salt: string; - maker: string; - signer: string; - taker: string; - tokenId: string; - makerAmount: string; - takerAmount: string; - side: number; // 0 = BUY, 1 = SELL - expiration: string; - nonce: string; - feeRateBps: string; - signatureType: number; - signature: string; -} -``` + + The order amount. For BUY orders this is a dollar amount; for SELL orders this is the number of shares. + + + + The side of the order (buy or sell). + + + + Optional price limit for the market order. Optional. + + + + Optional fee rate in basis points. Optional. + + + + Optional nonce for the order. Optional. + + + + Optional taker address for the order. Optional. + + + + Optional order type, either FOK (Fill-Or-Kill) or FAK (Fill-And-Kill). Optional. + + + + A random salt value for the signed order. + + + + The maker's address. + + + + The signer's address. + + + + The taker's address in the signed order. + + + + The token ID in the signed order. + + + + The maker amount as a string. + + + + The taker amount as a string. + + + + The side of the order as a number (0 = BUY, 1 = SELL). + + + + The expiration timestamp as a string. + + + + The nonce as a string. + + + + The fee rate in basis points as a string. + + + + The type identifier for the signature scheme used. + + + + The cryptographic signature of the order. + *** @@ -232,7 +344,7 @@ interface SignedOrder { **Solution:** - * Verify your private key is a valid hex string (starts with "0x") + * 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 @@ -249,9 +361,7 @@ interface SignedOrder { 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. + **Solution:** Check your proxy wallet address at [polymarket.com/settings](https://polymarket.com/settings). If it doesn't exist, the user has never logged in to Polymarket.com — deploy the proxy wallet first before creating L2 credentials. @@ -262,7 +372,7 @@ interface SignedOrder { - Unfortunately, there's no way to recover lost API credentials without the nonce. You'll need to create new credentials: + There's no way to recover lost credentials without the nonce. Create new ones: ```typescript theme={null} // Create fresh credentials with a new nonce @@ -277,19 +387,19 @@ interface SignedOrder { ## See Also - - Deep dive into L1 and L2 authentication + + Deep dive into L1 and L2 authentication. - - Initialize the CLOB quickly and place your first order. + + Initialize the client and place your first order. - - Access market data, orderbooks, and prices. + + Access market data, orderbooks, and prices without auth. - - Manage and close orders. Creating orders requires signer. + + Place and manage orders with API credentials. diff --git a/docs/developers/CLOB/clients/methods-l2.md b/docs/developers/CLOB/clients/methods-l2.md index e367332..fddb21a 100644 --- a/docs/developers/CLOB/clients/methods-l2.md +++ b/docs/developers/CLOB/clients/methods-l2.md @@ -4,13 +4,11 @@ # L2 Methods -> These methods require user API credentials (L2 headers). Use these for placing trades and managing user's positions. - -*** +> 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 the signer, signatureType, user API credentials, and funder. +L2 methods require the client to initialize with a signer, signature type, API credentials, and funder address. @@ -18,7 +16,7 @@ L2 methods require the client to initialize with the signer, signatureType, user import { ClobClient } from "@polymarket/clob-client"; import { Wallet } from "ethers"; - const signer = new Wallet(process.env.PRIVATE_KEY) + const signer = new Wallet(process.env.PRIVATE_KEY); const apiCreds = { apiKey: process.env.API_KEY, @@ -31,11 +29,11 @@ L2 methods require the client to initialize with the signer, signatureType, user 137, signer, apiCreds, - 2, // Deployed Safe proxy wallet - process.env.FUNDER_ADDRESS // Address of deployed Safe proxy wallet + 2, // GNOSIS_SAFE + process.env.FUNDER_ADDRESS ); - // Ready to send authenticated requests to the CLOB API! + // Ready to send authenticated requests const order = await client.postOrder(signedOrder); ``` @@ -57,12 +55,12 @@ L2 methods require the client to initialize with the signer, signatureType, user chain_id=137, key=os.getenv("PRIVATE_KEY"), creds=api_creds, - signature_type=2, # Deployed Safe proxy wallet - funder=os.getenv("FUNDER_ADDRESS") # Address of deployed Safe proxy wallet + signature_type=2, # GNOSIS_SAFE + funder=os.getenv("FUNDER_ADDRESS") ) - # Ready to send authenticated requests to the CLOB API! - order = await client.post_order(signed_order) + # Ready to send authenticated requests + order = client.post_order(signed_order) ``` @@ -75,8 +73,7 @@ L2 methods require the client to initialize with the signer, signatureType, user ### createAndPostOrder() -A convenience method that creates, prompts signature, and posts an order in a single call. -Use when you want to buy/sell at a specific price and can wait. +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( @@ -86,44 +83,83 @@ async createAndPostOrder( ): Promise ``` -```typescript Params theme={null} -interface UserOrder { - tokenID: string; - price: number; - size: number; - side: Side; - feeRateBps?: number; - nonce?: number; - expiration?: number; - taker?: string; -} +**Params** -type CreateOrderOptions = { - tickSize: TickSize; - negRisk?: boolean; -} + + The token ID of the outcome to trade. + -type TickSize = "0.1" | "0.01" | "0.001" | "0.0001"; -``` + + The limit price for the order. + -```typescript Response theme={null} -interface OrderResponse { - success: boolean; - errorMsg: string; - orderID: string; - transactionsHashes: string[]; - status: string; - takingAmount: string; - makingAmount: string; -} -``` + + The size of the order. + + + + The side of the order (buy or sell). + + + + Optional fee rate in basis points. + + + + Optional nonce for the order. + + + + Optional expiration timestamp for the order. + + + + Optional taker address. + + + + Tick size for the order. One of `"0.1"`, `"0.01"`, `"0.001"`, `"0.0001"`. + + + + Optional. Whether the market uses negative risk. + + +**Response** + + + Whether the order was successfully placed. + + + + Error message if the order was not successful. + + + + The ID of the placed order. + + + + Array of transaction hashes associated with the order. + + + + The current status of the order. + + + + The amount being taken in the order. + + + + The amount being made in the order. + *** ### createAndPostMarketOrder() -A convenience method that creates, prompts signature, and posts an order in a single call. -Use when you want to buy/sell right now at whatever the market price is. +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( @@ -133,103 +169,109 @@ async createAndPostMarketOrder( ): Promise ``` -```typescript Params theme={null} -interface UserMarketOrder { - tokenID: string; - amount: number; - side: Side; - price?: number; - feeRateBps?: number; - nonce?: number; - taker?: string; - orderType?: OrderType.FOK | OrderType.FAK; -} +**Params** -type CreateOrderOptions = { - tickSize: TickSize; - negRisk?: boolean; -} + + The token ID of the outcome to trade. + -type TickSize = "0.1" | "0.01" | "0.001" | "0.0001"; -``` + + The amount for the market order. + -```typescript Response theme={null} -interface OrderResponse { - success: boolean; - errorMsg: string; - orderID: string; - transactionsHashes: string[]; - status: string; - takingAmount: string; - makingAmount: string; -} -``` + + The side of the order (buy or sell). + + + + Optional price hint for the market order. + + + + Optional fee rate in basis points. + + + + Optional nonce for the order. + + + + Optional taker address. + + + + Optional order type override. Defaults to FOK. + + +**Response** + + + Whether the order was successfully placed. + + + + Error message if the order was not successful. + + + + The ID of the placed order. + + + + Array of transaction hashes associated with the order. + + + + The current status of the order. + + + + The amount being taken in the order. + + + + The amount being made in the order. + *** ### postOrder() -Posts a pre-signed and created order to the CLOB. +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 + postOnly?: boolean, // Defaults to false ): Promise ``` -```typescript Params theme={null} -order: SignedOrder // Pre-signed order from createOrder() or createMarketOrder() -orderType?: OrderType // Optional, defaults to GTC -postOnly?: boolean // Optional, defaults to false -``` - -```typescript Response theme={null} -interface OrderResponse { - success: boolean; - errorMsg: string; - orderID: string; - transactionsHashes: string[]; - status: string; - takingAmount: string; - makingAmount: string; -} -``` - *** ### postOrders() -Posts up to 15 pre-signed and created orders in a single batch. +Posts up to 15 pre-signed orders in a single batch. -```typescript theme={null} +```typescript Signature theme={null} async postOrders( args: PostOrdersArgs[], ): Promise ``` -```typescript Params theme={null} -interface PostOrdersArgs { - order: SignedOrder; - orderType: OrderType; - postOnly?: boolean; // Defaults to false -} -``` +**Params** -```typescript Response theme={null} -OrderResponse[] // Array of OrderResponse objects + + The pre-signed order to post. + -interface OrderResponse { - success: boolean; - errorMsg: string; - orderID: string; - transactionsHashes: string[]; - status: string; - takingAmount: string; - makingAmount: string; -} -``` + + The order type (e.g. GTC, FOK, FAK). + + + + Optional. Whether to post the order as post-only. Defaults to false. + *** @@ -241,12 +283,15 @@ Cancels a single open order. async cancelOrder(orderID: string): Promise ``` -```typescript Response theme={null} -interface CancelOrdersResponse { - canceled: string[]; - not_canceled: Record; -} -``` +**Response** + + + Array of order IDs that were successfully canceled. + + + + Map of order IDs to reasons why they could not be canceled. + *** @@ -258,17 +303,6 @@ Cancels multiple orders in a single batch. async cancelOrders(orderIDs: string[]): Promise ``` -```typescript Params theme={null} -orderIDs: string[]; -``` - -```typescript Response theme={null} -interface CancelOrdersResponse { - canceled: string[]; - not_canceled: Record; -} -``` - *** ### cancelAll() @@ -276,14 +310,7 @@ interface CancelOrdersResponse { Cancels all open orders. ```typescript Signature theme={null} -async cancelAll(): Promise -``` - -```typescript Response theme={null} -interface CancelOrdersResponse { - canceled: string[]; - not_canceled: Record; -} +async cancelAll(): Promise ``` *** @@ -298,19 +325,15 @@ async cancelMarketOrders( ): Promise ``` -```typescript Parameters theme={null} -interface OrderMarketCancelParams { - market?: string; - asset_id?: string; -} -``` +**Params** -```typescript Response theme={null} -interface CancelOrdersResponse { - canceled: string[]; - not_canceled: Record; -} -``` + + Optional. The market condition ID to cancel orders for. + + + + Optional. The token ID to cancel orders for. + *** @@ -320,31 +343,73 @@ interface CancelOrdersResponse { ### getOrder() -Get details for a specific order. +Get details for a specific order by ID. ```typescript Signature theme={null} async getOrder(orderID: string): Promise ``` -```typescript Response theme={null} -interface OpenOrder { - id: string; - status: string; - owner: string; - maker_address: string; - market: string; - asset_id: string; - side: string; - original_size: string; - size_matched: string; - price: string; - associate_trades: string[]; - outcome: string; - created_at: number; - expiration: string; - order_type: string; -} -``` +**Response** + + + The unique order ID. + + + + The current status of the order. + + + + The API key of the order owner. + + + + The on-chain address of the order maker. + + + + The market condition ID the order belongs to. + + + + The token ID the order is for. + + + + The side of the order (BUY or SELL). + + + + The original size of the order when it was placed. + + + + The amount of the order that has been matched so far. + + + + The limit price of the order. + + + + Array of trade IDs associated with this order. + + + + The outcome label for the order's token. + + + + Unix timestamp of when the order was created. + + + + The expiration time of the order. + + + + The order type (e.g. GTC, FOK, FAK, GTD). + *** @@ -356,40 +421,22 @@ Get all your open orders. async getOpenOrders( params?: OpenOrderParams, only_first_page?: boolean, -): Promise +): Promise ``` -```typescript Params theme={null} -interface OpenOrderParams { - id?: string; // Order ID - market?: string; // Market condition ID - asset_id?: string; // Token ID -} +**Params** -only_first_page?: boolean // Defaults to false -``` + + Optional. Filter by order ID. + -```typescript Response theme={null} -type OpenOrdersResponse = OpenOrder[]; + + Optional. Filter by market condition ID. + -interface OpenOrder { - id: string; - status: string; - owner: string; - maker_address: string; - market: string; - asset_id: string; - side: string; - original_size: string; - size_matched: string; - price: string; - associate_trades: string[]; - outcome: string; - created_at: number; - expiration: string; - order_type: string; -} -``` + + Optional. Filter by token ID. + *** @@ -404,53 +451,141 @@ async getTrades( ): Promise ``` -```typescript Params theme={null} -interface TradeParams { - id?: string; - maker_address?: string; - market?: string; - asset_id?: string; - before?: string; - after?: string; -} +**Params** -only_first_page?: boolean // Defaults to false -``` + + Optional. Filter by trade ID. + -```typescript Response theme={null} -interface Trade { - id: string; - taker_order_id: string; - market: string; - asset_id: string; - side: Side; - size: string; - fee_rate_bps: string; - price: string; - status: string; - match_time: string; - last_update: string; - outcome: string; - bucket_index: number; - owner: string; - maker_address: string; - maker_orders: MakerOrder[]; - transaction_hash: string; - trader_side: "TAKER" | "MAKER"; -} + + Optional. Filter by maker address. + -interface MakerOrder { - order_id: string; - owner: string; - maker_address: string; - matched_amount: string; - price: string; - fee_rate_bps: string; - asset_id: string; - outcome: string; - side: Side; -} -``` + + Optional. Filter by market condition ID. + + + + Optional. Filter by token ID. + + + + Optional. Return trades before this timestamp. + + + + Optional. Return trades after this timestamp. + + +**Response** + + + The unique trade ID. + + + + The order ID of the taker side. + + + + The market condition ID for the trade. + + + + The token ID for the trade. + + + + The side of the trade (BUY or SELL). + + + + The size of the trade. + + + + The fee rate in basis points. + + + + The price at which the trade was matched. + + + + The current status of the trade. + + + + The time at which the trade was matched. + + + + The time of the last update to this trade. + + + + The outcome label for the traded token. + + + + The bucket index for the trade. + + + + The API key of the trade owner. + + + + The on-chain address of the maker. + + + + Array of maker order objects that participated in this trade. Each `MakerOrder` contains the following fields: + + + + The maker order ID. + + + + The API key of the maker order owner. + + + + The on-chain address of the maker order maker. + + + + The amount matched for this maker order. + + + + The price of the maker order. + + + + The fee rate in basis points for the maker order. + + + + The token ID for the maker order. + + + + The outcome label for the maker order's token. + + + + The side of the maker order (BUY or SELL). + + + + The on-chain transaction hash for the trade. + + + + Whether the authenticated user is the taker or a maker in this trade. + *** @@ -464,24 +599,19 @@ async getTradesPaginated( ): Promise ``` -```typescript Params theme={null} -interface TradeParams { - id?: string; - maker_address?: string; - market?: string; - asset_id?: string; - before?: string; - after?: string; -} -``` +**Response** -```typescript Response theme={null} -interface TradesPaginatedResponse { - trades: Trade[]; - limit: number; - count: number; -} -``` + + Array of trade objects for the current page. + + + + The maximum number of trades returned per page. + + + + The total number of trades matching the query. + *** @@ -499,24 +629,25 @@ async getBalanceAllowance( ): Promise ``` -```typescript Params theme={null} -interface BalanceAllowanceParams { - asset_type: AssetType; - token_id?: string; -} +**Params** -enum AssetType { - COLLATERAL = "COLLATERAL", - CONDITIONAL = "CONDITIONAL", -} -``` + + The type of asset to query. One of `"COLLATERAL"` or `"CONDITIONAL"`. + -```typescript Response theme={null} -interface BalanceAllowanceResponse { - balance: string; - allowance: string; -} -``` + + Optional. The token ID to query (required when `asset_type` is `CONDITIONAL`). + + +**Response** + + + The current balance for the specified asset. + + + + The current allowance for the specified asset. + *** @@ -530,21 +661,11 @@ async updateBalanceAllowance( ): Promise ``` -```typescript Params theme={null} -interface BalanceAllowanceParams { - asset_type: AssetType; - token_id?: string; -} - -enum AssetType { - COLLATERAL = "COLLATERAL", - CONDITIONAL = "CONDITIONAL", -} -``` - *** -## API Key Management (L2) +## API Key Management + +*** ### getApiKeys() @@ -554,17 +675,11 @@ Get all API keys associated with your account. async getApiKeys(): Promise ``` -```typescript Response theme={null} -interface ApiKeysResponse { - apiKeys: ApiKeyCreds[]; -} +**Response** -interface ApiKeyCreds { - key: string; - secret: string; - passphrase: string; -} -``` + + Array of API key credential objects associated with the account. + *** @@ -572,9 +687,7 @@ interface ApiKeyCreds { Deletes (revokes) the currently authenticated API key. -**TypeScript Signature:** - -```typescript theme={null} +```typescript Signature theme={null} async deleteApiKey(): Promise ``` @@ -586,30 +699,39 @@ async deleteApiKey(): Promise ### getNotifications() -Retrieves all event notifications for the L2 authenticated user. -Records are removed automatically after 48 hours or if manually removed via dropNotifications(). +Retrieves all event notifications for the authenticated user. Records are automatically removed after 48 hours. ```typescript Signature theme={null} -public async getNotifications(): Promise +async getNotifications(): Promise ``` -```typescript Response theme={null} -interface Notification { - id: number; // Unique notification ID - owner: string; // User's L2 credential apiKey or empty string for global notifications - payload: any; // Type-specific payload data - timestamp?: number; // Unix timestamp - type: number; // Notification type (see type mapping below) -} -``` +**Response** -**Notification Type Mapping** + + Unique notification ID. + + + + The user's API key, or an empty string for global notifications. + + + + Type-specific payload data for the notification. + + + + Optional Unix timestamp of when the notification was created. + + + + Notification type (see below). + | 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 | +| 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 | *** @@ -618,33 +740,33 @@ interface Notification { Mark notifications as read/dismissed. ```typescript Signature theme={null} -public async dropNotifications(params?: DropNotificationParams): Promise +async dropNotifications(params?: DropNotificationParams): Promise ``` -```typescript Params theme={null} -interface DropNotificationParams { - ids: string[]; // Array of notification IDs to mark as read -} -``` +**Params** + + + Array of notification IDs to dismiss. + *** ## See Also - - Deep dive into L1 and L2 authentication + + Deep dive into L1 and L2 authentication. - - Access market data, orderbooks, and prices. + + Sign orders and derive API credentials with your private key. - - Private key authentication to create or derive API keys (L2 headers) + + Read market data and orderbooks without auth. - - Real-time market data streaming + + Real-time market data streaming. diff --git a/docs/developers/CLOB/clients/methods-overview.md b/docs/developers/CLOB/clients/methods-overview.md index c6202b4..a5fdb47 100644 --- a/docs/developers/CLOB/clients/methods-overview.md +++ b/docs/developers/CLOB/clients/methods-overview.md @@ -2,234 +2,96 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Methods Overview +# Clients & SDKs -> CLOB client methods require different levels of authentication. This reference is organized by what credentials you need to call each method. +> 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 + + + ```bash TypeScript theme={null} + npm install @polymarket/clob-client ethers@5 + ``` + + ```bash Python theme={null} + pip install py-clob-client + ``` + + ```bash Rust theme={null} + cargo add polymarket-client-sdk + ``` + + +## Quick Example + + + ```typescript TypeScript theme={null} + import { ClobClient } from "@polymarket/clob-client"; + + const client = new ClobClient( + "https://clob.polymarket.com", + 137, + signer, + apiCreds, + ); + + const markets = await client.getMarkets(); + ``` + + ```python Python theme={null} + from py_clob_client.client import ClobClient + + client = ClobClient( + "https://clob.polymarket.com", + key=private_key, + chain_id=137, + creds=api_creds, + ) + + markets = client.get_markets() + ``` + + +## Source Code + +| Language | Package | Repository | +| ---------- | ------------------------- | ------------------------------------------------------------------------------------ | +| TypeScript | `@polymarket/clob-client` | [github.com/Polymarket/clob-client](https://github.com/Polymarket/clob-client) | +| Python | `py-clob-client` | [github.com/Polymarket/py-clob-client](https://github.com/Polymarket/py-clob-client) | +| Rust | `polymarket-client-sdk` | [github.com/Polymarket/rs-clob-client](https://github.com/Polymarket/rs-clob-client) | + +Each repository includes working examples in the `/examples` directory. + +## Builder SDKs + +If you're building an app through the [Builder Program](/builders/overview), additional signing SDKs are available: + +| Language | Package | Repository | +| ---------- | --------------------------------- | ---------------------------------------------------------------------------------------------------- | +| TypeScript | `@polymarket/builder-signing-sdk` | [github.com/Polymarket/builder-signing-sdk](https://github.com/Polymarket/builder-signing-sdk) | +| Python | `py_builder_signing_sdk` | [github.com/Polymarket/py-builder-signing-sdk](https://github.com/Polymarket/py-builder-signing-sdk) | + +See [Order Attribution](/trading/orders/attribution) for usage details. + +## Relayer SDK + +For [gasless transactions](/trading/gasless) using proxy wallets, the relayer client handles submitting transactions through Polymarket's relayer: + +| 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 - - Access market data, orderbooks, and prices. + + Set up your client and place your first order. - - Private key authentication to create or derive API keys (L2 headers). - - - - Manage and close orders. Creating orders requires signer. - - - - Builder-specific operations for those in the Builders Program. - - - -*** - -## Client Initialization by Use Case - - - - - ```typescript TypeScript theme={null} - // No signer or credentials needed - const client = new ClobClient( - "https://clob.polymarket.com", - 137 - ); - - // All public methods available - const markets = await client.getMarkets(); - const book = await client.getOrderBook(tokenId); - const price = await client.getPrice(tokenId, "BUY"); - ``` - - ```python Python theme={null} - # No signer or credentials needed - client = new ClobClient( - host="https://clob.polymarket.com", - chain_id=137 - ) - - # All public methods available - markets = client.get_markets() - book = client.get_order_book() - price = client.get_price() - ``` - - - - - - ```typescript TypeScript theme={null} - // Create client with signer - const client = new ClobClient( - "https://clob.polymarket.com", - 137, - signer - ); - - // All public and L1 methods available - const newCreds = createApiKey(); - const derivedCreds = deriveApiKey(); - const creds = createOrDeriveApiKey(); - ``` - - ```python Python theme={null} - # Create client with signer - client = new ClobClient( - host="https://clob.polymarket.com", - chain_id=137 - key="private_key" - ) - - # All public and L1 methods available - new_creds = client.create_api_key() - derived_creds = client.derive_api_key() - creds = client.create_or_derive_api_key() - ``` - - - - - - ```typescript TypeScript theme={null} - // Create client with signer and creds - const client = new ClobClient( - "https://clob.polymarket.com", - 137, - signer, - creds, - 2, // Indicates Gnosis Safe proxy - funder // Safe wallet address holding funds - ); - - // All public, L1, and L2 methods available - const order = await client.createOrder({ /* ... */ }); - const result = await client.postOrder(order); - const trades = await client.getTrades(); - ``` - - ```python Python theme={null} - # Create client with signer and creds - const client = new ClobClient( - host="https://clob.polymarket.com", - chain_id=137, - key="private_key", - creds=creds, - signature_type=2, // Indicates Gnosis Safe proxy - funder="funder_address" // Safe wallet address holding funds - ) - - # All public, L1, and L2 methods available - order = client.create_order({ /* ... */ }) - result = client.post_order(order) - trades = client.get_trades() - ``` - - - - - - ```typescript TypeScript theme={null} - // Create client with builder's authentication headers - import { BuilderConfig, BuilderApiKeyCreds } from "@polymarket/builder-signing-sdk"; - - const builderCreds: BuilderApiKeyCreds = { - key: process.env.POLY_BUILDER_API_KEY!, - secret: process.env.POLY_BUILDER_SECRET!, - passphrase: process.env.POLY_BUILDER_PASSPHRASE! - }; - - const builderConfig: BuilderConfig = { - localBuilderCreds: builderCreds - }; - - const client = new ClobClient( - "https://clob.polymarket.com", - 137, - signer, - creds, // User's API credentials - 2, - funder, - undefined, - false, - builderConfig // Builder's API credentials - ); - - // You can call all methods including builder methods - const builderTrades = await client.getBuilderTrades(); - ``` - - ```python Python theme={null} - # Create client with builder's authentication headers - from py_clob_client.client import ClobClient - from py_clob_client.clob_types import ApiCreds - from py_builder_signing_sdk.config import BuilderConfig, BuilderApiKeyCreds - - builder_creds = BuilderApiKeyCreds( - key="POLY_BUILDER_API_KEY", - secret="POLY_BUILDER_SECRET, - passphrase="POLY_BUILDER_PASSPHRASE" - ) - - builder_config = BuilderConfig( - local_builder_creds=builder_creds - ) - - client = ClobClient( - host="https://clob.polymarket.com", - chain_id=137, - key="private_key", - creds=creds, # User's API credentials - signature_type=2, - funder=funder_address, - builder_config=builder_config # Builder's API credentials - ) - - # You can call all methods including builder methods - builder_trades = client.get_builder_trades() - ``` - - - Learn more about the Builders Program and Relay Client here - - - -*** - -## Resources - - - - Open source TypeScript client on GitHub - - - - Open source Python client for GitHub - - - - Open source Rust client on GitHub - - - - TypeScript client method examples - - - - Python client method examples - - - - Rust client method examples - - - - Complete REST endpoint documentation - - - - Real-time market data streaming + + Understand L1/L2 auth and API credentials. diff --git a/docs/developers/CLOB/clients/methods-public.md b/docs/developers/CLOB/clients/methods-public.md index c2de873..5e85742 100644 --- a/docs/developers/CLOB/clients/methods-public.md +++ b/docs/developers/CLOB/clients/methods-public.md @@ -35,7 +35,7 @@ Public methods require the client to initialize with the host URL and Polygon ch ) # Ready to call public methods - markets = await client.get_markets() + markets = client.get_markets() ``` @@ -68,50 +68,121 @@ Get details for a single market by condition ID. async getMarket(conditionId: string): Promise ``` -```typescript Response theme={null} -interface MarketToken { - outcome: string; - price: number; - token_id: string; - winner: boolean; -} + + Timestamp from which the market started accepting orders, or null if not set. + -interface Market { - accepting_order_timestamp: string | null; - accepting_orders: boolean; - active: boolean; - archived: boolean; - closed: boolean; - condition_id: string; - description: string; - enable_order_book: boolean; - end_date_iso: string; - fpmm: string; - game_start_time: string; - icon: string; - image: string; - is_50_50_outcome: boolean; - maker_base_fee: number; - market_slug: string; - minimum_order_size: number; - minimum_tick_size: number; - neg_risk: boolean; - neg_risk_market_id: string; - neg_risk_request_id: string; - notifications_enabled: boolean; - question: string; - question_id: string; - rewards: { - max_spread: number; - min_size: number; - rates: any | null; - }; - seconds_delay: number; - tags: string[]; - taker_base_fee: number; - tokens: MarketToken[]; -} -``` + + Whether the market is currently accepting orders. + + + + Whether the market is active. + + + + Whether the market has been archived. + + + + Whether the market is closed. + + + + The unique condition ID for the market. + + + + Human-readable description of the market. + + + + Whether the order book is enabled for this market. + + + + ISO 8601 end date of the market. + + + + Address of the Fixed Product Market Maker contract. + + + + Start time of the underlying game or event. + + + + URL of the market icon image. + + + + URL of the market image. + + + + Whether the market has equal 50/50 outcomes. + + + + Base fee charged to makers in basis points. + + + + URL-friendly slug identifier for the market. + + + + Minimum order size allowed in this market. + + + + Minimum price increment allowed in this market. + + + + Whether the market uses negative risk (binary complementary tokens). + + + + Negative risk market identifier, if applicable. + + + + Negative risk request identifier, if applicable. + + + + Whether notifications are enabled for this market. + + + + The market question text. + + + + Unique identifier for the market question. + + + + Object containing reward config: `max_spread` (number), `min_size` (number), `rates` (any) + + + + Delay in seconds before orders are processed. + + + + List of tags associated with the market. + + + + Base fee charged to takers in basis points. + + + + Array of market tokens, each containing `outcome` (string), `price` (number), `token_id` (string), and `winner` (boolean). + *** @@ -123,56 +194,17 @@ Get details for multiple markets paginated. async getMarkets(): Promise ``` -```typescript Response theme={null} -interface PaginationPayload { - limit: number; - count: number; - data: Market[]; -} + + Maximum number of results per page. + -interface Market { - accepting_order_timestamp: string | null; - accepting_orders: boolean; - active: boolean; - archived: boolean; - closed: boolean; - condition_id: string; - description: string; - enable_order_book: boolean; - end_date_iso: string; - fpmm: string; - game_start_time: string; - icon: string; - image: string; - is_50_50_outcome: boolean; - maker_base_fee: number; - market_slug: string; - minimum_order_size: number; - minimum_tick_size: number; - neg_risk: boolean; - neg_risk_market_id: string; - neg_risk_request_id: string; - notifications_enabled: boolean; - question: string; - question_id: string; - rewards: { - max_spread: number; - min_size: number; - rates: any | null; - }; - seconds_delay: number; - tags: string[]; - taker_base_fee: number; - tokens: MarketToken[]; -} + + Total number of markets returned. + -interface MarketToken { - outcome: string; - price: number; - token_id: string; - winner: boolean; -} -``` + + Array of Market objects. See `getMarket()` for the full Market structure. + *** @@ -184,129 +216,38 @@ Get simplified market data paginated for faster loading. async getSimplifiedMarkets(): Promise ``` -```typescript Response theme={null} -interface PaginationPayload { - limit: number; - count: number; - data: SimplifiedMarket[]; -} + + Maximum number of results per page. + -interface SimplifiedMarket { - accepting_orders: boolean; - active: boolean; - archived: boolean; - closed: boolean; - condition_id: string; - rewards: { - rates: any | null; - min_size: number; - max_spread: number; - }; - tokens: SimplifiedToken[]; -} + + Total number of markets returned. + -interface SimplifiedToken { - outcome: string; - price: number; - token_id: string; -} -``` + + 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). + *** ### getSamplingMarkets() +Get markets eligible for sampling/liquidity rewards. + ```typescript Signature theme={null} async getSamplingMarkets(): Promise ``` -```typescript Response theme={null} -interface PaginationPayload { - limit: number; - count: number; - data: Market[]; -} - -interface Market { - accepting_order_timestamp: string | null; - accepting_orders: boolean; - active: boolean; - archived: boolean; - closed: boolean; - condition_id: string; - description: string; - enable_order_book: boolean; - end_date_iso: string; - fpmm: string; - game_start_time: string; - icon: string; - image: string; - is_50_50_outcome: boolean; - maker_base_fee: number; - market_slug: string; - minimum_order_size: number; - minimum_tick_size: number; - neg_risk: boolean; - neg_risk_market_id: string; - neg_risk_request_id: string; - notifications_enabled: boolean; - question: string; - question_id: string; - rewards: { - max_spread: number; - min_size: number; - rates: any | null; - }; - seconds_delay: number; - tags: string[]; - taker_base_fee: number; - tokens: MarketToken[]; -} - -interface MarketToken { - outcome: string; - price: number; - token_id: string; - winner: boolean; -} -``` - *** ### getSamplingSimplifiedMarkets() +Get simplified market data for markets eligible for sampling/liquidity rewards. + ```typescript Signature theme={null} async getSamplingSimplifiedMarkets(): Promise ``` -```typescript Response theme={null} -interface PaginationPayload { - limit: number; - count: number; - data: SimplifiedMarket[]; -} - -interface SimplifiedMarket { - accepting_orders: boolean; - active: boolean; - archived: boolean; - closed: boolean; - condition_id: string; - rewards: { - rates: any | null; - min_size: number; - max_spread: number; - }; - tokens: SimplifiedToken[]; -} - -interface SimplifiedToken { - outcome: string; - price: number; - token_id: string; -} -``` - *** ## Order Books and Prices @@ -315,6 +256,8 @@ interface SimplifiedToken { ### calculateMarketPrice() +Calculate the estimated price for a market order of a given size. + ```typescript Signature theme={null} async calculateMarketPrice( tokenID: string, @@ -324,23 +267,25 @@ async calculateMarketPrice( ): Promise ``` -```typescript Params theme={null} -enum OrderType { - GTC = "GTC", // Good Till Cancelled - FOK = "FOK", // Fill or Kill - GTD = "GTD", // Good Till Date - FAK = "FAK", // Fill and Kill -} + + The token ID to calculate the market price for. + -enum Side { - BUY = "BUY", - SELL = "SELL", -} -``` + + The side of the order. One of: `BUY`, `SELL` + -```typescript Response theme={null} -number // calculated market price -``` + + The size of the order to calculate price for. + + + + The order type. One of: `GTC` (Good Till Cancelled), `FOK` (Fill or Kill), `GTD` (Good Till Date), `FAK` (Fill and Kill). Defaults to `FOK`. + + + + The calculated estimated market price for the given order size. + *** @@ -352,24 +297,41 @@ Get the order book for a specific token ID. async getOrderBook(tokenID: string): Promise ``` -```typescript Response theme={null} -interface OrderBookSummary { - market: string; - asset_id: string; - timestamp: string; - bids: OrderSummary[]; - asks: OrderSummary[]; - min_order_size: string; - tick_size: string; - neg_risk: boolean; - hash: string; -} + + The market condition ID. + -interface OrderSummary { - price: string; - size: string; -} -``` + + The token/asset ID for this order book. + + + + Timestamp of the order book snapshot. + + + + Array of bid entries, each with `price` (string) and `size` (string). + + + + Array of ask entries, each with `price` (string) and `size` (string). + + + + Minimum order size for this market. + + + + Minimum price increment for this market. + + + + Whether the market uses negative risk. + + + + Hash of the order book state. + *** @@ -381,16 +343,17 @@ Get order books for multiple token IDs. async getOrderBooks(params: BookParams[]): Promise ``` -```typescript Params theme={null} -interface BookParams { - token_id: string; - side: Side; // Side.BUY or Side.SELL -} -``` + + The token ID to fetch the order book for. + -```typescript Response theme={null} -OrderBookSummary[] -``` + + The side of the book to query. One of: `BUY`, `SELL` + + + + Array of OrderBookSummary objects. See `getOrderBook()` for the full structure. + *** @@ -405,11 +368,9 @@ async getPrice( ): Promise ``` -```typescript Response theme={null} -{ - price: string; -} -``` + + The current best price for the requested side. + *** @@ -421,23 +382,9 @@ Get the current best prices for multiple token IDs. async getPrices(params: BookParams[]): Promise ``` -```typescript Params theme={null} -interface BookParams { - token_id: string; - side: Side; // Side.BUY or Side.SELL -} -``` - -```typescript Response theme={null} -interface TokenPrices { - BUY?: string; - SELL?: string; -} - -type PricesResponse = { - [tokenId: string]: TokenPrices; -} -``` + + A map of token IDs to their prices. Each entry contains an optional `BUY` (string) and/or `SELL` (string) price. + *** @@ -449,34 +396,23 @@ Get the midpoint price (average of best bid and best ask) for a token ID. async getMidpoint(tokenID: string): Promise ``` -```typescript Response theme={null} -{ - mid: string; -} -``` + + The midpoint price, calculated as the average of best bid and best ask. + *** ### getMidpoints() -Get the midpoint prices (average of best bid and best ask) for multiple token IDs. +Get the midpoint prices for multiple token IDs. ```typescript Signature theme={null} async getMidpoints(params: BookParams[]): Promise ``` -```typescript Params theme={null} -interface BookParams { - token_id: string; - side: Side; // Side is ignored -} -``` - -```typescript Response theme={null} -{ - [tokenId: string]: string; -} -``` + + 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. + *** @@ -488,34 +424,23 @@ Get the spread (difference between best ask and best bid) for a token ID. async getSpread(tokenID: string): Promise ``` -```typescript Response theme={null} -interface SpreadResponse { - spread: string; -} -``` + + The spread value, calculated as the difference between best ask and best bid. + *** ### getSpreads() -Get the spreads (difference between best ask and best bid) for multiple token IDs. +Get the spreads for multiple token IDs. ```typescript Signature theme={null} async getSpreads(params: BookParams[]): Promise ``` -```typescript Params theme={null} -interface BookParams { - token_id: string; - side: Side; -} -``` - -```typescript Response theme={null} -type SpreadsResponse = { - [tokenId: string]: string; -} -``` + + A map of token IDs to their spread strings. Each key is a token ID and its value is the spread as a string. + *** @@ -527,30 +452,33 @@ Get historical price data for a token. async getPricesHistory(params: PriceHistoryFilterParams): Promise ``` -```typescript Params theme={null} -interface PriceHistoryFilterParams { - market: string; // tokenID - startTs?: number; - endTs?: number; - fidelity?: number; - interval: PriceHistoryInterval; -} + + The token ID to fetch price history for. + -enum PriceHistoryInterval { - MAX = "max", - ONE_WEEK = "1w", - ONE_DAY = "1d", - SIX_HOURS = "6h", - ONE_HOUR = "1h", -} -``` + + Optional start timestamp (Unix seconds) for the price history range. + -```typescript Response theme={null} -interface MarketPrice { - t: number; // timestamp - p: number; // price -} -``` + + Optional end timestamp (Unix seconds) for the price history range. + + + + Optional fidelity/resolution of the price history data. + + + + Time interval for the price history. One of: `max`, `1w`, `1d`, `6h`, `1h` + + + + Unix timestamp of the price data point. + + + + Price value at the corresponding timestamp. + *** @@ -566,73 +494,91 @@ Get the price of the most recent trade for a token. async getLastTradePrice(tokenID: string): Promise ``` -```typescript Response theme={null} -interface LastTradePrice { - price: string; - side: string; -} -``` + + The price of the most recent trade. + + + + The side of the most recent trade. + *** ### getLastTradesPrices() -Get the price of the most recent trade for a token. +Get the most recent trade prices for multiple tokens. ```typescript Signature theme={null} async getLastTradesPrices(params: BookParams[]): Promise ``` -```typescript Params theme={null} -interface BookParams { - token_id: string; - side: Side; -} -``` + + The price of the most recent trade for the token. + -```typescript Response theme={null} -interface LastTradePriceWithToken { - price: string; - side: string; - token_id: string; -} -``` + + The side of the most recent trade. + + + + The token ID this trade price corresponds to. + *** -### getMarketTradesEvents +### getMarketTradesEvents() + +Get recent trade events for a market. ```typescript Signature theme={null} async getMarketTradesEvents(conditionID: string): Promise ``` -```typescript Response theme={null} -interface MarketTradeEvent { - event_type: string; - market: { - condition_id: string; - asset_id: string; - question: string; - icon: string; - slug: string; - }; - user: { - address: string; - username: string; - profile_picture: string; - optimized_profile_picture: string; - pseudonym: string; - }; - side: Side; - size: string; - fee_rate_bps: string; - price: string; - outcome: string; - outcome_index: number; - transaction_hash: string; - timestamp: string; -} -``` + + The type of trade event. + + + + Object containing market info: `condition_id` (string), `asset_id` (string), `question` (string), `icon` (string), `slug` (string). + + + + Object containing user info: `address` (string), `username` (string), `profile_picture` (string), `optimized_profile_picture` (string), `pseudonym` (string). + + + + The side of the trade. One of: `BUY`, `SELL` + + + + The size of the trade. + + + + The fee rate in basis points for the trade. + + + + The price at which the trade was executed. + + + + The outcome label for the traded token. + + + + The index of the outcome in the market. + + + + The on-chain transaction hash for the trade. + + + + The timestamp of when the trade event occurred. + + +*** ## Market Parameters @@ -646,9 +592,9 @@ Get the fee rate in basis points for a token. async getFeeRateBps(tokenID: string): Promise ``` -```typescript Response theme={null} -number -``` + + The fee rate in basis points for the specified token. + *** @@ -660,9 +606,9 @@ Get the tick size (minimum price increment) for a market. async getTickSize(tokenID: string): Promise ``` -```typescript Response theme={null} -type TickSize = "0.1" | "0.01" | "0.001" | "0.0001"; -``` + + The tick size for the market. One of: `0.1`, `0.01`, `0.001`, `0.0001` + *** @@ -674,9 +620,9 @@ Check if a market uses negative risk (binary complementary tokens). async getNegRisk(tokenID: string): Promise ``` -```typescript Response theme={null} -boolean -``` + + Whether the market uses negative risk. + *** @@ -690,28 +636,28 @@ Get the current server timestamp. async getServerTime(): Promise ``` -```typescript Response theme={null} -number // Unix timestamp in seconds -``` + + Unix timestamp in seconds representing the current server time. + *** ## See Also - - Private key authentication to create or derive API keys (L2 headers). + + Private key authentication to create or derive API credentials. - - Manage and close orders. Creating orders requires signer. + + Place orders, cancel orders, and query your trades. - - Complete REST endpoint documentation + + Complete REST endpoint documentation. - - Real-time market data streaming + + Real-time market data streaming. diff --git a/docs/developers/CLOB/geoblock.md b/docs/developers/CLOB/geoblock.md index fb5ea20..24690aa 100644 --- a/docs/developers/CLOB/geoblock.md +++ b/docs/developers/CLOB/geoblock.md @@ -4,27 +4,18 @@ # Geographic Restrictions -> Check geographic restrictions before placing orders on Polymarket's CLOB +> Check geographic restrictions before placing orders on the Polymarket API -## Overview - -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. +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. - 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. + 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. *** -## Server Infrastructure - -* **Primary Servers**: eu-west-2 -* **Closest Non-Georestricted Region**: eu-west-1 - -*** - ## Geoblock Endpoint Check the geographic eligibility of the requesting IP address: @@ -33,14 +24,16 @@ Check the geographic eligibility of the requesting IP address: GET https://polymarket.com/api/geoblock ``` +This endpoint is on `polymarket.com`, not the API servers. + ### Response -```typescript theme={null} +```json theme={null} { - "blocked": boolean; - "ip": string; - "country": string; - "region": string; + "blocked": true, + "ip": "203.0.113.42", + "country": "US", + "region": "NY" } ``` @@ -55,43 +48,43 @@ GET https://polymarket.com/api/geoblock ## Blocked Countries -The following **33 countries** are completely restricted from placing orders on Polymarket: +The following countries are restricted from placing orders on Polymarket. Countries marked as **close-only** can close existing positions but cannot open new ones: -| Country Code | Country Name | -| ------------ | ------------------------------------ | -| AU | Australia | -| BE | Belgium | -| BY | Belarus | -| BI | Burundi | -| CF | Central African Republic | -| CD | Congo (Kinshasa) | -| CU | Cuba | -| DE | Germany | -| ET | Ethiopia | -| FR | France | -| GB | United Kingdom | -| IR | Iran | -| IQ | Iraq | -| IT | Italy | -| KP | North Korea | -| LB | Lebanon | -| LY | Libya | -| MM | Myanmar | -| NI | Nicaragua | -| PL | Poland | -| RU | Russia | -| SG | Singapore | -| SO | Somalia | -| SS | South Sudan | -| SD | Sudan | -| SY | Syria | -| TH | Thailand | -| TW | Taiwan | -| UM | United States Minor Outlying Islands | -| US | United States | -| VE | Venezuela | -| YE | Yemen | -| ZW | Zimbabwe | +| 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 | +| KP | North Korea | Blocked | +| LB | Lebanon | Blocked | +| LY | Libya | Blocked | +| MM | Myanmar | Blocked | +| NI | Nicaragua | 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 | *** @@ -108,6 +101,22 @@ In addition to fully blocked countries, the following specific regions within ot *** +## 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 + +*** + ## Usage Examples @@ -154,3 +163,31 @@ In addition to fully blocked countries, the following specific regions within ot ``` + +*** + +## 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 + + + + Learn how to authenticate trading requests. + + + + Start placing orders (from eligible regions). + + diff --git a/docs/developers/CLOB/introduction.md b/docs/developers/CLOB/introduction.md index f4d4479..fa09274 100644 --- a/docs/developers/CLOB/introduction.md +++ b/docs/developers/CLOB/introduction.md @@ -2,55 +2,199 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# CLOB Introduction +# Overview -Welcome to the Polymarket Order Book API! This documentation provides overviews, explanations, examples, and annotations to simplify interaction with the order book. The following sections detail the Polymarket Order Book and the API usage. +> Trading on the Polymarket CLOB -## System +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 — users can always cancel orders onchain independently. -Polymarket's Order Book, or CLOB (Central Limit Order Book), is hybrid-decentralized. It includes an operator for off-chain matching/ordering, with settlement executed on-chain, non-custodially, via signed order messages. +We recommend using the open-source SDK clients, which handle order signing, authentication, and submission: -The exchange uses a custom Exchange contract facilitating atomic swaps between binary Outcome Tokens (CTF ERC1155 assets and ERC20 PToken assets) and collateral assets (ERC20), following signed limit orders. Designed for binary markets, the contract enables complementary tokens to match across a unified order book. + + +

+ npm install @polymarket/clob-client +

+
-Orders are EIP712-signed structured data. Matched orders have one maker and one or more takers, with price improvements benefiting the taker. The operator handles off-chain order management and submits matched trades to the blockchain for on-chain execution. + +

pip install py-clob-client

+
+
-## API + + You can also use the REST API directly, but you'll need to manage [EIP-712 + order + signing](https://github.com/Polymarket/clob-client/blob/main/src/signing/eip712.ts) + and [HMAC authentication + headers](https://github.com/Polymarket/clob-client/blob/main/src/signing/hmac.ts) + yourself. See [REST API Headers](#rest-api-headers) below. + -The Polymarket Order Book API enables market makers and traders to programmatically manage market orders. Orders of any amount can be created, listed, fetched, or read from the market order books. Data includes all available markets, market prices, and order history via REST and WebSocket endpoints. +*** -## Security +## Authentication -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 CLOB uses two levels of authentication: -The operator's privileges are limited to order matching, non-censorship, and ensuring correct ordering. Operators can't set prices or execute unauthorized trades. Users can cancel orders on-chain independently if trust issues arise. +| 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 | -## Fees +You use your private key once to derive **L2 credentials** (API key, secret, passphrase), which authenticate all subsequent trading requests. -### Schedule + + ```typescript TypeScript theme={null} + import { ClobClient } from "@polymarket/clob-client"; + import { Wallet } from "ethers"; // v5.8.0 -> Subject to change + const signer = new Wallet(process.env.PRIVATE_KEY); -| Volume Level | Maker Fee Base Rate (bps) | Taker Fee Base Rate (bps) | -| ------------ | ------------------------- | ------------------------- | -| >0 USDC | 0 | 0 | + // Derive L2 API credentials + const tempClient = new ClobClient("https://clob.polymarket.com", 137, signer); + const apiCreds = await tempClient.createOrDeriveApiKey(); + ``` -### Overview + ```python Python theme={null} + from py_clob_client.client import ClobClient + import os -Fees apply symmetrically in output assets (proceeds). This symmetry ensures fairness and market integrity. Fees are calculated differently depending on whether you are buying or selling: + private_key = os.getenv("PRIVATE_KEY") -* **Selling outcome tokens (base) for collateral (quote):** + # 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_creds() + ``` + -$$ -feeQuote = baseRate \times \min(price, 1 - price) \times size -$$ +*** -* **Buying outcome tokens (base) with collateral (quote):** +## Signature Types -$$ -feeBase = baseRate \times \min(price, 1 - price) \times \frac{size}{price} -$$ +When initializing the trading client, you must specify your wallet's **signature type** and **funder address**: -## Additional Resources +| 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` | Polymarket account via Magic Link (email/Google login). Requires [exported private key](https://polymarket.com/settings) from Polymarket.com | Your proxy wallet address | +| **GNOSIS\_SAFE** | `2` | Polymarket account via browser wallet (MetaMask, Rabby) or embedded wallet (Privy, Turnkey). Most common type | Your proxy wallet address | -* [Exchange contract source code](https://github.com/Polymarket/ctf-exchange/tree/main/src) -* [Exchange contract documentation](https://github.com/Polymarket/ctf-exchange/blob/main/docs/Overview.md) + + If you have a Polymarket.com account, your funds are in a proxy wallet visible + in the profile dropdown. Use type `1` or `2`. Type `0` is for standalone EOA + wallets only. + + +### Initialize the Trading Client + + + ```typescript TypeScript theme={null} + const client = new ClobClient( + "https://clob.polymarket.com", + 137, + signer, + apiCreds, + 2, // GNOSIS_SAFE + "0x...", // Your proxy wallet address + ); + ``` + + ```python Python theme={null} + client = ClobClient( + "https://clob.polymarket.com", + key=private_key, + chain_id=137, + creds=api_creds, + signature_type=2, # GNOSIS_SAFE + funder="0x..." # Your proxy wallet address + ) + ``` + + +*** + +## 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 | + + + 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. + + +*** + +## Client Methods + + + + Market data, orderbooks, prices, and spreads — no auth required. + + + + Sign orders and derive API credentials with your private key. + + + + Place orders, cancel orders, query trades, and manage notifications. + + + + Track attributed trades and manage builder credentials. + + + +*** + +## What's in This Section + + + + Place your first order end-to-end + + + + Reading the orderbook, prices, spreads, and midpoints + + + + Order types, tick sizes, creating, cancelling, and querying orders + + + + Fee structure, fee-enabled markets, and maker rebates + + + + Execute onchain operations without paying gas + + + + Split, merge, and redeem outcome tokens + + + + Deposit and withdraw funds across chains + + diff --git a/docs/developers/CLOB/orders/cancel-orders.md b/docs/developers/CLOB/orders/cancel-orders.md index 0816c0f..c712a57 100644 --- a/docs/developers/CLOB/orders/cancel-orders.md +++ b/docs/developers/CLOB/orders/cancel-orders.md @@ -2,172 +2,328 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Cancel Orders(s) +# Cancel Order -> Multiple endpoints to cancel a single order, multiple orders, all orders or all orders from a single market. +> Cancel single, multiple, or all open orders -# Cancel an single Order +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). - This endpoint requires a L2 Header. +*** -Cancel an order. - -**HTTP REQUEST** - -`DELETE //order` - -### Request Payload Parameters - -| Name | Required | Type | Description | -| ------- | -------- | ------ | --------------------- | -| orderID | yes | string | ID of order to cancel | - -### Response Format - -| Name | Type | Description | -| ------------- | --------- | -------------------------------------------------------------------------- | -| canceled | string\[] | list of canceled orders | -| not\_canceled | {} | a order id -> reason map that explains why that order couldn't be canceled | +## Cancel a Single Order - ```python Python theme={null} - resp = client.cancel(order_id="0x38a73eed1e6d177545e9ab027abddfb7e08dbe975fa777123b1752d203d6ac88") - print(resp) + ```typescript TypeScript theme={null} + const resp = await client.cancelOrder("0xb816482a..."); + console.log(resp); + // { canceled: ["0xb816482a..."], not_canceled: {} } ``` - ```javascript Typescript theme={null} - async function main() { - // Send it to the server - const resp = await clobClient.cancelOrder({ - orderID: - "0x38a73eed1e6d177545e9ab027abddfb7e08dbe975fa777123b1752d203d6ac88", - }); - console.log(resp); - console.log(`Done!`); - } - main(); + ```python Python theme={null} + resp = client.cancel(order_id="0xb816482a...") + print(resp) + # {"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..."}' ``` -# Cancel Multiple Orders +*** - This endpoint requires a L2 Header. - -**HTTP REQUEST** - -`DELETE //orders` - -### Request Payload Parameters - -| Name | Required | Type | Description | -| ---- | -------- | --------- | --------------------------- | -| null | yes | string\[] | IDs of the orders to cancel | - -### Response Format - -| Name | Type | Description | -| ------------- | --------- | -------------------------------------------------------------------------- | -| canceled | string\[] | list of canceled orders | -| not\_canceled | {} | a order id -> reason map that explains why that order couldn't be canceled | +## Cancel Multiple Orders - ```python Python theme={null} - resp = client.cancel_orders(["0x38a73eed1e6d177545e9ab027abddfb7e08dbe975fa777123b1752d203d6ac88", "0xaaaa..."]) - print(resp) + ```typescript TypeScript theme={null} + const resp = await client.cancelOrders(["0xb816482a...", "0xc927593b..."]); ``` - ```javascript Typescript theme={null} - async function main() { - // Send it to the server - const resp = await clobClient.cancelOrders([ - "0x38a73eed1e6d177545e9ab027abddfb7e08dbe975fa777123b1752d203d6ac88", - "0xaaaa...", - ]); - console.log(resp); - console.log(`Done!`); - } - main(); + ```python Python theme={null} + resp = client.cancel_orders([ + "0xb816482a...", + "0xc927593b...", + ]) + ``` + + ```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..."]' ``` -# Cancel ALL Orders +*** - This endpoint requires a L2 Header. +## Cancel All Orders -Cancel all open orders posted by a user. - -**HTTP REQUEST** - -`DELETE //cancel-all` - -### Response Format - -| Name | Type | Description | -| ------------- | --------- | -------------------------------------------------------------------------- | -| canceled | string\[] | list of canceled orders | -| not\_canceled | {} | a order id -> reason map that explains why that order couldn't be canceled | +Cancel every open order across all markets: + ```typescript TypeScript theme={null} + const resp = await client.cancelAll(); + ``` + ```python Python theme={null} resp = client.cancel_all() - print(resp) - print("Done!") ``` - ```javascript Typescript theme={null} - async function main() { - const resp = await clobClient.cancelAll(); - console.log(resp); - console.log(`Done!`); - } - - main(); + ```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: ..." ``` -# Cancel orders from market +*** - This endpoint requires a L2 Header. +## Cancel by Market -Cancel orders from market. - -**HTTP REQUEST** - -`DELETE //cancel-market-orders` - -### Request Payload Parameters - -| Name | Required | Type | Description | -| --------- | -------- | ------ | -------------------------- | -| market | no | string | condition id of the market | -| asset\_id | no | string | id of the asset/token | - -### Response Format - -| Name | Type | Description | -| ------------- | --------- | -------------------------------------------------------------------------- | -| canceled | string\[] | list of canceled orders | -| not\_canceled | {} | a order id -> reason map that explains why that order couldn't be canceled | +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. - ```python Python theme={null} - resp = client.cancel_market_orders(market="0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af", asset_id="52114319501245915516055106046884209969926127482827954674443846427813813222426") - print(resp) - + ```typescript TypeScript theme={null} + const resp = await client.cancelMarketOrders({ + market: "0xbd31dc8a...", // optional: condition ID + asset_id: "52114319501245...", // optional: specific token + }); ``` - ```javascript Typescript theme={null} - async function main() { - // Send it to the server - const resp = await clobClient.cancelMarketOrders({ - market: - "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af", - asset_id: - "52114319501245915516055106046884209969926127482827954674443846427813813222426", - }); - console.log(resp); - console.log(`Done!`); - } - main(); + ```python Python theme={null} + resp = client.cancel_market_orders( + market="0xbd31dc8a...", + asset_id="52114319501245...", # optional + ) + ``` + + ```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..."}' ``` + +*** + +## Onchain Cancellation + +If the API is unavailable, you can cancel orders directly on the [Exchange contract](https://github.com/Polymarket/ctf-exchange/tree/main/src) by calling `cancelOrder(Order order)` onchain. Pass the full order struct that was signed when placing the order. + +Use the `CTFExchange` or `NegRiskCTFExchange` contract depending on the market type. See [Contract Addresses](/resources/contract-addresses) for addresses. + +This is a fallback mechanism — API cancellation is instant while onchain cancellation requires a transaction. + +*** + +## Querying Orders + +### Get a Single Order + + + ```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"]) + ``` + + +### Get Open Orders + +Retrieve all open orders, optionally filtered by market or token: + + + ```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.clob_types import OpenOrderParams + + # All open orders + orders = client.get_orders() + + # Filtered by market + market_orders = client.get_orders( + OpenOrderParams(market="0xbd31dc8a...") + ) + ``` + + +### 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 | + + + ```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.clob_types import TradeParams + + trades = client.get_trades() + + market_trades = client.get_trades( + TradeParams(market="0xbd31dc8a...") + ) + ``` + + +Additional filter parameters: `id`, `maker_address`, `asset_id`, `before`, `after`. + +For large result sets, use the paginated variant: + + + ```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...")) + ``` + + +### 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 | + + + 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. + + +*** + +## Order Scoring + +Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring: + + + ```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.clob_types import OrderScoringParams, OrdersScoringParams + + scoring = client.is_order_scoring( + OrderScoringParams(orderId="0x...") + ) + + batch = client.are_orders_scoring( + OrdersScoringParams(orderIds=["0x...", "0x..."]) + ) + ``` + + +*** + +## Next Steps + + + + Attribute orders to your builder account for volume credit + + + + Understand fee structures and maker rebates + + diff --git a/docs/developers/CLOB/orders/check-scoring.md b/docs/developers/CLOB/orders/check-scoring.md index b364a8f..19a87c4 100644 --- a/docs/developers/CLOB/orders/check-scoring.md +++ b/docs/developers/CLOB/orders/check-scoring.md @@ -2,95 +2,462 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Check Order Reward Scoring +# Overview -> Check if an order is eligble or scoring for Rewards purposes +> Order types, tick sizes, and querying orders - This endpoint requires a L2 Header. +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. -Returns a boolean value where it is indicated if an order is scoring or not. +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) or [Python](https://github.com/Polymarket/py-clob-client) SDK clients, which handle signing and submission for you. -**HTTP REQUEST** + + 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. + -`GET //order-scoring?order_id={...}` +*** -### Request Parameters +## Order Types -| Name | Required | Type | Description | -| ------- | -------- | ------ | ------------------------------------ | -| orderId | yes | string | id of order to get information about | +| 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 | -### Response Format +* **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. -| Name | Type | Description | -| ---- | ------------- | ------------------ | -| null | OrdersScoring | order scoring data | + + **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`. + -An `OrdersScoring` object is of the form: +### Post-Only Orders -| Name | Type | Description | -| ------- | ------- | ---------------------------------------- | -| scoring | boolean | indicates if the order is scoring or not | +Post-only orders are limit orders that will only rest on the book and not match immediately on entry. -# Check if some orders are scoring +* 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. -> This endpoint requires a L2 Header. +*** -Returns to a dictionary with boolean value where it is indicated if an order is scoring or not. +## Tick Sizes -**HTTP REQUEST** +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. -`POST //orders-scoring` +| 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 | -### Request Parameters +Retrieve the tick size for a market using the SDK: -| Name | Required | Type | Description | -| -------- | -------- | --------- | ------------------------------------------ | -| orderIds | yes | string\[] | ids of the orders to get information about | + + ```typescript TypeScript theme={null} + const tickSize = await client.getTickSize(tokenID); + // Returns: "0.1" | "0.01" | "0.001" | "0.0001" + ``` -### Response Format - -| Name | Type | Description | -| ---- | ------------- | ------------------- | -| null | OrdersScoring | orders scoring data | - -An `OrdersScoring` object is a dictionary that indicates the order by if it score. - - ```python Python theme={null} + tick_size = client.get_tick_size(token_id) + # Returns: "0.1" | "0.01" | "0.001" | "0.0001" + ``` + + + + You can also check the `minimum_tick_size` field on a market object returned + by the [Markets API](/market-data/fetching-markets). + + +*** + +## 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. + + + ```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} + response = client.create_and_post_order( + OrderArgs( + token_id="TOKEN_ID", + price=0.50, + size=10, + side=BUY, + ), + options={ + "tick_size": "0.01", + "neg_risk": True, # Required for multi-outcome markets + } + ) + ``` + + +You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field: + + + ```typescript TypeScript theme={null} + const isNegRisk = await client.getNegRisk(tokenID); + ``` + + ```python Python theme={null} + is_neg_risk = client.get_neg_risk(token_id) + ``` + + +*** + +## 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 **USDC.e** 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 +* Onchain order cancellations + + + Any maker caught intentionally abusing these checks will be blacklisted. + + +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 USDC.e 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). + +### Get a Single Order + +Retrieve details for a specific order by its ID: + + + ```typescript TypeScript theme={null} + const order = await client.getOrder("0xb816482a..."); + console.log(order); + ``` + + ```python Python theme={null} + order = client.get_order("0xb816482a...") + print(order) + ``` + + +### Get Open Orders + +Retrieve your open orders, optionally filtered by market or asset: + + + ```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.clob_types import OpenOrderParams + + # All open orders + orders = client.get_orders() + + # Filtered by market + market_orders = client.get_orders( + OpenOrderParams( + market="0xbd31dc8a...", + ) + ) + ``` + + +### 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: + + + ```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.clob_types import TradeParams + + # All trades + trades = client.get_trades() + + # Filtered by market + market_trades = client.get_trades( + TradeParams( + market="0xbd31dc8a...", + ) + ) + ``` + + +*** + +## 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**. + + + ```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) + ``` + + +* 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: + + + ```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.clob_types import OrderScoringParams, OrdersScoringParams + + # Single order scoring = client.is_order_scoring( - OrderScoringParams( - orderId="0x..." - ) + OrderScoringParams(orderId="0x...") ) - print(scoring) - scoring = client.are_orders_scoring( - OrdersScoringParams( - orderIds=["0x..."] - ) + # Multiple orders + batch_scoring = client.are_orders_scoring( + OrdersScoringParams(orderIds=["0x...", "0x..."]) ) - print(scoring) ``` + - ```javascript Typescript theme={null} - async function main() { - const scoring = await clobClient.isOrderScoring({ - orderId: "0x...", - }); - console.log(scoring); - } +*** - main(); +## Onchain Order Info - async function main() { - const scoring = await clobClient.areOrdersScoring({ - orderIds: ["0x..."], - }); - console.log(scoring); - } +When a trade is settled onchain, the Exchange contract emits an `OrderFilled` event with the following fields: - main(); +| 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 USDC.e for outcome tokens) | +| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving USDC.e 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. Users can cancel orders onchain independently if trust issues arise. + +*** + +## Next Steps + + + + Build, sign, and submit orders + + + + Cancel single, multiple, or all orders + + diff --git a/docs/developers/CLOB/orders/create-order-batch.md b/docs/developers/CLOB/orders/create-order-batch.md index 980c7e0..20d80ad 100644 --- a/docs/developers/CLOB/orders/create-order-batch.md +++ b/docs/developers/CLOB/orders/create-order-batch.md @@ -2,233 +2,532 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Place Multiple Orders (Batching) +# Create Order -> Instructions for placing multiple orders(Batch) +> Build, sign, and submit orders - This endpoint requires a L2 Header +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. -Polymarket’s CLOB supports batch orders, allowing you to place up to `15` orders in a single request. Before using this feature, make sure you're comfortable placing a single order first. You can find the documentation for that [here.](/developers/CLOB/orders/create-order) + + 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. + -**HTTP REQUEST** +*** -`POST //orders` +## Order Types -### Request Payload Parameters +| 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 | -| Name | Required | Type | Description | -| --------- | -------- | ------------- | ---------------------------------------------------------------- | -| PostOrder | yes | PostOrders\[] | list of signed order objects (Signed Order + Order Type + Owner) | +* **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 -A `PostOrder` object is the form: +*** -| Name | Required | Type | Description | -| --------- | -------- | ------- | -------------------------------------------------------------------------------------------- | -| order | yes | order | See below table for details on crafting this object | -| orderType | yes | string | order type ("FOK", "GTC", "GTD", "FAK") | -| owner | yes | string | api key of order owner | -| postOnly | no | boolean | if `true`, the order will only rest on the book and not match immediately (default: `false`) | +## Limit Orders -An `order` object is the form: +The simplest way to place a limit order — create, sign, and submit in one call: -| Name | Required | Type | Description | -| ------------- | -------- | ------- | -------------------------------------------------- | -| salt | yes | integer | random salt used to create unique order | -| maker | yes | string | maker address (funder) | -| signer | yes | string | signing address | -| taker | yes | string | taker address (operator) | -| tokenId | yes | string | ERC1155 token ID of conditional token being traded | -| makerAmount | yes | string | maximum amount maker is willing to spend | -| takerAmount | yes | string | minimum amount taker will pay the maker in return | -| expiration | yes | string | unix expiration timestamp | -| nonce | yes | string | maker's exchange nonce of the order is associated | -| feeRateBps | yes | string | fee rate basis points as required by the operator | -| side | yes | string | buy or sell enum index | -| signatureType | yes | integer | signature type enum index | -| signature | yes | string | hex encoded signature | + + ```typescript TypeScript theme={null} + import { ClobClient, Side, OrderType } from "@polymarket/clob-client"; -### Order types + const response = await client.createAndPostOrder( + { + tokenID: "TOKEN_ID", + price: 0.5, + size: 10, + side: Side.BUY, + }, + { + tickSize: "0.01", + negRisk: false, + }, + OrderType.GTC, + ); -* **FOK**: A Fill-Or-Kill order is an market order to buy (in dollars) or sell (in shares) shares that must be executed immediately in its entirety; otherwise, the entire order will be cancelled. -* **FAK**: A Fill-And-Kill order is a market order to buy (in dollars) or sell (in shares) that will be executed immediately for as many shares as are available; any portion not filled at once is cancelled. -* **GTC**: A Good-Til-Cancelled order is a limit order that is active until it is fulfilled or cancelled. -* **GTD**: A Good-Til-Date order is a type of order that is active until its specified date (UTC seconds timestamp), unless it has already been fulfilled or cancelled. There is a security threshold of one minute. If the order needs to expire in 90 seconds the correct expiration value is: now + 1 minute + 30 seconds + console.log("Order ID:", response.orderID); + console.log("Status:", response.status); + ``` -### Response Format - -| Name | Type | Description | -| ----------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------- | -| success | boolean | boolean indicating if server-side err (`success = false`) -> server-side error | -| errorMsg | string | error message in case of unsuccessful placement (in case `success = false`, e.g. `client-side error`, the reason is in `errorMsg`) | -| orderId | string | id of order | -| orderHashes | string\[] | hash of settlement transaction order was marketable and triggered a match | - -### Insert Error Messages - -If the `errorMsg` field of the response object from placement is not an empty string, the order was not able to be immediately placed. This might be because of a delay or because of a failure. If the `success` is not `true`, then there was an issue placing the order. The following `errorMessages` are possible: - -#### Error - -| Error | Success | Message | Description | -| ------------------------------------ | ------- | --------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | -| INVALID\_ORDER\_MIN\_TICK\_SIZE | yes | order is invalid. Price breaks minimum tick size rules | order price isn't accurate to correct tick sizing | -| INVALID\_ORDER\_MIN\_SIZE | yes | order is invalid. Size lower than the minimum | order size must meet min size threshold requirement | -| INVALID\_ORDER\_DUPLICATED | yes | order is invalid. Duplicated. Same order has already been placed, can't be placed again | | -| INVALID\_ORDER\_NOT\_ENOUGH\_BALANCE | yes | not enough balance / allowance | funder address doesn't have sufficient balance or allowance for order | -| INVALID\_ORDER\_EXPIRATION | yes | invalid expiration | expiration field expresses a time before now | -| INVALID\_ORDER\_ERROR | yes | could not insert order | system error while inserting order | -| INVALID\_POST\_ONLY\_ORDER\_TYPE | yes | invalid post-only order: only GTC and GTD order types are allowed | post only flag attached to a market order | -| INVALID\_POST\_ONLY\_ORDER | yes | invalid post-only order: order crosses book | post only order would match | -| EXECUTION\_ERROR | yes | could not run the execution | system error while attempting to execute trade | -| ORDER\_DELAYED | no | order match delayed due to market conditions | order placement delayed | -| DELAYING\_ORDER\_ERROR | yes | error delaying the order | system error while delaying order | -| FOK\_ORDER\_NOT\_FILLED\_ERROR | yes | order couldn't be fully filled, FOK orders are fully filled/killed | FOK order not fully filled so can't be placed | -| MARKET\_NOT\_READY | no | the market is not yet ready to process new orders | system not accepting orders for market yet | - -### Insert Statuses - -When placing an order, a status field is included. The status field provides additional information regarding the order's state as a result of the placement. Possible values include: - -#### Status - -| Status | Description | -| --------- | ------------------------------------------------------------ | -| matched | order placed and matched with an existing resting order | -| live | order placed and resting on the book | -| delayed | order marketable, but subject to matching delay | -| unmatched | order marketable, but failure delaying, placement successful | - - ```python Python theme={null} - from py_clob_client.client import ClobClient - from py_clob_client.clob_types import OrderArgs, OrderType, PostOrdersArgs + from py_clob_client.clob_types import OrderArgs, OrderType from py_clob_client.order_builder.constants import BUY + response = client.create_and_post_order( + OrderArgs( + token_id="TOKEN_ID", + price=0.50, + size=10, + side=BUY, + ), + options={ + "tick_size": "0.01", + "neg_risk": False, + }, + order_type=OrderType.GTC + ) - host: str = "https://clob.polymarket.com" - key: str = "" ##This is your Private Key. Export from https://reveal.magic.link/polymarket or from your Web3 Application - chain_id: int = 137 #No need to adjust this - POLYMARKET_PROXY_ADDRESS: str = '' #This is the address listed below your profile picture when using the Polymarket site. + print("Order ID:", response["orderID"]) + print("Status:", response["status"]) + ``` + - #Select from the following 3 initialization options to matches your login method, and remove any unused lines so only one client is initialized. +### Two-Step: Sign Then Submit +For more control, you can separate signing from submission. This is useful for batch orders or custom submission logic: - ### Initialization of a client using a Polymarket Proxy associated with an Email/Magic account. If you login with your email use this example. - client = ClobClient(host, key=key, chain_id=chain_id, signature_type=1, funder=POLYMARKET_PROXY_ADDRESS) + + ```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 }, + ); - ### Initialization of a client using a Polymarket Proxy associated with a Browser Wallet(Metamask, Coinbase Wallet, etc) - client = ClobClient(host, key=key, chain_id=chain_id, signature_type=2, funder=POLYMARKET_PROXY_ADDRESS) + // Step 2: Submit to the CLOB + const response = await client.postOrder(signedOrder, OrderType.GTC); + ``` - ### Initialization of a client that trades directly from an EOA. - client = ClobClient(host, key=key, chain_id=chain_id) + ```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={ + "tick_size": "0.01", + "neg_risk": False, + } + ) - ## Create and sign a limit order buying 100 YES tokens for 0.50c each - #Refer to the Markets API documentation to locate a tokenID: https://docs.polymarket.com/developers/gamma-markets-api/get-markets + # Step 2: Submit to the CLOB + response = client.post_order(signed_order, OrderType.GTC) + ``` + - client.set_api_creds(client.create_or_derive_api_creds()) +*** - resp = client.post_orders([ +## GTD Orders (Expiring) + +GTD orders auto-expire at a specified time. Useful for quoting around known events. + + + ```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={ + "tick_size": "0.01", + "neg_risk": False, + }, + order_type=OrderType.GTD + ) + ``` + + + + 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`. + + +*** + +## Market Orders + +Market orders execute immediately against resting liquidity using FOK or FAK types: + + + ```typescript TypeScript theme={null} + import { Side, OrderType } from "@polymarket/clob-client"; + + // 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.order_builder.constants import BUY, SELL + from py_clob_client.clob_types import OrderType + + # FOK BUY: spend exactly $100 or cancel entirely + buy_order = client.create_market_order( + token_id="TOKEN_ID", + side=BUY, + amount=100, # dollar amount + price=0.50, # worst-price limit (slippage protection) + options={"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( + token_id="TOKEN_ID", + side=SELL, + amount=200, # number of shares + price=0.45, # worst-price limit (slippage protection) + options={"tick_size": "0.01", "neg_risk": False}, + ) + client.post_order(sell_order, OrderType.FOK) + ``` + + +* **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: + + + ```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} + response = client.create_and_post_market_order( + token_id="TOKEN_ID", + side=BUY, + amount=100, + price=0.50, + options={"tick_size": "0.01", "neg_risk": False}, + order_type=OrderType.FOK, + ) + ``` + + +*** + +## 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. + + + ```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) + ``` + + +* 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: + + + ```typescript TypeScript theme={null} + import { OrderType, Side, PostOrdersArgs } from "@polymarket/clob-client"; + + 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.clob_types import OrderArgs, OrderType, PostOrdersArgs + from py_clob_client.order_builder.constants import BUY, SELL + + response = client.post_orders([ PostOrdersArgs( - # Create and sign a limit order buying 100 YES tokens for 0.50 each order=client.create_order(OrderArgs( - price=0.01, - size=5, + price=0.48, + size=500, side=BUY, - token_id="88613172803544318200496156596909968959424174365708473463931555296257475886634", - )), - orderType=OrderType.GTC, # Good 'Til Cancelled + token_id="TOKEN_ID", + ), options={"tick_size": "0.01", "neg_risk": False}), + orderType=OrderType.GTC, ), PostOrdersArgs( - # Create and sign a limit order selling 200 NO tokens for 0.25 each order=client.create_order(OrderArgs( - price=0.01, - size=5, - side=BUY, - token_id="93025177978745967226369398316375153283719303181694312089956059680730874301533", - )), - orderType=OrderType.GTC, # Good 'Til Cancelled - ) + price=0.52, + size=500, + side=SELL, + token_id="TOKEN_ID", + ), options={"tick_size": "0.01", "neg_risk": False}), + orderType=OrderType.GTC, + ), ]) - print(resp) - print("Done!") + ``` + + +*** + +## 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), 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 | + + + ```typescript TypeScript theme={null} + const tickSize = await client.getTickSize("TOKEN_ID"); ``` - ```javascript typescript theme={null} - import { ethers } from "ethers"; - import { config as dotenvConfig } from "dotenv"; - import { resolve } from "path"; - import { ApiKeyCreds, Chain, ClobClient, OrderType, PostOrdersArgs, Side } from "../src"; + ```python Python theme={null} + tick_size = client.get_tick_size("TOKEN_ID") + ``` + - dotenvConfig({ path: resolve(__dirname, "../.env") }); +### Negative Risk - async function main() { - const wallet = new ethers.Wallet(`${process.env.PK}`); - const chainId = parseInt(`${process.env.CHAIN_ID || Chain.AMOY}`) as Chain; - console.log(`Address: ${await wallet.getAddress()}, chainId: ${chainId}`); +Multi-outcome events (3+ outcomes) use the Neg Risk CTF Exchange. Pass `negRisk: true` for these markets. - const host = process.env.CLOB_API_URL || "https://clob.polymarket.com"; - const creds: ApiKeyCreds = { - key: `${process.env.CLOB_API_KEY}`, - secret: `${process.env.CLOB_SECRET}`, - passphrase: `${process.env.CLOB_PASS_PHRASE}`, - }; - const clobClient = new ClobClient(host, chainId, wallet, creds); - - await clobClient.cancelAll(); - - const YES = "71321045679252212594626385532706912750332728571942532289631379312455583992563"; - const orders: PostOrdersArgs[] = [ - { - order: await clobClient.createOrder({ - tokenID: YES, - price: 0.4, - side: Side.BUY, - size: 100, - }), - orderType: OrderType.GTC, - }, - { - order: await clobClient.createOrder({ - tokenID: YES, - price: 0.45, - side: Side.BUY, - size: 100, - }), - orderType: OrderType.GTC, - }, - { - order: await clobClient.createOrder({ - tokenID: YES, - price: 0.55, - side: Side.SELL, - size: 100, - }), - orderType: OrderType.GTC, - }, - { - order: await clobClient.createOrder({ - tokenID: YES, - price: 0.6, - side: Side.SELL, - size: 100, - }), - orderType: OrderType.GTC, - }, - ]; - - // Send it to the server - const resp = await clobClient.postOrders(orders); - console.log(resp); - } - - main(); + + ```typescript TypeScript theme={null} + const isNegRisk = await client.getNegRisk("TOKEN_ID"); ``` - ```REQUEST Example Payload theme={null} - [ - {'order': {'salt': 660377097, 'maker': '0x17A9568474b5fc84B1D1C44f081A0a3aDE750B2b', 'signer': '0x17A9568474b5fc84B1D1C44f081A0a3aDE750B2b', 'taker': '0x0000000000000000000000000000000000000000', 'tokenId': '88613172803544318200496156596909968959424174365708473463931555296257475886634', 'makerAmount': '50000', 'takerAmount': '5000000', 'expiration': '0', 'nonce': '0', 'feeRateBps': '0', 'side': 'BUY', 'signatureType': 0, 'signature': '0xccb8d1298d698ebc0859e6a26044c848ac4a4b0e20a391a4574e42b9c9bf237e5fa09fc00743e3e2d2f8e909a21d60f276ce083cc35c6661410b892f5bcbe2291c'}, 'owner': 'PRIVATEKEY', 'orderType': 'GTC'}, - {'order': {'salt': 1207111323, 'maker': '0x17A9568474b5fc84B1D1C44f081A0a3aDE750B2b', 'signer': '0x17A9568474b5fc84B1D1C44f081A0a3aDE750B2b', 'taker': '0x0000000000000000000000000000000000000000', 'tokenId': '93025177978745967226369398316375153283719303181694312089956059680730874301533', 'makerAmount': '50000', 'takerAmount': '5000000', 'expiration': '0', 'nonce': '0', 'feeRateBps': '0', 'side': 'BUY', 'signatureType': 0, 'signature': '0x0feca28666283824c27d7bead0bc441dde6df20dd71ef5ff7c84d3d1d5bf8aa4296fa382769dc11a92abe05b6f731d6c32556e9b4fb29e6eb50131af23a9ac941c'}, 'owner': 'PRIVATEKEY', 'orderType': 'GTC'} - ] - + ```python Python theme={null} + is_neg_risk = client.get_neg_risk("TOKEN_ID") ``` - + + + + Both values are also available on the market object: `minimum_tick_size` and + `neg_risk`. + + +*** + +## Prerequisites + +Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens: + +* **BUY orders**: USDC.e 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}) +$$ + + + Orders are continuously monitored for validity — balances, allowances, and + onchain cancellations are tracked in real time. Any maker caught intentionally + abusing these checks will be blacklisted. + + +### Advanced Parameters + +These optional fields can be passed in the `UserOrder` object for fine-grained control: + +| Parameter | Type | Description | +| ------------ | ------ | ----------------------------------------------- | +| `feeRateBps` | number | Fee rate in basis points (default: market rate) | +| `nonce` | number | Custom nonce for order uniqueness | +| `taker` | string | Restrict the order to a specific taker address | + +### 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 **3-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 subject to a matching delay | +| `unmatched` | Marketable but failed to delay — placement still successful | + +### 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**. + + + ```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) + ``` + + +* 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 + + + + Cancel single, multiple, or all open orders + + + + Attribute orders to your builder account for volume credit + + diff --git a/docs/developers/CLOB/orders/create-order.md b/docs/developers/CLOB/orders/create-order.md index e723f47..20d80ad 100644 --- a/docs/developers/CLOB/orders/create-order.md +++ b/docs/developers/CLOB/orders/create-order.md @@ -2,263 +2,532 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Place Single Order +# Create Order -> Detailed instructions for creating, placing, and managing orders using Polymarket's CLOB API. +> Build, sign, and submit orders -# Create and Place an Order +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. - This endpoint requires a L2 Header + + 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. + -Create and place an order using the Polymarket CLOB API clients. All orders are represented as "limit" orders, but "market" orders are also supported. To place a market order, simply ensure your price is marketable against current resting limit orders, which are executed on input at the best price. +*** -**HTTP REQUEST** +## Order Types -`POST //order` +| 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 | -### Request Payload Parameters +* **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 -| Name | Required | Type | Description | -| --------- | -------- | ------- | -------------------------------------------------------------------------------------------- | -| order | yes | Order | signed object | -| owner | yes | string | api key of order owner | -| orderType | yes | string | order type ("FOK", "GTC", "GTD") | -| postOnly | no | boolean | if `true`, the order will only rest on the book and not match immediately (default: `false`) | +*** -### Post-only orders +## Limit Orders -* postOnly submits a limit order that will not match resting liquidity upon entry. -* If a postOnly order would cross the spread (i.e., it is marketable), it will be rejected rather than executed. -* postOnly cannot be combined with market order types (e.g., FOK or FAK). If `postOnly = true` is sent with a market order type, the order will be rejected. +The simplest way to place a limit order — create, sign, and submit in one call: -An `order` object is the form: + + ```typescript TypeScript theme={null} + import { ClobClient, Side, OrderType } from "@polymarket/clob-client"; -| Name | Required | Type | Description | -| ------------- | -------- | ------- | -------------------------------------------------- | -| salt | yes | integer | random salt used to create unique order | -| maker | yes | string | maker address (funder) | -| signer | yes | string | signing address | -| taker | yes | string | taker address (operator) | -| tokenId | yes | string | ERC1155 token ID of conditional token being traded | -| makerAmount | yes | string | maximum amount maker is willing to spend | -| takerAmount | yes | string | minimum amount taker will pay the maker in return | -| expiration | yes | string | unix expiration timestamp | -| nonce | yes | string | maker's exchange nonce of the order is associated | -| feeRateBps | yes | string | fee rate basis points as required by the operator | -| side | yes | string | buy or sell enum index | -| signatureType | yes | integer | signature type enum index | -| signature | yes | string | hex encoded signature | + const response = await client.createAndPostOrder( + { + tokenID: "TOKEN_ID", + price: 0.5, + size: 10, + side: Side.BUY, + }, + { + tickSize: "0.01", + negRisk: false, + }, + OrderType.GTC, + ); -### Order types + console.log("Order ID:", response.orderID); + console.log("Status:", response.status); + ``` -* **FOK**: A Fill-Or-Kill order is an market order to buy (in dollars) or sell (in shares) shares that must be executed immediately in its entirety; otherwise, the entire order will be cancelled. -* **FAK**: A Fill-And-Kill order is a market order to buy (in dollars) or sell (in shares) that will be executed immediately for as many shares as are available; any portion not filled at once is cancelled. -* **GTC**: A Good-Til-Cancelled order is a limit order that is active until it is fulfilled or cancelled. -* **GTD**: A Good-Til-Date order is a type of order that is active until its specified date (UTC seconds timestamp), unless it has already been fulfilled or cancelled. There is a security threshold of one minute. If the order needs to expire in 90 seconds the correct expiration value is: now + 1 minute + 30 seconds - -### Response Format - -| Name | Type | Description | -| ----------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------- | -| success | boolean | boolean indicating if server-side err (`success = false`) -> server-side error | -| errorMsg | string | error message in case of unsuccessful placement (in case `success = false`, e.g. `client-side error`, the reason is in `errorMsg`) | -| orderId | string | id of order | -| orderHashes | string\[] | hash of settlement transaction order was marketable and triggered a match | - -### Insert Error Messages - -If the `errorMsg` field of the response object from placement is not an empty string, the order was not able to be immediately placed. This might be because of a delay or because of a failure. If the `success` is not `true`, then there was an issue placing the order. The following `errorMessages` are possible: - -#### Error - -| Error | Success | Message | Description | -| ------------------------------------ | ------- | --------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | -| INVALID\_ORDER\_MIN\_TICK\_SIZE | yes | order is invalid. Price breaks minimum tick size rules | order price isn't accurate to correct tick sizing | -| INVALID\_ORDER\_MIN\_SIZE | yes | order is invalid. Size lower than the minimum | order size must meet min size threshold requirement | -| INVALID\_ORDER\_DUPLICATED | yes | order is invalid. Duplicated. Same order has already been placed, can't be placed again | | -| INVALID\_ORDER\_NOT\_ENOUGH\_BALANCE | yes | not enough balance / allowance | funder address doesn't have sufficient balance or allowance for order | -| INVALID\_ORDER\_EXPIRATION | yes | invalid expiration | expiration field expresses a time before now | -| INVALID\_ORDER\_ERROR | yes | could not insert order | system error while inserting order | -| INVALID\_POST\_ONLY\_ORDER\_TYPE | yes | invalid post-only order: only GTC and GTD order types are allowed | post only flag attached to a market order | -| INVALID\_POST\_ONLY\_ORDER | yes | invalid post-only order: order crosses book | post only order would match | -| EXECUTION\_ERROR | yes | could not run the execution | system error while attempting to execute trade | -| ORDER\_DELAYED | no | order match delayed due to market conditions | order placement delayed | -| DELAYING\_ORDER\_ERROR | yes | error delaying the order | system error while delaying order | -| FOK\_ORDER\_NOT\_FILLED\_ERROR | yes | order couldn't be fully filled, FOK orders are fully filled/killed | FOK order not fully filled so can't be placed | -| MARKET\_NOT\_READY | no | the market is not yet ready to process new orders | system not accepting orders for market yet | - -### Insert Statuses - -When placing an order, a status field is included. The status field provides additional information regarding the order's state as a result of the placement. Possible values include: - -#### Status - -| Status | Description | -| --------- | ------------------------------------------------------------ | -| matched | order placed and matched with an existing resting order | -| live | order placed and resting on the book | -| delayed | order marketable, but subject to matching delay | -| unmatched | order marketable, but failure delaying, placement successful | - - ```python Python theme={null} - from py_clob_client.client import ClobClient from py_clob_client.clob_types import OrderArgs, OrderType from py_clob_client.order_builder.constants import BUY - host: str = "https://clob.polymarket.com" - key: str = "" #This is your Private Key. Export from reveal.polymarket.com or from your Web3 Application - chain_id: int = 137 #No need to adjust this - POLYMARKET_PROXY_ADDRESS: str = '' #This is the address you deposit/send USDC to to FUND your Polymarket account. - - #Select from the following 3 initialization options to matches your login method, and remove any unused lines so only one client is initialized. - - - ### Initialization of a client using a Polymarket Proxy associated with an Email/Magic account. If you login with your email use this example. - client = ClobClient(host, key=key, chain_id=chain_id, signature_type=1, funder=POLYMARKET_PROXY_ADDRESS) - - ### Initialization of a client using a Polymarket Proxy associated with a Browser Wallet(Metamask, Coinbase Wallet, etc) - client = ClobClient(host, key=key, chain_id=chain_id, signature_type=2, funder=POLYMARKET_PROXY_ADDRESS) - - ### Initialization of a client that trades directly from an EOA. - client = ClobClient(host, key=key, chain_id=chain_id) - - ## Create and sign a limit order buying 100 YES tokens for 0.50c each - #Refer to the Markets API documentation to locate a tokenID: https://docs.polymarket.com/developers/gamma-markets-api/get-markets - - client.set_api_creds(client.create_or_derive_api_creds()) - - order_args = OrderArgs( - price=0.01, - size=5.0, - side=BUY, - token_id="", #Token ID you want to purchase goes here. + response = client.create_and_post_order( + OrderArgs( + token_id="TOKEN_ID", + price=0.50, + size=10, + side=BUY, + ), + options={ + "tick_size": "0.01", + "neg_risk": False, + }, + order_type=OrderType.GTC ) - signed_order = client.create_order(order_args) - ## GTC(Good-Till-Cancelled) Order - resp = client.post_order(signed_order, OrderType.GTC) - print(resp) + print("Order ID:", response["orderID"]) + print("Status:", response["status"]) + ``` + + +### Two-Step: Sign Then Submit + +For more control, you can separate signing from submission. This is useful for batch orders or custom submission logic: + + + ```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); ``` - ```javascript typescript theme={null} - // GTC Order example - // - import { Side, OrderType } from "@polymarket/clob-client"; + ```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={ + "tick_size": "0.01", + "neg_risk": False, + } + ) - async function main() { - // Create a buy order for 100 YES for 0.50c - // YES: 71321045679252212594626385532706912750332728571942532289631379312455583992563 - const order = await clobClient.createOrder({ - tokenID: - "71321045679252212594626385532706912750332728571942532289631379312455583992563", + # Step 2: Submit to the CLOB + response = client.post_order(signed_order, OrderType.GTC) + ``` + + +*** + +## GTD Orders (Expiring) + +GTD orders auto-expire at a specified time. Useful for quoting around known events. + + + ```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, - size: 100, - feeRateBps: 0, - nonce: 1, - }); - console.log("Created Order", order); + expiration, + }, + { tickSize: "0.01", negRisk: false }, + OrderType.GTD, + ); + ``` - // Send it to the server + ```python Python theme={null} + import time - // GTC Order - const resp = await clobClient.postOrder(order, OrderType.GTC); - console.log(resp); - } + # Expire in 1 hour (+ 60s security threshold buffer) + expiration = int(time.time()) + 60 + 3600 - main(); - // GTD Order example - // + response = client.create_and_post_order( + OrderArgs( + token_id="TOKEN_ID", + price=0.50, + size=10, + side=BUY, + expiration=expiration, + ), + options={ + "tick_size": "0.01", + "neg_risk": False, + }, + order_type=OrderType.GTD + ) + ``` + + + + 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`. + + +*** + +## Market Orders + +Market orders execute immediately against resting liquidity using FOK or FAK types: + + + ```typescript TypeScript theme={null} import { Side, OrderType } from "@polymarket/clob-client"; - async function main() { - // Create a buy order for 100 YES for 0.50c that expires in 1 minute - // YES: 71321045679252212594626385532706912750332728571942532289631379312455583992563 - - // There is a 1 minute of security threshold for the expiration field. - // If we need the order to expire in 30 seconds the correct expiration value is: - // now + 1 miute + 30 seconds - const oneMinute = 60 * 1000; - const seconds = 30 * 1000; - const expiration = parseInt( - ((new Date().getTime() + oneMinute + seconds) / 1000).toString() - ); - - const order = await clobClient.createOrder({ - tokenID: - "71321045679252212594626385532706912750332728571942532289631379312455583992563", - price: 0.5, + // FOK BUY: spend exactly $100 or cancel entirely + const buyOrder = await client.createMarketOrder( + { + tokenID: "TOKEN_ID", side: Side.BUY, - size: 100, - feeRateBps: 0, - nonce: 1, - // There is a 1 minute of security threshold for the expiration field. - // If we need the order to expire in 30 seconds the correct expiration value is: - // now + 1 miute + 30 seconds - expiration: expiration, - }); - console.log("Created Order", order); + amount: 100, // dollar amount + price: 0.5, // worst-price limit (slippage protection) + }, + { tickSize: "0.01", negRisk: false }, + ); + await client.postOrder(buyOrder, OrderType.FOK); - // Send it to the server - - // GTD Order - const resp = await clobClient.postOrder(order, OrderType.GTD); - console.log(resp); - } - - main(); - // FOK BUY Order example - // - import { Side, OrderType } from "@polymarket/clob-client"; - - async function main() { - // Create a market buy order for $100 - // YES: 71321045679252212594626385532706912750332728571942532289631379312455583992563 - - const marketOrder = await clobClient.createMarketOrder({ - side: Side.BUY, - tokenID: - "71321045679252212594626385532706912750332728571942532289631379312455583992563", - amount: 100, // $$$ - feeRateBps: 0, - nonce: 0, - price: 0.5, - }); - console.log("Created Order", order); - - // Send it to the server - // FOK Order - const resp = await clobClient.postOrder(order, OrderType.FOK); - console.log(resp); - } - - main(); - // FOK SELL Order example - // - import { Side, OrderType } from "@polymarket/clob-client"; - - async function main() { - // Create a market sell order for 100 shares - // YES: 71321045679252212594626385532706912750332728571942532289631379312455583992563 - - const marketOrder = await clobClient.createMarketOrder({ + // FOK SELL: sell exactly 200 shares or cancel entirely + const sellOrder = await client.createMarketOrder( + { + tokenID: "TOKEN_ID", side: Side.SELL, - tokenID: - "71321045679252212594626385532706912750332728571942532289631379312455583992563", - amount: 100, // shares - feeRateBps: 0, - nonce: 0, - price: 0.5, - }); - console.log("Created Order", order); - - // Send it to the server - // FOK Order - const resp = await clobClient.postOrder(order, OrderType.FOK); - console.log(resp); - } - - main(); + 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.order_builder.constants import BUY, SELL + from py_clob_client.clob_types import OrderType + + # FOK BUY: spend exactly $100 or cancel entirely + buy_order = client.create_market_order( + token_id="TOKEN_ID", + side=BUY, + amount=100, # dollar amount + price=0.50, # worst-price limit (slippage protection) + options={"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( + token_id="TOKEN_ID", + side=SELL, + amount=200, # number of shares + price=0.45, # worst-price limit (slippage protection) + options={"tick_size": "0.01", "neg_risk": False}, + ) + client.post_order(sell_order, OrderType.FOK) + ``` + + +* **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: + + + ```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} + response = client.create_and_post_market_order( + token_id="TOKEN_ID", + side=BUY, + amount=100, + price=0.50, + options={"tick_size": "0.01", "neg_risk": False}, + order_type=OrderType.FOK, + ) + ``` + + +*** + +## 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. + + + ```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) + ``` + + +* 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: + + + ```typescript TypeScript theme={null} + import { OrderType, Side, PostOrdersArgs } from "@polymarket/clob-client"; + + 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.clob_types import OrderArgs, OrderType, PostOrdersArgs + from py_clob_client.order_builder.constants import BUY, SELL + + response = client.post_orders([ + PostOrdersArgs( + order=client.create_order(OrderArgs( + price=0.48, + size=500, + side=BUY, + token_id="TOKEN_ID", + ), options={"tick_size": "0.01", "neg_risk": False}), + orderType=OrderType.GTC, + ), + PostOrdersArgs( + order=client.create_order(OrderArgs( + price=0.52, + size=500, + side=SELL, + token_id="TOKEN_ID", + ), options={"tick_size": "0.01", "neg_risk": False}), + orderType=OrderType.GTC, + ), + ]) + ``` + + +*** + +## 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), 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 | + + + ```typescript TypeScript theme={null} + const tickSize = await client.getTickSize("TOKEN_ID"); + ``` + + ```python Python theme={null} + tick_size = client.get_tick_size("TOKEN_ID") + ``` + + +### Negative Risk + +Multi-outcome events (3+ outcomes) use the Neg Risk CTF Exchange. Pass `negRisk: true` for these markets. + + + ```typescript TypeScript theme={null} + const isNegRisk = await client.getNegRisk("TOKEN_ID"); + ``` + + ```python Python theme={null} + is_neg_risk = client.get_neg_risk("TOKEN_ID") + ``` + + + + Both values are also available on the market object: `minimum_tick_size` and + `neg_risk`. + + +*** + +## Prerequisites + +Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens: + +* **BUY orders**: USDC.e 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}) +$$ + + + Orders are continuously monitored for validity — balances, allowances, and + onchain cancellations are tracked in real time. Any maker caught intentionally + abusing these checks will be blacklisted. + + +### Advanced Parameters + +These optional fields can be passed in the `UserOrder` object for fine-grained control: + +| Parameter | Type | Description | +| ------------ | ------ | ----------------------------------------------- | +| `feeRateBps` | number | Fee rate in basis points (default: market rate) | +| `nonce` | number | Custom nonce for order uniqueness | +| `taker` | string | Restrict the order to a specific taker address | + +### 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 **3-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 subject to a matching delay | +| `unmatched` | Marketable but failed to delay — placement still successful | + +### 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**. + + + ```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) + ``` + + +* 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 + + + + Cancel single, multiple, or all open orders + + + + Attribute orders to your builder account for volume credit + + diff --git a/docs/developers/CLOB/orders/get-active-order.md b/docs/developers/CLOB/orders/get-active-order.md index f62c320..19a87c4 100644 --- a/docs/developers/CLOB/orders/get-active-order.md +++ b/docs/developers/CLOB/orders/get-active-order.md @@ -2,52 +2,462 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Get Active Orders +# Overview - This endpoint requires a L2 Header. +> Order types, tick sizes, and querying orders -Get active order(s) for a specific market. +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. -**HTTP REQUEST** +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) or [Python](https://github.com/Polymarket/py-clob-client) SDK clients, which handle signing and submission for you. -`GET //data/orders` + + 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. + -### Request Parameters +*** -| Name | Required | Type | Description | -| --------- | -------- | ------ | ------------------------------------ | -| id | no | string | id of order to get information about | -| market | no | string | condition id of market | -| asset\_id | no | string | id of the asset/token | +## Order Types -### Response Format +| 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 | -| Name | Type | Description | -| ---- | ------------ | ---------------------------------------------------- | -| null | OpenOrder\[] | list of open orders filtered by the query parameters | +* **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. + + + **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`. + + +### 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: + + + ```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" + ``` + + + + You can also check the `minimum_tick_size` field on a market object returned + by the [Markets API](/market-data/fetching-markets). + + +*** + +## 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. + + + ```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} + response = client.create_and_post_order( + OrderArgs( + token_id="TOKEN_ID", + price=0.50, + size=10, + side=BUY, + ), + options={ + "tick_size": "0.01", + "neg_risk": True, # Required for multi-outcome markets + } + ) + ``` + + +You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field: + + + ```typescript TypeScript theme={null} + const isNegRisk = await client.getNegRisk(tokenID); + ``` + + ```python Python theme={null} + is_neg_risk = client.get_neg_risk(token_id) + ``` + + +*** + +## 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 **USDC.e** 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 +* Onchain order cancellations + + + Any maker caught intentionally abusing these checks will be blacklisted. + + +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 USDC.e 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). + +### Get a Single Order + +Retrieve details for a specific order by its ID: + + + ```typescript TypeScript theme={null} + const order = await client.getOrder("0xb816482a..."); + console.log(order); + ``` + + ```python Python theme={null} + order = client.get_order("0xb816482a...") + print(order) + ``` + + +### Get Open Orders + +Retrieve your open orders, optionally filtered by market or asset: + + + ```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.clob_types import OpenOrderParams - resp = client.get_orders( + # All open orders + orders = client.get_orders() + + # Filtered by market + market_orders = client.get_orders( OpenOrderParams( - market="0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af", + market="0xbd31dc8a...", ) ) - print(resp) - print("Done!") + ``` + + +### 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: + + + ```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...", + }); ``` - ```javascript Typescript theme={null} - async function main() { - const resp = await clobClient.getOpenOrders({ - market: - "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af", - }); - console.log(resp); - console.log(`Done!`); - } - main(); + ```python Python theme={null} + from py_clob_client.clob_types import TradeParams + + # All trades + trades = client.get_trades() + + # Filtered by market + market_trades = client.get_trades( + TradeParams( + market="0xbd31dc8a...", + ) + ) ``` - + + +*** + +## 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**. + + + ```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) + ``` + + +* 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: + + + ```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.clob_types 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..."]) + ) + ``` + + +*** + +## 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 USDC.e for outcome tokens) | +| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving USDC.e 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. Users can cancel orders onchain independently if trust issues arise. + +*** + +## Next Steps + + + + Build, sign, and submit orders + + + + Cancel single, multiple, or all orders + + diff --git a/docs/developers/CLOB/orders/get-order.md b/docs/developers/CLOB/orders/get-order.md index 39662de..19a87c4 100644 --- a/docs/developers/CLOB/orders/get-order.md +++ b/docs/developers/CLOB/orders/get-order.md @@ -2,65 +2,462 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Get Order +# Overview -> Get information about an existing order +> Order types, tick sizes, and querying orders -This endpoint requires a L2 Header. +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. -Get single order by id. +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) or [Python](https://github.com/Polymarket/py-clob-client) SDK clients, which handle signing and submission for you. -**HTTP REQUEST** + + 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. + -`GET //data/order/` +*** -### Request Parameters +## Order Types -| Name | Required | Type | Description | -| ---- | -------- | ------ | ------------------------------------ | -| id | no | string | id of order to get information about | +| 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 | -### Response Format +* **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. -| Name | Type | Description | -| ----- | --------- | ------------------ | -| order | OpenOrder | order if it exists | + + **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`. + -An `OpenOrder` object is of the form: +### Post-Only Orders -| Name | Type | Description | -| ----------------- | --------- | -------------------------------------------------------------- | -| associate\_trades | string\[] | any Trade id the order has been partially included in | -| id | string | order id | -| status | string | order current status | -| market | string | market id (condition id) | -| original\_size | string | original order size at placement | -| outcome | string | human readable outcome the order is for | -| maker\_address | string | maker address (funder) | -| owner | string | api key | -| price | string | price | -| side | string | buy or sell | -| size\_matched | string | size of order that has been matched/filled | -| asset\_id | string | token id | -| expiration | string | unix timestamp when the order expired, 0 if it does not expire | -| type | string | order type (GTC, FOK, GTD) | -| created\_at | string | unix timestamp when the order was created | +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: + + + ```typescript TypeScript theme={null} + const tickSize = await client.getTickSize(tokenID); + // Returns: "0.1" | "0.01" | "0.001" | "0.0001" + ``` - ```python Python theme={null} - order = clob_client.get_order("0xb816482a5187a3d3db49cbaf6fe3ddf24f53e6c712b5a4bf5e01d0ec7b11dabc") + tick_size = client.get_tick_size(token_id) + # Returns: "0.1" | "0.01" | "0.001" | "0.0001" + ``` + + + + You can also check the `minimum_tick_size` field on a market object returned + by the [Markets API](/market-data/fetching-markets). + + +*** + +## 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. + + + ```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} + response = client.create_and_post_order( + OrderArgs( + token_id="TOKEN_ID", + price=0.50, + size=10, + side=BUY, + ), + options={ + "tick_size": "0.01", + "neg_risk": True, # Required for multi-outcome markets + } + ) + ``` + + +You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field: + + + ```typescript TypeScript theme={null} + const isNegRisk = await client.getNegRisk(tokenID); + ``` + + ```python Python theme={null} + is_neg_risk = client.get_neg_risk(token_id) + ``` + + +*** + +## 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 **USDC.e** 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 +* Onchain order cancellations + + + Any maker caught intentionally abusing these checks will be blacklisted. + + +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 USDC.e 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). + +### Get a Single Order + +Retrieve details for a specific order by its ID: + + + ```typescript TypeScript theme={null} + const order = await client.getOrder("0xb816482a..."); + console.log(order); + ``` + + ```python Python theme={null} + order = client.get_order("0xb816482a...") print(order) ``` + - ```javascript Typescript theme={null} - async function main() { - const order = await clobClient.getOrder( - "0xb816482a5187a3d3db49cbaf6fe3ddf24f53e6c712b5a4bf5e01d0ec7b11dabc" - ); - console.log(order); - } +### Get Open Orders - main(); +Retrieve your open orders, optionally filtered by market or asset: + + ```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.clob_types import OpenOrderParams + + # All open orders + orders = client.get_orders() + + # Filtered by market + market_orders = client.get_orders( + OpenOrderParams( + market="0xbd31dc8a...", + ) + ) + ``` + + +### 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: + + + ```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.clob_types import TradeParams + + # All trades + trades = client.get_trades() + + # Filtered by market + market_trades = client.get_trades( + TradeParams( + market="0xbd31dc8a...", + ) + ) + ``` + + +*** + +## 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**. + + + ```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) + ``` + + +* 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: + + + ```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.clob_types 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..."]) + ) + ``` + + +*** + +## 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 USDC.e for outcome tokens) | +| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving USDC.e 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. Users can cancel orders onchain independently if trust issues arise. + +*** + +## Next Steps + + + + Build, sign, and submit orders + + + + Cancel single, multiple, or all orders + + diff --git a/docs/developers/CLOB/orders/onchain-order-info.md b/docs/developers/CLOB/orders/onchain-order-info.md index aea129d..19a87c4 100644 --- a/docs/developers/CLOB/orders/onchain-order-info.md +++ b/docs/developers/CLOB/orders/onchain-order-info.md @@ -2,17 +2,462 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Onchain Order Info +# Overview -## How do I interpret the OrderFilled onchain event? +> Order types, tick sizes, and querying orders -Given an OrderFilled event: +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. -* `orderHash`: a unique hash for the Order being filled -* `maker`: the user generating the order and the source of funds for the order -* `taker`: the user filling the order OR the Exchange contract if the order fills multiple limit orders -* `makerAssetId`: id of the asset that is given out. If 0, indicates that the Order is a BUY, giving USDC in exchange for Outcome tokens. Else, indicates that the Order is a SELL, giving Outcome tokens in exchange for USDC. -* `takerAssetId`: id of the asset that is received. If 0, indicates that the Order is a SELL, receiving USDC in exchange for Outcome tokens. Else, indicates that the Order is a BUY, receiving Outcome tokens in exchange for USDC. -* `makerAmountFilled`: the amount of the asset that is given out. -* `takerAmountFilled`: the amount of the asset that is received. -* `fee`: the fees paid by the order maker +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) or [Python](https://github.com/Polymarket/py-clob-client) SDK clients, which handle signing and submission for you. + + + 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. + + +*** + +## 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. + + + **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`. + + +### 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: + + + ```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" + ``` + + + + You can also check the `minimum_tick_size` field on a market object returned + by the [Markets API](/market-data/fetching-markets). + + +*** + +## 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. + + + ```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} + response = client.create_and_post_order( + OrderArgs( + token_id="TOKEN_ID", + price=0.50, + size=10, + side=BUY, + ), + options={ + "tick_size": "0.01", + "neg_risk": True, # Required for multi-outcome markets + } + ) + ``` + + +You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field: + + + ```typescript TypeScript theme={null} + const isNegRisk = await client.getNegRisk(tokenID); + ``` + + ```python Python theme={null} + is_neg_risk = client.get_neg_risk(token_id) + ``` + + +*** + +## 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 **USDC.e** 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 +* Onchain order cancellations + + + Any maker caught intentionally abusing these checks will be blacklisted. + + +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 USDC.e 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). + +### Get a Single Order + +Retrieve details for a specific order by its ID: + + + ```typescript TypeScript theme={null} + const order = await client.getOrder("0xb816482a..."); + console.log(order); + ``` + + ```python Python theme={null} + order = client.get_order("0xb816482a...") + print(order) + ``` + + +### Get Open Orders + +Retrieve your open orders, optionally filtered by market or asset: + + + ```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.clob_types import OpenOrderParams + + # All open orders + orders = client.get_orders() + + # Filtered by market + market_orders = client.get_orders( + OpenOrderParams( + market="0xbd31dc8a...", + ) + ) + ``` + + +### 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: + + + ```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.clob_types import TradeParams + + # All trades + trades = client.get_trades() + + # Filtered by market + market_trades = client.get_trades( + TradeParams( + market="0xbd31dc8a...", + ) + ) + ``` + + +*** + +## 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**. + + + ```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) + ``` + + +* 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: + + + ```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.clob_types 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..."]) + ) + ``` + + +*** + +## 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 USDC.e for outcome tokens) | +| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving USDC.e 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. Users can cancel orders onchain independently if trust issues arise. + +*** + +## Next Steps + + + + Build, sign, and submit orders + + + + Cancel single, multiple, or all orders + + diff --git a/docs/developers/CLOB/orders/orders.md b/docs/developers/CLOB/orders/orders.md index ed8df37..19a87c4 100644 --- a/docs/developers/CLOB/orders/orders.md +++ b/docs/developers/CLOB/orders/orders.md @@ -2,32 +2,462 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Orders Overview +# Overview -> Detailed instructions for creating, placing, and managing orders using Polymarket's CLOB API. +> Order types, tick sizes, and querying orders -All orders are expressed as limit orders (can be marketable). The underlying order primitive must be in the form expected and executable by the on-chain binary limit order protocol contract. Preparing such an order is quite involved (structuring, hashing, signing), thus Polymarket suggests using the open source typescript, python and golang libraries. +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) or [Python](https://github.com/Polymarket/py-clob-client) SDK clients, which handle signing and submission for you. + + + 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. + + +*** + +## 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. + + + **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`. + + +### 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: + + + ```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" + ``` + + + + You can also check the `minimum_tick_size` field on a market object returned + by the [Markets API](/market-data/fetching-markets). + + +*** + +## 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. + + + ```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} + response = client.create_and_post_order( + OrderArgs( + token_id="TOKEN_ID", + price=0.50, + size=10, + side=BUY, + ), + options={ + "tick_size": "0.01", + "neg_risk": True, # Required for multi-outcome markets + } + ) + ``` + + +You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field: + + + ```typescript TypeScript theme={null} + const isNegRisk = await client.getNegRisk(tokenID); + ``` + + ```python Python theme={null} + is_neg_risk = client.get_neg_risk(token_id) + ``` + + +*** ## Allowances -To place an order, allowances must be set by the funder address for the specified `maker` asset for the Exchange contract. When buying, this means the funder must have set a USDC allowance greater than or equal to the spending amount. When selling, the funder must have set an allowance for the conditional token that is greater than or equal to the selling amount. This allows the Exchange contract to execute settlement according to the signed order instructions created by a user and matched by the operator. +Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens: -## Signature Types +* **Buying**: the funder must have set a **USDC.e** 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. -Polymarket’s CLOB supports 3 signature types. Orders must identify what signature type they use. The available typescript and python clients abstract the complexity of signing and preparing orders with the following signature types by allowing a funder address and signer type to be specified on initialization. The supported signature types are: +This allows the Exchange contract to execute settlement according to your signed order instructions. -| Type | ID | Description | -| ------------------ | -- | ------------------------------------------------------------------------------------------ | -| EOA | 0 | EIP712 signature signed by an EOA | -| POLY\_PROXY | 1 | EIP712 signatures signed by a signer associated with funding Polymarket proxy wallet | -| POLY\_GNOSIS\_SAFE | 2 | EIP712 signatures signed by a signer associated with funding Polymarket gnosis safe wallet | +*** ## Validity Checks -Orders are continually monitored to make sure they remain valid. Specifically, this includes continually tracking underlying balances, allowances and on-chain order cancellations. Any maker that is caught intentionally abusing these checks (which are essentially real time) will be blacklisted. +Orders are continually monitored to make sure they remain valid. This includes tracking: -Additionally, there are rails on order placement in a market. Specifically, 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 USDC in your funding wallet, you can place one order to buy 1000 YES in marketA @ \$.50, then any additional buy orders to that market will be rejected since your entire balance is reserved for the first (and only) buy order. More explicitly the max size you can place for an order is: +* Underlying balances +* Allowances +* Onchain order cancellations + + + Any maker caught intentionally abusing these checks will be blacklisted. + + +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 USDC.e 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). + +### Get a Single Order + +Retrieve details for a specific order by its ID: + + + ```typescript TypeScript theme={null} + const order = await client.getOrder("0xb816482a..."); + console.log(order); + ``` + + ```python Python theme={null} + order = client.get_order("0xb816482a...") + print(order) + ``` + + +### Get Open Orders + +Retrieve your open orders, optionally filtered by market or asset: + + + ```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.clob_types import OpenOrderParams + + # All open orders + orders = client.get_orders() + + # Filtered by market + market_orders = client.get_orders( + OpenOrderParams( + market="0xbd31dc8a...", + ) + ) + ``` + + +### 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: + + + ```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.clob_types import TradeParams + + # All trades + trades = client.get_trades() + + # Filtered by market + market_trades = client.get_trades( + TradeParams( + market="0xbd31dc8a...", + ) + ) + ``` + + +*** + +## 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**. + + + ```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) + ``` + + +* 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: + + + ```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.clob_types 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..."]) + ) + ``` + + +*** + +## 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 USDC.e for outcome tokens) | +| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving USDC.e 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. Users can cancel orders onchain independently if trust issues arise. + +*** + +## Next Steps + + + + Build, sign, and submit orders + + + + Cancel single, multiple, or all orders + + diff --git a/docs/developers/CLOB/quickstart.md b/docs/developers/CLOB/quickstart.md index a790018..392c9ed 100644 --- a/docs/developers/CLOB/quickstart.md +++ b/docs/developers/CLOB/quickstart.md @@ -4,274 +4,211 @@ # Quickstart -> Initialize the CLOB and place your first order. +> Place your first order on Polymarket -## Installation +This guide walks you through placing an order on Polymarket end-to-end. - - ```bash TypeScript theme={null} - npm install @polymarket/clob-client ethers - ``` + + + + ```bash TypeScript theme={null} + npm install @polymarket/clob-client ethers@5 + ``` - ```bash Python theme={null} - pip install py-clob-client - ``` + ```bash Python theme={null} + pip install py-clob-client + ``` + + - ```bash Rust theme={null} - cargo add polymarket-client-sdk - ``` - + + Derive your API credentials and initialize the trading client. This example uses an EOA wallet (type `0`) — your wallet pays its own gas and acts as the funder: -*** + + ```typescript TypeScript theme={null} + import { ClobClient } from "@polymarket/clob-client"; + import { Wallet } from "ethers"; // v5.8.0 -## Quick Start + const HOST = "https://clob.polymarket.com"; + const CHAIN_ID = 137; // Polygon mainnet + const signer = new Wallet(process.env.PRIVATE_KEY); -### 1. Setup Client + // Derive API credentials + const tempClient = new ClobClient(HOST, CHAIN_ID, signer); + const apiCreds = await tempClient.createOrDeriveApiKey(); - - ```typescript TypeScript theme={null} - import { ClobClient } from "@polymarket/clob-client"; - import { Wallet } from "ethers"; // v5.8.0 + // Initialize trading client + const client = new ClobClient( + HOST, + CHAIN_ID, + signer, + apiCreds, + 0, // EOA + signer.address, + ); + ``` - const HOST = "https://clob.polymarket.com"; - const CHAIN_ID = 137; // Polygon mainnet - const signer = new Wallet(process.env.PRIVATE_KEY); + ```python Python theme={null} + from py_clob_client.client import ClobClient + import os - // Create or derive user API credentials - const tempClient = new ClobClient(HOST, CHAIN_ID, signer); - const apiCreds = await tempClient.createOrDeriveApiKey(); - - // See 'Signature Types' note below - const signatureType = 0; - - // Initialize trading client - const client = new ClobClient( - HOST, - CHAIN_ID, - signer, - apiCreds, - signatureType - ); - ``` - - ```python Python theme={null} - from py_clob_client.client import ClobClient - import os - - host = "https://clob.polymarket.com" - chain_id = 137 # Polygon mainnet - private_key = os.getenv("PRIVATE_KEY") - - # Create or derive user API credentials - temp_client = ClobClient(host, key=private_key, chain_id=chain_id) - api_creds = await temp_client.create_or_derive_api_key() - - # See 'Signature Types' note below - signature_type = 0 - - # Initialize trading client - client = ClobClient( - host, - key=private_key, - chain_id=chain_id, - creds=api_creds, - signature_type=signature_type - ) - ``` - - - - This quick start sets your EOA as the trading account. You'll need to fund this - wallet to trade and pay for gas on transactions. Gas-less transactions are only - available by deploying a proxy wallet and using Polymarket's Polygon relayer - infrastructure. - - - - | Wallet Type | ID | When to Use | - | ------------ | --- | ------------------------------------------------------ | - | EOA | `0` | Standard Ethereum wallet (MetaMask) | - | Custom Proxy | `1` | Specific to Magic Link users from Polymarket only | - | Gnosis Safe | `2` | Injected providers (Metamask, Rabby, embedded wallets) | - - -*** - -### 2. Place an Order - - - ```typescript TypeScript theme={null} - import { Side } from "@polymarket/clob-client"; - - // Place a limit order in one step - const response = await client.createAndPostOrder({ - tokenID: "YOUR_TOKEN_ID", // Get from Gamma API - price: 0.65, // Price per share - size: 10, // Number of shares - side: Side.BUY, // or SELL - }); - - console.log(`Order placed! ID: ${response.orderID}`); - ``` - - ```python Python theme={null} - from py_clob_client.clob_types import OrderArgs - from py_clob_client.order_builder.constants import BUY - - # Place a limit order in one step - response = await client.create_and_post_order( - OrderArgs( - token_id="YOUR_TOKEN_ID", # Get from Gamma API - price=0.65, # Price per share - size=10, # Number of shares - side=BUY, # or SELL - ) - ) - - print(f"Order placed! ID: {response['orderID']}") - ``` - - -*** - -### 3. Check Your Orders - - - ```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`); - ``` - - ```python Python theme={null} - # View all open orders - open_orders = await client.get_open_orders() - print(f"You have {len(open_orders)} open orders") - - # View your trade history - trades = await client.get_trades() - print(f"You've made {len(trades)} trades") - ``` - - -*** - -## Complete Example - - - ```typescript TypeScript theme={null} - import { ClobClient, Side } from "@polymarket/clob-client"; - import { Wallet } from "ethers"; - - async function trade() { - const HOST = "https://clob.polymarket.com"; - const CHAIN_ID = 137; // Polygon mainnet - const signer = new Wallet(process.env.PRIVATE_KEY); - - const tempClient = new ClobClient(HOST, CHAIN_ID, signer); - const apiCreds = await tempClient.createOrDeriveApiKey(); - - const signatureType = 0; - - const client = new ClobClient( - HOST, - CHAIN_ID, - signer, - apiCreds, - signatureType - ); - - const response = await client.createAndPostOrder({ - tokenID: "YOUR_TOKEN_ID", - price: 0.65, - size: 10, - side: Side.BUY, - }); - - console.log(`Order placed! ID: ${response.orderID}`); - } - - trade(); - ``` - - ```python Python theme={null} - from py_clob_client.client import ClobClient - from py_clob_client.clob_types import OrderArgs - from py_clob_client.order_builder.constants import BUY - import asyncio - import os - - async def trade(): host = "https://clob.polymarket.com" - chain_id = 137 # Polygon mainnet + chain_id = 137 # Polygon mainnet private_key = os.getenv("PRIVATE_KEY") + # Derive API credentials temp_client = ClobClient(host, key=private_key, chain_id=chain_id) - creds = await temp_client.create_or_derive_api_key() - - signature_type=0 + api_creds = temp_client.create_or_derive_api_creds() + # Initialize trading client client = ClobClient( host, - chain_id=chain_id, key=private_key, - creds=creds, - signature_type=signature_type + chain_id=chain_id, + creds=api_creds, + signature_type=0, # EOA + funder="YOUR_WALLET_ADDRESS" ) + ``` + - response = await client.create_and_post_order( + + If you have a Polymarket.com account, your funds are in a proxy wallet — use + signature type `1` or `2` instead. See [Signature + Types](/trading/overview#signature-types) for details. + + + + Before trading, your funder address needs **USDC.e** (for buying outcome + tokens) and **POL** (for gas, if using EOA type `0`). Proxy wallet users + (types `1` and `2`) can use Polymarket's gasless relayer instead. + + + + + Get a token ID from the [Markets API](/market-data/fetching-markets), then create and submit your order: + + + ```typescript TypeScript theme={null} + import { Side, OrderType } from "@polymarket/clob-client"; + + 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.clob_types import OrderArgs, OrderType + from py_clob_client.order_builder.constants import BUY + + response = client.create_and_post_order( OrderArgs( token_id="YOUR_TOKEN_ID", - price=0.65, + price=0.50, size=10, - side=BUY - ) + side=BUY, + ), + options={ + "tick_size": "0.01", + "neg_risk": False, # Set to True for multi-outcome markets + }, + order_type=OrderType.GTC ) - print(f"Order placed! ID: {response['orderID']}") + print("Order ID:", response["orderID"]) + print("Status:", response["status"]) + ``` + - if __name__ == "__main__": - asyncio.run(trade()) - ``` - + + 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. + + + + + + ```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"]) + ``` + + + *** ## Troubleshooting - - You forgot to call `createOrDeriveApiKey()`. Make sure you initialize the client with API credentials: + + Wrong private key, signature type, or funder address for the derived API credentials. - ```typescript theme={null} - const creds = await clobClient.createOrDeriveApiKey(); - const client = new ClobClient(host, chainId, wallet, creds); - ``` + * Check that `signatureType` matches your account type (`0`, `1`, or `2`) + * Ensure `funder` is correct for your wallet type + * Re-derive credentials with `createOrDeriveApiKey()` if unsure - Ensure you have: + Your funder address doesn't have enough tokens: - * **USDC** in your funder address for BUY orders - * **Outcome tokens** in your funder address for SELL orders - - Check your balance at [polymarket.com/portfolio](https://polymarket.com/portfolio). + * **BUY orders**: need USDC.e in your funder address + * **SELL orders**: need outcome tokens in your funder address + * Ensure you have more USDC.e than what's committed in open orders - You need to approve the Exchange contract to spend your tokens. This is typically done through the Polymarket UI on your first trade. Or use the CTF contract's `setApprovalForAll()` method. + You need to approve the Exchange contract to spend your tokens. This is + typically done through the Polymarket UI on your first trade, or using the CTF + contract's `setApprovalForAll()` method. - Your funder address is the Polymarket proxy wallet where you deposit funds. Find it: + Your funder address is the wallet where your funds are held: - 1. Go to [polymarket.com/settings](https://polymarket.com/settings) - 2. Look for "Wallet Address" or "Profile Address" - 3. This is your `FUNDER_ADDRESS` + * **EOA (type 0)**: Your wallet address directly + * **Proxy wallet (type 1 or 2)**: Go to [polymarket.com/settings](https://polymarket.com/settings) and look for the wallet address in the profile dropdown + + If the proxy wallet doesn't exist, log into Polymarket.com first (it's deployed on first login). + + + + You're trying to place a trade from a restricted region. See [Geographic Restrictions](/api-reference/geoblock) for details. @@ -279,27 +216,12 @@ ## Next Steps - - - Complete Next.js examples demonstrating integration of embedded wallets - (Privy, Magic, Turnkey, wagmi) and the CLOB and Builder Relay clients - - - - - Deep dive into L1 and L2 authentication + + Order types, tick sizes, and error handling - - Explore the complete client reference - - - - Use Gamma API to discover markets - - - - Get real-time order updates + + Attribute orders to your builder account for volume credit diff --git a/docs/developers/CLOB/status.md b/docs/developers/CLOB/status.md index 6c5052f..bf9f2a9 100644 --- a/docs/developers/CLOB/status.md +++ b/docs/developers/CLOB/status.md @@ -1,9 +1,134 @@ -> ## 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 - Status

Polymarket - Status Page

Website - Operational

100% - uptime

CLOB API - Operational

100% - uptime

Markets API - Operational

100% - uptime

Polygon (RPC) - Operational

100% - uptime

User auth - Operational

100% - uptime

Sports API - Operational

100% - uptime

Recent notices

Show notice history
diff --git a/docs/developers/CLOB/timeseries.md b/docs/developers/CLOB/timeseries.md index b724c39..de671aa 100644 --- a/docs/developers/CLOB/timeseries.md +++ b/docs/developers/CLOB/timeseries.md @@ -2,153 +2,134 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Historical Timeseries Data +# Get prices history -> Fetches historical price data for a specified market token. +> Retrieve historical price data for a market. -The CLOB provides detailed price history for each traded token. - -**HTTP REQUEST** - -`GET //prices-history` - -We also have a Interactive Notebook to visualize the data from this endpoint available [here](https://colab.research.google.com/drive/1s4TCOR4K7fRP7EwAH1YmOactMakx24Cs?usp=sharing#scrollTo=mYCJBcfB9Zu4). - ## OpenAPI -````yaml GET /prices-history -openapi: 3.0.3 +````yaml api-spec/clob-openapi.yaml get /prices-history +openapi: 3.1.0 info: - title: CLOB (Central Limit Order Book) API - description: >- - API for interacting with the Central Limit Order Book system, providing - orderbook data, prices, midpoints, and spreads - version: 1.0.0 - contact: - name: CLOB API Team + 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 server + - url: https://clob.polymarket.com + description: Production CLOB API + - url: https://clob-staging.polymarket.com + description: Staging CLOB API security: [] tags: - - name: Orderbook - description: Order book related operations - - name: Pricing - description: Price and midpoint operations - - name: Spreads - description: Spread calculation operations + - 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 paths: /prices-history: get: tags: - - Pricing - summary: Get price history for a traded token - description: Fetches historical price data for a specified market token + - 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 - description: The CLOB token ID for which to fetch price history - example: '1234567890' - name: startTs in: query required: false + description: Filter by items after this unix timestamp. schema: type: number - description: The start time, a Unix timestamp in UTC - example: 1697875200 + format: double - name: endTs in: query required: false + description: Filter by items before this unix timestamp. schema: type: number - description: The end time, a Unix timestamp in UTC - example: 1697961600 + 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 - - max - description: >- - A string representing a duration ending at the current time. - Mutually exclusive with startTs and endTs - example: 1d - name: fidelity in: query required: false + description: Accuracy of the data expressed in minutes. Default is 1 minute. schema: - type: number - description: The resolution of the data, in minutes - example: 60 + type: integer responses: '200': - description: A list of timestamp/price pairs + description: Successful response with price history content: application/json: schema: - $ref: '#/components/schemas/PriceHistoryResponse' + $ref: '#/components/schemas/PricesHistoryResponse' '400': - description: Bad request + description: Bad Request - Missing or invalid query parameters content: application/json: schema: - $ref: '#/components/schemas/Error' - '404': - description: Market not found - content: - application/json: - schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ErrorResponse' '500': description: Internal server error content: application/json: schema: - $ref: '#/components/schemas/Error' + $ref: '#/components/schemas/ErrorResponse' + security: [] components: schemas: - PriceHistoryResponse: + PricesHistoryResponse: type: object - required: - - history properties: history: type: array items: - type: object - required: - - t - - p - properties: - t: - type: number - description: UTC timestamp - example: 1697875200 - p: - type: number - description: Price - example: 1800.75 - Error: + $ref: '#/components/schemas/MarketPrice' + ErrorResponse: type: object required: - error properties: error: type: string - description: Error message describing what went wrong - example: Invalid token id + description: Error message + MarketPrice: + type: object + properties: + t: + type: integer + format: uint32 + p: + type: number + format: float -```` \ No newline at end of file +```` diff --git a/docs/developers/CLOB/trades/trades-overview.md b/docs/developers/CLOB/trades/trades-overview.md index 87f0776..fa09274 100644 --- a/docs/developers/CLOB/trades/trades-overview.md +++ b/docs/developers/CLOB/trades/trades-overview.md @@ -2,18 +2,199 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Trades Overview +# Overview -## Overview +> Trading on the Polymarket CLOB -All historical trades can be fetched via the Polymarket CLOB REST API. A trade is initiated by a "taker" who creates a marketable limit order. This limit order can be matched against one or more resting limit orders on the associated book. A trade can be in various states as described below. Note: in some cases (due to gas limitations) the execution of a "trade" must be broken into multiple transactions which case separate trade entities will be returned. To associate trade entities, there is a bucket\_index field and a match\_time field. Trades that have been broken into multiple trade objects can be reconciled by combining trade objects with the same market\_order\_id, match\_time and incrementing bucket\_index's into a top level "trade" client side. +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 — users can always cancel orders onchain independently. -## Statuses +We recommend using the open-source SDK clients, which handle order signing, authentication, and submission: -| Status | Terminal? | Description | -| --------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| MATCHED | no | trade has been matched and sent to the executor service by the operator, the executor service submits the trade as a transaction to the Exchange contract | -| MINED | no | trade is 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 | + + +

+ npm install @polymarket/clob-client +

+
+ + +

pip install py-clob-client

+
+
+ + + You can also use the REST API directly, but you'll need to manage [EIP-712 + order + signing](https://github.com/Polymarket/clob-client/blob/main/src/signing/eip712.ts) + and [HMAC authentication + headers](https://github.com/Polymarket/clob-client/blob/main/src/signing/hmac.ts) + yourself. See [REST API Headers](#rest-api-headers) below. + + +*** + +## 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. + + + ```typescript TypeScript theme={null} + import { ClobClient } from "@polymarket/clob-client"; + import { Wallet } from "ethers"; // v5.8.0 + + const signer = new Wallet(process.env.PRIVATE_KEY); + + // Derive L2 API credentials + const tempClient = new ClobClient("https://clob.polymarket.com", 137, signer); + const apiCreds = await tempClient.createOrDeriveApiKey(); + ``` + + ```python Python theme={null} + from py_clob_client.client 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_creds() + ``` + + +*** + +## 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` | Polymarket account via Magic Link (email/Google login). Requires [exported private key](https://polymarket.com/settings) from Polymarket.com | Your proxy wallet address | +| **GNOSIS\_SAFE** | `2` | Polymarket account via browser wallet (MetaMask, Rabby) or embedded wallet (Privy, Turnkey). Most common type | Your proxy wallet address | + + + If you have a Polymarket.com account, your funds are in a proxy wallet visible + in the profile dropdown. Use type `1` or `2`. Type `0` is for standalone EOA + wallets only. + + +### Initialize the Trading Client + + + ```typescript TypeScript theme={null} + const client = new ClobClient( + "https://clob.polymarket.com", + 137, + signer, + apiCreds, + 2, // GNOSIS_SAFE + "0x...", // Your proxy wallet address + ); + ``` + + ```python Python theme={null} + client = ClobClient( + "https://clob.polymarket.com", + key=private_key, + chain_id=137, + creds=api_creds, + signature_type=2, # GNOSIS_SAFE + funder="0x..." # Your proxy wallet address + ) + ``` + + +*** + +## 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 | + + + 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. + + +*** + +## Client Methods + + + + Market data, orderbooks, prices, and spreads — no auth required. + + + + Sign orders and derive API credentials with your private key. + + + + Place orders, cancel orders, query trades, and manage notifications. + + + + Track attributed trades and manage builder credentials. + + + +*** + +## What's in This Section + + + + Place your first order end-to-end + + + + Reading the orderbook, prices, spreads, and midpoints + + + + Order types, tick sizes, creating, cancelling, and querying orders + + + + Fee structure, fee-enabled markets, and maker rebates + + + + Execute onchain operations without paying gas + + + + Split, merge, and redeem outcome tokens + + + + Deposit and withdraw funds across chains + + diff --git a/docs/developers/CLOB/trades/trades.md b/docs/developers/CLOB/trades/trades.md index d1a3251..fa09274 100644 --- a/docs/developers/CLOB/trades/trades.md +++ b/docs/developers/CLOB/trades/trades.md @@ -2,95 +2,199 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Get Trades +# Overview - This endpoint requires a L2 Header. +> Trading on the Polymarket CLOB -Get trades for the authenticated user based on the provided filters. +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 — users can always cancel orders onchain independently. -**HTTP REQUEST** +We recommend using the open-source SDK clients, which handle order signing, authentication, and submission: -`GET //data/trades` + + +

+ npm install @polymarket/clob-client +

+
-### Request Parameters + +

pip install py-clob-client

+
+
-| Name | Required | Type | Description | -| ------ | -------- | ------ | --------------------------------------------------------------------------------------------------- | -| id | no | string | id of trade to fetch | -| taker | no | string | address to get trades for where it is included as a taker | -| maker | no | string | address to get trades for where it is included as a maker | -| market | no | string | market for which to get the trades (condition ID) | -| before | no | string | unix timestamp representing the cutoff up to which trades that happened before then can be included | -| after | no | string | unix timestamp representing the cutoff for which trades that happened after can be included | + + You can also use the REST API directly, but you'll need to manage [EIP-712 + order + signing](https://github.com/Polymarket/clob-client/blob/main/src/signing/eip712.ts) + and [HMAC authentication + headers](https://github.com/Polymarket/clob-client/blob/main/src/signing/hmac.ts) + yourself. See [REST API Headers](#rest-api-headers) below. + -### Response Format +*** -| Name | Type | Description | -| ---- | -------- | ------------------------------------------- | -| null | Trade\[] | list of trades filtered by query parameters | +## Authentication -A `Trade` object is of the form: +The CLOB uses two levels of authentication: -| Name | Type | Description | -| ----------------- | ------------- | ---------------------------------------------------------------------------- | -| id | string | trade id | -| taker\_order\_id | string | hash of taker order (market order) that catalyzed the trade | -| market | string | market id (condition id) | -| asset\_id | string | asset id (token id) of taker order (market order) | -| side | string | buy or sell | -| size | string | size | -| fee\_rate\_bps | string | the fees paid for the taker order expressed in basic points | -| price | string | limit price of taker order | -| status | string | trade status (see above) | -| match\_time | string | time at which the trade was matched | -| last\_update | string | timestamp of last status update | -| outcome | string | human readable outcome of the trade | -| maker\_address | string | funder address of the taker of the trade | -| owner | string | api key of taker of the trade | -| transaction\_hash | string | hash of the transaction where the trade was executed | -| bucket\_index | integer | index of bucket for trade in case trade is executed in multiple transactions | -| maker\_orders | MakerOrder\[] | list of the maker trades the taker trade was filled against | -| type | string | side of the trade: TAKER or MAKER | +| 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 | -A `MakerOrder` object is of the form: +You use your private key once to derive **L2 credentials** (API key, secret, passphrase), which authenticate all subsequent trading requests. -| Name | Type | Description | -| --------------- | ------ | ----------------------------------------------------------- | -| order\_id | string | id of maker order | -| maker\_address | string | maker address of the order | -| owner | string | api key of the owner of the order | -| matched\_amount | string | size of maker order consumed with this trade | -| fee\_rate\_bps | string | the fees paid for the taker order expressed in basic points | -| price | string | price of maker order | -| asset\_id | string | token/asset id | -| outcome | string | human readable outcome of the maker order | -| side | string | the side of the maker order. Can be `buy` or `sell` | + + ```typescript TypeScript theme={null} + import { ClobClient } from "@polymarket/clob-client"; + import { Wallet } from "ethers"; // v5.8.0 + + const signer = new Wallet(process.env.PRIVATE_KEY); + + // Derive L2 API credentials + const tempClient = new ClobClient("https://clob.polymarket.com", 137, signer); + const apiCreds = await tempClient.createOrDeriveApiKey(); + ``` - ```python Python theme={null} - from py_clob_client.clob_types import TradeParams + from py_clob_client.client import ClobClient + import os - resp = client.get_trades( - TradeParams( - maker_address=client.get_address(), - market="0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af", - ), + 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_creds() + ``` + + +*** + +## 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` | Polymarket account via Magic Link (email/Google login). Requires [exported private key](https://polymarket.com/settings) from Polymarket.com | Your proxy wallet address | +| **GNOSIS\_SAFE** | `2` | Polymarket account via browser wallet (MetaMask, Rabby) or embedded wallet (Privy, Turnkey). Most common type | Your proxy wallet address | + + + If you have a Polymarket.com account, your funds are in a proxy wallet visible + in the profile dropdown. Use type `1` or `2`. Type `0` is for standalone EOA + wallets only. + + +### Initialize the Trading Client + + + ```typescript TypeScript theme={null} + const client = new ClobClient( + "https://clob.polymarket.com", + 137, + signer, + apiCreds, + 2, // GNOSIS_SAFE + "0x...", // Your proxy wallet address + ); + ``` + + ```python Python theme={null} + client = ClobClient( + "https://clob.polymarket.com", + key=private_key, + chain_id=137, + creds=api_creds, + signature_type=2, # GNOSIS_SAFE + funder="0x..." # Your proxy wallet address ) - print(resp) - print("Done!") ``` + - ```typescript Typescript theme={null} - async function main() { - const trades = await clobClient.getTrades({ - market: - "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af", - maker_address: await wallet.getAddress(), - }); - console.log(`trades: `); - console.log(trades); - } +*** - main(); - ``` - +## 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 | + + + 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. + + +*** + +## Client Methods + + + + Market data, orderbooks, prices, and spreads — no auth required. + + + + Sign orders and derive API credentials with your private key. + + + + Place orders, cancel orders, query trades, and manage notifications. + + + + Track attributed trades and manage builder credentials. + + + +*** + +## What's in This Section + + + + Place your first order end-to-end + + + + Reading the orderbook, prices, spreads, and midpoints + + + + Order types, tick sizes, creating, cancelling, and querying orders + + + + Fee structure, fee-enabled markets, and maker rebates + + + + Execute onchain operations without paying gas + + + + Split, merge, and redeem outcome tokens + + + + Deposit and withdraw funds across chains + + diff --git a/docs/developers/CLOB/websocket/market-channel.md b/docs/developers/CLOB/websocket/market-channel.md index 6d60766..65843f5 100644 --- a/docs/developers/CLOB/websocket/market-channel.md +++ b/docs/developers/CLOB/websocket/market-channel.md @@ -4,39 +4,37 @@ # Market Channel -Public channel for updates related to market updates (level 2 price data). +> Real-time orderbook, price, and trade data -**SUBSCRIBE** +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. -` market` +## Endpoint -## book Message +``` +wss://ws-subscriptions-clob.polymarket.com/ws/market +``` -Emitted When: +## Subscription -* First subscribed to a market -* When there is a trade that affects the book +```json theme={null} +{ + "assets_ids": ["", ""], + "type": "market", + "custom_feature_enabled": true +} +``` -### Structure +Set `custom_feature_enabled: true` to receive `best_bid_ask`, `new_market`, and `market_resolved` events. -| Name | Type | Description | -| ----------- | --------------- | --------------------------------------------------------------------------- | -| event\_type | string | "book" | -| asset\_id | string | asset ID (token ID) | -| market | string | condition ID of market | -| timestamp | string | unix timestamp the current book generation in milliseconds (1/1,000 second) | -| hash | string | hash summary of the orderbook content | -| buys | OrderSummary\[] | list of type (size, price) aggregate book levels for buys | -| sells | OrderSummary\[] | list of type (size, price) aggregate book levels for sells | +## Message Types -Where a `OrderSummary` object is of the form: +Each message includes an `event_type` field identifying the type. -| Name | Type | Description | -| ----- | ------ | ---------------------------------- | -| price | string | price of the orderbook level | -| size | string | size available at that price level | +### book -```json Response theme={null} +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", @@ -56,137 +54,79 @@ Where a `OrderSummary` object is of the form: } ``` -## price\_change Message +### price\_change -
- ⚠️ Breaking Change Notice: The price\_change message schema will be updated on September 15, 2025 at 11 PM UTC. Please see the [migration guide](/developers/CLOB/websocket/market-channel-migration-guide) for details. -
+Emitted when a new order is placed or an order is cancelled. -Emitted When: - -* A new order is placed -* An order is cancelled - -### Structure - -| Name | Type | Description | -| -------------- | -------------- | ------------------------------ | -| event\_type | string | "price\_change" | -| market | string | condition ID of market | -| price\_changes | PriceChange\[] | array of price change objects | -| timestamp | string | unix timestamp in milliseconds | - -Where a `PriceChange` object is of the form: - -| Name | Type | Description | -| --------- | ------ | ---------------------------------- | -| asset\_id | string | asset ID (token ID) | -| price | string | price level affected | -| size | string | new aggregate size for price level | -| side | string | "BUY" or "SELL" | -| hash | string | hash of the order | -| best\_bid | string | current best bid price | -| best\_ask | string | current best ask price | - -```json Response theme={null} +```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" + "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" } ``` -## tick\_size\_change Message +A `size` of `"0"` means the price level has been removed from the book. -Emitted When: +### tick\_size\_change -* The minimum tick size of the market changes. This happens when the book's price reaches the limits: price > 0.96 or price \< 0.04 +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. -### Structure - -| Name | Type | Description | -| --------------- | ------ | -------------------------- | -| event\_type | string | "price\_change" | -| asset\_id | string | asset ID (token ID) | -| market | string | condition ID of market | -| old\_tick\_size | string | previous minimum tick size | -| new\_tick\_size | string | current minimum tick size | -| side | string | buy/sell | -| timestamp | string | time of event | - -```json Response theme={null} +```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" + "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 Message +### last\_trade\_price -Emitted When: +Emitted when a maker and taker order is matched, creating a trade event. -* When a maker and taker order is matched creating a trade event. - -```json Response theme={null} +```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" + "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 Message +### best\_bid\_ask -Emitted When: +Requires `custom_feature_enabled: true`. -* The best bid and ask prices for a market change. +Emitted when the best bid or ask prices for a market change. -(This message is behind the `custom_feature_enabled` flag) - -### Structure - -| Name | Type | Description | -| ----------- | ------ | ------------------------------- | -| event\_type | string | "best\_bid\_ask" | -| market | string | condition ID of market | -| asset\_id | string | asset ID (token ID) | -| best\_bid | string | current best bid price | -| best\_ask | string | current best ask price | -| spread | string | spread between best bid and ask | -| timestamp | string | unix timestamp in milliseconds | - -### Example - -```json Response theme={null} +```json theme={null} { "event_type": "best_bid_ask", "market": "0x0005c0d312de0be897668695bae9f32b624b4a1ae8b140c49f08447fcc74f442", @@ -198,126 +138,64 @@ Emitted When: } ``` -## new\_market Message +### new\_market -Emitted When: +Requires `custom_feature_enabled: true`. -* A new market is created. +Emitted when a new market is created. -(This message is behind the `custom_feature_enabled` flag) - -### Structure - -| Name | Type | Description | -| -------------- | --------- | ------------------------------ | -| id | string | market ID | -| question | string | market question | -| market | string | condition ID of market | -| slug | string | market slug | -| description | string | market description | -| assets\_ids | string\[] | list of asset IDs | -| outcomes | string\[] | list of outcomes | -| event\_message | object | event message object | -| timestamp | string | unix timestamp in milliseconds | -| event\_type | string | "new\_market" | - -Where a `EventMessage` object is of the form: - -| Name | Type | Description | -| ----------- | ------ | ------------------------- | -| id | string | event message ID | -| ticker | string | event message ticker | -| slug | string | event message slug | -| title | string | event message title | -| description | string | event message description | - -### Example - -```json Response theme={null} +```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 for NVIDIA (NVDA) on the final trading day of January 2026 is higher than the listed price. Otherwise, this market will resolve to \"No\".\n\nIf the final trading day of the month is shortened (for example, due to a market-holiday schedule), the official closing price published for that shortened session will still be used for resolution.\n\nIf no official closing price is published for that session (for example, due to a trading halt into the close, system issue, or other disruption), the market will use the last valid on-exchange trade price of the regular session as the effective closing price.\n\nThe resolution source for this market is Yahoo Finance — specifically, the NVIDIA (NVDA) \"Close\" prices available at https://finance.yahoo.com/quote/NVDA/history, published under \"Historical Prices.\"\n\nIn the event of a stock split, reverse stock split, or similar corporate action affecting the listed company during the listed time frame, this market will resolve based on split-adjusted prices as displayed on Yahoo Finance.", - "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 for NVIDIA (NVDA) on the final trading day of January 2026 is higher than the listed price. Otherwise, this market will resolve to \"No\".\n\nIf the final trading day of the month is shortened (for example, due to a market-holiday schedule), the official closing price published for that shortened session will still be used for resolution.\n\nIf no official closing price is published for that session (for example, due to a trading halt into the close, system issue, or other disruption), the market will use the last valid on-exchange trade price of the regular session as the effective closing price.\n\nThe resolution source for this market is Yahoo Finance — specifically, the NVIDIA (NVDA) \"Close\" prices available at https://finance.yahoo.com/quote/NVDA/history, published under \"Historical Prices.\"\n\nIn the event of a stock split, reverse stock split, or similar corporate action affecting the listed company during the listed time frame, this market will resolve based on split-adjusted prices as displayed on Yahoo Finance." - }, - "timestamp": "1766790415550", - "event_type": "new_market" + "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" } ``` -## market\_resolved Message +### market\_resolved -Emitted When: +Requires `custom_feature_enabled: true`. -* A market is resolved. +Emitted when a market is resolved. -(This message is behind the `custom_feature_enabled` flag) - -### Structure - -| Name | Type | Description | -| ------------------ | --------- | ------------------------------ | -| id | string | market ID | -| question | string | market question | -| market | string | condition ID of market | -| slug | string | market slug | -| description | string | market description | -| assets\_ids | string\[] | list of asset IDs | -| outcomes | string\[] | list of outcomes | -| winning\_asset\_id | string | winning asset ID | -| winning\_outcome | string | winning outcome | -| event\_message | object | event message object | -| timestamp | string | unix timestamp in milliseconds | -| event\_type | string | "market\_resolved" | - -Where a `EventMessage` object is of the form: - -| Name | Type | Description | -| ----------- | ------ | ------------------------- | -| id | string | event message ID | -| ticker | string | event message ticker | -| slug | string | event message slug | -| title | string | event message title | -| description | string | event message description | - -### Example - -```json Response theme={null} +```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 for NVIDIA (NVDA) on the final trading day of January 2026 is higher than the listed price. Otherwise, this market will resolve to \"No\".\n\nIf the final trading day of the month is shortened (for example, due to a market-holiday schedule), the official closing price published for that shortened session will still be used for resolution.\n\nIf no official closing price is published for that session (for example, due to a trading halt into the close, system issue, or other disruption), the market will use the last valid on-exchange trade price of the regular session as the effective closing price.\n\nThe resolution source for this market is Yahoo Finance — specifically, the NVIDIA (NVDA) \"Close\" prices available at https://finance.yahoo.com/quote/NVDA/history, published under \"Historical Prices.\"\n\nIn the event of a stock split, reverse stock split, or similar corporate action affecting the listed company during the listed time frame, this market will resolve based on split-adjusted prices as displayed on Yahoo Finance.", - "assets_ids": [ - "76043073756653678226373981964075571318267289248134717369284518995922789326425", - "31690934263385727664202099278545688007799199447969475608906331829650099442770" - ], - "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 for NVIDIA (NVDA) on the final trading day of January 2026 is higher than the listed price. Otherwise, this market will resolve to \"No\".\n\nIf the final trading day of the month is shortened (for example, due to a market-holiday schedule), the official closing price published for that shortened session will still be used for resolution.\n\nIf no official closing price is published for that session (for example, due to a trading halt into the close, system issue, or other disruption), the market will use the last valid on-exchange trade price of the regular session as the effective closing price.\n\nThe resolution source for this market is Yahoo Finance — specifically, the NVIDIA (NVDA) \"Close\" prices available at https://finance.yahoo.com/quote/NVDA/history, published under \"Historical Prices.\"\n\nIn the event of a stock split, reverse stock split, or similar corporate action affecting the listed company during the listed time frame, this market will resolve based on split-adjusted prices as displayed on Yahoo Finance." - }, - "timestamp": "1766790415550", - "event_type": "new_market" + "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" } ``` diff --git a/docs/developers/CLOB/websocket/user-channel.md b/docs/developers/CLOB/websocket/user-channel.md index 3f3054d..f7eb507 100644 --- a/docs/developers/CLOB/websocket/user-channel.md +++ b/docs/developers/CLOB/websocket/user-channel.md @@ -4,54 +4,50 @@ # User Channel -Authenticated channel for updates related to user activities (orders, trades), filtered for authenticated user by apikey. +> Authenticated order and trade updates -**SUBSCRIBE** +Authenticated channel for updates related to your orders and trades, filtered by API key. -` user` +## Endpoint -## Trade Message +``` +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" +} +``` + + + Never expose your API credentials in client-side code. Use the user channel + only from server environments. + + +## Message Types + +Each message includes a `type` field identifying the event. + +### trade Emitted when: -* when a market order is matched ("MATCHED") -* when a limit order for the user is included in a trade ("MATCHED") -* subsequent status changes for trade ("MINED", "CONFIRMED", "RETRYING", "FAILED") +* 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`) -### Structure - -| Name | Type | Description | -| ---------------- | ------------- | ------------------------------------------- | -| asset\_id | string | asset id (token ID) of order (market order) | -| event\_type | string | "trade" | -| id | string | trade id | -| last\_update | string | time of last update to trade | -| maker\_orders | MakerOrder\[] | array of maker order details | -| market | string | market identifier (condition ID) | -| matchtime | string | time trade was matched | -| outcome | string | outcome | -| owner | string | api key of event owner | -| price | string | price | -| side | string | BUY/SELL | -| size | string | size | -| status | string | trade status | -| taker\_order\_id | string | id of taker order | -| timestamp | string | time of event | -| trade\_owner | string | api key of trade owner | -| type | string | "TRADE" | - -Where a `MakerOrder` object is of the form: - -| Name | Type | Description | -| --------------- | ------ | -------------------------------------- | -| asset\_id | string | asset of the maker order | -| matched\_amount | string | amount of maker order matched in trade | -| order\_id | string | maker order ID | -| outcome | string | outcome | -| owner | string | owner of maker order | -| price | string | price of maker order | - -```json Response theme={null} +```json theme={null} { "asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426", "event_type": "trade", @@ -82,34 +78,33 @@ Where a `MakerOrder` object is of the form: } ``` -## Order Message +#### 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: -* When an order is placed (PLACEMENT) -* When an order is updated (some of it is matched) (UPDATE) -* When an order is canceled (CANCELLATION) +* An order is placed (`PLACEMENT`) +* An order is updated — some of it is matched (`UPDATE`) +* An order is cancelled (`CANCELLATION`) -### Structure - -| Name | Type | Description | -| ----------------- | --------- | ------------------------------------------------------------------- | -| asset\_id | string | asset ID (token ID) of order | -| associate\_trades | string\[] | array of ids referencing trades that the order has been included in | -| event\_type | string | "order" | -| id | string | order id | -| market | string | condition ID of market | -| order\_owner | string | owner of order | -| original\_size | string | original order size | -| outcome | string | outcome | -| owner | string | owner of orders | -| price | string | price of order | -| side | string | BUY/SELL | -| size\_matched | string | size of order that has been matched | -| timestamp | string | time of event | -| type | string | PLACEMENT/UPDATE/CANCELLATION | - -```json Response theme={null} +```json theme={null} { "asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426", "associate_trades": null, diff --git a/docs/developers/CLOB/websocket/wss-auth.md b/docs/developers/CLOB/websocket/wss-auth.md index 3158469..e0ecfc1 100644 --- a/docs/developers/CLOB/websocket/wss-auth.md +++ b/docs/developers/CLOB/websocket/wss-auth.md @@ -2,12 +2,180 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# WSS Authentication +# Overview - Only connections to `user` channel require authentication. +> Real-time market data and trading updates via WebSocket -| Field | Optional | Description | -| ---------- | -------- | ------------------------------------- | -| apikey | yes | Polygon account's CLOB api key | -| secret | yes | Polygon account's CLOB api secret | -| passphrase | yes | Polygon account's CLOB api passphrase | +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" +} +``` + + + 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. + + +| Field | Type | Description | +| --------- | --------- | -------------------------------------------------- | +| `auth` | object | API credentials (`apiKey`, `secret`, `passphrase`) | +| `markets` | string\[] | Condition IDs to receive events for | +| `type` | string | Channel identifier | + + + 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). + + +### 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 & 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 +``` + + + If you don't respond to the server's ping within 10 seconds, the connection + will be closed. + + +## Troubleshooting + + + Send a valid subscription message immediately after connecting. The server may + close connections that don't subscribe within a timeout period. + + + + 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. + + + + 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 + + + + Verify your API credentials are correct and haven't expired. + diff --git a/docs/developers/CLOB/websocket/wss-overview.md b/docs/developers/CLOB/websocket/wss-overview.md index 39b34c8..e0ecfc1 100644 --- a/docs/developers/CLOB/websocket/wss-overview.md +++ b/docs/developers/CLOB/websocket/wss-overview.md @@ -2,35 +2,180 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# WSS Overview +# Overview -> Overview and general information about the Polymarket Websocket +> Real-time market data and trading updates via WebSocket -## Overview +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). -The Polymarket CLOB API provides websocket (wss) channels through which clients can get pushed updates. These endpoints allow clients to maintain almost real-time views of their orders, their trades and markets in general. There are two available channels `user` and `market`. +## Channels -## Subscription +| 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 | -To subscribe send a message including the following authentication and intent information upon opening the connection. +### Market Channel -| Field | Type | Description | -| ------------------------ | --------- | --------------------------------------------------------------------------- | -| auth | Auth | see next page for auth information | -| markets | string\[] | array of markets (condition IDs) to receive events for (for `user` channel) | -| assets\_ids | string\[] | array of asset ids (token IDs) to receive events for (for `market` channel) | -| type | string | id of channel to subscribe to (USER or MARKET) | -| custom\_feature\_enabled | bool | enabling / disabling custom features | +| 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 | -Where the `auth` field is of type `Auth` which has the form described in the WSS Authentication section below. +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" +} +``` + + + 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. + + +| Field | Type | Description | +| --------- | --------- | -------------------------------------------------- | +| `auth` | object | API credentials (`apiKey`, `secret`, `passphrase`) | +| `markets` | string\[] | Condition IDs to receive events for | +| `type` | string | Channel identifier | + + + 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). + + +### 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 -Once connected, the client can subscribe and unsubscribe to `asset_ids` by sending the following message: +```json theme={null} +{ + "assets_ids": ["new_asset_id_1", "new_asset_id_2"], + "operation": "subscribe", + "custom_feature_enabled": true +} +``` -| Field | Type | Description | -| ------------------------ | --------- | ------------------------------------------------------------------------------ | -| assets\_ids | string\[] | array of asset ids (token IDs) to receive events for (for `market` channel) | -| markets | string\[] | array of market ids (condition IDs) to receive events for (for `user` channel) | -| operation | string | "subscribe" or "unsubscribe" | -| custom\_feature\_enabled | bool | enabling / disabling custom features | +### 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 & 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 +``` + + + If you don't respond to the server's ping within 10 seconds, the connection + will be closed. + + +## Troubleshooting + + + Send a valid subscription message immediately after connecting. The server may + close connections that don't subscribe within a timeout period. + + + + 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. + + + + 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 + + + + Verify your API credentials are correct and haven't expired. + diff --git a/docs/developers/CTF/deployment-resources.md b/docs/developers/CTF/deployment-resources.md index 4ad1b01..6aebddc 100644 --- a/docs/developers/CTF/deployment-resources.md +++ b/docs/developers/CTF/deployment-resources.md @@ -2,27 +2,91 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Deployment and Additional Information +# Contract Addresses -## Deployment +> All Polymarket smart contract addresses on Polygon -The CTF contract is deployed (and verified) at the following addresses: +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. -| Network | Deployed Address | -| --------------- | ------------------------------------------------------------------------------------------------------------------------ | -| Polygon Mainnet | [0x4D97DCd97eC945f40cF65F87097ACe5EA0476045](https://polygonscan.com/address/0x4D97DCd97eC945f40cF65F87097ACe5EA0476045) | -| Polygon Mainnet | [0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E](https://polygonscan.com/address/0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E) | +*** -Polymarket provides code samples in both Python and TypeScript for interacting -with our smart chain contracts. You will need an RPC endpoint to access the -blockchain, and you'll be responsible for paying gas fees when executing these -RPC/function calls. Please ensure you're using the correct example for your wallet -type (Safe Wallet vs Proxy Wallet) when implementing. +## Core Trading Contracts -## Resources +| Contract | Address | Description | +| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | +| CTF Exchange | [`0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E`](https://polygonscan.com/address/0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E) | Standard market order matching and settlement | +| Neg Risk CTF Exchange | [`0xC5d563A36AE78145C45a50134d48A1215220f80a`](https://polygonscan.com/address/0xC5d563A36AE78145C45a50134d48A1215220f80a) | Order matching for [neg risk](/advanced/neg-risk) (multi-outcome) markets | +| Neg Risk Adapter | [`0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296`](https://polygonscan.com/address/0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296) | Converts No tokens between outcomes in neg risk markets | +| Conditional Tokens (CTF) | [`0x4D97DCd97eC945f40cF65F87097ACe5EA0476045`](https://polygonscan.com/address/0x4D97DCd97eC945f40cF65F87097ACe5EA0476045) | ERC1155 token storage — split, merge, and redeem operations | -* [On-Chain Code Samples](https://github.com/Polymarket/examples/tree/main/examples) -* [Polygon RPC List](https://chainlist.org/chain/137) -* [CTF Source Code](https://github.com/gnosis/conditional-tokens-contracts) -* [Audits](https://github.com/gnosis/conditional-tokens-contracts/tree/master/docs/audit) -* [Gist For positionId Calculation](https://gist.github.com/L-Kov/950bce141a9d1aa1ed3b1cfce6d30217) +*** + +## Token Contracts + +| Contract | Address | Description | +| --------------------- | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | +| USDC.e (Bridged USDC) | [`0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174`](https://polygonscan.com/address/0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174) | Collateral token used for all Polymarket trading (6 decimals) | + +*** + +## Wallet Factory Contracts + +| Contract | Address | Description | +| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- | --------------------- | +| Gnosis Safe Factory | [`0xaacfeea03eb1561c4e67d661e40682bd20e3541b`](https://polygonscan.com/address/0xaacfeea03eb1561c4e67d661e40682bd20e3541b) | Deploys Safe wallets | +| Polymarket Proxy Factory | [`0xaB45c5A4B0c941a2F231C04C3f49182e1A254052`](https://polygonscan.com/address/0xaB45c5A4B0c941a2F231C04C3f49182e1A254052) | Deploys proxy wallets | + +*** + +## Resolution Contracts + +| Contract | Address | Description | +| --------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | +| UMA Adapter | [`0x6A9D222616C90FcA5754cd1333cFD9b7fb6a4F74`](https://polygonscan.com/address/0x6A9D222616C90FcA5754cd1333cFD9b7fb6a4F74) | Adapter connecting Polymarket to the UMA Optimistic Oracle | +| UMA Optimistic Oracle | [`0xCB1822859cEF82Cd2Eb4E6276C7916e692995130`](https://polygonscan.com/address/0xCB1822859cEF82Cd2Eb4E6276C7916e692995130) | Handles market resolution proposals and disputes | + +*** + +## Liquidity + +| Contract | Address | Description | +| --------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | +| Uniswap v3 USDC.e/USDC Pool | [`0xd36ec33c8bed5a9f7b6630855f1533455b98a418`](https://polygonscan.com/address/0xd36ec33c8bed5a9f7b6630855f1533455b98a418) | Used for USDC.e ↔ USDC conversion during withdrawals | + +*** + +## Source Code + + + + Order matching and settlement contracts + + + + Gnosis Conditional Token Framework (ERC1155) + + + +*** + +## Usage in Code + + + ```typescript TypeScript theme={null} + const ADDRESSES = { + USDC_E: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", + CTF: "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045", + CTF_EXCHANGE: "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", + NEG_RISK_CTF_EXCHANGE: "0xC5d563A36AE78145C45a50134d48A1215220f80a", + }; + ``` + + ```python Python theme={null} + ADDRESSES = { + "USDC_E": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", + "CTF": "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045", + "CTF_EXCHANGE": "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", + "NEG_RISK_CTF_EXCHANGE": "0xC5d563A36AE78145C45a50134d48A1215220f80a", + } + ``` + diff --git a/docs/developers/CTF/merge.md b/docs/developers/CTF/merge.md index c732919..664a3f2 100644 --- a/docs/developers/CTF/merge.md +++ b/docs/developers/CTF/merge.md @@ -2,12 +2,62 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Merging Tokens +# Merge Tokens -In addition to splitting collateral for a full set, the inverse can also happen; a full set can be "merged" for collateral. This operation can again happen at any time after a condition has been prepared on the CTF contract. One unit of each position in a full set is burned in return for 1 collateral unit. This operation happens via the `mergePositions()` function on the CTF contract with the following parameters: +> Convert outcome token pairs back to USDC.e -* `collateralToken`: IERC20 - The address of the positions' backing collateral token. -* `parentCollectionId`: bytes32 - The ID of the outcome collections common to the position being merged and the merge target positions. Null in Polymarket case. -* `conditionId`: bytes32 - The ID of the condition to merge on. -* `partition`: uint\[] - An array of disjoint index sets representing a nontrivial partition of the outcome slots of the given condition. E.G. A|B and C but not A|B and B|C (is not disjoint). Each element's a number which, together with the condition, represents the outcome collection. E.G. 0b110 is A|B, 0b010 is B, etc. In the Polymarket case 1|2. -* `amount` - The number of full sets to merge. Also the amount of collateral to receive. +**Merging** is the inverse of splitting — it converts a full set of outcome tokens back into USDC.e collateral. For every 1 Yes token and 1 No token you merge, you receive \$1 USDC.e. The condition must already be prepared on the CTF contract (via `prepareCondition`). + +``` +100 Yes tokens + 100 No tokens → $100 USDC.e +``` + +## 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 + +## How It Works + +1. You call `mergePositions()` 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 CTF contract releases USDC.e back to your wallet + +The operation is atomic — if you don't have enough of both tokens, the transaction reverts. + +## Function Parameters + + + USDC.e (Bridged USDC) contract address: `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174` + + + + Always `0x0000...0000` (32 zero bytes) for Polymarket markets + + + + The market's condition ID, available from the Markets API + + + + Array of index sets: `[1, 2]` for binary markets + + + + The number of full sets to merge. Also the amount of collateral to receive. + + +## Next Steps + + + + Exchange winning tokens for USDC.e after resolution + + + + Learn more about the Conditional Token Framework + + diff --git a/docs/developers/CTF/overview.md b/docs/developers/CTF/overview.md index 6af9012..7d36bb2 100644 --- a/docs/developers/CTF/overview.md +++ b/docs/developers/CTF/overview.md @@ -2,33 +2,139 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Overview +# Conditional Token Framework -All outcomes on Polymarket are tokenized on the Polygon network. Specifically, Polymarket outcomes shares are binary outcomes (ie "YES" and "NO") using Gnosis' Conditional Token Framework (CTF). They are distinct ERC1155 tokens related to a parent condition and backed by the same collateral. More technically, the binary outcome tokens are referred to as "positionIds" in Gnosis's documentation. "PositionIds" are derived from a collateral token and distinct "collectionIds". "CollectionIds" are derived from a "parentCollectionId", (always bytes32(0) in our case) a "conditionId", and a unique "indexSet". +> Onchain token mechanics powering Polymarket positions -The "indexSet" is a 256 bit array denoting which outcome slots are in an outcome collection; it MUST be a nonempty proper subset of a condition's outcome slots. In the binary case, which we are interested in, there are two "indexSets", one for the first outcome and one for the second. The first outcome's "indexSet" is 0b01 = 1 and the second's is 0b10 = 2. The parent "conditionId" (shared by both "collectionIds" and therefore "positionIds") is derived from a "questionId" (a hash of the UMA ancillary data), an "oracle" (the UMA adapter V2), and an "outcomeSlotCount" (always 2 in the binary case). The steps for calculating the ERC1155 token ids (positionIds) is as follows: +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. -1. Get the conditionId - 1. Function: - 1. `getConditionId(oracle, questionId, outcomeSlotCount)` - 2. Inputs: - 1. `oracle`: address - UMA adapter V2 - 2. `questionId`: bytes32 - hash of the UMA ancillary data - 3. `outcomeSlotCount`: uint - 2 for binary markets +## What is CTF? -2. Get the two collectionIds - 1. Function: - 1. `getCollectionId(parentCollectionId, conditionId, indexSet)` - 2. Inputs: - 1. `parentCollectionId`: bytes32 - bytes32(0) - 2. `conditionId`: bytes32 - the conditionId derived from (1) - 3. `indexSet`: uint - 1 (0b01) for the first and 2 (0b10) for the second. +The Conditional Token Framework creates **ERC1155 tokens** representing outcomes of prediction markets. Each binary market has two tokens: -3. Get the two positionIds - 1. Function: - 1. `getPositionId(collateralToken, collectionId)` - 2. Inputs: - 1. `collateralToken`: IERC20 - address of ERC20 token collateral (USDC) - 2. `collectionId`: bytes32 - the two collectionIds derived from (3) +| Token | Redeems for | Condition | +| ------- | ------------- | -------------------- | +| **Yes** | \$1.00 USDC.e | Event occurs | +| **No** | \$1.00 USDC.e | Event does not occur | -Leveraging the relations above, specifically "conditionIds" -> "positionIds" the Gnosis CTF contract allows for "splitting" and "merging" full outcome sets. We explore these actions and provide code examples below. +These tokens are always **fully collateralized** — every Yes/No pair is backed by exactly \$1.00 USDC.e locked in the CTF contract. + +## Core Operations + +CTF provides three fundamental operations: + + + + Convert USDC.e into Yes + No token pairs + + + + Convert Yes + No pairs back to USDC.e + + + + Exchange winning tokens for USDC.e after resolution + + + +## Token Flow + + + + + + + +## 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` | USDC.e 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. + + + 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. + + +## 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 [Contract Addresses](/resources/contract-addresses) for all Polymarket smart contract addresses on Polygon. + +## Resources + + + + Gnosis Conditional Tokens smart contracts + + + + Python and TypeScript examples for onchain operations + + + +## Next Steps + + + + Create outcome token pairs from USDC.e + + + + Convert token pairs back to USDC.e + + + + Collect winnings after resolution + + diff --git a/docs/developers/CTF/redeem.md b/docs/developers/CTF/redeem.md index 0d0b919..40d0539 100644 --- a/docs/developers/CTF/redeem.md +++ b/docs/developers/CTF/redeem.md @@ -2,11 +2,93 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Reedeeming Tokens +# Redeem Tokens -Once a condition has had it's payouts reported (ie by the UMACTFAdapter calling `reportPayouts` on the CTF contract), users with shares in the winning outcome can redeem them for the underlying collateral. Specifically, users can call the `redeemPositions` function on the CTF contract which will burn all valuable conditional tokens in return for collateral according to the reported payout vector. This function has the following parameters: +> Exchange winning tokens for USDC.e after market resolution -* `collateralToken`: IERC20 - The address of the positions' backing collateral token. -* `parentCollectionId`: bytes32 - The ID of the outcome collections common to the position being redeemed. Null in Polymarket case. -* `indexSets`: uint\[] - The ID of the condition to redeem. -* `indexSets`: uint\[] - An array of disjoint index sets representing a nontrivial partition of the outcome slots of the given condition. E.G. A|B and C but not A|B and B|C (is not disjoint). Each element's a number which, together with the condition, represents the outcome collection. E.G. 0b110 is A|B, 0b010 is B, etc. In the Polymarket case 1|2. +**Redeeming** converts winning outcome tokens into USDC.e 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 USDC.e + 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 USDC.e each +* **Losing tokens** are worth \$0 and produce no payout + + + You can redeem at any time after resolution — there's no deadline. Your + winning tokens will always be redeemable. + + +## 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 + +## Function Parameters + + + USDC.e (Bridged USDC) contract address: `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174` + + + + Always `0x0000...0000` (32 zero bytes) for Polymarket markets + + + + The market's condition ID + + + + Array of index sets to redeem: `[1, 2]` redeems both outcomes (only winning + pays) + + + + Redemption burns your entire token balance for the condition — there is no + amount parameter. + + +## 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 call `redeemPositions()`: + +* Your token balance is multiplied by the payout +* Winning tokens are burned +* USDC.e is transferred to your wallet +* Losing tokens are burned as well, but produce a \$0 payout + +## Next Steps + + + + Learn more about the Conditional Token Framework + + + + Understand how markets are resolved + + diff --git a/docs/developers/CTF/split.md b/docs/developers/CTF/split.md index e92c4ce..8869e8c 100644 --- a/docs/developers/CTF/split.md +++ b/docs/developers/CTF/split.md @@ -2,12 +2,68 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Splitting USDC +# Split Tokens -At any time, after a condition has been prepared on the CTF contract (via `prepareCondition`), it is possible to "split" collateral into a full (position) set. In other words, one unit USDC can be split into 1 YES unit and 1 NO unit. If splitting from the collateral, the CTF contract will attempt to transfer `amount` collateral from the message sender to itself. If successful, `amount` stake will be minted in the split target positions. If any of the transfers, mints, or burns fail, the transaction will revert. The transaction will also revert if the given partition is trivial, invalid, or refers to more slots than the condition is prepared with. This operation happens via the `splitPosition()` function on the CTF contract with the following parameters: +> Convert USDC.e into outcome token pairs -* `collateralToken`: IERC20 - The address of the positions' backing collateral token. -* `parentCollectionId`: bytes32 - The ID of the outcome collections common to the position being split and the split target positions. Null in Polymarket case. -* `conditionId`: bytes32 - The ID of the condition to split on. -* `partition`: uint\[] - An array of disjoint index sets representing a nontrivial partition of the outcome slots of the given condition. E.G. A|B and C but not A|B and B|C (is not disjoint). Each element's a number which, together with the condition, represents the outcome collection. E.G. 0b110 is A|B, 0b010 is B, etc. In the Polymarket case 1|2. -* `amount` - The amount of collateral or stake to split. Also the number of full sets to receive. +**Splitting** converts USDC.e collateral into a full (position) set of outcome tokens. For every \$1 USDC.e you split, you receive 1 Yes token and 1 No token. + +``` +$100 USDC.e → 100 Yes tokens + 100 No tokens +``` + +## Prerequisites + +Before splitting, ensure you have: + +1. **USDC.e balance** on Polygon +2. **USDC.e approval** for the CTF contract to spend your tokens +3. **Condition ID** of the market — the condition must already be prepared on the CTF contract (via `prepareCondition`) + + + If the partition is trivial, invalid, or refers to more slots than the + condition is prepared with, the transaction will revert. + + +## How It Works + +1. You approve the CTF contract to spend your USDC.e +2. You call `splitPosition()` with the amount and market details +3. The CTF contract transfers USDC.e from your wallet and mints both outcome tokens + +The operation is atomic — if any step fails, the entire transaction reverts. + +## Function Parameters + + + USDC.e (Bridged USDC) contract address: `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174` + + + + Always `0x0000...0000` (32 zero bytes) for Polymarket markets + + + + The market's condition ID, available from the Markets API + + + + Array of index sets: `[1, 2]` for binary markets (Yes = 1, No = 2) + + + + The amount of collateral or stake to split. Also the number of full sets to + receive. + + +## Next Steps + + + + Convert token pairs back to USDC.e + + + + Place orders using your newly split tokens + + diff --git a/docs/developers/RTDS/RTDS-comments.md b/docs/developers/RTDS/RTDS-comments.md index 2e93cab..ffd0f0a 100644 --- a/docs/developers/RTDS/RTDS-comments.md +++ b/docs/developers/RTDS/RTDS-comments.md @@ -2,123 +2,259 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# RTDS Comments +# Real-Time Data Socket + +> Stream comments and crypto prices via WebSocket + +The Polymarket Real-Time Data Socket (RTDS) is a WebSocket-based streaming service that provides real-time updates for **comments** and **crypto prices**. Official RTDS TypeScript client (`real-time-data-client`). -## Overview +## Endpoint -The comments subscription provides real-time updates for comment-related events on the Polymarket platform. This includes new comments being created, as well as other comment interactions like reactions and replies. +``` +wss://ws-live-data.polymarket.com +``` -## Subscription Details +Some user-specific streams may require `gamma_auth` with your wallet address. -* **Topic**: `comments` -* **Type**: `comment_created` (and potentially other comment event types like `reaction_created`) -* **Authentication**: May require Gamma authentication for user-specific data -* **Filters**: Optional (can filter by specific comment IDs, users, or events) +## Subscribing -## Subscription Message +Send a JSON message to subscribe to data streams: ```json theme={null} { "action": "subscribe", "subscriptions": [ { - "topic": "comments", + "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. + +Only the subscription types documented below are supported. + +## 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`, `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 (`crypto_prices`) + +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 (`crypto_prices_chainlink`) + + + **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/). + + +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 + +## 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 Format +### Message Types -When subscribed to comments, you'll receive messages with the following structure: - -```json theme={null} -{ - "topic": "comments", - "type": "comment_created", - "timestamp": 1753454975808, - "payload": { - "body": "do you know what the term encircle means? it means to surround from all sides, Russia has present on only 1 side, that's the opposite of an encirclement", - "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" - } -} -``` - -## 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 -Triggered when a user creates a new comment on an event or in reply to another comment. - -### comment\_removed - -Triggered when a comment is removed or deleted. - -### reaction\_created - -Triggered when a user adds a reaction to an existing comment. - -### reaction\_removed - -Triggered when a reaction is removed from a 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 (e.g., "Event", "Market") | -| `profile` | object | Profile information of the user who created the comment | -| `reactionCount` | number | Current number of reactions on this comment | -| `replyAddress` | string | Polygon address for replies (may be different from userAddress) | -| `reportCount` | number | Current number of reports on this comment | -| `userAddress` | string | Polygon address of the user who created the comment | - -### Profile Object Fields - -| Field | Type | Description | -| ----------------------- | ------- | ------------------------------------------------- | -| `baseAddress` | string | User profile address | -| `displayUsernamePublic` | boolean | Whether the username should be displayed publicly | -| `name` | string | User's display name | -| `proxyWallet` | string | Proxy wallet address used for transactions | -| `pseudonym` | string | Generated pseudonym for the user | - -## Parent Entity Types - -The following parent entity types are supported: - -* `Event` - Comments on prediction events -* `Market` - Comments on specific markets -* Additional entity types may be available - -## Example Messages - -### New Comment Created +Emitted when a user posts a new comment or replies to an existing one. ```json theme={null} { @@ -126,7 +262,7 @@ The following parent entity types are supported: "type": "comment_created", "timestamp": 1753454975808, "payload": { - "body": "do you know what the term encircle means? it means to surround from all sides, Russia has present on only 1 side, that's the opposite of an encirclement", + "body": "That's a good point about the definition.", "createdAt": "2025-07-25T14:49:35.801298Z", "id": "1763355", "parentCommentID": "1763325", @@ -147,7 +283,7 @@ The following parent entity types are supported: } ``` -### Reply to Existing Comment +A reply to the above comment — note `parentCommentID` references the parent: ```json theme={null} { @@ -155,7 +291,7 @@ The following parent entity types are supported: "type": "comment_created", "timestamp": 1753454985123, "payload": { - "body": "That's a good point about the definition of encirclement.", + "body": "I agree, the resolution criteria should be clearer.", "createdAt": "2025-07-25T14:49:45.120000Z", "id": "1763356", "parentCommentID": "1763355", @@ -176,27 +312,50 @@ The following parent entity types are supported: } ``` -## Comment Hierarchy +### 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` +* All comments are associated with a `parentEntityID` and `parentEntityType` (`Event` or `Market`) -## Use Cases +## Troubleshooting -* Real-time comment feed displays -* Discussion thread monitoring -* Community sentiment analysis + + Send `PING` messages every 5 seconds to keep the connection alive. Connection errors will trigger automatic reconnection attempts. + -## Content + + Verify your subscription message is valid JSON with the correct `action`, `topic`, and `type` fields. Invalid subscription messages may result in connection closure. + -* Comments include `reactionCount` and `reportCount` -* Comment body contains the full text content - -## Notes - -* The `createdAt` timestamp uses ISO 8601 format with timezone information -* The outer `timestamp` field represents when the WebSocket message was sent -* User profiles include both primary addresses and proxy wallet addresses + + If subscribing to user-specific streams, ensure your `gamma_auth` object includes a valid wallet `address`. Authentication failures will prevent subscription to protected topics. + diff --git a/docs/developers/RTDS/RTDS-crypto-prices.md b/docs/developers/RTDS/RTDS-crypto-prices.md index 3644e65..ffd0f0a 100644 --- a/docs/developers/RTDS/RTDS-crypto-prices.md +++ b/docs/developers/RTDS/RTDS-crypto-prices.md @@ -2,32 +2,77 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# RTDS Crypto Prices +# Real-Time Data Socket + +> Stream comments and crypto prices via WebSocket + +The Polymarket Real-Time Data Socket (RTDS) is a WebSocket-based streaming service that provides real-time updates for **comments** and **crypto prices**. Official RTDS TypeScript client (`real-time-data-client`). -## Overview +## Endpoint -The crypto prices subscription provides real-time updates for cryptocurrency price data from two different sources: +``` +wss://ws-live-data.polymarket.com +``` -* **Binance Source** (`crypto_prices`): Real-time price data from Binance exchange -* **Chainlink Source** (`crypto_prices_chainlink`): Price data from Chainlink oracle networks +Some user-specific streams may require `gamma_auth` with your wallet address. -Both streams deliver current market prices for various cryptocurrency trading pairs, but use different symbol formats and subscription structures. +## Subscribing -## Binance Source (`crypto_prices`) +Send a JSON message to subscribe to data streams: -### Subscription Details +```json theme={null} +{ + "action": "subscribe", + "subscriptions": [ + { + "topic": "topic_name", + "type": "message_type", + "filters": "optional_filter_string", + "gamma_auth": { + "address": "wallet_address" + } + } + ] +} +``` -* **Topic**: `crypto_prices` -* **Type**: `update` -* **Authentication**: Not required -* **Filters**: Optional (specific symbols can be filtered) -* **Symbol Format**: Lowercase concatenated pairs (e.g., `solusdt`, `btcusdt`) +To unsubscribe, send the same structure with `"action": "unsubscribe"`. -### Subscription Message +Subscriptions can be added, removed, and modified without disconnecting. Send `PING` messages every 5 seconds to maintain the connection. + +Only the subscription types documented below are supported. + +## 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`, `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 (`crypto_prices`) + +Subscribe to all symbols: ```json theme={null} { @@ -41,13 +86,11 @@ Both streams deliver current market prices for various cryptocurrency trading pa } ``` -### With Symbol Filter - -To subscribe to specific cryptocurrency symbols, include a filters parameter: +Subscribe to specific symbols with a comma-separated filter: ```json theme={null} { - "action": "subscribe", + "action": "subscribe", "subscriptions": [ { "topic": "crypto_prices", @@ -58,21 +101,45 @@ To subscribe to specific cryptocurrency symbols, include a filters parameter: } ``` -## Chainlink Source (`crypto_prices_chainlink`) +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 (`crypto_prices_chainlink`) **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/). -### Subscription Details - -* **Topic**: `crypto_prices_chainlink` -* **Type**: `*` (all types) -* **Authentication**: Not required -* **Filters**: Optional (JSON object with symbol specification) -* **Symbol Format**: Slash-separated pairs (e.g., `eth/usd`, `btc/usd`) - -### Subscription Message +Subscribe to all symbols: ```json theme={null} { @@ -87,9 +154,7 @@ To subscribe to specific cryptocurrency symbols, include a filters parameter: } ``` -### With Symbol Filter - -To subscribe to specific cryptocurrency symbols, include a JSON filters parameter: +Subscribe to a specific symbol with a JSON filter: ```json theme={null} { @@ -104,33 +169,14 @@ To subscribe to specific cryptocurrency symbols, include a JSON filters paramete } ``` -## Message Format +Symbols use slash-separated format (e.g., `eth/usd`, `btc/usd`). -### Binance Source Message Format - -When subscribed to Binance crypto prices (`crypto_prices`), you'll receive messages with the following structure: - -```json theme={null} -{ - "topic": "crypto_prices", - "type": "update", - "timestamp": 1753314064237, - "payload": { - "symbol": "solusdt", - "timestamp": 1753314064213, - "value": 189.55 - } -} -``` - -### Chainlink Source Message Format - -When subscribed to Chainlink crypto prices (`crypto_prices_chainlink`), you'll receive messages with the following structure: +**Ethereum price update:** ```json theme={null} { "topic": "crypto_prices_chainlink", - "type": "update", + "type": "update", "timestamp": 1753314064237, "payload": { "symbol": "eth/usd", @@ -140,71 +186,12 @@ When subscribed to Chainlink crypto prices (`crypto_prices_chainlink`), you'll r } ``` -## 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 | Price timestamp in Unix milliseconds | -| `value` | number | Current price value in the quote currency | - -## Example Messages - -### Binance Source Examples - -#### Solana Price Update (Binance) - -```json theme={null} -{ - "topic": "crypto_prices", - "type": "update", - "timestamp": 1753314064237, - "payload": { - "symbol": "solusdt", - "timestamp": 1753314064213, - "value": 189.55 - } -} -``` - -#### Bitcoin Price Update (Binance) - -```json theme={null} -{ - "topic": "crypto_prices", - "type": "update", - "timestamp": 1753314088421, - "payload": { - "symbol": "btcusdt", - "timestamp": 1753314088395, - "value": 67234.50 - } -} -``` - -### Chainlink Source Examples - -#### Ethereum Price Update (Chainlink) +**Bitcoin 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 (Chainlink) - -```json theme={null} -{ - "topic": "crypto_prices_chainlink", - "type": "update", "timestamp": 1753314088421, "payload": { "symbol": "btc/usd", @@ -214,31 +201,161 @@ When subscribed to Chainlink crypto prices (`crypto_prices_chainlink`), you'll r } ``` -## Supported Symbols +### Price Payload Fields -### Binance Source Symbols +| 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 | -The Binance source supports various cryptocurrency trading pairs using lowercase concatenated format: +### Supported Symbols -* `btcusdt` - Bitcoin to USDT -* `ethusdt` - Ethereum to USDT -* `solusdt` - Solana to USDT -* `xrpusdt` - XRP to USDT +**Binance Source** — lowercase concatenated format: -### Chainlink Source Symbols +* `btcusdt` — Bitcoin to USDT +* `ethusdt` — Ethereum to USDT +* `solusdt` — Solana to USDT +* `xrpusdt` — XRP to USDT -The Chainlink source supports cryptocurrency trading pairs using slash-separated format: +**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 +* `btc/usd` — Bitcoin to USD +* `eth/usd` — Ethereum to USD +* `sol/usd` — Solana to USD +* `xrp/usd` — XRP to USD -## Notes +## Comments -### General +Real-time comment events on the Polymarket platform, including new comments, replies, reactions, and removals. May require Gamma authentication for user-specific data. -* Price updates are sent as market prices change -* The timestamp in the payload represents when the price was recorded -* The outer timestamp represents when the message was sent via WebSocket -* No authentication is required for crypto price 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 + + + Send `PING` messages every 5 seconds to keep the connection alive. Connection errors will trigger automatic reconnection attempts. + + + + Verify your subscription message is valid JSON with the correct `action`, `topic`, and `type` fields. Invalid subscription messages may result in connection closure. + + + + If subscribing to user-specific streams, ensure your `gamma_auth` object includes a valid wallet `address`. Authentication failures will prevent subscription to protected topics. + diff --git a/docs/developers/RTDS/RTDS-overview.md b/docs/developers/RTDS/RTDS-overview.md index 0bff6cf..ffd0f0a 100644 --- a/docs/developers/RTDS/RTDS-overview.md +++ b/docs/developers/RTDS/RTDS-overview.md @@ -2,9 +2,9 @@ > 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 +# Real-Time Data Socket -## Overview +> Stream comments and crypto prices via WebSocket The Polymarket Real-Time Data Socket (RTDS) is a WebSocket-based streaming service that provides real-time updates for **comments** and **crypto prices**. @@ -12,57 +12,17 @@ The Polymarket Real-Time Data Socket (RTDS) is a WebSocket-based streaming servi Official RTDS TypeScript client (`real-time-data-client`).
-### Connection Details +## Endpoint -* **WebSocket URL**: `wss://ws-live-data.polymarket.com` -* **Protocol**: WebSocket -* **Data Format**: JSON - -### Authentication - -Some user-specific streams may require `gamma_auth`: - -* `address`: User wallet address - -### Connection Management - -The WebSocket connection supports: - -* **Dynamic Subscriptions**: Without disconnecting from the socket users can add, remove and modify topics and filters they are subscribed to. -* **Ping/Pong**: You should send PING messages (every 5 seconds ideally) to maintain connection - -## Available Subscription Types - -Only the subscription types documented below are supported. - -The RTDS currently supports the following subscription types: - -1. **[Crypto Prices](/developers/RTDS/RTDS-crypto-prices)** - Real-time cryptocurrency price updates -2. **[Comments](/developers/RTDS/RTDS-comments)** - Comment-related events including reactions - -## Message Structure - -All messages received from the WebSocket follow this structure: - -```json theme={null} -{ - "topic": "string", - "type": "string", - "timestamp": "number", - "payload": "object" -} +``` +wss://ws-live-data.polymarket.com ``` -* `topic`: The subscription topic (e.g., "crypto\_prices", "comments") -* `type`: The message type/event (e.g., "update", "reaction\_created") -* `timestamp`: Unix timestamp in milliseconds -* `payload`: Event-specific data object +Some user-specific streams may require `gamma_auth` with your wallet address. -## Subscription Management +## Subscribing -### Subscribe to Topics - -To subscribe to data streams, send a JSON message with this structure: +Send a JSON message to subscribe to data streams: ```json theme={null} { @@ -80,12 +40,322 @@ To subscribe to data streams, send a JSON message with this structure: } ``` -### Unsubscribe from Topics +To unsubscribe, send the same structure with `"action": "unsubscribe"`. -To unsubscribe from data streams, send a similar message with `"action": "unsubscribe"`. +Subscriptions can be added, removed, and modified without disconnecting. Send `PING` messages every 5 seconds to maintain the connection. -## Error Handling +Only the subscription types documented below are supported. -* Connection errors will trigger automatic reconnection attempts -* Invalid subscription messages may result in connection closure -* Authentication failures will prevent successful subscription to protected topics +## 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`, `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 (`crypto_prices`) + +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 (`crypto_prices_chainlink`) + + + **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/). + + +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 + +## 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 + + + Send `PING` messages every 5 seconds to keep the connection alive. Connection errors will trigger automatic reconnection attempts. + + + + Verify your subscription message is valid JSON with the correct `action`, `topic`, and `type` fields. Invalid subscription messages may result in connection closure. + + + + If subscribing to user-specific streams, ensure your `gamma_auth` object includes a valid wallet `address`. Authentication failures will prevent subscription to protected topics. + diff --git a/docs/developers/builders/blockchain-data-resources.md b/docs/developers/builders/blockchain-data-resources.md index de08c3e..6aebddc 100644 --- a/docs/developers/builders/blockchain-data-resources.md +++ b/docs/developers/builders/blockchain-data-resources.md @@ -2,69 +2,91 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Blockchain Data Resources +# Contract Addresses -> Access Polymarket on-chain activity for data & analytics +> All Polymarket smart contract addresses on Polygon -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. +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. *** -## Data +## Core Trading Contracts -### Goldsky +| Contract | Address | Description | +| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | +| CTF Exchange | [`0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E`](https://polygonscan.com/address/0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E) | Standard market order matching and settlement | +| Neg Risk CTF Exchange | [`0xC5d563A36AE78145C45a50134d48A1215220f80a`](https://polygonscan.com/address/0xC5d563A36AE78145C45a50134d48A1215220f80a) | Order matching for [neg risk](/advanced/neg-risk) (multi-outcome) markets | +| Neg Risk Adapter | [`0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296`](https://polygonscan.com/address/0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296) | Converts No tokens between outcomes in neg risk markets | +| Conditional Tokens (CTF) | [`0x4D97DCd97eC945f40cF65F87097ACe5EA0476045`](https://polygonscan.com/address/0x4D97DCd97eC945f40cF65F87097ACe5EA0476045) | ERC1155 token storage — split, merge, and redeem operations | -[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. +## Token Contracts -### Dune +| Contract | Address | Description | +| --------------------- | -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | +| USDC.e (Bridged USDC) | [`0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174`](https://polygonscan.com/address/0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174) | Collateral token used for all Polymarket trading (6 decimals) | -[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: +## Wallet Factory Contracts -| 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) | +| Contract | Address | Description | +| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- | --------------------- | +| Gnosis Safe Factory | [`0xaacfeea03eb1561c4e67d661e40682bd20e3541b`](https://polygonscan.com/address/0xaacfeea03eb1561c4e67d661e40682bd20e3541b) | Deploys Safe wallets | +| Polymarket Proxy Factory | [`0xaB45c5A4B0c941a2F231C04C3f49182e1A254052`](https://polygonscan.com/address/0xaB45c5A4B0c941a2F231C04C3f49182e1A254052) | Deploys proxy wallets | -### 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. +## Resolution Contracts -\-- +| Contract | Address | Description | +| --------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | +| UMA Adapter | [`0x6A9D222616C90FcA5754cd1333cFD9b7fb6a4F74`](https://polygonscan.com/address/0x6A9D222616C90FcA5754cd1333cFD9b7fb6a4F74) | Adapter connecting Polymarket to the UMA Optimistic Oracle | +| UMA Optimistic Oracle | [`0xCB1822859cEF82Cd2Eb4E6276C7916e692995130`](https://polygonscan.com/address/0xCB1822859cEF82Cd2Eb4E6276C7916e692995130) | Handles market resolution proposals and disputes | -## Dashboards +*** -Third-party blockchain analytics platforms that aggregate and visualize Polymarket data: +## Liquidity - - +| Contract | Address | Description | +| --------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | +| Uniswap v3 USDC.e/USDC Pool | [`0xd36ec33c8bed5a9f7b6630855f1533455b98a418`](https://polygonscan.com/address/0xd36ec33c8bed5a9f7b6630855f1533455b98a418) | Used for USDC.e ↔ USDC conversion during withdrawals | - +*** - +## Source Code - + + + Order matching and settlement contracts + - - - - - + + Gnosis Conditional Token Framework (ERC1155) + -### Community Dashboards +*** -Community-created Dune dashboards of Polymarket on-chain analytics: +## Usage in Code -| 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) | + + ```typescript TypeScript theme={null} + const ADDRESSES = { + USDC_E: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", + CTF: "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045", + CTF_EXCHANGE: "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", + NEG_RISK_CTF_EXCHANGE: "0xC5d563A36AE78145C45a50134d48A1215220f80a", + }; + ``` + + ```python Python theme={null} + ADDRESSES = { + "USDC_E": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", + "CTF": "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045", + "CTF_EXCHANGE": "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", + "NEG_RISK_CTF_EXCHANGE": "0xC5d563A36AE78145C45a50134d48A1215220f80a", + } + ``` + diff --git a/docs/developers/builders/builder-intro.md b/docs/developers/builders/builder-intro.md index e758892..7a76bba 100644 --- a/docs/developers/builders/builder-intro.md +++ b/docs/developers/builders/builder-intro.md @@ -2,76 +2,95 @@ > 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 Introduction +# Builder Program -> Learn about Polymarket's Builder Program and how to integrate +> Build applications that route orders through Polymarket -## What is a Builder? - -A "builder" is a person, group, or organization that routes orders from their users to Polymarket. -If you've created a platform that allows users to trade on Polymarket via your system, this program is for you. - -*** +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 - - - All onchain operations are gasless through our relayer + + + All onchain operations are gas-free through our relayer - Get credited for orders and compete for weekly rewards on the Builder Leaderboard - - - - Earn a share of fees on routed orders + Get credit for orders and compete for grants on the Builder Leaderboard -### Relayer Access + + Earn a share of fees on orders you route + -We expose our relayer to builders, providing gasless transactions for users with -Polymarket's Proxy Wallets deployed via [Relayer Client](/developers/builders/relayer-client). +### What You Get -When transactions are routed through proxy wallets, Polymarket pays all gas fees for: - -* Deploying Gnosis Safe Wallets or Custom Proxy (Magic Link users) Wallets -* Token approvals (USDC, outcome tokens) -* CTF operations (split, merge, redeem) -* Order execution (via [CLOB API](/developers/CLOB/introduction)) +| Benefit | Description | +| ------------------- | ------------------------------------------------------------------------------- | +| **Relayer Access** | Gas-free wallet deployment, approvals, order execution and CTF operations | +| **Volume Tracking** | All orders attributed to your builder profile | +| **Weekly Rewards** | USDC rewards program based on volume (Verified+) | +| **Leaderboard** | Public visibility on [builders.polymarket.com](https://builders.polymarket.com) | +| **Support** | Telegram channel and engineering support (Verified+) | - EOA wallets do not have relayer access. Users trading directly from an EOA pay their own gas fees. + EOA wallets do not have relayer access. Users trading directly from an EOA pay + their own gas fees. -### Trading Attribution +## How It Works -Attach custom headers to orders to identify your builder account: + + + User places an order through your application. + -* Orders attributed to your builder account -* Compete on the [Builder Leaderboard](https://builders.polymarket.com/) for weekly rewards -* Track performance via the Data API - * [Leaderboard API](/api-reference/builders/get-aggregated-builder-leaderboard): Get aggregated builder rankings for a time period - * [Volume API](/api-reference/builders/get-daily-builder-volume-time-series): Get daily time-series volume data for trend analysis + + Your app signs the request with Builder API credentials. + -*** + + Order is submitted to Polymarket's CLOB with attribution headers. + + + + Polymarket matches the order and covers gas fees for onchain operations. + + + + Volume is credited to your builder account. + + ## Getting Started -1. **Get Builder Credentials**: Generate API keys from your [Builder Profile](/developers/builders/builder-profile) -2. **Configure Order Attribution**: Set up CLOB client to credit trades to your account ([guide](/developers/builders/order-attribution)) -3. **Enable Gasless Transactions**: Use the Relayer for gas-free wallet deployment and trading ([guide](/developers/builders/relayer-client)) + + + Go to + [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder) + and generate your API keys. + - - See [Example Apps](/developers/builders/examples) for complete Next.js reference implementations. - + + Set up your CLOB client to include builder authentication headers with every + order. + -*** + + Use the Relayer Client for gas-free wallet deployment and onchain + operations. + + + + Monitor your volume on the [Builder + Leaderboard](https://builders.polymarket.com). + + ## SDKs & Libraries - + Place orders with builder attribution @@ -80,16 +99,16 @@ Attach custom headers to orders to identify your builder account: Place orders with builder attribution - - Place orders with builder attribution - - - Gasless onchain transactions for your users + Gasless onchain transactions - Gasless onchain transactions for your users + Gasless onchain transactions + + + + Place orders with builder attribution @@ -100,3 +119,100 @@ Attach custom headers to orders to identify your builder account: Sign builder authentication headers + +## 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. + + + + Multiple wallet providers + + + + Safe & Proxy wallet support + + + + Orders, positions, CTF ops + + + +### Safe Wallet Examples + +Deploy Gnosis Safe wallets for your users: + + + + MetaMask, Phantom, Rabby, and other browser wallets + + + + Privy embedded wallets + + + + Magic Link email/social authentication + + + + Turnkey embedded wallets + + + +### Proxy Wallet Examples + +For existing Magic Link users from Polymarket.com: + + + + Auto-deploying proxy wallets for Polymarket.com Magic users + + + +### What Each Demo Covers + + + + * User sign-in via wallet provider + * User API credential derivation (L2 auth) + * Builder config with remote signing + * Signature types for Safe vs Proxy wallets + + + + * Safe wallet deployment via Relayer + * Batch token approvals (USDC.e + outcome tokens) + * CTF operations (split, merge, redeem) + * Transaction monitoring + + + + * CLOB client initialization + * Order placement with builder attribution + * Position and order management + * Market discovery via Gamma API + + + +*** + +## Next Steps + + + + Create and manage your Builder API credentials. + + + + Learn about rate limits and how to upgrade. + + + + Configure your client to credit trades to your account. + + + + Set up gasless transactions for your users. + + diff --git a/docs/developers/builders/builder-profile.md b/docs/developers/builders/builder-profile.md index e25eef5..7a76bba 100644 --- a/docs/developers/builders/builder-profile.md +++ b/docs/developers/builders/builder-profile.md @@ -2,75 +2,217 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Builder Profile & Keys +# Builder Program -> Learn how to access your builder profile and obtain API credentials +> Build applications that route orders through Polymarket -## Accessing Your Builder Profile +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 - - Go to [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder) + + All onchain operations are gas-free through our relayer - - Click your profile image and Select "Builders" + + Get credit for orders and compete for grants on the Builder Leaderboard -*** + + Earn a share of fees on orders you route + -## Builder Profile Settings +### What You Get -Builder Settings Page +| Benefit | Description | +| ------------------- | ------------------------------------------------------------------------------- | +| **Relayer Access** | Gas-free wallet deployment, approvals, order execution and CTF operations | +| **Volume Tracking** | All orders attributed to your builder profile | +| **Weekly Rewards** | USDC rewards program based on volume (Verified+) | +| **Leaderboard** | Public visibility on [builders.polymarket.com](https://builders.polymarket.com) | +| **Support** | Telegram channel and engineering support (Verified+) | -### Customize Your Builder Identity + + EOA wallets do not have relayer access. Users trading directly from an EOA pay + their own gas fees. + -* **Profile Picture**: Upload a custom image for the [Builder Leaderboard](https://builders.polymarket.com/) -* **Builder Name**: Set the name displayed publicly on the leaderboard +## How It Works -### View Your Builder Information + + + User places an order through your application. + -* **Builder Address**: Your unique builder address for identification -* **Creation Date**: When your builder account was created -* **Current Tier**: Your rate limit tier (Unverified or Verified) + + Your app signs the request with Builder API credentials. + -*** + + Order is submitted to Polymarket's CLOB with attribution headers. + -## Builder API Keys + + Polymarket matches the order and covers gas fees for onchain operations. + -Builder API keys are required to access the relayer and for CLOB order attribution. + + Volume is credited to your builder account. + + -### Creating API Keys +## Getting Started -In the **Builder Keys** section of your profile's **Builder Settings**: + + + Go to + [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder) + and generate your API keys. + -1. View existing API keys with their creation dates and status -2. Click **"+ Create New"** to generate a new API key + + Set up your CLOB client to include builder authentication headers with every + order. + -Each API key includes: + + Use the Relayer Client for gas-free wallet deployment and onchain + operations. + -| Credential | Description | -| ------------ | ------------------------------------ | -| `apiKey` | Your builder API key identifier | -| `secret` | Secret key for signing requests | -| `passphrase` | Additional authentication passphrase | + + Monitor your volume on the [Builder + Leaderboard](https://builders.polymarket.com). + + -### Managing API Keys +## SDKs & Libraries -* **Multiple Keys**: Create separate keys for different environments -* **Active Status**: Keys show "ACTIVE" when operational + + + Place orders with builder attribution + + + + Place orders with builder attribution + + + + Gasless onchain transactions + + + + Gasless onchain transactions + + + + Place orders with builder attribution + + + + Sign builder authentication headers + + + + Sign builder authentication headers + + + +## 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. + + + + Multiple wallet providers + + + + Safe & Proxy wallet support + + + + Orders, positions, CTF ops + + + +### Safe Wallet Examples + +Deploy Gnosis Safe wallets for your users: + + + + MetaMask, Phantom, Rabby, and other browser wallets + + + + Privy embedded wallets + + + + Magic Link email/social authentication + + + + Turnkey embedded wallets + + + +### Proxy Wallet Examples + +For existing Magic Link users from Polymarket.com: + + + + Auto-deploying proxy wallets for Polymarket.com Magic users + + + +### What Each Demo Covers + + + + * User sign-in via wallet provider + * User API credential derivation (L2 auth) + * Builder config with remote signing + * Signature types for Safe vs Proxy wallets + + + + * Safe wallet deployment via Relayer + * Batch token approvals (USDC.e + outcome tokens) + * CTF operations (split, merge, redeem) + * Transaction monitoring + + + + * CLOB client initialization + * Order placement with builder attribution + * Position and order management + * Market discovery via Gamma API + + *** ## Next Steps - - Start attributing customer orders to your account + + Create and manage your Builder API credentials. - - View your public profile and stats + + Learn about rate limits and how to upgrade. + + + + Configure your client to credit trades to your account. + + + + Set up gasless transactions for your users. diff --git a/docs/developers/builders/builder-tiers.md b/docs/developers/builders/builder-tiers.md index 0499544..c713cff 100644 --- a/docs/developers/builders/builder-tiers.md +++ b/docs/developers/builders/builder-tiers.md @@ -2,14 +2,11 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Builder Tiers +# Tiers -> Permissionless integration with tiered rate limits, rewards, and revenue generating opportunities as you scale +> Rate limits, rewards, and how to upgrade -## Overview - -Polymarket Builders lets anyone integrate without approval. -Tiers exist to manage rate limits while rewarding high performing integrations with weekly rewards and revenue sharing opportunities. Higher tiers also unlock engineering support, marketing promotion, and priority access. +The Builder Program uses a tiered system to manage rate limits while rewarding high-performing integrations. Higher tiers unlock increased limits, weekly rewards, revenue sharing, and priority support. ## Feature Definitions @@ -20,78 +17,90 @@ Tiers exist to manage rate limits while rewarding high performing integrations w | **Subsidized Transactions** | Gas fees subsidized for Relayer and CLOB operations via Safe/Proxy wallets | | **Order Attribution** | Orders tracked and attributed to your Builder profile | | **RevShare Protocol** | Infrastructure allowing Builders to charge fees | -| **Leaderboard Visibility** | Visibility on the [Builder leaderboard](https://builders.polymarket.com/) | +| **Leaderboard Visibility** | Visibility on the [Builder Leaderboard](https://builders.polymarket.com/) | | **Weekly Rewards** | Weekly USDC rewards program for visible builders based on volume | +| **Grants** | Builder grants subject to approval, awarded based on innovation and impact | | **Telegram Channel** | Private Builders channel for announcements and support | | **Badge** | Verified Builder affiliate badge on your Builder profile | | **Engineering Support** | Direct access to engineering team | | **Marketing Support** | Promotion via official Polymarket social accounts | -| **Weekly Rewards Boost** | Multiplier on the weekly USDC rewards program for visible builders | +| **Weekly Reward Boosts** | Multiplier on the weekly USDC rewards program for visible builders | | **Priority Access** | Early access to new features and products | -## Tier Comparison - -| Feature | Unverified | Verified | Partner | -| --------------------------- | :--------: | :-------: | :-------: | -| **Daily Relayer Txn Limit** | 100/day | 3,000/day | Unlimited | -| **API Rate Limits** | Standard | Standard | Highest | -| **Subsidized Transactions** | ✅ | ✅ | ✅ | -| **Order Attribution** | ✅ | ✅ | ✅ | -| **RevShare Protocol** | ❌ | ✅ | ✅ | -| **Leaderboard Visibility** | ❌ | ✅ | ✅ | -| **Weekly Rewards** | ❌ | ✅ | ✅ | -| **Telegram Channel** | ❌ | ✅ | ✅ | -| **Badge** | ❌ | ✅ | ✅ | -| **Engineering Support** | ❌ | Standard | Elevated | -| **Marketing Support** | ❌ | Standard | Elevated | -| **Weekly Reward Boosts** | ❌ | ❌ | ✅ | -| **Priority Access** | ❌ | ❌ | ✅ | - *** -### Unverified +## Tier Comparison + +| Feature | Unverified | Verified | Partner | +| --------------------------- | :-----------------: | :-----------------: | :-----------------: | +| **Daily Relayer Txn Limit** | 100/day | 3,000/day | Unlimited | +| **API Rate Limits** | Standard | Standard | Highest | +| **Subsidized Transactions** | Yes | Yes | Yes | +| **Order Attribution** | Yes | Yes | Yes | +| **RevShare Protocol** | — | Yes | Yes | +| **Leaderboard Visibility** | — | Yes | Yes | +| **Weekly Rewards** | — | Yes | Yes | +| **Grants** | Subject to approval | Subject to approval | Subject to approval | +| **Telegram Channel** | — | Yes | Yes | +| **Badge** | — | Yes | Yes | +| **Engineering Support** | — | Standard | Elevated | +| **Marketing Support** | — | Standard | Elevated | +| **Weekly Reward Boosts** | — | — | Yes | +| **Priority Access** | — | — | Yes | + +*** + +## Unverified - The default tier for all new builders. Create Builder API keys instantly from your Polymarket profile. + The default tier for all new builders. Start immediately with no approval + required. **How to get started:** 1. Go to [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder) -2. Create a builder profile and click **"+ Create New"** to generate builder API keys -3. Implement [builder signing](/developers/builders/order-attribution); required for Relayer access and CLOB order attribution +2. Create a builder profile +3. Click **"+ Create New"** to generate API keys +4. Implement [builder signing](/trading/orders/attribution) — required for Relayer access and CLOB order attribution -**Included:** +**What's included:** * Gasless trading on all CLOB orders through Safe/Proxy wallets -* Gas subsidized on all Relayer transactions through Safe/Proxy wallets up to daily limit -* Order attribution credit to your Builder profile +* Gas subsidized on all Relayer transactions up to daily limit (through Safe/Proxy wallets) +* Order attribution to your builder profile * Access to all client libraries and documentation *** -### Verified +## Verified - For builders who need higher throughput. Requires manual approval by Polymarket. + For builders who need higher throughput. Requires manual approval. **How to upgrade:** -Contact us with your Builder API Key, use case, expected volume, and relevant info (app, docs, X profile). +Contact us with: + +* Your Builder API Key +* Use case description +* Expected volume +* Links to your app, docs, or X profile **Unlocks over Unverified:** -* 15x daily Relayer transaction limit -* RevShare Protocol Access -* Telegram channel -* Leaderboard visibility -* Eligible for Weekly Rewards Program -* Promotion and verified affiliate badge from @PolymarketBuild +* 30x daily Relayer transaction limit +* RevShare Protocol access +* Leaderboard visibility at [builders.polymarket.com](https://builders.polymarket.com) +* Weekly USDC rewards based on volume +* Private Telegram channel for announcements and support +* Verified affiliate badge and promotion from [@PolymarketBuild](https://x.com/PolymarketBuild) +* Grants (subject to approval) *** -### Partner +## Partner Enterprise tier for high-volume integrations and strategic partners. @@ -99,7 +108,7 @@ Contact us with your Builder API Key, use case, expected volume, and relevant in **How to apply:** -Reach out to discuss partnership opportunities. +Reach out to [builder@polymarket.com](mailto:builder@polymarket.com) to discuss partnership opportunities. **Unlocks over Verified:** @@ -112,13 +121,35 @@ Reach out to discuss partnership opportunities. *** +## How to Upgrade + + + + Start with the Unverified tier and build your integration. + + + + Route orders through Polymarket and demonstrate consistent usage. + + + + Email [builder@polymarket.com](mailto:builder@polymarket.com) with your + builder key and use case. + + + + The Polymarket team reviews applications and responds within a few business + days. + + + ## Contact Ready to upgrade or have questions? -* [builder@polymarket.com](mailto:builder@polymarket.com) - -*** + + Email us with your Builder API Key and use case details. + ## FAQ @@ -128,11 +159,13 @@ Ready to upgrade or have questions? - 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. + 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. - For special events or product launches, contact [builder@polymarket.com](mailto:builder@polymarket.com) + For special events or product launches, contact [builder@polymarket.com](mailto:builder@polymarket.com). @@ -141,11 +174,11 @@ Ready to upgrade or have questions? ## Next Steps - - Create Builder API credentials to get started + + Create your Builder API credentials. - - Configure Builder API credentials to attribute orders + + Configure your client to credit trades to your account. diff --git a/docs/developers/builders/examples.md b/docs/developers/builders/examples.md index 5efbc9b..7a76bba 100644 --- a/docs/developers/builders/examples.md +++ b/docs/developers/builders/examples.md @@ -2,11 +2,125 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Examples +# Builder Program -> Complete Next.js applications demonstrating Polymarket builder integration +> Build applications that route orders through Polymarket -## Overview +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 + + + + All onchain operations are gas-free through our relayer + + + + Get credit for orders and compete for grants on the Builder Leaderboard + + + + + Earn a share of fees on orders you route + + +### 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 | +| **Weekly Rewards** | USDC rewards program based on volume (Verified+) | +| **Leaderboard** | Public visibility on [builders.polymarket.com](https://builders.polymarket.com) | +| **Support** | Telegram channel and engineering support (Verified+) | + + + EOA wallets do not have relayer access. Users trading directly from an EOA pay + their own gas fees. + + +## How It Works + + + + User places an order through your application. + + + + Your app signs the request with Builder API credentials. + + + + Order is submitted to Polymarket's CLOB with attribution headers. + + + + Polymarket matches the order and covers gas fees for onchain operations. + + + + Volume is credited to your builder account. + + + +## Getting Started + + + + Go to + [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder) + and generate your API keys. + + + + Set up your CLOB client to include builder authentication headers with every + order. + + + + Use the Relayer Client for gas-free wallet deployment and onchain + operations. + + + + Monitor your volume on the [Builder + Leaderboard](https://builders.polymarket.com). + + + +## SDKs & Libraries + + + + Place orders with builder attribution + + + + Place orders with builder attribution + + + + Gasless onchain transactions + + + + Gasless onchain transactions + + + + Place orders with builder attribution + + + + Sign builder authentication headers + + + + Sign builder authentication headers + + + +## 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. @@ -24,9 +138,7 @@ These open-source demo applications show how to integrate Polymarket's CLOB Clie -*** - -## Safe Wallet Examples +### Safe Wallet Examples Deploy Gnosis Safe wallets for your users: @@ -48,7 +160,7 @@ Deploy Gnosis Safe wallets for your users:
-## Proxy Wallet Examples +### Proxy Wallet Examples For existing Magic Link users from Polymarket.com: @@ -58,9 +170,7 @@ For existing Magic Link users from Polymarket.com: -*** - -## What Each Demo Covers +### What Each Demo Covers @@ -84,3 +194,25 @@ For existing Magic Link users from Polymarket.com: * Market discovery via Gamma API + +*** + +## Next Steps + + + + Create and manage your Builder API credentials. + + + + Learn about rate limits and how to upgrade. + + + + Configure your client to credit trades to your account. + + + + Set up gasless transactions for your users. + + diff --git a/docs/developers/builders/order-attribution.md b/docs/developers/builders/order-attribution.md index 7e4b684..59ea528 100644 --- a/docs/developers/builders/order-attribution.md +++ b/docs/developers/builders/order-attribution.md @@ -4,20 +4,19 @@ # Order Attribution -> Learn how to attribute orders to your builder account +> Attribute orders to your builder key for volume credit -## Overview - -The [CLOB (Central Limit Order Book)](/developers/CLOB/introduction) is Polymarket's order matching system. Order attribution adds builder authentication headers when placing orders through the CLOB Client, enabling Polymarket to credit trades to your builder account. This allows you to: +Order attribution adds builder authentication headers when placing orders through the CLOB, enabling Polymarket to credit trades to your builder account. This allows you to: * Track volume on the [Builder Leaderboard](https://builders.polymarket.com/) +* Earn rewards through the [Builder Program](/builders/overview) * Monitor performance via the Data API *** ## Builder API Credentials -Each builder receives API credentials from their [Builder Profile](/developers/builders/builder-profile): +Each builder receives API credentials from their [Builder Profile](https://polymarket.com/settings?tab=builder): | Credential | Description | | ------------ | ------------------------------------ | @@ -26,305 +25,217 @@ Each builder receives API credentials from their [Builder Profile](/developers/b | `passphrase` | Additional authentication passphrase | - **Security Notice**: Your Builder API keys must be kept secure. Never expose them in client-side code. + Builder API credentials are **not** the same as user API credentials. Builder + credentials are for order attribution only — you still need user credentials + for authentication. Never expose builder credentials in client-side code or + commit them to version control. *** -## Signing Methods +## Remote Signing (Recommended) - - - Remote signing keeps your credentials secure on a server you control. +Remote signing keeps your builder credentials secure on a server you control. The user's client sends order details to your server, which adds the builder headers before forwarding to the CLOB. - **How it works:** +### Server Implementation - 1. User signs an order payload - 2. Payload is sent to your builder signing server - 3. Your server adds builder authentication headers - 4. Complete order is sent to the CLOB +Your signing server receives request details and returns the authentication headers: - ### Server Implementation + + ```typescript TypeScript theme={null} + import { + buildHmacSignature, + BuilderApiKeyCreds, + } from "@polymarket/builder-signing-sdk"; - Your signing server receives request details and returns the authentication headers. Use the `buildHmacSignature` function from the SDK: + const BUILDER_CREDENTIALS: BuilderApiKeyCreds = { + key: process.env.POLY_BUILDER_API_KEY!, + secret: process.env.POLY_BUILDER_SECRET!, + passphrase: process.env.POLY_BUILDER_PASSPHRASE!, + }; - - ```typescript TypeScript theme={null} - import { - buildHmacSignature, - BuilderApiKeyCreds - } from "@polymarket/builder-signing-sdk"; + // POST /sign - receives { method, path, body } from the client SDK + export async function handleSignRequest(request) { + const { method, path, body } = await request.json(); + const timestamp = Date.now().toString(); - const BUILDER_CREDENTIALS: BuilderApiKeyCreds = { - key: process.env.POLY_BUILDER_API_KEY!, - secret: process.env.POLY_BUILDER_SECRET!, - passphrase: process.env.POLY_BUILDER_PASSPHRASE!, - }; + const signature = buildHmacSignature( + BUILDER_CREDENTIALS.secret, + parseInt(timestamp), + method, + path, + body, + ); - // POST /sign - receives { method, path, body } from the client SDK - export async function handleSignRequest(request) { - const { method, path, body } = await request.json(); - - const timestamp = Date.now().toString(); - - const signature = buildHmacSignature( + return { + POLY_BUILDER_SIGNATURE: signature, + POLY_BUILDER_TIMESTAMP: timestamp, + POLY_BUILDER_API_KEY: BUILDER_CREDENTIALS.key, + POLY_BUILDER_PASSPHRASE: BUILDER_CREDENTIALS.passphrase, + }; + } + ``` + + ```python Python theme={null} + import os + import time + from py_builder_signing_sdk.signing.hmac import build_hmac_signature + from py_builder_signing_sdk import BuilderApiKeyCreds + + BUILDER_CREDENTIALS = BuilderApiKeyCreds( + key=os.environ["POLY_BUILDER_API_KEY"], + secret=os.environ["POLY_BUILDER_SECRET"], + passphrase=os.environ["POLY_BUILDER_PASSPHRASE"], + ) + + # POST /sign - receives { method, path, body } from the client SDK + def handle_sign_request(method: str, path: str, body: str): + timestamp = str(int(time.time())) + + signature = build_hmac_signature( BUILDER_CREDENTIALS.secret, - parseInt(timestamp), + timestamp, method, path, body - ); + ) - return { - POLY_BUILDER_SIGNATURE: signature, - POLY_BUILDER_TIMESTAMP: timestamp, - POLY_BUILDER_API_KEY: BUILDER_CREDENTIALS.key, - POLY_BUILDER_PASSPHRASE: BUILDER_CREDENTIALS.passphrase, - }; + return { + "POLY_BUILDER_SIGNATURE": signature, + "POLY_BUILDER_TIMESTAMP": timestamp, + "POLY_BUILDER_API_KEY": BUILDER_CREDENTIALS.key, + "POLY_BUILDER_PASSPHRASE": BUILDER_CREDENTIALS.passphrase, } - ``` + ``` + - ```python Python theme={null} - import os - import time - from py_builder_signing_sdk.signing.hmac import build_hmac_signature - from py_builder_signing_sdk import BuilderApiKeyCreds +### Client Configuration - BUILDER_CREDENTIALS = BuilderApiKeyCreds( - key=os.environ["POLY_BUILDER_API_KEY"], - secret=os.environ["POLY_BUILDER_SECRET"], - passphrase=os.environ["POLY_BUILDER_PASSPHRASE"], +Point the CLOB client to your signing server: + + + ```typescript TypeScript theme={null} + import { ClobClient } from "@polymarket/clob-client"; + import { BuilderConfig } from "@polymarket/builder-signing-sdk"; + + const builderConfig = new BuilderConfig({ + remoteBuilderConfig: { + url: "https://your-server.com/sign", + token: "optional-auth-token", // optional + }, + }); + + const client = new ClobClient( + "https://clob.polymarket.com", + 137, + signer, + apiCreds, + 2, // signature type + funderAddress, + undefined, + false, + builderConfig, + ); + + // Orders automatically include builder headers + const response = await client.createAndPostOrder(/* ... */); + ``` + + ```python Python theme={null} + from py_clob_client.client import ClobClient + from py_builder_signing_sdk import BuilderConfig, RemoteBuilderConfig + + builder_config = BuilderConfig( + remote_builder_config=RemoteBuilderConfig( + url="https://your-server.com/sign", + token="optional-auth-token", # optional ) + ) - # POST /sign - receives { method, path, body } from the client SDK - def handle_sign_request(method: str, path: str, body: str): - timestamp = str(int(time.time())) - - signature = build_hmac_signature( - BUILDER_CREDENTIALS.secret, - timestamp, - method, - path, - body - ) + client = ClobClient( + host="https://clob.polymarket.com", + chain_id=137, + key=private_key, + creds=api_creds, + signature_type=2, + funder=funder_address, + builder_config=builder_config + ) - return { - "POLY_BUILDER_SIGNATURE": signature, - "POLY_BUILDER_TIMESTAMP": timestamp, - "POLY_BUILDER_API_KEY": BUILDER_CREDENTIALS.key, - "POLY_BUILDER_PASSPHRASE": BUILDER_CREDENTIALS.passphrase, - } - ``` - + # Orders automatically include builder headers + response = client.create_and_post_order(...) + ``` + - - Never commit credentials to version control. Use environment variables or a secrets manager. - +*** - ### Client Configuration +## Local Signing - Point your client to your signing server: +Sign orders locally when you control the entire order placement flow (e.g., your backend places orders on behalf of users): - - ```typescript TypeScript theme={null} - import { ClobClient } from "@polymarket/clob-client"; - import { BuilderConfig } from "@polymarket/builder-signing-sdk"; + + ```typescript TypeScript theme={null} + import { ClobClient } from "@polymarket/clob-client"; + import { + BuilderConfig, + BuilderApiKeyCreds, + } from "@polymarket/builder-signing-sdk"; - // Point to your signing server - const builderConfig = new BuilderConfig({ - remoteBuilderConfig: { - url: "https://your-server.com/sign" - } - }); + const builderCreds: BuilderApiKeyCreds = { + key: process.env.POLY_BUILDER_API_KEY!, + secret: process.env.POLY_BUILDER_SECRET!, + passphrase: process.env.POLY_BUILDER_PASSPHRASE!, + }; - // Or with optional authorization token - const builderConfigWithAuth = new BuilderConfig({ - remoteBuilderConfig: { - url: "https://your-server.com/sign", - token: "your-auth-token" - } - }); + const builderConfig = new BuilderConfig({ + localBuilderCreds: builderCreds, + }); - const client = new ClobClient( - "https://clob.polymarket.com", - 137, - signer, // ethers v5.x EOA signer - creds, // User's API Credentials - 2, // signatureType for the Safe proxy wallet - funderAddress, // Safe proxy wallet address - undefined, - false, - builderConfig - ); + const client = new ClobClient( + "https://clob.polymarket.com", + 137, + signer, + apiCreds, + 2, + funderAddress, + undefined, + false, + builderConfig, + ); - // Orders automatically use the signing server - const order = await client.createOrder({ - price: 0.40, - side: Side.BUY, - size: 5, - tokenID: "YOUR_TOKEN_ID" - }); + // Orders automatically include builder headers + const response = await client.createAndPostOrder(/* ... */); + ``` - const response = await client.postOrder(order); - ``` + ```python Python theme={null} + import os + from py_clob_client.client import ClobClient + from py_builder_signing_sdk import BuilderConfig, BuilderApiKeyCreds - ```python Python theme={null} - from py_clob_client.client import ClobClient - from py_builder_signing_sdk import BuilderConfig, RemoteBuilderConfig + builder_creds = BuilderApiKeyCreds( + key=os.environ["POLY_BUILDER_API_KEY"], + secret=os.environ["POLY_BUILDER_SECRET"], + passphrase=os.environ["POLY_BUILDER_PASSPHRASE"], + ) - # Point to your signing server - builder_config = BuilderConfig( - remote_builder_config=RemoteBuilderConfig( - url="https://your-server.com/sign" - ) - ) + builder_config = BuilderConfig( + local_builder_creds=builder_creds, + ) - # Or with optional authorization token - builder_config_with_auth = BuilderConfig( - remote_builder_config=RemoteBuilderConfig( - url="https://your-server.com/sign", - token="your-auth-token" - ) - ) + client = ClobClient( + host="https://clob.polymarket.com", + chain_id=137, + key=private_key, + creds=api_creds, + signature_type=2, + funder=funder_address, + builder_config=builder_config + ) - client = ClobClient( - host="https://clob.polymarket.com", - chain_id=137, - key=private_key, - creds=creds, # User's API Credentials - signature_type=2, # signatureType for the Safe proxy wallet - funder=funder_address, # Safe proxy wallet address - builder_config=builder_config - ) - - # Orders automatically use the signing server - order = client.create_order({ - "price": 0.40, - "side": "BUY", - "size": 5, - "token_id": "YOUR_TOKEN_ID" - }) - - response = client.post_order(order) - ``` - - - ### Troubleshooting - - - - **Error:** Client receives invalid signature errors - - **Solution:** - - 1. Verify the request body is passed correctly as JSON - 2. Check that `path`, `body`, and `method` match what the client sends - 3. Ensure your server and client use the same Builder API credentials - - - - **Error:** `Builder credentials not configured` or undefined values - - **Solution:** Ensure your environment variables are set: - - * `POLY_BUILDER_API_KEY` - * `POLY_BUILDER_SECRET` - * `POLY_BUILDER_PASSPHRASE` - - - - - - Sign orders locally when you control the entire order placement flow. - - **How it works:** - - 1. Your system creates and signs orders on behalf of users - 2. Your system uses Builder API credentials locally to add headers - 3. Complete signed order is sent directly to the CLOB - - - ```typescript TypeScript theme={null} - import { ClobClient } from "@polymarket/clob-client"; - import { BuilderConfig, BuilderApiKeyCreds } from "@polymarket/builder-signing-sdk"; - - // Configure with local builder credentials - const builderCreds: BuilderApiKeyCreds = { - key: process.env.POLY_BUILDER_API_KEY!, - secret: process.env.POLY_BUILDER_SECRET!, - passphrase: process.env.POLY_BUILDER_PASSPHRASE! - }; - - const builderConfig = new BuilderConfig({ - localBuilderCreds: builderCreds - }); - - const client = new ClobClient( - "https://clob.polymarket.com", - 137, - signer, // ethers v5.x EOA signer - creds, // User's API Credentials - 2, // signatureType for the Safe proxy wallet - funderAddress, // Safe proxy wallet address - undefined, - false, - builderConfig - ); - - // Orders automatically include builder headers - const order = await client.createOrder({ - price: 0.40, - side: Side.BUY, - size: 5, - tokenID: "YOUR_TOKEN_ID" - }); - - const response = await client.postOrder(order); - ``` - - ```python Python theme={null} - import os - from py_clob_client.client import ClobClient - from py_builder_signing_sdk import BuilderConfig, BuilderApiKeyCreds - - # Configure with local builder credentials - builder_creds = BuilderApiKeyCreds( - key=os.environ["POLY_BUILDER_API_KEY"], - secret=os.environ["POLY_BUILDER_SECRET"], - passphrase=os.environ["POLY_BUILDER_PASSPHRASE"] - ) - - builder_config = BuilderConfig( - local_builder_creds=builder_creds - ) - - client = ClobClient( - host="https://clob.polymarket.com", - chain_id=137, - key=private_key, - creds=creds, # User's API Credentials - signature_type=2, # signatureType for the Safe proxy wallet - funder=funder_address, # Safe proxy wallet address - builder_config=builder_config - ) - - # Orders automatically include builder headers - order = client.create_order({ - "price": 0.40, - "side": "BUY", - "size": 5, - "token_id": "YOUR_TOKEN_ID" - }) - - response = client.post_order(order) - ``` - - - - Never commit credentials to version control. Use environment variables or a secrets manager. - - - + # Orders automatically include builder headers + response = client.create_and_post_order(...) + ``` + *** @@ -340,19 +251,89 @@ The SDK automatically generates and attaches these headers to each request: | `POLY_BUILDER_SIGNATURE` | HMAC signature of the request | - With **local signing**, the SDK constructs and attaches these headers automatically. With **remote signing**, your server must return these headers (see Server Implementation above), and the SDK attaches them to the request. + With **local signing**, the SDK constructs and attaches these headers + automatically. With **remote signing**, your server returns these headers and + the SDK attaches them. *** +## Verifying Attribution + +### Get Builder Trades + +Query trades attributed to your builder account to verify attribution is working: + + + ```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..." + ) + ``` + + +Each `BuilderTrade` includes: `id`, `market`, `assetId`, `side`, `size`, `price`, `status`, `outcome`, `owner`, `maker`, `transactionHash`, `matchTime`, `fee`, and `feeUsdc`. + +### Revoke Builder API Key + +If your credentials are compromised, revoke them immediately: + + + ```typescript TypeScript theme={null} + await client.revokeBuilderApiKey(); + ``` + + ```python Python theme={null} + client.revoke_builder_api_key() + ``` + + +After revoking, generate new credentials from your [Builder Profile](https://polymarket.com/settings?tab=builder). + +*** + +## Troubleshooting + + + + * Verify the request body is passed correctly as JSON - Check that `path`, + `body`, and `method` match what the client sends - Ensure your server and + client use the same Builder API credentials + + + + Ensure your environment variables are set: - `POLY_BUILDER_API_KEY` - + `POLY_BUILDER_SECRET` - `POLY_BUILDER_PASSPHRASE` + + + + * Confirm your builder credentials are valid and not revoked - Check that + orders are being placed with the builder config attached - Allow up to 24 + hours for volume to appear on the leaderboard + + + +*** + ## Next Steps - - Learn how to configure and use the Relay Client too! + + Learn about the Builder Program tiers and rewards - - Explore the complete CLOB client reference + + Build, sign, and submit orders diff --git a/docs/developers/builders/relayer-client.md b/docs/developers/builders/relayer-client.md index 8e95a09..50f7186 100644 --- a/docs/developers/builders/relayer-client.md +++ b/docs/developers/builders/relayer-client.md @@ -2,91 +2,132 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Relayer Client +# Gasless Transactions -> Use Polymarket's Polygon relayer to execute gasless transactions for your users +> Execute onchain operations without paying gas fees -## Overview +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 USDC.e to trade. -The Relayer Client routes onchain transactions through Polymarket's infrastructure, providing gasless transactions for your users. Builder authentication is required to access the relayer. +## How It Works - - - Polymarket pays all gas fees - +The relayer acts as a transaction sponsor: - - Deploy Safe or Proxy wallets - +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 - - Split, merge, and redeem positions - - + + Gasless transactions require **Builder Program** membership. You'll need + Builder API credentials to authenticate with the relayer. + -*** +## What's Covered -## Builder API Credentials +Polymarket pays gas for all operations routed through the relayer: -Each builder receives API credentials from their [Builder Profile](/developers/builders/builder-profile): +| Operation | Description | +| --------------------- | --------------------------------------------------- | +| **Wallet deployment** | Deploy Safe or Proxy wallets for new users | +| **Token approvals** | Approve contracts to spend USDC.e or outcome tokens | +| **CTF operations** | Split, merge, and redeem positions | +| **Transfers** | Move tokens between addresses | -| Credential | Description | -| ------------ | ------------------------------------ | -| `key` | Your builder API key identifier | -| `secret` | Secret key for signing requests | -| `passphrase` | Additional authentication passphrase | +## Prerequisites - - **Security Notice**: Your Builder API keys must be kept secure. Never expose them in client-side code. - +Before using the relayer, you need: -*** +| Requirement | Source | +| ---------------------------- | -------------------------------------------------------------- | +| Builder API credentials | [Builder Profile](https://polymarket.com/settings?tab=builder) | +| User's private key or signer | Your wallet integration | +| USDC.e balance | For trading (not for gas) | ## Installation - ```bash TypeScript theme={null} - npm install @polymarket/builder-relayer-client + ```bash npm theme={null} + npm install @polymarket/builder-relayer-client @polymarket/builder-signing-sdk ``` - ```bash Python theme={null} - pip install py-builder-relayer-client + ```bash pip theme={null} + pip install py-builder-relayer-client py-builder-signing-sdk ``` -*** +## Client Setup -## Relayer Endpoint - -All relayer requests are sent to Polymarket's relayer service on Polygon: - -``` -https://relayer-v2.polymarket.com/ -``` - -*** - -## Signing Methods +Initialize the relayer client with your signing configuration: - - Remote signing keeps your credentials secure on a server you control. - - **How it works:** - - 1. Client sends request details to your signing server - 2. Your server generates the HMAC signature - 3. Client attaches headers and sends to relayer - - ### Server Implementation - - Your signing server receives request details and returns the authentication headers: + + Use local signing when your backend handles all transactions securely. ```typescript TypeScript theme={null} - import { - buildHmacSignature, - BuilderApiKeyCreds + import { createWalletClient, http, Hex } from "viem"; + import { privateKeyToAccount } from "viem/accounts"; + import { polygon } from "viem/chains"; + import { RelayClient } from "@polymarket/builder-relayer-client"; + import { BuilderConfig } from "@polymarket/builder-signing-sdk"; + + const account = privateKeyToAccount(process.env.PRIVATE_KEY as Hex); + const wallet = createWalletClient({ + account, + chain: polygon, + transport: http(process.env.RPC_URL), + }); + + const builderConfig = new BuilderConfig({ + localBuilderCreds: { + key: process.env.POLY_BUILDER_API_KEY!, + secret: process.env.POLY_BUILDER_SECRET!, + passphrase: process.env.POLY_BUILDER_PASSPHRASE!, + }, + }); + + const client = new RelayClient( + "https://relayer-v2.polymarket.com/", + 137, + wallet, + builderConfig, + ); + ``` + + ```python Python theme={null} + import os + from py_builder_relayer_client.client import RelayClient + from py_builder_signing_sdk import BuilderConfig, BuilderApiKeyCreds + + builder_config = BuilderConfig( + local_builder_creds=BuilderApiKeyCreds( + key=os.getenv("POLY_BUILDER_API_KEY"), + secret=os.getenv("POLY_BUILDER_SECRET"), + passphrase=os.getenv("POLY_BUILDER_PASSPHRASE"), + ) + ) + + client = RelayClient( + "https://relayer-v2.polymarket.com", + 137, + os.getenv("PRIVATE_KEY"), + builder_config + ) + ``` + + + + + Use remote signing to keep credentials on a secure server you control. + + **Your signing server** receives request details and returns authentication headers: + + + ```typescript Server (TypeScript) theme={null} + import { + buildHmacSignature, + BuilderApiKeyCreds, } from "@polymarket/builder-signing-sdk"; const BUILDER_CREDENTIALS: BuilderApiKeyCreds = { @@ -95,18 +136,17 @@ https://relayer-v2.polymarket.com/ passphrase: process.env.POLY_BUILDER_PASSPHRASE!, }; - // POST /sign - receives { method, path, body } from the client SDK + // POST /sign endpoint export async function handleSignRequest(request) { const { method, path, body } = await request.json(); - const timestamp = Date.now().toString(); - + const signature = buildHmacSignature( BUILDER_CREDENTIALS.secret, parseInt(timestamp), method, path, - body + body, ); return { @@ -118,7 +158,7 @@ https://relayer-v2.polymarket.com/ } ``` - ```python Python theme={null} + ```python Server (Python) theme={null} import os import time from py_builder_signing_sdk.signing.hmac import build_hmac_signature @@ -130,10 +170,10 @@ https://relayer-v2.polymarket.com/ passphrase=os.environ["POLY_BUILDER_PASSPHRASE"], ) - # POST /sign - receives { method, path, body } from the client SDK + # POST /sign endpoint def handle_sign_request(method: str, path: str, body: str): timestamp = str(int(time.time())) - + signature = build_hmac_signature( BUILDER_CREDENTIALS.secret, timestamp, @@ -151,56 +191,31 @@ https://relayer-v2.polymarket.com/ ``` - - Never commit credentials to version control. Use environment variables or a secrets manager. - - - ### Client Configuration - - Point your client to your signing server: + **Your client** points to your signing server: - ```typescript TypeScript theme={null} - import { createWalletClient, http, Hex } from "viem"; - import { privateKeyToAccount } from "viem/accounts"; - import { polygon } from "viem/chains"; + ```typescript Client (TypeScript) theme={null} import { RelayClient } from "@polymarket/builder-relayer-client"; import { BuilderConfig } from "@polymarket/builder-signing-sdk"; - // Create wallet - const account = privateKeyToAccount(process.env.PRIVATE_KEY as Hex); - const wallet = createWalletClient({ - account, - chain: polygon, - transport: http(process.env.RPC_URL) - }); - - // Configure remote signing const builderConfig = new BuilderConfig({ - remoteBuilderConfig: { - url: "https://your-server.com/sign" - } + remoteBuilderConfig: { + url: "https://your-server.com/sign", + }, }); - const RELAYER_URL = "https://relayer-v2.polymarket.com/"; - const CHAIN_ID = 137; - const client = new RelayClient( - RELAYER_URL, - CHAIN_ID, + "https://relayer-v2.polymarket.com/", + 137, wallet, - builderConfig + builderConfig, ); ``` - ```python Python theme={null} - import os + ```python Client (Python) theme={null} from py_builder_relayer_client.client import RelayClient from py_builder_signing_sdk import BuilderConfig, RemoteBuilderConfig - private_key = os.getenv("PRIVATE_KEY") - - # Configure remote signing builder_config = BuilderConfig( remote_builder_config=RemoteBuilderConfig( url="https://your-server.com/sign" @@ -216,702 +231,325 @@ https://relayer-v2.polymarket.com/ ``` - - - Sign locally when your backend handles all transactions. - - **How it works:** - - 1. Your system creates transactions on behalf of users - 2. Your system uses Builder API credentials locally to add headers - 3. Complete signed request is sent directly to the relayer - - - ```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"; - import { BuilderConfig } from "@polymarket/builder-signing-sdk"; - - // Create wallet - const account = privateKeyToAccount(process.env.PRIVATE_KEY as Hex); - const wallet = createWalletClient({ - account, - chain: polygon, - transport: http(process.env.RPC_URL) - }); - - // Configure local signing - const builderConfig = new BuilderConfig({ - localBuilderCreds: { - key: process.env.POLY_BUILDER_API_KEY!, - secret: process.env.POLY_BUILDER_SECRET!, - passphrase: process.env.POLY_BUILDER_PASSPHRASE! - } - }); - - const RELAYER_URL = "https://relayer-v2.polymarket.com/"; - const CHAIN_ID = 137; - - const client = new RelayClient( - RELAYER_URL, - CHAIN_ID, - wallet, - builderConfig - ); - ``` - - ```python Python theme={null} - import os - from py_builder_relayer_client.client import RelayClient - from py_builder_signing_sdk import BuilderConfig, BuilderApiKeyCreds - - private_key = os.getenv("PRIVATE_KEY") - - # Configure local signing - builder_config = BuilderConfig( - local_builder_creds=BuilderApiKeyCreds( - key=os.getenv("POLY_BUILDER_API_KEY"), - secret=os.getenv("POLY_BUILDER_SECRET"), - passphrase=os.getenv("POLY_BUILDER_PASSPHRASE"), - ) - ) - - client = RelayClient( - "https://relayer-v2.polymarket.com", - 137, - private_key, - builder_config - ) - ``` - - - - Never commit credentials to version control. Use environment variables or a secrets manager. - - -*** + + Never expose Builder API credentials in client-side code. Use environment + variables or a secrets manager. + -## Authentication Headers +### Relayer Authentication Headers -The SDK automatically generates and attaches these headers to each request: +All requests to the relayer must include these authentication headers: -| Header | Description | -| ------------------------- | ------------------------------------ | -| `POLY_BUILDER_API_KEY` | Your builder API key | -| `POLY_BUILDER_TIMESTAMP` | Unix timestamp of signature creation | -| `POLY_BUILDER_PASSPHRASE` | Your builder passphrase | -| `POLY_BUILDER_SIGNATURE` | HMAC signature of the request | +| Header | Description | +| ------------------------- | ----------------------- | +| `POLY_BUILDER_API_KEY` | Your Builder API key | +| `POLY_BUILDER_TIMESTAMP` | Unix timestamp | +| `POLY_BUILDER_PASSPHRASE` | Your Builder passphrase | +| `POLY_BUILDER_SIGNATURE` | HMAC-SHA256 signature | - - With **local signing**, the SDK constructs and attaches these headers automatically. With **remote signing**, your server must return these headers (see Server Implementation above), and the SDK attaches them to the request. - - -*** +The SDKs handle header generation automatically when you provide your credentials via `BuilderConfig`. ## Wallet Types -Choose your wallet type before using the relayer: +Choose a wallet type when initializing the client: - - - Gnosis Safe-based proxy wallets that require explicit deployment before use. - - * **Best for:** Most builder integrations - * **Deployment:** Call `client.deploy()` before first transaction - * **Gas fees:** Paid by Polymarket - - - ```typescript TypeScript theme={null} - const client = new RelayClient( - "https://relayer-v2.polymarket.com", - 137, - eoaSigner, - builderConfig, - RelayerTxType.SAFE // Default - ); - - // Deploy before first use - 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, RelayerTxType - - client = RelayClient( - "https://relayer-v2.polymarket.com", - 137, - private_key, - builder_config, - RelayerTxType.SAFE # Default - ) - - # Deploy before first use - response = client.deploy() - result = response.wait() - print(f"Safe Address: {result.proxy_address}") - ``` - - - - - Custom Polymarket proxy wallets that auto-deploy on first transaction. - - * **Used for:** Magic Link users from Polymarket.com - * **Deployment:** Automatic on first transaction - * **Gas fees:** Paid by Polymarket - - - ```typescript TypeScript theme={null} - const client = new RelayClient( - "https://relayer-v2.polymarket.com", - 137, - eoaSigner, - builderConfig, - RelayerTxType.PROXY - ); - - // No deploy() needed - auto-deploys on first tx - await client.execute([transaction], "First transaction"); - ``` - - ```python Python theme={null} - from py_builder_relayer_client.client import RelayClient, RelayerTxType - - client = RelayClient( - "https://relayer-v2.polymarket.com", - 137, - private_key, - builder_config, - RelayerTxType.PROXY - ) - - # No deploy() needed - auto-deploys on first tx - client.execute([transaction], "First transaction") - ``` - - - - - - | Feature | Safe Wallets | Proxy Wallets | - | ----------------- | :-----------------: | :---------------------: | - | Deployment | Explicit `deploy()` | Auto-deploy on first tx | - | Gas Fees | Polymarket pays | Polymarket pays | - | ERC20 Approvals | ✅ | ✅ | - | CTF Operations | ✅ | ✅ | - | Send Transactions | ✅ | ✅ | - - -*** - -## Usage - -### Deploy a Wallet - -For Safe wallets, deploy before executing transactions: +| Type | Deployment | Best For | +| --------- | ---------------------------------------- | ------------------------- | +| **Safe** | Call `deploy()` before first transaction | Most builder integrations | +| **Proxy** | Auto-deploys on first transaction | Magic Link users | - ```typescript TypeScript theme={null} + ```typescript Safe Wallet (TypeScript) theme={null} + import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client"; + + const client = new RelayClient( + "https://relayer-v2.polymarket.com/", + 137, + wallet, + builderConfig, + RelayerTxType.SAFE, + ); + + // Deploy before first transaction const response = await client.deploy(); const result = await response.wait(); - - if (result) { - console.log("Safe deployed successfully!"); - console.log("Transaction Hash:", result.transactionHash); - console.log("Safe Address:", result.proxyAddress); - } + console.log("Safe Address:", result?.proxyAddress); ``` - ```python Python theme={null} + ```python Safe Wallet (Python) theme={null} + from py_builder_relayer_client.client import RelayClient + + # client initialized with builder_config (see Client Setup above) + + # Deploy before first transaction response = client.deploy() result = response.wait() + print("Safe Address:", result.get("proxyAddress")) + ``` - if result: - print("Safe deployed successfully!") - print(f"Transaction Hash: {result.transaction_hash}") - print(f"Safe Address: {result.proxy_address}") + ```typescript Proxy Wallet (TypeScript) theme={null} + import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client"; + + const client = new RelayClient( + "https://relayer-v2.polymarket.com/", + 137, + wallet, + builderConfig, + 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 builder_config (see Client Setup above) + # No deploy needed - auto-deploys on first transaction ``` -### Execute Transactions +## Executing Transactions -The `execute` method sends transactions through the relayer. Pass an array of transactions to batch multiple operations in a single call. +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: ```typescript TypeScript theme={null} - interface Transaction { - to: string; // Target contract or wallet address - data: string; // Encoded function call (use "0x" for simple transfers) - value: string; // Amount of MATIC to send (usually "0") - } + import { encodeFunctionData, maxUint256 } from "viem"; - const response = await client.execute(transactions, "Description"); - const result = await response.wait(); + const USDC = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"; + const CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"; - if (result) { - console.log("Transaction confirmed:", result.transactionHash); - } - ``` - - ```python Python theme={null} - # Transaction dict format: - # { "to": str, "data": str, "value": str } - - response = client.execute(transactions, "Description") - result = response.wait() - - if result: - print(f"Transaction confirmed: {result.transaction_hash}") - ``` - - -### Transaction Examples - - - - Transfer tokens to any address (e.g., withdrawals): - - - ```typescript TypeScript theme={null} - import { encodeFunctionData, parseUnits } from "viem"; - - const transferTx = { - to: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", // USDCe - data: encodeFunctionData({ - abi: [{ - name: "transfer", - type: "function", - inputs: [ - { name: "to", type: "address" }, - { name: "amount", type: "uint256" } - ], - outputs: [{ type: "bool" }] - }], - functionName: "transfer", - args: [ - "0xRecipientAddressHere", - parseUnits("100", 6) // 100 USDCe (6 decimals) - ] - }), - value: "0" - }; - - const response = await client.execute([transferTx], "Transfer USDCe"); - await response.wait(); - ``` - - ```python Python theme={null} - from web3 import Web3 - - USDC_E = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" - - transfer_tx = { - "to": USDC_E, - "data": Web3().eth.contract( - address=USDC_E, - abi=[{"name": "transfer", "type": "function", "inputs": [{"name": "to", "type": "address"}, {"name": "amount", "type": "uint256"}], "outputs": [{"type": "bool"}]}] - ).encode_abi(abi_element_identifier="transfer", args=["0xRecipientAddressHere", 100 * 10**6]), - "value": "0" - } - - response = client.execute([transfer_tx], "Transfer USDCe") - response.wait() - ``` - - - - - Set token allowances to enable trading: - - - ```typescript TypeScript theme={null} - import { encodeFunctionData, maxUint256 } from "viem"; - - const approveTx = { - to: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", // USDCe - data: encodeFunctionData({ - abi: [{ - name: "approve", - type: "function", - inputs: [ - { name: "spender", type: "address" }, - { name: "amount", type: "uint256" } - ], - outputs: [{ type: "bool" }] - }], - functionName: "approve", - args: [ - "0x4d97dcd97ec945f40cf65f87097ace5ea0476045", // CTF - maxUint256 - ] - }), - value: "0" - }; - - const response = await client.execute([approveTx], "Approve USDCe for CTF"); - await response.wait(); - ``` - - ```python Python theme={null} - from web3 import Web3 - - USDC_E = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" - CTF = "0x4d97dcd97ec945f40cf65f87097ace5ea0476045" - MAX_UINT256 = 2**256 - 1 - - approve_tx = { - "to": USDC_E, - "data": Web3().eth.contract( - address=USDC_E, - 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 USDCe for CTF") - response.wait() - ``` - - - - - Redeem winning conditional tokens after market resolution: - - - ```typescript TypeScript theme={null} - import { encodeFunctionData } from "viem"; - - const redeemTx = { - to: ctfAddress, - 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} - from web3 import Web3 - - 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() - ``` - - - - - Split collateral tokens into conditional outcome tokens: - - - ```typescript TypeScript theme={null} - import { encodeFunctionData } from "viem"; - - const splitTx = { - to: ctfAddress, - data: encodeFunctionData({ - abi: [{ - name: "splitPosition", - type: "function", - inputs: [ - { name: "collateralToken", type: "address" }, - { name: "parentCollectionId", type: "bytes32" }, - { name: "conditionId", type: "bytes32" }, - { name: "partition", type: "uint256[]" }, - { name: "amount", type: "uint256" } - ], - outputs: [] - }], - functionName: "splitPosition", - args: [collateralToken, parentCollectionId, conditionId, partition, amount] - }), - value: "0" - }; - - const response = await client.execute([splitTx], "Split positions"); - await response.wait(); - ``` - - ```python Python theme={null} - from web3 import Web3 - - CTF = "0x4d97dcd97ec945f40cf65f87097ace5ea0476045" - - split_tx = { - "to": CTF, - "data": Web3().eth.contract( - address=CTF, - abi=[{"name": "splitPosition", "type": "function", "inputs": [{"name": "collateralToken", "type": "address"}, {"name": "parentCollectionId", "type": "bytes32"}, {"name": "conditionId", "type": "bytes32"}, {"name": "partition", "type": "uint256[]"}, {"name": "amount", "type": "uint256"}], "outputs": []}] - ).encode_abi(abi_element_identifier="splitPosition", args=[collateral_token, parent_collection_id, condition_id, partition, amount]), - "value": "0" - } - - response = client.execute([split_tx], "Split positions") - response.wait() - ``` - - - - - Merge conditional tokens back into collateral: - - - ```typescript TypeScript theme={null} - import { encodeFunctionData } from "viem"; - - const mergeTx = { - to: ctfAddress, - data: encodeFunctionData({ - abi: [{ - name: "mergePositions", - type: "function", - inputs: [ - { name: "collateralToken", type: "address" }, - { name: "parentCollectionId", type: "bytes32" }, - { name: "conditionId", type: "bytes32" }, - { name: "partition", type: "uint256[]" }, - { name: "amount", type: "uint256" } - ], - outputs: [] - }], - functionName: "mergePositions", - args: [collateralToken, parentCollectionId, conditionId, partition, amount] - }), - value: "0" - }; - - const response = await client.execute([mergeTx], "Merge positions"); - await response.wait(); - ``` - - ```python Python theme={null} - from web3 import Web3 - - CTF = "0x4d97dcd97ec945f40cf65f87097ace5ea0476045" - - merge_tx = { - "to": CTF, - "data": Web3().eth.contract( - address=CTF, - abi=[{"name": "mergePositions", "type": "function", "inputs": [{"name": "collateralToken", "type": "address"}, {"name": "parentCollectionId", "type": "bytes32"}, {"name": "conditionId", "type": "bytes32"}, {"name": "partition", "type": "uint256[]"}, {"name": "amount", "type": "uint256"}], "outputs": []}] - ).encode_abi(abi_element_identifier="mergePositions", args=[collateral_token, parent_collection_id, condition_id, partition, amount]), - "value": "0" - } - - response = client.execute([merge_tx], "Merge positions") - response.wait() - ``` - - - - - Execute multiple transactions atomically in a single call: - - - ```typescript TypeScript theme={null} - import { encodeFunctionData, parseUnits, maxUint256 } from "viem"; - - const erc20Abi = [ + const approveTx = { + to: USDC, + data: encodeFunctionData({ + abi: [ { name: "approve", type: "function", inputs: [ { name: "spender", type: "address" }, - { name: "amount", type: "uint256" } + { name: "amount", type: "uint256" }, ], - outputs: [{ type: "bool" }] + outputs: [{ type: "bool" }], }, + ], + functionName: "approve", + args: [CTF, maxUint256], + }), + value: "0", + }; + + const response = await client.execute([approveTx], "Approve USDC.e for CTF"); + await response.wait(); + ``` + + ```python Python theme={null} + from web3 import Web3 + + USDC = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" + CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045" + MAX_UINT256 = 2**256 - 1 + + approve_tx = { + "to": USDC, + "data": Web3().eth.contract( + address=USDC, + 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 USDC.e for CTF") + response.wait() + ``` + + +### Redeem Positions + +Exchange winning tokens for USDC.e after market resolution: + + + ```typescript TypeScript theme={null} + import { encodeFunctionData } from "viem"; + + const redeemTx = { + to: CTF_ADDRESS, + data: encodeFunctionData({ + abi: [ { - name: "transfer", + name: "redeemPositions", type: "function", inputs: [ - { name: "to", type: "address" }, - { name: "amount", type: "uint256" } + { name: "collateralToken", type: "address" }, + { name: "parentCollectionId", type: "bytes32" }, + { name: "conditionId", type: "bytes32" }, + { name: "indexSets", type: "uint256[]" }, ], - outputs: [{ type: "bool" }] - } - ] as const; + outputs: [], + }, + ], + functionName: "redeemPositions", + args: [collateralToken, parentCollectionId, conditionId, indexSets], + }), + value: "0", + }; - // Approve CTF to spend USDCe - const approveTx = { - to: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", - data: encodeFunctionData({ - abi: erc20Abi, - functionName: "approve", - args: ["0x4d97dcd97ec945f40cf65f87097ace5ea0476045", maxUint256] - }), - value: "0" - }; - - // Transfer some USDCe to another wallet - const transferTx = { - to: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", - data: encodeFunctionData({ - abi: erc20Abi, - functionName: "transfer", - args: ["0xRecipientAddressHere", parseUnits("50", 6)] - }), - value: "0" - }; - - // Both transactions execute in one call - const response = await client.execute( - [approveTx, transferTx], - "Approve and transfer" - ); - await response.wait(); - ``` - - ```python Python theme={null} - from web3 import Web3 - - USDC_E = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" - CTF = "0x4d97dcd97ec945f40cf65f87097ace5ea0476045" - MAX_UINT256 = 2**256 - 1 - - erc20_abi = [ - {"name": "approve", "type": "function", "inputs": [{"name": "spender", "type": "address"}, {"name": "amount", "type": "uint256"}], "outputs": [{"type": "bool"}]}, - {"name": "transfer", "type": "function", "inputs": [{"name": "to", "type": "address"}, {"name": "amount", "type": "uint256"}], "outputs": [{"type": "bool"}]} - ] - - contract = Web3().eth.contract(address=USDC_E, abi=erc20_abi) - - # Approve CTF to spend USDCe - approve_tx = { - "to": USDC_E, - "data": contract.encode_abi(abi_element_identifier="approve", args=[CTF, MAX_UINT256]), - "value": "0" - } - - # Transfer some USDCe to another wallet - transfer_tx = { - "to": USDC_E, - "data": contract.encode_abi(abi_element_identifier="transfer", args=["0xRecipientAddressHere", 50 * 10**6]), - "value": "0" - } - - # Both transactions execute in one call - response = client.execute([approve_tx, transfer_tx], "Approve and transfer") - response.wait() - ``` - - - - Batching reduces latency and ensures all transactions succeed or fail together. - - - - -*** - -## Reference - -### Contracts & Approvals - -| Contract | Address | USDCe | Outcome Tokens | -| --------------------- | -------------------------------------------- | :---: | :------------: | -| USDCe | `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174` | — | — | -| CTF | `0x4d97dcd97ec945f40cf65f87097ace5ea0476045` | ✅ | — | -| CTF Exchange | `0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E` | ✅ | ✅ | -| Neg Risk CTF Exchange | `0xC5d563A36AE78145C45a50134d48A1215220f80a` | ✅ | ✅ | -| Neg Risk Adapter | `0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296` | — | ✅ | - -### Transaction States - -| State | Description | -| ----------------- | -------------------------------------------- | -| `STATE_NEW` | Transaction received by relayer | -| `STATE_EXECUTED` | Transaction executed onchain | -| `STATE_MINED` | Transaction included in a block | -| `STATE_CONFIRMED` | Transaction confirmed (final ✅) | -| `STATE_FAILED` | Transaction failed (terminal ❌) | -| `STATE_INVALID` | Transaction rejected as invalid (terminal ❌) | - -### TypeScript Types - - - ```typescript theme={null} - // Transaction type used in all examples - interface Transaction { - to: string; - data: string; - value: string; - } - - // Wallet type selector - enum RelayerTxType { - SAFE = "SAFE", - PROXY = "PROXY" - } - - // Transaction states - enum RelayerTransactionState { - STATE_NEW = "STATE_NEW", - STATE_EXECUTED = "STATE_EXECUTED", - STATE_MINED = "STATE_MINED", - STATE_CONFIRMED = "STATE_CONFIRMED", - STATE_FAILED = "STATE_FAILED", - STATE_INVALID = "STATE_INVALID" - } - - // Response from relayer - interface RelayerTransaction { - transactionID: string; - transactionHash: string; - from: string; - to: string; - proxyAddress: string; - data: string; - state: string; - type: string; - metadata: string; - createdAt: Date; - updatedAt: Date; - } + 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() + ``` + + +### Batch Transactions + +Execute multiple operations atomically in a single call: + + + ```typescript TypeScript theme={null} + const approveTx = { + to: USDC, + data: encodeFunctionData({ + abi: erc20Abi, + functionName: "approve", + args: [CTF, maxUint256], + }), + value: "0", + }; + + const transferTx = { + to: USDC, + 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": USDC, + "data": contract.encode_abi( + abi_element_identifier="approve", + args=[CTF, MAX_UINT256] + ), + "value": "0" + } + + transfer_tx = { + "to": USDC, + "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() + ``` + + + + Batching reduces latency and ensures all transactions succeed or fail + together. + + +## 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 [Contract Addresses](/resources/contract-addresses) 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) +* [Builder Signing SDK (TypeScript)](https://github.com/Polymarket/builder-signing-sdk) +* [Builder Signing SDK (Python)](https://github.com/Polymarket/py-builder-signing-sdk) ## Next Steps - - Attribute orders to your builder account + + Learn about capital-efficient trading for multi-outcome events. - - Complete integration examples + + Understand token operations like split, merge, and redeem. diff --git a/docs/developers/gamma-markets-api/fetch-markets-guide.md b/docs/developers/gamma-markets-api/fetch-markets-guide.md index d713a5f..ee119af 100644 --- a/docs/developers/gamma-markets-api/fetch-markets-guide.md +++ b/docs/developers/gamma-markets-api/fetch-markets-guide.md @@ -2,76 +2,80 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# How to Fetch Markets +# Fetching Markets -Both the getEvents and getMarkets are paginated. See [pagination section](#pagination) for details. -This guide covers the three recommended approaches for fetching market data from the Gamma API, each optimized for different use cases. +> Three strategies for discovering and querying markets -## Overview + + Both the events and markets endpoints are paginated. See + [pagination](#pagination) for details. + -There are three main strategies for retrieving market data: +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 +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 *** -## 1. Fetch by Slug +## Fetch by Slug -**Use Case:** When you need to retrieve a specific market or event that you already know about. +**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/` or `/market/`: +From any Polymarket URL, the slug is the path segment after `/event/`: ``` -https://polymarket.com/event/fed-decision-in-october?tid=1758818660485 - ↑ - Slug: fed-decision-in-october +https://polymarket.com/event/fed-decision-in-october + ↑ + Slug: fed-decision-in-october ``` -### API Endpoints - -**For Events:** [GET /events/slug/{slug}](/api-reference/events/list-events) - -**For Markets:** [GET /markets/slug/{slug}](/api-reference/markets/list-markets) - ### 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" +``` + *** -## 2. Fetch by Tags +## Fetch by Tags -**Use Case:** When you want to filter markets by category, sport, or topic. +**Use case:** When you want to filter markets by category, sport, or topic. -Tags provide a powerful way to categorize and filter markets. You can discover available tags and then use them to filter your market requests. +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](/api-reference/tags/list-tags) +**General tags:** `GET /tags` (Gamma API) -**Sports Tags & Metadata:** [GET /sports](/api-reference/sports/get-sports-metadata-information) +**Sports tags and metadata:** `GET /sports` (Gamma API) -The `/sports` endpoint returns comprehensive metadata for sports including tag IDs, images, resolution sources, and series information. +The `/sports` endpoint returns metadata for sports including tag IDs, images, resolution sources, and series information. -### Using Tags in Market Requests +### Filter by Tag -Once you have tag IDs, you can use them with the `tag_id` parameter in both markets and events endpoints. - -**Markets with Tags:** [GET /markets](/api-reference/markets/list-markets) - -**Events with Tags:** [GET /events](/api-reference/events/list-events) +Once you have tag IDs, use the `tag_id` parameter in both events and markets endpoints: ```bash theme={null} -curl "https://gamma-api.polymarket.com/events?tag_id=100381&limit=1&closed=false" - +# 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 @@ -81,80 +85,76 @@ 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" +``` + *** -## 3. Fetch All Active Markets +## Fetch All Active Markets -**Use Case:** When you need to retrieve all available active markets, typically for broader analysis or market discovery. +**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 and work backwards, as events contain their associated markets. +The most efficient approach is to use the events endpoint with `active=true&closed=false`, as events contain their associated markets. -**Events Endpoint:** [GET /events](/api-reference/events/list-events) - -**Markets Endpoint:** [GET /markets](/api-reference/markets/list-markets) +```bash theme={null} +curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=100" +``` ### Key Parameters -* `order=id` - Order by event ID -* `ascending=false` - Get newest events first -* `closed=false` - Only active markets -* `limit` - Control response size -* `offset` - For pagination - -### Examples +| 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 | +| `limit` | Results per page | +| `offset` | Number of results to skip for pagination | ```bash theme={null} -curl "https://gamma-api.polymarket.com/events?order=id&ascending=false&closed=false&limit=100" +# Get the highest volume active events +curl "https://gamma-api.polymarket.com/events?active=true&closed=false&order=volume_24hr&ascending=false&limit=100" ``` -This approach gives you all active markets ordered from newest to oldest, allowing you to systematically process all available trading opportunities. +*** -### Pagination +## Pagination -For large datasets, use pagination with `limit` and `offset` parameters: - -* `limit=50` - Return 50 results per page -* `offset=0` - Start from the beginning (increment by limit for subsequent pages) - -**Pagination Examples:** +All list endpoints return paginated responses with `limit` and `offset` parameters: ```bash theme={null} -# Page 1: First 50 results (offset=0) -curl "https://gamma-api.polymarket.com/events?order=id&ascending=false&closed=false&limit=50&offset=0" -``` +# Page 1: First 50 results +curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=50&offset=0" -```bash theme={null} -# Page 2: Next 50 results (offset=50) -curl "https://gamma-api.polymarket.com/events?order=id&ascending=false&closed=false&limit=50&offset=50" -``` +# Page 2: Next 50 results +curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=50&offset=50" -```bash theme={null} -# Page 3: Next 50 results (offset=100) -curl "https://gamma-api.polymarket.com/events?order=id&ascending=false&closed=false&limit=50&offset=100" -``` - -```bash theme={null} -# Paginating through markets with tag filtering -curl "https://gamma-api.polymarket.com/markets?tag_id=100381&closed=false&limit=25&offset=0" -``` - -```bash theme={null} -# Next page of markets with tag filtering -curl "https://gamma-api.polymarket.com/markets?tag_id=100381&closed=false&limit=25&offset=25" +# 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:** Always use the slug method for best performance -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 `closed=false`:** Unless you specifically need historical data -5. **Implement Rate Limiting:** Respect API limits for production applications +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&closed=false`** unless you specifically need historical data +5. **Use the events endpoint** and work backwards — events contain their associated markets, reducing the number of API calls needed -## Related Endpoints +*** -* [Get Markets](/developers/gamma-markets-api/get-markets) - Full markets endpoint documentation -* [Get Events](/developers/gamma-markets-api/get-events) - Full events endpoint documentation -* [Search Markets](/developers/gamma-markets-api/get-public-search) - Search functionality +## Next Steps + + + + Full endpoint documentation with parameters and response schemas. + + + + Query onchain data directly from the Polymarket subgraph. + + diff --git a/docs/developers/gamma-markets-api/gamma-structure.md b/docs/developers/gamma-markets-api/gamma-structure.md index ab712f4..1a2fedd 100644 --- a/docs/developers/gamma-markets-api/gamma-structure.md +++ b/docs/developers/gamma-markets-api/gamma-structure.md @@ -2,26 +2,107 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Gamma Structure +# Markets & Events -Gamma provides some organizational models. These include events, and markets. The most fundamental element is always markets and the other models simply provide additional organization. +> Understanding the fundamental building blocks of Polymarket -# Detail +Every prediction on Polymarket is structured around two core concepts: **markets** and **events**. Understanding how they relate is essential for building on the platform. -1. **Market** - 1. Contains data related to a market that is traded on. Maps onto a pair of clob token ids, a market address, a question id and a condition id + + -2. **Event** - 1. Contains a set of markets - 2. Variants: - 1. Event with 1 market (i.e., resulting in an SMP) - 2. Event with 2 or more markets (i.e., resulting in an GMP) + + -# Example +## Markets -* **\[Event]** Where will Barron Trump attend College? - * **\[Market]** Will Barron attend Georgetown? - * **\[Market]** Will Barron attend NYU? - * **\[Market]** Will Barron attend UPenn? - * **\[Market]** Will Barron attend Harvard? - * **\[Market]** Will Barron attend another college? +A **market** is the fundamental tradable unit on Polymarket. Each market represents a single binary question with Yes/No outcomes. + + + + + + + +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 | + + + 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. + + +### 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 + + + + Learn how prices are determined and how the order book works. + + + + Start querying markets and events from the API. + + diff --git a/docs/developers/gamma-markets-api/overview.md b/docs/developers/gamma-markets-api/overview.md index 2574113..a114bc8 100644 --- a/docs/developers/gamma-markets-api/overview.md +++ b/docs/developers/gamma-markets-api/overview.md @@ -2,10 +2,110 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# null +# Overview -All market data necessary for market resolution is available on-chain (ie ancillaryData in UMA 00 request), but Polymarket also provides a hosted service, Gamma, that indexes this data and provides additional market metadata (ie categorization, indexed volume, etc). This service is made available through a REST API. For public users, this resource read only and can be used to fetch useful information about markets for things like non-profit research projects, alternative trading interfaces, automated trading systems etc. +> Fetch market data with no authentication required -# Endpoint +All market data is available through public REST endpoints. No API key, no authentication, no wallet required. -[https://gamma-api.polymarket.com](https://gamma-api.polymarket.com) +```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. + + + + A top-level object representing a question (e.g., "Who will win the 2024 + Presidential Election?"). Contains one or more markets. + + + + 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. + + + +### 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) +``` + +Markets can be traded via the CLOB if `enableOrderBook` is `true`. + +*** + +## 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 (`gamma-api.polymarket.com`) — Events, Markets & 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 (`clob.polymarket.com`) — Prices & 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 (`data-api.polymarket.com`) — Positions, Trades & 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 + + + + Three strategies for discovering and querying markets. + + + + Full endpoint documentation with parameters and response schemas. + + diff --git a/docs/developers/market-makers/data-feeds.md b/docs/developers/market-makers/data-feeds.md index 28f9901..ee119af 100644 --- a/docs/developers/market-makers/data-feeds.md +++ b/docs/developers/market-makers/data-feeds.md @@ -2,165 +2,159 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Data Feeds +# Fetching Markets -> Real-time and historical data sources for market makers +> Three strategies for discovering and querying markets -## Overview + + Both the events and markets endpoints are paginated. See + [pagination](#pagination) for details. + -Market makers need fast, reliable data to price markets and manage inventory. Polymarket provides several data feeds at different latency and detail levels. +There are three main strategies for retrieving market data, each optimized for different use cases: -| Feed | Latency | Use Case | Access | -| --------- | ---------- | ------------------------- | ------ | -| WebSocket | \~100ms | Standard MM operations | Public | -| Gamma API | \~1s | Market metadata, indexing | Public | -| Onchain | Block time | Settlement, resolution | Public | +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 -## WebSocket Feeds +*** -The WebSocket API provides real-time market data with low latency. This is sufficient for most market making strategies. +## Fetch by Slug -### Connecting +**Use case:** When you need to retrieve a specific market or event that you already know about. -```typescript theme={null} -const ws = new WebSocket("wss://ws-subscriptions-clob.polymarket.com/ws/market"); +Individual markets and events are best fetched using their unique slug identifier. The slug can be found directly in the Polymarket frontend URL. -ws.onopen = () => { - // Subscribe to orderbook updates - ws.send(JSON.stringify({ - type: "market", - assets_ids: [tokenId] - })); -}; +### How to Extract the Slug -ws.onmessage = (event) => { - const data = JSON.parse(event.data); - // Handle orderbook update -}; +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 ``` -### Available Channels +### Examples -| Channel | Message Types | Documentation | -| -------- | ------------------------------------------ | ----------------------------------------------------------- | -| `market` | `book`, `price_change`, `last_trade_price` | [Market Channel](/developers/CLOB/websocket/market-channel) | -| `user` | Order fills, cancellations | [User Channel](/developers/CLOB/websocket/user-channel) | +```bash theme={null} +# Fetch an event by slug (query parameter) +curl "https://gamma-api.polymarket.com/events?slug=fed-decision-in-october" -### User Channel (Authenticated) - -Monitor your order activity in real-time: - -```typescript theme={null} -// Requires authentication -const userWs = new WebSocket("wss://ws-subscriptions-clob.polymarket.com/ws/user"); - -userWs.onopen = () => { - userWs.send(JSON.stringify({ - type: "user", - auth: { - apiKey: "your-api-key", - secret: "your-secret", - passphrase: "your-passphrase" - }, - markets: [conditionId] // Optional: filter to specific markets - })); -}; - -userWs.onmessage = (event) => { - const data = JSON.parse(event.data); - // Handle order fills, cancellations, etc. -}; +# Or use the path endpoint +curl "https://gamma-api.polymarket.com/events/slug/fed-decision-in-october" ``` -See [WebSocket Authentication](/developers/CLOB/websocket/wss-auth) for auth details. +```bash theme={null} +# Fetch a market by slug (query parameter) +curl "https://gamma-api.polymarket.com/markets?slug=fed-decision-in-october" -### Best Practices - -1. **Reconnection logic** - Implement automatic reconnection with exponential backoff -2. **Heartbeats** - Respond to ping messages to maintain connection -3. **Local orderbook** - Maintain a local copy and apply incremental updates -4. **Sequence numbers** - Track sequence to detect missed messages - -See [WebSocket Overview](/developers/CLOB/websocket/wss-overview) for complete documentation. - -## Gamma API - -The Gamma API provides market metadata and indexing. Use it for: - -* Market titles, slugs, categories -* Event/condition mapping -* Volume and liquidity data -* Outcome token metadata - -### Get Markets - -```typescript theme={null} -const response = await fetch( - "https://gamma-api.polymarket.com/markets?active=true" -); -const markets = await response.json(); +# Or use the path endpoint +curl "https://gamma-api.polymarket.com/markets/slug/fed-decision-in-october" ``` -### Get Events +*** -```typescript theme={null} -const response = await fetch( - "https://gamma-api.polymarket.com/events?slug=us-presidential-election" -); -const event = await response.json(); +## 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" ``` -### Key Fields for MMs +### Additional Tag Filtering -| Field | Description | -| --------------- | ------------------------ | -| `conditionId` | Unique market identifier | -| `clobTokenIds` | Outcome token IDs | -| `outcomes` | Outcome names | -| `outcomePrices` | Current outcome prices | -| `volume` | Trading volume | -| `liquidity` | Current liquidity | +You can also: -See [Gamma API Overview](/developers/gamma-markets-api/overview) for complete documentation. +* Use `related_tags=true` to include related tag markets +* Exclude specific tags with `exclude_tag_id` -## Onchain Data +```bash theme={null} +# Include related tags +curl "https://gamma-api.polymarket.com/events?tag_id=100381&related_tags=true&active=true&closed=false" +``` -For settlement, resolution, and position tracking, market makers may query onchain data directly. +*** -### Data Sources +## Fetch All Active Markets -| Data | Source | Use Case | -| -------------------- | ------------------- | ---------------------------- | -| Token balances | ERC1155 `balanceOf` | Position tracking | -| Resolution | UMA Oracle events | Pre-resolution risk modeling | -| Condition resolution | CTF contract | Post-resolution redemption | +**Use case:** When you need to retrieve all available active markets, typically for broader analysis or market discovery. -### RPC Providers +The most efficient approach is to use the events endpoint with `active=true&closed=false`, as events contain their associated markets. -Common providers for Polygon: +```bash theme={null} +curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=100" +``` -* Alchemy -* QuickNode -* Infura +### Key Parameters -### UMA Oracle +| 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 | +| `limit` | Results per page | +| `offset` | Number of results to skip for pagination | -Markets are resolved via UMA's Optimistic Oracle. Monitor resolution events for risk management. +```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" +``` -See [Resolution](/developers/resolution/UMA) for details on the resolution process. +*** -## Related Documentation +## Pagination - - - Complete WebSocket documentation +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&closed=false`** unless you specifically 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 + + + + Full endpoint documentation with parameters and response schemas. - - Market metadata and indexing - - - - UMA Oracle resolution process + + Query onchain data directly from the Polymarket subgraph. diff --git a/docs/developers/market-makers/introduction.md b/docs/developers/market-makers/introduction.md index 6c77808..e4c68bc 100644 --- a/docs/developers/market-makers/introduction.md +++ b/docs/developers/market-makers/introduction.md @@ -2,74 +2,81 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Market Maker Introduction +# Overview -> Overview of market making on Polymarket and available tools for liquidity providers +> Market making on Polymarket -## What is a Market Maker? +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. -A Market Maker (MM) on Polymarket is a sophisticated 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. -Market makers are essential to Polymarket's ecosystem: + + **Not a Market Maker?** If you're building an application that routes orders + for your users, see the [Builder Program](/builders/overview) instead. + -* **Provide liquidity** across all markets -* **Tighten spreads** for better user experience -* **Enable price discovery** through continuous quoting -* **Absorb trading flow** from retail and institutional users - -**Not a Market Maker?** If you're building an application that routes orders for your -users, see the [Builders Program](/developers/builders/builder-intro) instead. Builders -get access to gasless transactions via the Relayer Client. +*** ## Getting Started -To become a market maker on Polymarket: + + + Deploy wallets, fund with USDC.e, and set token approvals. See the [Getting + Started](/market-makers/getting-started) guide. + -1. **Complete setup** - Deploy wallets, fund with USDCe, set token approvals -2. **Connect to data feeds** - WebSocket for orderbook, RTDS for low-latency data -3. **Start quoting** - Post orders via CLOB REST API + + WebSocket for real-time orderbook updates, Gamma API for market metadata. + See [Market Data](/market-data/overview). + -## Available Tools + + Post orders via the CLOB REST API. See [Trading ](/market-makers/trading). + + -### By Action Type - - - - Deposits, token approvals, wallet deployment, API keys - - - - CLOB order entry, order types, quoting best practices - - - - WebSocket, RTDS, Gamma API, on-chain data - - - - Split, merge, and redeem outcome tokens - - - - Earn rewards for providing liquidity - - - - Earn rebates for providing liquidity - - +*** ## Quick Reference -| Action | Tool | Documentation | -| --------------------- | -------------- | ------------------------------------------------------------- | -| Deposit USDCe | Bridge API | [Bridge Overview](/developers/misc-endpoints/bridge-overview) | -| Approve tokens | Relayer Client | [Setup Guide](/developers/market-makers/setup) | -| Post limit orders | CLOB REST API | [CLOB Client](/developers/CLOB/clients/methods-l2) | -| Monitor orderbook | WebSocket | [WebSocket Overview](/developers/CLOB/websocket/wss-overview) | -| Low-latency data | RTDS | [Data Feeds](/developers/market-makers/data-feeds) | -| Split USDCe to tokens | CTF / Relayer | [Inventory](/developers/market-makers/inventory) | -| Merge tokens to USDCe | CTF / Relayer | [Inventory](/developers/market-makers/inventory) | +| Action | Tool | Documentation | +| ---------------------- | -------------- | ------------------------------------------------- | +| Deposit USDC.e | 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 USDC.e to tokens | CTF / Relayer | [Inventory](/market-makers/inventory) | +| Merge tokens to USDC.e | CTF / Relayer | [Inventory](/market-makers/inventory) | + +*** + +## What's in This Section + + + + Deposits, token approvals, wallet deployment, API keys + + + + Quoting best practices, strategies, and risk controls + + + + Split, merge, and redeem outcome tokens + + + + Earn rewards for providing liquidity + + + +## Risks + + + 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. + ## Support diff --git a/docs/developers/market-makers/inventory.md b/docs/developers/market-makers/inventory.md deleted file mode 100644 index e746b53..0000000 --- a/docs/developers/market-makers/inventory.md +++ /dev/null @@ -1,247 +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. - -# Inventory Management - -> Split, merge, and redeem outcome tokens for market making - -## Overview - -Market makers need to manage their inventory of outcome tokens. This involves: - -1. **Splitting** USDCe into YES/NO tokens to have inventory to quote -2. **Merging** tokens back to USDCe to reduce exposure -3. **Redeeming** winning tokens after market resolution - -All these operations use the Conditional Token Framework (CTF) contract, typically via the Relayer Client for gasless execution. - - - These examples assume you have initialized a RelayClient. See [Setup](/developers/market-makers/setup) for client initialization. - - -## Splitting USDCe into Tokens - -Split 1 USDCe into 1 YES + 1 NO token. This creates inventory for quoting both sides. - -### Via Relayer Client (Recommended) - -```typescript theme={null} -import { ethers } from "ethers"; -import { Interface } from "ethers/lib/utils"; -import { RelayClient, Transaction } from "@polymarket/builder-relayer-client"; - -const CTF_ADDRESS = "0x4d97dcd97ec945f40cf65f87097ace5ea0476045"; -const USDCe_ADDRESS = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"; - -const ctfInterface = new Interface([ - "function splitPosition(address collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint[] partition, uint amount)" -]); - -// Split $1000 USDCe into YES/NO tokens -const amount = ethers.utils.parseUnits("1000", 6); // USDCe has 6 decimals - -const splitTx: Transaction = { - to: CTF_ADDRESS, - data: ctfInterface.encodeFunctionData("splitPosition", [ - USDCe_ADDRESS, // collateralToken - ethers.constants.HashZero, // parentCollectionId (null for Polymarket) - conditionId, // conditionId from market - [1, 2], // partition: [YES, NO] - amount - ]), - value: "0" -}; - -const response = await client.execute([splitTx], "Split USDCe into tokens"); -const result = await response.wait(); -console.log("Split completed:", result?.transactionHash); -``` - -### Result - -After splitting 1000 USDCe: - -* Receive 1000 YES tokens -* Receive 1000 NO tokens -* USDCe balance decreases by 1000 - -## Merging Tokens to USDCe - -Merge equal amounts of YES + NO tokens back into USDCe. Useful for: - -* Reducing inventory -* Exiting a market -* Converting profits to USDCe - -### Via Relayer Client - -```typescript theme={null} -const ctfInterface = new Interface([ - "function mergePositions(address collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint[] partition, uint amount)" -]); - -// Merge 500 YES + 500 NO back to 500 USDCe -const amount = ethers.utils.parseUnits("500", 6); - -const mergeTx: Transaction = { - to: CTF_ADDRESS, - data: ctfInterface.encodeFunctionData("mergePositions", [ - USDCe_ADDRESS, - ethers.constants.HashZero, - conditionId, - [1, 2], - amount - ]), - value: "0" -}; - -const response = await client.execute([mergeTx], "Merge tokens to USDCe"); -await response.wait(); -``` - -### Result - -After merging 500 of each: - -* YES tokens decrease by 500 -* NO tokens decrease by 500 -* USDCe balance increases by 500 - -## Redeeming After Resolution - -After a market resolves, redeem winning tokens for USDCe. - -### Check Resolution Status - -```typescript theme={null} -// Via CLOB API -const market = await clobClient.getMarket(conditionId); -if (market.closed) { - // Market is resolved - const winningToken = market.tokens.find(t => t.winner); - console.log("Winning outcome:", winningToken?.outcome); -} -``` - -### Redeem Winning Tokens - -```typescript theme={null} -const ctfInterface = new Interface([ - "function redeemPositions(address collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint[] indexSets)" -]); - -const redeemTx: Transaction = { - to: CTF_ADDRESS, - data: ctfInterface.encodeFunctionData("redeemPositions", [ - USDCe_ADDRESS, - ethers.constants.HashZero, - conditionId, - [1, 2] // Redeem both YES and NO (only winners pay out) - ]), - value: "0" -}; - -const response = await client.execute([redeemTx], "Redeem winning tokens"); -await response.wait(); -``` - -### Payout - -* If YES wins: Each YES token redeems for \$1 USDCe -* If NO wins: Each NO token redeems for \$1 USDCe -* Losing tokens are worthless (redeem for \$0) - -## Negative Risk Markets - -Multi-outcome markets use the Negative Risk CTF Exchange. The split/merge process is similar but uses different contract addresses. - -```typescript theme={null} -const NEG_RISK_ADAPTER = "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296"; -const NEG_RISK_CTF_EXCHANGE = "0xC5d563A36AE78145C45a50134d48A1215220f80a"; -``` - -See [Negative Risk Overview](/developers/neg-risk/overview) for details. - -## Inventory Strategies - -### Pre-market Preparation - -Before quoting a market: - -1. Check market metadata via Gamma API -2. Split sufficient USDCe to cover expected quoting size -3. Set token approvals if not already done - -### During Trading - -Monitor inventory and adjust: - -* Skew quotes when inventory is imbalanced -* Merge excess tokens to free up capital -* Split more when inventory runs low - -### Post-Resolution - -After market closes: - -1. Cancel all open orders -2. Wait for resolution -3. Redeem winning tokens -4. Merge any remaining pairs - -## Batch Operations - -For efficiency, batch multiple operations: - -```typescript theme={null} -const transactions: Transaction[] = [ - // Split on Market A - { - to: CTF_ADDRESS, - data: ctfInterface.encodeFunctionData("splitPosition", [ - USDCe_ADDRESS, - ethers.constants.HashZero, - conditionIdA, - [1, 2], - ethers.utils.parseUnits("1000", 6) - ]), - value: "0" - }, - // Split on Market B - { - to: CTF_ADDRESS, - data: ctfInterface.encodeFunctionData("splitPosition", [ - USDCe_ADDRESS, - ethers.constants.HashZero, - conditionIdB, - [1, 2], - ethers.utils.parseUnits("1000", 6) - ]), - value: "0" - } -]; - -const response = await client.execute(transactions, "Batch inventory setup"); -await response.wait(); -``` - -## Related Documentation - - - - Conditional Token Framework basics - - - - Detailed split documentation - - - - Detailed merge documentation - - - - Gasless transaction execution - - diff --git a/docs/developers/market-makers/liquidity-rewards.md b/docs/developers/market-makers/liquidity-rewards.md deleted file mode 100644 index c8fadef..0000000 --- a/docs/developers/market-makers/liquidity-rewards.md +++ /dev/null @@ -1,126 +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. - -# Liquidity Rewards - -> Polymarket provides incentives aimed at catalyzing the supply and demand side of the marketplace. Specifically there is a public liquidity rewards program as well as one-off public pnl/volume competitions. - -## Overview - -By posting resting limit orders, liquidity providers (makers) are automatically eligible for Polymarket's incentive program. The overall goal of this program is to catalyze a healthy, liquid marketplace. We can further define this as creating incentives that: - -* Catalyze liquidity across all markets -* Encourage liquidity throughout a market's entire lifecycle -* Motivate passive, balanced quoting tight to a market's mid-point -* Encourages trading activity -* Discourages blatantly exploitative behaviors - -This program is heavily inspired by dYdX's liquidity provider rewards which you can read more about [here](https://www.dydx.foundation/blog/liquidity-provider-rewards). In fact, the incentive methodology is essentially a copy of dYdX's successful methodology but with some adjustments including specific adaptations for binary contract markets with distinct books, no staking mechanic a slightly modified order utility-relative depth function and reward amounts isolated per market. Rewards are distributed directly to the maker's addresses daily at midnight UTC. - -## Methodology - -Polymarket liquidity providers will be rewarded based on a formula that rewards participation in markets (complementary consideration!), boosts two-sided depth (single-sided orders still score), and spread (vs. mid-market, adjusted for the size cutoff!). Each market still configure a max spread and min size cutoff within which orders are considered the average of rewards earned is determined by the relative share of each participant's Qn in market m. - -| Variable | Description | -| -------------- | ---------------------------------------------------------------- | -| \$ | order position scoring function | -| v | max spread from midpoint (in cents) | -| s | spread from size-cutoff-adjusted midpoint | -| b | in-game multiplier | -| m | market | -| m' | market complement (i.e NO if m = YES) | -| n | trader index | -| u | sample index | -| c | scaling factor (currently 3.0 on all markets) | -| Qne | point total for book one for a sample | -| Qno | point total for book two for a sample | -| Spread% | distance from midpoint (bps or relative) for order n in market m | -| BidSize | share-denominated quantity of bid | -| AskSize | share-denominated quantity of ask | - -## Equations - -**Equation 1:** - -$S(v,s)= (\frac{v-s}{v})^2 \cdot b$ - -**Equation 2:** - -$Q_{one}= S(v,Spread_{m_1}) \cdot BidSize_{m_1} + S(v,Spread_{m_2}) \cdot BidSize_{m_2} + \dots $ -$ + S(v, Spread_{m^\prime_1}) \cdot AskSize_{m^\prime_1} + S(v, Spread_{m^\prime_2}) \cdot AskSize_{m^\prime_2}$ - -**Equation 3:** - -$Q_{two}= S(v,Spread_{m_1}) \cdot AskSize_{m_1} + S(v,Spread_{m_2}) \cdot AskSize_{m_2} + \dots $ -$ + S(v, Spread_{m^\prime_1}) \cdot BidSize_{m^\prime_1} + S(v, Spread_{m^\prime_2}) \cdot BidSize_{m^\prime_2}$ - -**Equation 4:** - -**Equation 4a:** - -If midpoint is in range \[0.10,0.90] allow single sided liq to score: - -$Q_{\min} = \max(\min({Q_{one}, Q_{two}}), \max(Q_{one}/c, Q_{two}/c))$ - -**Equation 4b:** - -If midpoint is in either range \[0,0.10) or (.90,1.0] require liq to be double sided to score: - -$Q_{\min} = \min({Q_{one}, Q_{two}})$ - -**Equation 5:** - -$Q_{normal} = \frac{Q_{min}}{\sum_{n=1}^{N}{(Q_{min})_n}}$ - -**Equation 6:** - -$Q_{epoch} = \sum_{u=1}^{10,080}{(Q_{normal})_u}$ - -**Equation 7:** - -$Q_{final}=\frac{Q_{epoch}}{\sum_{n=1}^{N}{(Q_{epoch})_n}}$ - -## Steps - -1. Quadratic scoring rule for an order based on position between the adjusted midpoint and the minimum qualifying spread - -2. Calculate first market side score. Assume a trader has the following open orders: - - * 100Q bid on m @0.49 (adjusted midpoint is 0.50 then spread of this order is 0.01 or 1c) - * 200Q bid on m @0.48 - * 100Q ask on m' @0.51 - - and assume an adjusted market midpoint of 0.50 and maxSpread config of 3c for both m and m'. Then the trader's score is: - - $$ - Q_{ne} = \left( \frac{(3-1)}{3} \right)^2 \cdot 100 + \left( \frac{(3-2)}{3} \right)^2 \cdot 200 + \left( \frac{(3-1)}{3} \right)^2 \cdot 100 - $$ - - $Q_{ne}$ is calculated every minute using random sampling - -3. Calculate second market side score. Assume a trader has the following open orders: - - * 100Q bid on m @0.485 - * 100Q bid on m' @0.48 - * 200Q ask on m' @0.505 - - and assume an adjusted market midpoint of 0.50 and maxSpread config of 3c for both m and m'. Then the trader's score is: - - $$ - Q_{no} = \left( \frac{(3-1.5)}{3} \right)^2 \cdot 100 + \left( \frac{(3-2)}{3} \right)^2 \cdot 100 + \left( \frac{(3-.5)}{3} \right)^2 \cdot 200 - $$ - - $Q_{no}$ is calculated every minute using random sampling - -4. Boosts 2-sided liquidity by taking the minimum of $Q_{ne}$ and $Q_{no}$, and rewards 1-side liquidity at a reduced rate (divided by c) - - Calculated every minute - -5. $Q_{normal}$ is the $Q_{min}$ of a market maker divided by the sum of all the $Q_{min}$ of other market makers in a given sample - -6. $Q_{epoch}$ is the sum of all $Q_{normal}$ for a trader in a given epoch - -7. $Q_{final}$ normalizes $Q_{epoch}$ by dividing it by the sum of all other market maker's $Q_{epoch}$ in a given epoch this value is multiplied by the rewards available for the market to get a trader's reward - -Both min\_incentive\_size and max\_incentive\_spread can be fetched alongside full market objects via both the CLOB API and Markets API. Reward allocations for an epoch can be fetched via the Markets API. diff --git a/docs/developers/market-makers/setup.md b/docs/developers/market-makers/setup.md index 86fcc4c..ca9a8f5 100644 --- a/docs/developers/market-makers/setup.md +++ b/docs/developers/market-makers/setup.md @@ -2,175 +2,231 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Setup +# Getting Started -> One-time setup for market making on Polymarket: deposits, approvals, wallets, and API keys +> One-time setup for market making on Polymarket -## Overview +Before you can start market making, you need to complete these one-time setup steps — deposit USDC.e to Polygon, deploy a wallet, approve tokens for trading, and generate API credentials. -Before you can start market making on Polymarket, you need to complete these one-time setup steps: + + + Market makers need USDC.e on Polygon to fund their trading operations. -1. Deposit bridged USDCe to Polygon -2. Deploy a wallet (EOA or Safe) -3. Approve tokens for trading -4. Generate API credentials + | Method | Best For | Documentation | + | ----------------------- | ------------------------------------ | ---------------------------------------------------- | + | Bridge API | Automated deposits from other chains | [Bridge Deposit](/trading/bridge/deposit) | + | Direct Polygon transfer | Already have USDC.e on Polygon | N/A | + | Cross-chain bridge | Large deposits from Ethereum | [Supported Assets](/trading/bridge/supported-assets) | -## Deposit USDCe + ### Using the Bridge API -Market makers need USDCe on Polygon to fund their trading operations. + ```typescript theme={null} + // Get deposit 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", + }), + }); -### Options + // Returns deposit addresses for EVM, SVM, and BTC networks + const addresses = await deposit.json(); + // Send USDC to the appropriate address for your source chain + ``` + -| Method | Best For | Documentation | -| ----------------------- | ------------------------------------ | ----------------------------------------------------------------------- | -| Bridge API | Automated deposits from other chains | [Bridge Overview](/developers/misc-endpoints/bridge-overview) | -| Direct Polygon transfer | Already have USDCe on Polygon | N/A | -| Cross-chain bridge | Large deposits from Ethereum | [Large Deposits](/polymarket-learn/deposits/large-cross-chain-deposits) | + + ### EOA (Externally Owned Account) -### Using the Bridge API + Standard Ethereum wallet. You pay for all onchain transactions (approvals, splits, merges, trade execution). -```typescript theme={null} -// Deposit USDCe from Ethereum to Polygon -const deposit = await fetch("https://clob.polymarket.com/deposit", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ - chainId: "1", - fromChain: "ethereum", - toChain: "polygon", - asset: "USDCe", - amount: "100000000000" // $100,000 in USDCe (6 decimals) - }) -}); -``` + ### Safe Wallet (Recommended) -See [Bridge Deposit](/api-reference/bridge/create-deposit-addresses) for full API details. + Gnosis Safe-based wallet deployed via Polymarket's relayer. Benefits: -## Wallet Options + * **Gasless transactions** — Polymarket pays gas fees for onchain operations + * **Contract wallet** — Enables advanced features like batched transactions -### EOA (Externally Owned Account) + Deploy a Safe wallet using the Relayer Client: -Standard Ethereum wallet. You pay for all onchain transactions (approvals, splits, merges, trade exedcution). + + ```typescript TypeScript theme={null} + import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client"; -### Safe Wallet (Recommended) + const client = new RelayClient( + "https://relayer-v2.polymarket.com/", + 137, // Polygon mainnet + signer, + builderConfig, + RelayerTxType.SAFE, + ); -Gnosis Safe-based wallet deployed via Polymarket's relayer. Benefits: + // Deploy the Safe wallet + const response = await client.deploy(); + const result = await response.wait(); + console.log("Safe Address:", result?.proxyAddress); + ``` -* **Gasless transactions** - Polymarket pays gas fees for onchain operations -* **Contract wallet** - Enables advanced features like batched transactions. + ```python Python theme={null} + from py_builder_relayer_client.client import RelayClient -Deploy a Safe wallet using the [Relayer Client](/developers/builders/relayer-client): + # client initialized with builder_config -```typescript theme={null} -import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client"; + # Deploy the Safe wallet + response = client.deploy() + result = response.wait() + print("Safe Address:", result.get("proxyAddress")) + ``` + -const client = new RelayClient( - "https://relayer-v2.polymarket.com/", - 137, // Polygon mainnet - signer, - builderConfig, - RelayerTxType.SAFE -); + + See [Gasless Transactions](/trading/gasless) for full Relayer Client setup + including local and remote signing configurations. + + -// Deploy the Safe wallet -const response = await client.deploy(); -const result = await response.wait(); -console.log("Safe Address:", result?.proxyAddress); -``` + + Before trading, you must approve the exchange contracts to spend your tokens. -## Token Approvals + ### Required Approvals -Before trading, you must approve the exchange contracts to spend your tokens. + | Token | Spender | Purpose | + | -------------------- | --------------------- | -------------------------------- | + | USDC.e | CTF Contract | Split USDC.e into outcome tokens | + | CTF (outcome tokens) | CTF Exchange | Trade outcome tokens | + | CTF (outcome tokens) | Neg Risk CTF Exchange | Trade neg-risk market tokens | -### Required Approvals + ### Contract Addresses (Polygon Mainnet) -| Token | Spender | Purpose | -| -------------------- | --------------------- | ------------------------------- | -| USDCe | CTF Contract | Split USDCe into outcome tokens | -| CTF (outcome tokens) | CTF Exchange | Trade outcome tokens | -| CTF (outcome tokens) | Neg Risk CTF Exchange | Trade neg-risk market tokens | + ```typescript theme={null} + const ADDRESSES = { + USDCe: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", + CTF: "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045", + CTF_EXCHANGE: "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", + NEG_RISK_CTF_EXCHANGE: "0xC5d563A36AE78145C45a50134d48A1215220f80a", + NEG_RISK_ADAPTER: "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296", + }; + ``` -### Contract Addresses (Polygon Mainnet) + ### Approve via Relayer Client -```typescript theme={null} -const ADDRESSES = { - USDCe: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", - CTF: "0x4d97dcd97ec945f40cf65f87097ace5ea0476045", - CTF_EXCHANGE: "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", - NEG_RISK_CTF_EXCHANGE: "0xC5d563A36AE78145C45a50134d48A1215220f80a", - NEG_RISK_ADAPTER: "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296" -}; -``` + + ```typescript TypeScript theme={null} + import { ethers } from "ethers"; + import { Interface } from "ethers/lib/utils"; -### Approve via Relayer Client + const erc20Interface = new Interface([ + "function approve(address spender, uint256 amount) returns (bool)", + ]); -```typescript theme={null} -import { ethers } from "ethers"; -import { Interface } from "ethers/lib/utils"; + // Approve USDCe for CTF contract + const approveTx = { + to: ADDRESSES.USDCe, + data: erc20Interface.encodeFunctionData("approve", [ + ADDRESSES.CTF, + ethers.constants.MaxUint256, + ]), + value: "0", + }; -const erc20Interface = new Interface([ - "function approve(address spender, uint256 amount) returns (bool)" -]); + const response = await client.execute([approveTx], "Approve USDCe for CTF"); + await response.wait(); + ``` -// Approve USDCe for CTF contract -const approveTx = { - to: ADDRESSES.USDCe, - data: erc20Interface.encodeFunctionData("approve", [ - ADDRESSES.CTF, - ethers.constants.MaxUint256 - ]), - value: "0" -}; + ```python Python theme={null} + from web3 import Web3 -const response = await client.execute([approveTx], "Approve USDCe for CTF"); -await response.wait(); -``` + USDC = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" + CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045" + MAX_UINT256 = 2**256 - 1 -See [Relayer Client](/developers/builders/relayer-client) for complete examples. + approve_tx = { + "to": USDC, + "data": Web3().eth.contract( + address=USDC, + 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" + } -## API Key Generation + response = client.execute([approve_tx], "Approve USDC for CTF") + response.wait() + ``` + + -To place orders and access authenticated endpoints, you need L2 API credentials. + + To place orders and access authenticated endpoints, you need L2 API credentials derived from your wallet. -### Generate API Key + + ```typescript TypeScript theme={null} + import { ClobClient } from "@polymarket/clob-client"; -```typescript theme={null} -import { ClobClient } from "@polymarket/clob-client"; + const client = new ClobClient("https://clob.polymarket.com", 137, signer); -const client = new ClobClient( - "https://clob.polymarket.com", - 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); + ``` -// Derive API credentials from your wallet -const credentials = await client.deriveApiKey(); -console.log("API Key:", credentials.key); -console.log("Secret:", credentials.secret); -console.log("Passphrase:", credentials.passphrase); -``` + ```python Python theme={null} + from py_clob_client.client import ClobClient + import os -### Using Credentials + private_key = os.getenv("PRIVATE_KEY") -Once you have credentials, initialize the client for authenticated operations: + temp_client = ClobClient("https://clob.polymarket.com", key=private_key, chain_id=137) + credentials = temp_client.create_or_derive_api_creds() + ``` + -```typescript theme={null} -const client = new ClobClient( - "https://clob.polymarket.com", - 137, - wallet, - credentials -); -``` + Once you have credentials, initialize the client for authenticated operations: -See [CLOB Authentication](/developers/CLOB/authentication) for full details. + + ```typescript TypeScript theme={null} + const tradingClient = new ClobClient( + "https://clob.polymarket.com", + 137, + wallet, + credentials, + ); + ``` + + ```python Python theme={null} + client = ClobClient( + "https://clob.polymarket.com", + key=private_key, + chain_id=137, + creds=credentials, + ) + ``` + + + See [Authentication](/trading/overview#authentication) for full details on signature types and REST API headers. + + + +*** ## Next Steps -Once setup is complete: - - - + + Post limit orders and manage quotes + + + Connect to real-time market data + diff --git a/docs/developers/market-makers/trading.md b/docs/developers/market-makers/trading.md deleted file mode 100644 index e24ad2b..0000000 --- a/docs/developers/market-makers/trading.md +++ /dev/null @@ -1,203 +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. - -# Trading - -> CLOB order entry and management for market makers - -## Overview - -Market makers primarily interact with Polymarket through the CLOB (Central Limit Order Book) API to post and manage limit orders. - -## Order Entry - -### Posting Limit Orders - -Use the CLOB client to create and post limit orders: - -```typescript theme={null} -import { ClobClient, Side, OrderType } from "@polymarket/clob-client"; - -const client = new ClobClient( - "https://clob.polymarket.com", - 137, - wallet, - credentials, - signatureType, - funder -); - -// Post a bid (buy order) -const bidOrder = await client.createAndPostOrder({ - tokenID: "34097058504275310827233323421517291090691602969494795225921954353603704046623", - side: Side.BUY, - price: 0.48, - size: 1000, - orderType: OrderType.GTC -}); - -// Post an ask (sell order) -const askOrder = await client.createAndPostOrder({ - tokenID: "34097058504275310827233323421517291090691602969494795225921954353603704046623", - side: Side.SELL, - price: 0.52, - size: 1000, - orderType: OrderType.GTC -}); -``` - -See [Create Order](/developers/CLOB/clients/methods-l1#createandpostorder) for full documentation. - -### Batch Orders - -For efficiency, post multiple orders in a single request: - -```typescript theme={null} -const orders = await Promise.all([ - client.createOrder({ tokenID, side: Side.BUY, price: 0.48, size: 500 }), - client.createOrder({ tokenID, side: Side.BUY, price: 0.47, size: 500 }), - client.createOrder({ tokenID, side: Side.SELL, price: 0.52, size: 500 }), - client.createOrder({ tokenID, side: Side.SELL, price: 0.53, size: 500 }) -]); - -const response = await client.postOrders( - orders.map(order => ({ order, orderType: OrderType.GTC })) -); -``` - -See [Post Orders Batch](/developers/CLOB/clients/methods-l2#postorders) for details. - -## Order Types - -| Type | Behavior | MM Use Case | -| ----------------------------- | --------------------------------------- | --------------------------------------- | -| **GTC** (Good Till Cancelled) | Rests on book until filled or cancelled | Default for passive quoting | -| **GTD** (Good Till Date) | Auto-expires at specified time | Auto-expire before events | -| **FOK** (Fill or Kill) | Fill entirely immediately or cancel | Aggressive rebalancing (all or nothing) | -| **FAK** (Fill and Kill) | Fill available immediately, cancel rest | Partial rebalancing acceptable | - -### When to Use Each - -**For passive market making (maker orders):** - -* **GTC** - Standard quotes that sit on the book -* **GTD** - Time-limited quotes (e.g., expire before market close) - -**For rebalancing (taker orders):** - -* **FOK** - When you need exact size or nothing -* **FAK** - When partial fills are acceptable - -```typescript theme={null} -// GTD example: expire in 1 hour -const expiringOrder = await client.createOrder({ - tokenID, - side: Side.BUY, - price: 0.50, - size: 1000, - orderType: OrderType.GTD, - expiration: Math.floor(Date.now() / 1000) + 3600 // 1 hour from now -}); -``` - -## Order Management - -### Cancel Orders - -Cancel individual orders or all orders: - -```typescript theme={null} -// Cancel single order -await client.cancelOrder(orderId); - -// Cancel multiple orders in a single calls -await client.cancelOrders(orderIds: string[]); - -// Cancel all orders for a market -await client.cancelMarketOrders(conditionId); - -// Cancel all orders -await client.cancelAll(); -``` - -See [Cancel Orders](/developers/CLOB/clients/methods-l2#cancelorder) for full documentation. - -### Get Active Orders - -Monitor your open orders: - -```typescript theme={null} -// Get active order -const order = await client.getOrder(orderId); - -// Get active orders optionally filtered -const orders = await client.getOpenOrders({ - id?: string; // Order ID (hash) - market?: string; // Market condition ID - asset_id?: string; // Token ID -}); -``` - -See [Get Active Orders](/developers/CLOB/clients/methods-l2#getorder) for details. - -## Best Practices - -### Quote Management - -1. **Two-sided quoting** - Post both bids and asks to earn maximum [liquidity rewards](/developers/market-makers/liquidity-rewards) -2. **Monitor inventory** - Skew quotes based on your position -3. **Cancel stale quotes** - Remove orders when market conditions change -4. **Use GTD for events** - Auto-expire quotes before known events - -### Latency Optimization - -1. **Batch orders** - Use `postOrders()` instead of multiple `createAndPostOrder()` calls -2. **WebSocket for data** - Use WebSocket feeds instead of polling REST endpoints - -### Risk Management - -1. **Size limits** - Check token balances before quoting; don't exceed inventory -2. **Price guards** - Validate against book midpoint; reject outlier prices -3. **Kill switch** - Use `cancelAll()` on error or position breach -4. **Monitor fills** - Subscribe to WebSocket user channel for real-time fill updates - -## Tick Sizes - -Markets have different minimum price increments: - -```typescript theme={null} -const tickSize = await client.getTickSize(tokenID); -// Returns: "0.1" | "0.01" | "0.001" | "0.0001" -``` - -Ensure your prices conform to the market's tick size. - -## Fee Structure - -| Role | Fee | -| ----- | ----- | -| Maker | 0 bps | -| Taker | 0 bps | - -Current fees are 0% for both makers and takers. See [CLOB Introduction](/developers/CLOB/introduction) for fee calculation details. - -## Related Documentation - - - - Complete client method reference - - - - Authenticated order management methods - - - - Real-time order and market data - - - - Earn rewards for providing liquidity - - diff --git a/docs/developers/misc-endpoints/bridge-overview.md b/docs/developers/misc-endpoints/bridge-overview.md index 17682d8..d9ffc9a 100644 --- a/docs/developers/misc-endpoints/bridge-overview.md +++ b/docs/developers/misc-endpoints/bridge-overview.md @@ -2,39 +2,104 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Overview +# Deposit -> Bridge and swap assets to Polymarket +> Bridge assets from any supported chain to fund your Polymarket account -The Polymarket Bridge API enables seamless deposits and withdrawals between multiple networks and Polymarket. +Polymarket uses **USDC.e** (Bridged USDC) 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 USDC.e on Polygon. -### USDC.e on Polygon +## How It Works -**Polymarket uses USDC.e (Bridged USDC) on Polygon as collateral** for all trading activities. USDC.e is the bridged version of USDC from Ethereum, and it serves as the native currency for placing orders and settling trades on Polymarket. +1. Request deposit addresses for your Polymarket wallet +2. Send assets to the appropriate address for your source chain +3. Assets are bridged and swapped to USDC.e automatically +4. USDC.e is credited to your wallet for trading -When you deposit assets to Polymarket: +## Create Deposit Addresses -1. You can deposit from various supported chains (Ethereum, Solana, Arbitrum, Base, etc.) -2. Your assets are automatically bridged/swapped to USDC.e on Polygon -3. USDC.e is credited to your Polymarket wallet so you can trade on any market +Generate unique deposit addresses linked to your Polymarket wallet. See the [Bridge API Reference](/api-reference/introduction) for full request and response schemas. -## Base URL - -``` -https://bridge.polymarket.com +```bash theme={null} +curl -X POST https://bridge.polymarket.com/deposit \ + -H "Content-Type: application/json" \ + -d '{"address": "0x56687bf447db6ffa42ffe2204a05edaa20f55839"}' ``` -## Key Features +### Address Types -* **Multi-chain deposits**: Bridge assets from EVM chains (Ethereum, Arbitrum, Base, etc.), Solana, and Bitcoin -* **Multi-chain withdrawals**: Withdraw USDC.e to any supported chain and token -* **Automatic conversion**: Assets are automatically bridged and swapped -* **Simple addressing**: One deposit address per blockchain type (EVM, SVM, BTC) +| Address | Use For | +| ------- | -------------------------------------------------------- | +| `evm` | Ethereum, Arbitrum, Base, Optimism, and other EVM chains | +| `svm` | Solana | +| `btc` | Bitcoin | +| `tvm` | Tron | -## Endpoints + + Each address is unique to your wallet. Only send assets from supported chains + to the correct address type. + -* `GET /supported-assets` - Get all supported chains and tokens -* `POST /quote` - Get a quote for a deposit or withdrawal -* `POST /deposit` - Create deposit addresses for bridging assets to Polymarket -* `POST /withdraw` - Create withdrawal addresses for bridging assets from Polymarket -* `GET /status/{address}` - Get transaction status for a given address +## Deposit Flow + + + + Call `POST /deposit` with your Polymarket wallet address to get deposit + addresses. + + + + Verify your token is supported and meets the minimum deposit amount via + `/supported-assets`. + + + + Transfer tokens to the appropriate deposit address from your source chain. + + + + Monitor your deposit progress using `/status/{address}`. + + + +## USDC vs USDC.e + +You can deposit either USDC (native) or USDC.e (bridged) to your Polymarket wallet. If you deposit native USDC, you will be prompted to "activate funds," which swaps it to USDC.e via the lowest-fee Uniswap pool (less than 10bp slippage). + +## 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) deposit 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 on Ethereum or Polygon, use these tools to recover your funds: + +* **Ethereum deposits**: [recovery.polymarket.com](https://recovery.polymarket.com/) +* **Polygon deposits**: [matic-recovery.polymarket.com](https://matic-recovery.polymarket.com/) + + + Sending unsupported tokens may cause **irrecoverable loss**. Always verify + your token is listed in [Supported Assets](/trading/bridge/supported-assets) + before depositing. + + +## Next Steps + + + + See all supported chains and tokens with minimum amounts. + + + + Track your deposit progress through completion. + + diff --git a/docs/developers/neg-risk/overview.md b/docs/developers/neg-risk/overview.md index 46bccf8..84f9ac7 100644 --- a/docs/developers/neg-risk/overview.md +++ b/docs/developers/neg-risk/overview.md @@ -2,38 +2,144 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Overview +# Negative Risk Markets -Certain events which meet the criteria of being "winner-take-all" may be deployed as **"negative risk"** events/markets. The Gamma API includes a boolean field on events, `negRisk`, which indicates whether the event is negative risk. +> Capital-efficient trading for multi-outcome events -Negative risk allows for increased capital efficiency by relating all markets within events via a convert action. More explicitly, a NO share in any market can be converted into 1 YES share in all other markets. Converts can be exercised via the [Negative Adapter](https://polygonscan.com/address/0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296). You can read more about negative risk [here](https://github.com/Polymarket/neg-risk-ctf-adapter). +**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 [Contract Addresses](/resources/contract-addresses) for the Neg Risk Adapter and Neg Risk CTF Exchange addresses. ## Augmented Negative Risk -There is a known issue with the negative risk architecture which is that the outcome universe must be complete before conversions are made or otherwise conversion will “cost” something. In most cases, the outcome universe can be made complete by deploying all the named outcomes and then an “other” option. But in some cases this is undesirable as new outcomes can come out of nowhere and you'd rather them be directly named versus grouped together in an “other”. +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). -To fix this, some markets use a system of **"augmented negative risk"**, where named outcomes, a collection of unnamed outcomes, and an *other* is deployed. When a new outcome needs to be added, an unnamed outcome can be clarified to be the new outcome via the bulletin board. This means the “other” in the case of augmented negative risk can effectively change definitions (outcomes can be taken out of it). +**Augmented negative risk** solves this with: -As such, trading should only happen on the named outcomes, and the other outcomes should be ignored until they are named or until resolution occurs. The Polymarket UI will not show unnamed outcomes. +| 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 | -If a market becomes resolvable and the correct outcome is not named (originally or via placeholder clarification), it should resolve to the *“other”* outcome. An event can be considered “augmented negative risk” when `enableNegRisk` is true **AND** `negRiskAugmented` is true. +### How Placeholders Work -The naming conventions are as follows: +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 -### Original Outcomes +### Trading Rules for Augmented Neg Risk -* Outcome A -* Outcome B -* ... + + 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. + -### Placeholder Outcomes +* 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 -* Person A -> can be clarified to a named outcome -* Person B -> can be clarified to a named outcome -* ... +### Identifying Augmented Neg Risk -### Explicit Other +An event is augmented neg risk when both flags are true: -* Other -> not meant to be traded as the definition of this changes as placeholder outcomes are clarified to named outcomes +```json theme={null} +{ + "enableNegRisk": true, + "negRiskAugmented": true +} +``` + + + 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. + + +## 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 + + + + Understand how multi-market events are structured. + + + + Learn about token operations like split, merge, and redeem. + + diff --git a/docs/developers/proxy-wallet.md b/docs/developers/proxy-wallet.md index 2870912..80dd436 100644 --- a/docs/developers/proxy-wallet.md +++ b/docs/developers/proxy-wallet.md @@ -2,21 +2,376 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# null +# Authentication -## Overview +> How to authenticate requests to the CLOB API -When a user first uses Polymarket.com to trade they are prompted to create a wallet. When they do this, a 1 of 1 multisig is deployed to Polygon which is controlled/owned by the accessing EOA (either MetaMask wallet or MagicLink wallet). This proxy wallet is where all the user's positions (ERC1155) and USDC (ERC20) are held. +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. -Using proxy wallets allows Polymarket to provide an improved UX where multi-step transactions can be executed atomically and transactions can be relayed by relayers on the gas station network. If you are a developer looking to programmatically access positions you accumulated via the Polymarket.com interface, you can either continue using the smart contract wallet by executing transactions through it from the owner account, or you can transfer these assets to a new address using the owner account. +## Public vs Authenticated + + + + The **Gamma API**, **Data API**, and CLOB read endpoints (orderbook, prices, spreads) require no authentication. + + + + CLOB trading endpoints (placing orders, cancellations, heartbeat) require all 5 `POLY_*` L2 HTTP headers. + + *** -## Deployments +## Two-Level Authentication Model -Each user has their own proxy wallet (and thus proxy wallet address) but the factories are available at the following deployed addresses on the **Polygon network**: +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 -| **Address** | **Details** | -| ------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- | -| [0xaacfeea03eb1561c4e67d661e40682bd20e3541b](https://polygonscan.com/address/0xaacfeea03eb1561c4e67d661e40682bd20e3541b) | **Gnosis safe factory** – Gnosis safes are used for all MetaMask users | -| [0xaB45c5A4B0c941a2F231C04C3f49182e1A254052](https://polygonscan.com/address/0xaB45c5A4B0c941a2F231C04C3f49182e1A254052) | **Polymarket proxy factory** – Polymarket custom proxy contracts are used for all MagicLink users | +### L1 Authentication (Private Key) + +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 (API Credentials) + +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 + + + Even with L2 authentication headers, methods that create user orders still + require the user to sign the order payload. + + +*** + +## Getting API Credentials + +Before making authenticated requests, you need to obtain API credentials using L1 authentication. + +### Using the SDK (Recommended) + + + + ```typescript theme={null} + import { ClobClient } from "@polymarket/clob-client"; + import { Wallet } from "ethers"; // v5.8.0 + + const client = new ClobClient( + "https://clob.polymarket.com", + 137, // Polygon mainnet + new Wallet(process.env.PRIVATE_KEY) + ); + + // Creates new credentials or derives existing ones + const credentials = await client.createOrDeriveApiKey(); + + console.log(credentials); + // { + // apiKey: "550e8400-e29b-41d4-a716-446655440000", + // secret: "base64EncodedSecretString", + // passphrase: "randomPassphraseString" + // } + ``` + + + + ```python theme={null} + from py_clob_client.client import ClobClient + import os + + client = ClobClient( + host="https://clob.polymarket.com", + chain_id=137, # Polygon mainnet + key=os.getenv("PRIVATE_KEY") + ) + + # Creates new credentials or derives existing ones + credentials = client.create_or_derive_api_creds() + + print(credentials) + # { + # "apiKey": "550e8400-e29b-41d4-a716-446655440000", + # "secret": "base64EncodedSecretString", + # "passphrase": "randomPassphraseString" + # } + ``` + + + + + **Never commit private keys to version control.** Always use environment + variables or secure key management systems. + + +### 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) or [TypeScript](https://github.com/Polymarket/clob-client) 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: + + + + ```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) + ``` + + + +Reference implementations: + +* [TypeScript](https://github.com/Polymarket/clob-client/blob/main/src/signing/eip712.ts) +* [Python](https://github.com/Polymarket/py-clob-client/blob/main/py_clob_client/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/blob/main/src/signing/hmac.ts) and [Python](https://github.com/Polymarket/py-clob-client/blob/main/py_clob_client/signing/hmac.py) clients. + +### CLOB Client (L2) + + + + ```typescript theme={null} + import { ClobClient } from "@polymarket/clob-client"; + import { Wallet } from "ethers"; // v5.8.0 + + const client = new ClobClient( + "https://clob.polymarket.com", + 137, + new Wallet(process.env.PRIVATE_KEY), + apiCreds, // Generated from L1 auth, API credentials enable L2 methods + 1, // signatureType explained below + funderAddress // funder explained below + ); + + // Now you can trade! + const order = await client.createAndPostOrder( + { tokenID: "123456", price: 0.65, size: 100, side: "BUY" }, + { tickSize: "0.01", negRisk: false } + ); + ``` + + + + ```python theme={null} + from py_clob_client.client import ClobClient + 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=1, # signatureType explained below + funder=os.getenv("FUNDER_ADDRESS") # funder explained below + ) + + # Now you can trade! + order = client.create_and_post_order( + {"token_id": "123456", "price": 0.65, "size": 100, "side": "BUY"}, + {"tick_size": "0.01", "neg_risk": False} + ) + ``` + + + + + Even with L2 authentication headers, methods that create user orders still + require the user to sign the order payload. + + +*** + +## 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` | A custom proxy wallet only used with users who logged in via Magic Link email/Google. Using this requires the user to have exported their PK from Polymarket.com and imported into your app. | +| GNOSIS\_SAFE | `2` | Gnosis Safe multisig proxy wallet (most common). Use this for any new or returning user who does not fit the other 2 types. | + + + The wallet address displayed to the user on Polymarket.com is the proxy wallet + and should be used as the funder. These can be deterministically derived or + you can deploy them on behalf of the user. These proxy wallets are + automatically deployed for the user on their first login to Polymarket.com. + + +*** + +## Security Best Practices + + + + 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... + ``` + + + + Never expose your API secret in client-side code. All authenticated requests should originate from your backend. + + + +*** + +## Troubleshooting + + + + 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 + + + + 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()` + + + + 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. + + + + 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! + ``` + + + +*** + +## Next Steps + + + + Learn how to create and submit orders. + + + + Check trading availability by region. + + diff --git a/docs/developers/resolution/UMA.md b/docs/developers/resolution/UMA.md index 9f1f928..3fef454 100644 --- a/docs/developers/resolution/UMA.md +++ b/docs/developers/resolution/UMA.md @@ -4,70 +4,148 @@ # Resolution -# UMA Optimistic Oracle Integration +> How markets are resolved and winning positions redeemed -## Overview +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 leverages UMA's Optimistic Oracle (OO) to resolve arbitrary questions, permissionlessly. From [UMA's docs](https://docs.uma.xyz/protocol-overview/how-does-umas-oracle-work): +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. -"UMA's Optimistic Oracle allows contracts to quickly request and receive data information ... The Optimistic Oracle acts as a generalized escalation game between contracts that initiate a price request and UMA's dispute resolution system known as the Data Verification Mechanism (DVM). Prices proposed by the Optimistic Oracle will not be sent to the DVM unless it is disputed. If a dispute is raised, a request is sent to the DVM. All contracts built on UMA use the DVM as a backstop to resolve disputes. Disputes sent to the DVM will be resolved within a few days -- after UMA tokenholders vote on what the correct outcome should have been." + + -To allow CTF markets to be resolved via the OO, Polymarket developed a custom adapter contract called `UmaCtfAdapter` that provides a way for the two contract systems to interface. + + + +## 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 + + + Always read the resolution rules before trading. The market title describes + the question, but the **rules** define how it resolves. + + + + + Anyone can propose a resolution by: + + 1. Selecting the winning outcome + 2. Posting a bond (typically \$750 USDC.e) + 3. Submitting the proposal to the UMA Oracle + + If the proposal is correct and undisputed, the proposer receives their bond back plus a reward. + + + 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. + + + + + 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 + + + + 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`). + + + + 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 | + + + +## 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, call the `redeemPositions` function on the CTF contract to exchange winning tokens for USDC.e. The contract burns your tokens and returns the corresponding collateral. + +``` +100 winning tokens → $100 USDC.e +``` ## Clarifications -Recent versions (v2+) of the `UmaCtfAdapter` also include a bulletin board feature that allows market creators to issue "clarifications". Questions that allow updates will include the sentence in their ancillary data: +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. -"Updates made by the question creator via the bulletin board on 0x6A5D0222186C0FceA7547534cC13c3CFd9b7b6A4F74 should be considered. In summary, clarifications that do not impact the question's intent should be considered." +Clarifications: -Where the [transaction](https://polygonscan.com/tx/0xa14f01b115c4913624fc3f508f960f4dea252758e73c28f5f07f8e19d7bca066) reference outlining what outlining should be considered. +* 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 -## Resolution Process + + If you believe a clarification is needed, request it in the [Polymarket + Discord](https://discord.com/invite/polymarket) `#market-review` channel. + -### Actions +## Resolution Timeline -* **Initiate** - Binary CTF markets are initialized via the `UmaCtfAdapter`'s `initialize()` function. This stores the question parameters on the contract, prepares the CTF and requests a price for a question from the OO. It returns a `questionID` that is also used to reference on the `UmaCtfAdapter`. The caller provides: - 1. `ancillaryData` - data used to resolve a question (i.e the question + clarifications) - 2. `rewardToken` - ERC20 token address used for payment of rewards and fees - 3. `reward` - Reward amount offered to a successful proposer. The caller must have set allowance so that the contract can pull this reward in. - 4. `proposalBond` - Bond required to be posted by OO proposers/disputers. If 0, the default OO bond is used. - 5. `liveness` - UMA liveness period in seconds. If 0, the default liveness period is used. +| Phase | Duration | +| --------------------------- | ----------- | +| Challenge period | 2 hours | +| Debate period (if disputed) | 24-48 hours | +| UMA voting (if disputed) | \~48 hours | -* **Propose Price** - Anyone can then propose a price to the question on the OO. To do this they must post the `proposalBond`. The liveness period begins after a price is proposed. +**Undisputed resolution**: \~2 hours after proposal -* **Dispute** - Anyone that disagrees with the proposed price has the opportunity to dispute the price by posting a counter bond via the OO, this proposed will now be escalated to the DVM for a voter-wide vote. +**Disputed resolution**: 4-6 days total -### Possible Flows +## Contract Addresses -When the first proposed price is disputed for a `questionID` on the adapter, a callback is made and posted as the reward for this new proposal. This means a second `questionID`, making a new `questionID` to the OO (the reward is returned before the callback is made and posted as the reward for this new proposal). This allows for a second round of resolution, and correspondingly a second dispute is required for it to go to the DVM. The thinking behind this is to doubles the cost of a potential griefing vector (two disputes are required just one) and also allows far-fetched (incorrect) first price proposals to not delay the resolution. As such there are two possible flows: +| Contract | Address | Network | +| ---------------------- | -------------------------------------------- | --------------- | +| **UmaCtfAdapter v3.0** | `0x157Ce2d672854c848c9b79C49a8Cc6cc89176a49` | Polygon Mainnet | +| **UmaCtfAdapter v2.0** | `0x6A9D222616C90FcA5754cd1333cFD9b7fb6a4F74` | Polygon Mainnet | +| **UmaCtfAdapter v1.0** | `0xCB1822859cEF82Cd2Eb4E6276C7916e692995130` | Polygon Mainnet | -* **Initialize (CTFAdapter) -> Propose (OO) -> Resolve (CTFAdapter)** -* **Initialize (CTFAdaptor) -> Propose (OO) -> Challenge (OO) -> Propose (OO) -> Resolve (CTFAdaptor)** -* **Initialize (CTFAdaptor) -> Propose (OO) -> Challenge (OO) -> Propose (OO) -> Challenge (CtfAdapter) -> Resolve (CTFAdaptor)** +## Resources -## Deployed Addresses +* [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 -### v3.0 +## Next Steps -| Network | Address | -| --------------- | ------------------------------------------------------------------------------------------------------------------------ | -| Polygon Mainnet | [0x157Ce2d672854c848c9b79C49a8Cc6cc89176a49](https://polygonscan.com/address/0x157Ce2d672854c848c9b79C49a8Cc6cc89176a49) | + + + Learn how to redeem winning tokens after resolution. + -### v2.0 - -| Network | Address | -| --------------- | --------------------------------------------------------------------------------------------------------------------------- | -| Polygon Mainnet | [0x6A9D0222186C0FceA7547534cC13c3CFd9b7b6A4F74](https://polygonscan.com/address/0x6A9D222616C90FcA5754cd1333cFD9b7fb6a4F74) | - -### v1.0 - -| Network | Address | -| --------------- | -------------------------------------------------------------------------------------------------------------------------- | -| Polygon Mainnet | [0xC8B122858a4EF82C2d4eE2E6A276C719e692995130](https://polygonscan.com/address/0xCB1822859cEF82Cd2Eb4E6276C7916e692995130) | - -## Additional Resources - -* [Audit](https://github.com/Polymarket/uma-ctf-adapter/blob/main/audit/Polymarket_UMA_Optimistic_Oracle_Adapter_Audit.pdf) -* [Source Code](https://github.com/Polymarket/uma-ctf-adapter) -* [UMA Documentation](https://docs.uma.xyz/) -* [UMA Oracle Portal](https://oracle.uma.xyz/) + + Understand how markets are structured. + + diff --git a/docs/developers/sports-websocket/message-format.md b/docs/developers/sports-websocket/message-format.md index b9b3859..d29c12f 100644 --- a/docs/developers/sports-websocket/message-format.md +++ b/docs/developers/sports-websocket/message-format.md @@ -2,15 +2,40 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Message Format +# Sports WebSocket -> Structure of sports result update messages +> Live sports scores and game state -Once connected to the Sports WebSocket, clients receive JSON messages whenever a sports event updates. Messages are broadcast to all connected clients automatically. +The Sports WebSocket provides real-time sports results updates, including scores, periods, and game status. No authentication required. -*** +## Endpoint -## sport\_result Message +``` +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: @@ -20,68 +45,13 @@ Emitted when: * A match ends * Possession changes (NFL and CFB only) -### Structure - - - Unique identifier for the game - - - - League identifier (e.g., `"nfl"`, `"nba"`, `"cs2"`) - - - - Home team name or abbreviation - - - - Away team name or abbreviation - - - - Game status (e.g., `"InProgress"`, `"finished"`) - - - - `true` if the match is currently in progress - - - - `true` if the match has concluded - - - - Current score (format varies by sport) - - - - Current period (e.g., `"Q4"`, `"2H"`, `"2/3"`) - - - - Time elapsed in current period (e.g., `"05:09"`) - - - - Timestamp when the match ended (only present when `ended: true`) - - - - Team abbreviation with possession (NFL/CFB only) - - - - The `turn` field is only present for NFL and CFB games and indicates which team currently has the ball. - - -### Example Messages - **NFL (in progress):** ```json theme={null} { "gameId": 19439, "leagueAbbreviation": "nfl", + "slug": "nfl-lac-buf-2025-01-26", "homeTeam": "LAC", "awayTeam": "BUF", "status": "InProgress", @@ -94,39 +64,27 @@ Emitted when: } ``` -**Esports - CS2 (finished):** +**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 + "ended": true, + "finished_timestamp": "2025-07-20T18:30:00.000Z" } ``` -*** +The `finished_timestamp` field is an ISO 8601 timestamp only present when `ended: true`. -## Slug Format - -The `slug` field follows a consistent naming convention: - -``` -{league}-{team1}-{team2}-{date} -``` - -**Examples:** - -* `nfl-buf-kc-2025-01-26` — NFL: Buffalo Bills vs Kansas City Chiefs -* `nba-lal-bos-2025-02-15` — NBA: LA Lakers vs Boston Celtics -* `mlb-nyy-bos-2025-04-01` — MLB: NY Yankees vs Boston Red Sox - -*** +The `slug` field follows the format `{league}-{team1}-{team2}-{date}` (e.g., `nfl-buf-kc-2025-01-26`). ## Period Values @@ -139,25 +97,119 @@ The `slug` field follows a consistent naming convention: | `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`, etc. | End of inning (MLB) | +| `End 1`, `End 2`, ... | End of inning (MLB) | | `1/3`, `2/3`, `3/3` | Map number in Bo3 series (Esports) | -| `1/5`, `2/5`, etc. | Map number in Bo5 series (Esports) | +| `1/5`, `2/5`, ... | Map number in Bo5 series (Esports) | -*** +## Game Status Values -## Handling Updates +Game status values vary by sport: -When processing messages, use the `gameId` field as the unique identifier to update your local state: +### NFL -```javascript theme={null} -// Update or insert based on gameId -setSportsData(prev => { - const existing = prev.find(item => item.gameId === data.gameId); - if (existing) { - return prev.map(item => - item.gameId === data.gameId ? data : item - ); - } - return [...prev, data]; -}); -``` +| 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 / 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 | diff --git a/docs/developers/sports-websocket/overview.md b/docs/developers/sports-websocket/overview.md index f9a2cd1..d29c12f 100644 --- a/docs/developers/sports-websocket/overview.md +++ b/docs/developers/sports-websocket/overview.md @@ -2,65 +2,214 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Overview +# Sports WebSocket -> Real-time sports results via WebSocket +> Live sports scores and game state -The Polymarket Sports WebSocket API provides real-time sports results updates. Clients connect to receive live match data including scores, periods, and game status as events happen. +The Sports WebSocket provides real-time sports results updates, including scores, periods, and game status. No authentication required. -**Endpoint:** +## Endpoint ``` wss://sports-api.polymarket.com/ws ``` - - No authentication is required. This is a public broadcast channel that streams updates for all active sports events. - +No subscription message required — connect and start receiving data for all active sports events. -## How It Works +## Heartbeat -Once connected, clients automatically receive JSON messages whenever a sports event updates. There is no subscription message required—simply connect and start receiving data. +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; + } -## Connection Management + // Handle JSON messages... +}; +``` -### Automatic Ping/Pong Heartbeat +## Message Type -The server sends PING messages at regular intervals. Clients **must** respond with PONG to maintain the connection. +Each message is a JSON object with game state fields. -| Parameter | Default | Description | -| ------------- | ---------- | --------------------------------------------- | -| PING Interval | 5 seconds | How often the server sends PING messages | -| PONG Timeout | 10 seconds | How long the server waits for a PONG response | +### sport\_result - - If your client doesn't respond to PING within 10 seconds, the connection will be closed automatically. - +Emitted when: -### Connection Health +* A match goes live +* The score changes +* The period changes (e.g., halftime, overtime) +* A match ends +* Possession changes (NFL and CFB only) -* Server sends `PING` → Client must respond with `PONG` -* No response within timeout → Connection terminated -* Clients should implement automatic reconnection with exponential backoff +**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" +} +``` -## Session Affinity +**Esports — CS2 (finished):** -The server uses cookie-based session affinity (`sports-results` cookie) to ensure clients maintain connection to the same backend instance. This is handled automatically by the browser. +```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`. -## Next Steps +The `slug` field follows the format `{league}-{team1}-{team2}-{date}` (e.g., `nfl-buf-kc-2025-01-26`). - - - Understand the structure of sports update messages - +## Period Values - - Implementation examples in JavaScript and TypeScript - - +| 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 / 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 | diff --git a/docs/developers/sports-websocket/quickstart.md b/docs/developers/sports-websocket/quickstart.md index 10593be..d29c12f 100644 --- a/docs/developers/sports-websocket/quickstart.md +++ b/docs/developers/sports-websocket/quickstart.md @@ -2,11 +2,11 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# Quickstart +# Sports WebSocket -> Connect to the Sports WebSocket and receive live updates +> Live sports scores and game state -Connect to the Sports WebSocket to receive real-time sports results. No authentication required—just connect and handle incoming messages. +The Sports WebSocket provides real-time sports results updates, including scores, periods, and game status. No authentication required. ## Endpoint @@ -14,244 +14,202 @@ Connect to the Sports WebSocket to receive real-time sports results. No authenti wss://sports-api.polymarket.com/ws ``` -*** +No subscription message required — connect and start receiving data for all active sports events. -## JavaScript Example +## Heartbeat - - ```javascript JavaScript theme={null} - const ws = new WebSocket('wss://sports-api.polymarket.com/ws'); - - ws.onopen = () => { - console.log('Connected to Sports WebSocket'); - }; - - ws.onmessage = (event) => { - // Respond to server PING - if (event.data === 'ping') { - ws.send('pong'); - return; - } - - // Parse and handle sports updates - const data = JSON.parse(event.data); - console.log('Update:', data.slug, data.score, data.period); - }; - - ws.onclose = () => { - console.log('Disconnected'); - // Reconnect after 1 second - setTimeout(() => location.reload(), 1000); - }; - - ws.onerror = (error) => { - console.error('WebSocket error:', error); - }; - ``` - - ```typescript React Hook theme={null} - import { useEffect, useRef, useState } from 'react'; - - interface SportsUpdate { - slug: string; - live: boolean; - ended: boolean; - score: string; - period: string; - elapsed: string; - last_update: string; - finished_timestamp?: string; - turn?: string; - } - - export function useSportsWebSocket() { - const [updates, setUpdates] = useState>(new Map()); - const wsRef = useRef(null); - - useEffect(() => { - const ws = new WebSocket('wss://sports-api.polymarket.com/ws'); - wsRef.current = ws; - - ws.onmessage = (event) => { - if (event.data === 'ping') { - ws.send('pong'); - return; - } - const data: SportsUpdate = JSON.parse(event.data); - setUpdates(prev => new Map(prev).set(data.slug, data)); - }; - - ws.onclose = () => setTimeout(() => location.reload(), 1000); - - return () => ws.close(); - }, []); - - return Array.from(updates.values()); - } - ``` - - -*** - -## Critical: PING/PONG Handling - -The server sends PING messages every 5 seconds. Your client **must** respond with PONG to stay connected. +The server sends `ping` every 5 seconds. Respond with `pong` within 10 seconds or the connection will close. ```javascript theme={null} -// CORRECT - Handle PING messages ws.onmessage = (event) => { - if (event.data === 'ping') { - ws.send('pong'); // Respond immediately + if (event.data === "ping") { + ws.send("pong"); return; } - // Handle other messages... - const data = JSON.parse(event.data); - handleUpdate(data); + + // Handle JSON messages... }; ``` -```javascript theme={null} -// WRONG - Ignoring PING messages will disconnect you -ws.onmessage = (event) => { - const data = JSON.parse(event.data); // Fails on "ping" string! - handleUpdate(data); -}; -``` +## Message Type - - If you don't respond to PING within 10 seconds, your connection will be terminated. - +Each message is a JSON object with game state fields. -*** +### sport\_result -## Connection State Management +Emitted when: -Always check connection state before sending: +* A match goes live +* The score changes +* The period changes (e.g., halftime, overtime) +* A match ends +* Possession changes (NFL and CFB only) -```javascript theme={null} -if (ws.readyState === WebSocket.OPEN) { - ws.send('pong'); -} else { - console.warn('WebSocket not connected'); +**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):** -## Browser Tab Visibility - -Connections may drop when browser tabs become inactive. Handle visibility changes: - -```javascript theme={null} -document.addEventListener('visibilitychange', () => { - if (!document.hidden && ws.readyState !== WebSocket.OPEN) { - console.log('Tab became visible, reconnecting...'); - connect(); - } -}); +```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`. -## Troubleshooting +The `slug` field follows the format `{league}-{team1}-{team2}-{date}` (e.g., `nfl-buf-kc-2025-01-26`). - - - Your PING/PONG handler isn't working correctly. +## Period Values - **Check:** +| 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) | - * You're responding to `"ping"` string messages (not JSON) - * You're sending `"pong"` as a string response - * No errors are preventing the PONG from being sent +## Game Status Values - ```javascript theme={null} - // Debug PING/PONG handling - ws.onmessage = (event) => { - console.log('Received:', event.data); - if (event.data === 'ping') { - console.log('Sending PONG response'); - ws.send('pong'); - return; - } - // Handle JSON messages... - }; - ``` - +Game status values vary by sport: - - This may be network instability or main thread blocking. +### NFL - **Solutions:** +| 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 | - * Implement exponential backoff for reconnection - * Ensure your message handler doesn't block the main thread - * Check network stability +### NHL - ```javascript theme={null} - handleReconnect() { - this.reconnectDelay = Math.min(this.reconnectDelay * 2, 30000); - setTimeout(() => this.connect(), this.reconnectDelay); - } - ``` - +| 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 | - - Ensure you're updating state correctly based on the `slug` identifier. +### MLB - ```javascript theme={null} - // Use slug as unique key - setSportsData(prev => { - const index = prev.findIndex(item => item.slug === data.slug); - if (index >= 0) { - const updated = [...prev]; - updated[index] = data; - return updated; - } - return [...prev, data]; - }); - ``` - +| 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 | - - Clean up properly when disconnecting: +### NBA / CBB - ```javascript theme={null} - const cleanup = () => { - if (reconnectTimeout) { - clearTimeout(reconnectTimeout); - } - if (ws) { - ws.close(); - ws = null; - } - }; +| 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 | - // React: cleanup in useEffect return - // Vanilla: call on page unload - window.addEventListener('beforeunload', cleanup); - ``` - - +### 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 | -## Debugging Tips +### Soccer -Enable verbose logging to diagnose connection issues: +| 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 | -```javascript theme={null} -ws.onopen = () => console.log('[connected]'); -ws.onclose = (e) => console.log('[closed]', e.code, e.reason); -ws.onerror = (e) => console.error('[error]', e); -ws.onmessage = (e) => console.log('[message]', e.data); -``` +### Esports -Monitor connection state: +| Status | Description | +| ------------- | ----------------------- | +| `not_started` | Match not yet started | +| `running` | Match currently playing | +| `finished` | Match completed | +| `postponed` | Match postponed | +| `canceled` | Match canceled | -```javascript theme={null} -setInterval(() => { - const states = ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED']; - console.log('WebSocket state:', states[ws.readyState]); -}, 5000); -``` +### Tennis + +| Status | Description | +| ------------ | ----------------------- | +| `scheduled` | Match not yet started | +| `inprogress` | Match currently playing | +| `suspended` | Match suspended | +| `finished` | Match completed | +| `postponed` | Match postponed | +| `cancelled` | Match canceled | diff --git a/docs/developers/subgraph/overview.md b/docs/developers/subgraph/overview.md index e30197e..b13638e 100644 --- a/docs/developers/subgraph/overview.md +++ b/docs/developers/subgraph/overview.md @@ -2,16 +2,96 @@ > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. -# null +# Subgraph -## Subgraph Overview +> Query onchain Polymarket data using GraphQL -Polymarket has written and open sourced a subgraph that provides, via a GraphQL query interface, useful aggregate calculations and event indexing for things like volume, user position, market and liquidity data. The subgraph updates in real time to be able to be mixed, and match core data from the primary Polymarket interface, providing positional data, activity history and more. The subgraph can be hosted by anyone. +Polymarket's subgraphs provide indexed onchain data via GraphQL. Use them to query positions, volume, liquidity data, orders, activity, and market data. -## Source +## Available Subgraphs -The Polymarket subgraph is entirely open source and can be found on the Polymarket Github. +| Subgraph | Description | Endpoint | +| ----------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| **Positions** | User token balances | [GraphQL Playground](https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/positions-subgraph/0.0.7/gn) | +| **Orders** | Order book and trade events | [GraphQL Playground](https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/orderbook-subgraph/0.0.1/gn) | +| **Activity** | Splits, merges, redemptions | [GraphQL Playground](https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/activity-subgraph/0.0.4/gn) | +| **Open Interest** | Market and global OI | [GraphQL Playground](https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/oi-subgraph/0.0.6/gn) | +| **PNL** | User position P\&L | [GraphQL Playground](https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/pnl-subgraph/0.0.14/gn) | -**[Subgraph Github Repository](https://github.com/Polymarket/polymarket-subgraph)** + + Subgraphs are hosted by [Goldsky](https://goldsky.com). Each endpoint includes + an interactive GraphQL playground for exploring the schema. + -> Note: The available models/schemas can be found in the `schema.graphql` file. +## Querying + +Send GraphQL queries via POST request to any subgraph endpoint. + +```bash theme={null} +curl -X POST \ + https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/orderbook-subgraph/0.0.1/gn \ + -H "Content-Type: application/json" \ + -d '{ + "query": "query MyQuery { orderbooks { id tradesQuantity } }" + }' +``` + +## Schema Reference + +### Positions + +| Query | Description | +| ---------------------------------------- | ------------------------------ | +| `userBalance` / `userBalances` | User token balances | +| `netUserBalance` / `netUserBalances` | Aggregated net balances | +| `tokenIdCondition` / `tokenIdConditions` | Token ID to condition mappings | +| `condition` / `conditions` | Market conditions | + +### Orders + +| Query | Description | +| ---------------------------------------------- | ----------------------- | +| `marketData` / `marketDatas` | Market-level data | +| `orderFilledEvent` / `orderFilledEvents` | Order fill events | +| `ordersMatchedEvent` / `ordersMatchedEvents` | Order match events | +| `orderbook` / `orderbooks` | Orderbook state | +| `ordersMatchedGlobal` / `ordersMatchedGlobals` | Global match statistics | + +### Activity + +| Query | Description | +| ------------------------------------------------------ | -------------------- | +| `split` / `splits` | USDC to token splits | +| `merge` / `merges` | Token to USDC merges | +| `redemption` / `redemptions` | Position redemptions | +| `negRiskConversion` / `negRiskConversions` | Neg risk conversions | +| `negRiskEvent` / `negRiskEvents` | Neg risk event data | +| `fixedProductMarketMaker` / `fixedProductMarketMakers` | FPMM data | +| `position` / `positions` | Position records | +| `condition` / `conditions` | Market conditions | + +### Open Interest + +| Query | Description | +| -------------------------------------------- | ------------------------ | +| `condition` / `conditions` | Market conditions | +| `negRiskEvent` / `negRiskEvents` | Neg risk event data | +| `marketOpenInterest` / `marketOpenInterests` | Per-market open interest | +| `globalOpenInterest` / `globalOpenInterests` | Global open interest | + +### PNL + +| Query | Description | +| -------------------------------- | ------------------------------- | +| `userPosition` / `userPositions` | User position P\&L data | +| `negRiskEvent` / `negRiskEvents` | Neg risk event data | +| `condition` / `conditions` | Market conditions | +| `fpmm` / `fpmms` | Fixed product market maker data | + +## Source Code + +The subgraph is open source. Review the schema and mappings on GitHub: + + + View source code, schema definitions, and deployment configuration. + diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..7ad6548 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,133 @@ +> ## 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 + +> Build on the world's largest prediction market. Trade, integrate, and access real-time market data with the Polymarket API. + +export const IconCard = ({ icon, title, description, href, color }) => { + return ( + +
+ +
+

+ {title} +

+

+ {description} +

+
+ ); +}; + + + + + +
+
+

+ Polymarket Documentation +

+ +
+ Build on the world's largest prediction market. APIs, SDKs, and tools for prediction market developers. +
+ +
+
+

+ Developer Quickstart +

+ +

+ Make your first API request in minutes. Learn the basics of the Polymarket platform, fetch market data, place orders, and redeem winning positions. +

+ + +
+ + + ```typescript TypeScript theme={null} + import { ClobClient, Side } from "@polymarket/clob-client"; + + const client = new ClobClient(host, chainId, signer, creds); + + const order = await client.createAndPostOrder( + { tokenID, price: 0.50, size: 10, side: Side.BUY }, + { tickSize: "0.01", negRisk: false } + ); + ``` + + ```python Python theme={null} + from py_clob_client.client import ClobClient + from py_clob_client.order_builder.constants import BUY + + client = ClobClient(host, key=key, chain_id=chain_id, creds=creds) + order = client.create_and_post_order( + OrderArgs(token_id=token_id, price=0.50, size=10, side=BUY), + options={"tick_size": "0.01", "neg_risk": False} + ) + ``` + +
+
+ +
+

+ Get Familiar with Polymarket +

+ +

+ Learn the fundamentals, explore our APIs, and start building on the world's largest prediction market. +

+ +
+ + + Set up your environment and make your first API call in minutes. + + + + Understand markets, events, tokens, and how trading works. + + + + Explore REST endpoints, WebSocket streams, and authentication. + + + + Official Python and TypeScript libraries for faster development. + + +
+ +
+ + Banner + +
+
+ +
+
+ + + + + +
+
+
diff --git a/docs/market-data/fetching-markets.md b/docs/market-data/fetching-markets.md new file mode 100644 index 0000000..ee119af --- /dev/null +++ b/docs/market-data/fetching-markets.md @@ -0,0 +1,160 @@ +> ## 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 + + + Both the events and markets endpoints are paginated. See + [pagination](#pagination) for details. + + +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 | +| `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&closed=false`** unless you specifically 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 + + + + Full endpoint documentation with parameters and response schemas. + + + + Query onchain data directly from the Polymarket subgraph. + + diff --git a/docs/market-data/overview.md b/docs/market-data/overview.md new file mode 100644 index 0000000..a114bc8 --- /dev/null +++ b/docs/market-data/overview.md @@ -0,0 +1,111 @@ +> ## 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. + + + + A top-level object representing a question (e.g., "Who will win the 2024 + Presidential Election?"). Contains one or more markets. + + + + 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. + + + +### 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) +``` + +Markets can be traded via the CLOB if `enableOrderBook` is `true`. + +*** + +## 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 (`gamma-api.polymarket.com`) — Events, Markets & 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 (`clob.polymarket.com`) — Prices & 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 (`data-api.polymarket.com`) — Positions, Trades & 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 + + + + Three strategies for discovering and querying markets. + + + + Full endpoint documentation with parameters and response schemas. + + diff --git a/docs/market-data/subgraph.md b/docs/market-data/subgraph.md new file mode 100644 index 0000000..b13638e --- /dev/null +++ b/docs/market-data/subgraph.md @@ -0,0 +1,97 @@ +> ## 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. + +# Subgraph + +> Query onchain Polymarket data using GraphQL + +Polymarket's subgraphs provide indexed onchain data via GraphQL. Use them to query positions, volume, liquidity data, orders, activity, and market data. + +## Available Subgraphs + +| Subgraph | Description | Endpoint | +| ----------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| **Positions** | User token balances | [GraphQL Playground](https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/positions-subgraph/0.0.7/gn) | +| **Orders** | Order book and trade events | [GraphQL Playground](https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/orderbook-subgraph/0.0.1/gn) | +| **Activity** | Splits, merges, redemptions | [GraphQL Playground](https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/activity-subgraph/0.0.4/gn) | +| **Open Interest** | Market and global OI | [GraphQL Playground](https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/oi-subgraph/0.0.6/gn) | +| **PNL** | User position P\&L | [GraphQL Playground](https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/pnl-subgraph/0.0.14/gn) | + + + Subgraphs are hosted by [Goldsky](https://goldsky.com). Each endpoint includes + an interactive GraphQL playground for exploring the schema. + + +## Querying + +Send GraphQL queries via POST request to any subgraph endpoint. + +```bash theme={null} +curl -X POST \ + https://api.goldsky.com/api/public/project_cl6mb8i9h0003e201j6li0diw/subgraphs/orderbook-subgraph/0.0.1/gn \ + -H "Content-Type: application/json" \ + -d '{ + "query": "query MyQuery { orderbooks { id tradesQuantity } }" + }' +``` + +## Schema Reference + +### Positions + +| Query | Description | +| ---------------------------------------- | ------------------------------ | +| `userBalance` / `userBalances` | User token balances | +| `netUserBalance` / `netUserBalances` | Aggregated net balances | +| `tokenIdCondition` / `tokenIdConditions` | Token ID to condition mappings | +| `condition` / `conditions` | Market conditions | + +### Orders + +| Query | Description | +| ---------------------------------------------- | ----------------------- | +| `marketData` / `marketDatas` | Market-level data | +| `orderFilledEvent` / `orderFilledEvents` | Order fill events | +| `ordersMatchedEvent` / `ordersMatchedEvents` | Order match events | +| `orderbook` / `orderbooks` | Orderbook state | +| `ordersMatchedGlobal` / `ordersMatchedGlobals` | Global match statistics | + +### Activity + +| Query | Description | +| ------------------------------------------------------ | -------------------- | +| `split` / `splits` | USDC to token splits | +| `merge` / `merges` | Token to USDC merges | +| `redemption` / `redemptions` | Position redemptions | +| `negRiskConversion` / `negRiskConversions` | Neg risk conversions | +| `negRiskEvent` / `negRiskEvents` | Neg risk event data | +| `fixedProductMarketMaker` / `fixedProductMarketMakers` | FPMM data | +| `position` / `positions` | Position records | +| `condition` / `conditions` | Market conditions | + +### Open Interest + +| Query | Description | +| -------------------------------------------- | ------------------------ | +| `condition` / `conditions` | Market conditions | +| `negRiskEvent` / `negRiskEvents` | Neg risk event data | +| `marketOpenInterest` / `marketOpenInterests` | Per-market open interest | +| `globalOpenInterest` / `globalOpenInterests` | Global open interest | + +### PNL + +| Query | Description | +| -------------------------------- | ------------------------------- | +| `userPosition` / `userPositions` | User position P\&L data | +| `negRiskEvent` / `negRiskEvents` | Neg risk event data | +| `condition` / `conditions` | Market conditions | +| `fpmm` / `fpmms` | Fixed product market maker data | + +## Source Code + +The subgraph is open source. Review the schema and mappings on GitHub: + + + View source code, schema definitions, and deployment configuration. + diff --git a/docs/market-data/websocket/market-channel.md b/docs/market-data/websocket/market-channel.md new file mode 100644 index 0000000..65843f5 --- /dev/null +++ b/docs/market-data/websocket/market-channel.md @@ -0,0 +1,201 @@ +> ## 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": ["", ""], + "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 + +Requires `custom_feature_enabled: true`. + +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 + +Requires `custom_feature_enabled: true`. + +Emitted when a new market is created. + +```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" +} +``` + +### market\_resolved + +Requires `custom_feature_enabled: true`. + +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" +} +``` diff --git a/docs/market-data/websocket/overview.md b/docs/market-data/websocket/overview.md new file mode 100644 index 0000000..e0ecfc1 --- /dev/null +++ b/docs/market-data/websocket/overview.md @@ -0,0 +1,181 @@ +> ## 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" +} +``` + + + 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. + + +| Field | Type | Description | +| --------- | --------- | -------------------------------------------------- | +| `auth` | object | API credentials (`apiKey`, `secret`, `passphrase`) | +| `markets` | string\[] | Condition IDs to receive events for | +| `type` | string | Channel identifier | + + + 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). + + +### 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 & 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 +``` + + + If you don't respond to the server's ping within 10 seconds, the connection + will be closed. + + +## Troubleshooting + + + Send a valid subscription message immediately after connecting. The server may + close connections that don't subscribe within a timeout period. + + + + 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. + + + + 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 + + + + Verify your API credentials are correct and haven't expired. + diff --git a/docs/market-data/websocket/rtds.md b/docs/market-data/websocket/rtds.md new file mode 100644 index 0000000..ffd0f0a --- /dev/null +++ b/docs/market-data/websocket/rtds.md @@ -0,0 +1,361 @@ +> ## 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 and crypto prices via WebSocket + +The Polymarket Real-Time Data Socket (RTDS) is a WebSocket-based streaming service that provides real-time updates for **comments** and **crypto prices**. + + + Official RTDS TypeScript client (`real-time-data-client`). + + +## 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. + +Only the subscription types documented below are supported. + +## 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`, `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 (`crypto_prices`) + +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 (`crypto_prices_chainlink`) + + + **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/). + + +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 + +## 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 + + + Send `PING` messages every 5 seconds to keep the connection alive. Connection errors will trigger automatic reconnection attempts. + + + + Verify your subscription message is valid JSON with the correct `action`, `topic`, and `type` fields. Invalid subscription messages may result in connection closure. + + + + If subscribing to user-specific streams, ensure your `gamma_auth` object includes a valid wallet `address`. Authentication failures will prevent subscription to protected topics. + diff --git a/docs/market-data/websocket/sports.md b/docs/market-data/websocket/sports.md new file mode 100644 index 0000000..d29c12f --- /dev/null +++ b/docs/market-data/websocket/sports.md @@ -0,0 +1,215 @@ +> ## 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. + +## 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 / 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 | diff --git a/docs/market-makers/getting-started.md b/docs/market-makers/getting-started.md new file mode 100644 index 0000000..ca9a8f5 --- /dev/null +++ b/docs/market-makers/getting-started.md @@ -0,0 +1,232 @@ +> ## 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 USDC.e to Polygon, deploy a wallet, approve tokens for trading, and generate API credentials. + + + + Market makers need USDC.e 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 USDC.e 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 deposit 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 deposit addresses for EVM, SVM, and BTC networks + const addresses = await deposit.json(); + // Send USDC to the appropriate address for your source chain + ``` + + + + ### EOA (Externally Owned Account) + + Standard Ethereum wallet. You pay for all onchain transactions (approvals, splits, merges, trade execution). + + ### Safe Wallet (Recommended) + + Gnosis Safe-based wallet deployed via Polymarket's relayer. Benefits: + + * **Gasless transactions** — Polymarket pays gas fees for onchain operations + * **Contract wallet** — Enables advanced features like batched transactions + + Deploy a Safe wallet using the Relayer Client: + + + ```typescript TypeScript theme={null} + import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client"; + + const client = new RelayClient( + "https://relayer-v2.polymarket.com/", + 137, // Polygon mainnet + signer, + builderConfig, + 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 builder_config + + # Deploy the Safe wallet + response = client.deploy() + result = response.wait() + print("Safe Address:", result.get("proxyAddress")) + ``` + + + + See [Gasless Transactions](/trading/gasless) for full Relayer Client setup + including local and remote signing configurations. + + + + + Before trading, you must approve the exchange contracts to spend your tokens. + + ### Required Approvals + + | Token | Spender | Purpose | + | -------------------- | --------------------- | -------------------------------- | + | USDC.e | CTF Contract | Split USDC.e 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 (Polygon Mainnet) + + ```typescript theme={null} + const ADDRESSES = { + USDCe: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", + CTF: "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045", + CTF_EXCHANGE: "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E", + NEG_RISK_CTF_EXCHANGE: "0xC5d563A36AE78145C45a50134d48A1215220f80a", + NEG_RISK_ADAPTER: "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296", + }; + ``` + + ### Approve via Relayer Client + + + ```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 USDCe for CTF contract + const approveTx = { + to: ADDRESSES.USDCe, + data: erc20Interface.encodeFunctionData("approve", [ + ADDRESSES.CTF, + ethers.constants.MaxUint256, + ]), + value: "0", + }; + + const response = await client.execute([approveTx], "Approve USDCe for CTF"); + await response.wait(); + ``` + + ```python Python theme={null} + from web3 import Web3 + + USDC = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" + CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045" + MAX_UINT256 = 2**256 - 1 + + approve_tx = { + "to": USDC, + "data": Web3().eth.contract( + address=USDC, + 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 USDC for CTF") + response.wait() + ``` + + + + + To place orders and access authenticated endpoints, you need L2 API credentials derived from your wallet. + + + ```typescript TypeScript theme={null} + import { ClobClient } from "@polymarket/clob-client"; + + const client = new ClobClient("https://clob.polymarket.com", 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.client 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_creds() + ``` + + + Once you have credentials, initialize the client for authenticated operations: + + + ```typescript TypeScript theme={null} + const tradingClient = new ClobClient( + "https://clob.polymarket.com", + 137, + wallet, + credentials, + ); + ``` + + ```python Python theme={null} + client = ClobClient( + "https://clob.polymarket.com", + key=private_key, + chain_id=137, + creds=credentials, + ) + ``` + + + See [Authentication](/trading/overview#authentication) for full details on signature types and REST API headers. + + + +*** + +## Next Steps + + + + Post limit orders and manage quotes + + + + Connect to real-time market data + + diff --git a/docs/market-makers/inventory.md b/docs/market-makers/inventory.md new file mode 100644 index 0000000..f919569 --- /dev/null +++ b/docs/market-makers/inventory.md @@ -0,0 +1,339 @@ +> ## 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. + +# Inventory Management + +> Managing outcome token inventory for market making + +Market makers need outcome tokens on both sides to quote a market. The three core inventory operations are **splitting** USDC.e into YES/NO token pairs, **merging** pairs back into USDC.e, and **redeeming** winning tokens after resolution — all executed gaslessly through the Relayer Client. + + + For a full breakdown of how the Conditional Token Framework works, see [CTF + Overview](/trading/ctf/overview). This page focuses on the MM workflow using + the Relayer Client. + + +*** + +## Splitting USDC.e into Tokens + +Split converts USDC.e into equal amounts of YES and NO tokens — creating the inventory you need to quote both sides of a market. + + + ```typescript TypeScript theme={null} + import { ethers } from "ethers"; + import { Interface } from "ethers/lib/utils"; + import { RelayClient, Transaction } from "@polymarket/builder-relayer-client"; + + const CTF_ADDRESS = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"; + const USDCe_ADDRESS = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"; + + const ctfInterface = new Interface([ + "function splitPosition(address collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint[] partition, uint amount)", + ]); + + // Split $1000 USDCe into YES/NO tokens + const amount = ethers.utils.parseUnits("1000", 6); // USDCe has 6 decimals + + const splitTx: Transaction = { + to: CTF_ADDRESS, + data: ctfInterface.encodeFunctionData("splitPosition", [ + USDCe_ADDRESS, // collateralToken + ethers.constants.HashZero, // parentCollectionId (always zero for Polymarket) + conditionId, // conditionId from market + [1, 2], // partition: [YES, NO] + amount, + ]), + value: "0", + }; + + const response = await client.execute([splitTx], "Split USDCe into tokens"); + const result = await response.wait(); + console.log("Split completed:", result?.transactionHash); + ``` + + ```python Python theme={null} + from web3 import Web3 + + CTF_ADDRESS = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045" + USDCe_ADDRESS = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" + + ctf_abi = [{ + "name": "splitPosition", + "type": "function", + "inputs": [ + {"name": "collateralToken", "type": "address"}, + {"name": "parentCollectionId", "type": "bytes32"}, + {"name": "conditionId", "type": "bytes32"}, + {"name": "partition", "type": "uint256[]"}, + {"name": "amount", "type": "uint256"} + ], + "outputs": [] + }] + + # Split $1000 USDCe into YES/NO tokens + amount = 1000 * 10**6 # USDCe has 6 decimals + + split_tx = { + "to": CTF_ADDRESS, + "data": Web3().eth.contract( + address=CTF_ADDRESS, abi=ctf_abi + ).encode_abi( + abi_element_identifier="splitPosition", + args=[ + USDCe_ADDRESS, + bytes(32), # parentCollectionId (always zero) + condition_id, # conditionId from market + [1, 2], # partition: [YES, NO] + amount, + ] + ), + "value": "0" + } + + response = client.execute([split_tx], "Split USDCe into tokens") + response.wait() + ``` + + +After splitting 1000 USDC.e, you receive 1000 YES tokens and 1000 NO tokens. Your USDC.e balance decreases by 1000. + +*** + +## Merging Tokens to USDC.e + +Merge converts equal amounts of YES and NO tokens back into USDC.e — useful for reducing exposure, exiting a market, or freeing up capital. + + + ```typescript TypeScript theme={null} + const ctfInterface = new Interface([ + "function mergePositions(address collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint[] partition, uint amount)", + ]); + + // Merge 500 YES + 500 NO back to 500 USDCe + const amount = ethers.utils.parseUnits("500", 6); + + const mergeTx: Transaction = { + to: CTF_ADDRESS, + data: ctfInterface.encodeFunctionData("mergePositions", [ + USDCe_ADDRESS, + ethers.constants.HashZero, + conditionId, + [1, 2], + amount, + ]), + value: "0", + }; + + const response = await client.execute([mergeTx], "Merge tokens to USDCe"); + await response.wait(); + ``` + + ```python Python theme={null} + merge_abi = [{ + "name": "mergePositions", + "type": "function", + "inputs": [ + {"name": "collateralToken", "type": "address"}, + {"name": "parentCollectionId", "type": "bytes32"}, + {"name": "conditionId", "type": "bytes32"}, + {"name": "partition", "type": "uint256[]"}, + {"name": "amount", "type": "uint256"} + ], + "outputs": [] + }] + + # Merge 500 YES + 500 NO back to 500 USDCe + amount = 500 * 10**6 + + merge_tx = { + "to": CTF_ADDRESS, + "data": Web3().eth.contract( + address=CTF_ADDRESS, abi=merge_abi + ).encode_abi( + abi_element_identifier="mergePositions", + args=[USDCe_ADDRESS, bytes(32), condition_id, [1, 2], amount] + ), + "value": "0" + } + + response = client.execute([merge_tx], "Merge tokens to USDCe") + response.wait() + ``` + + +After merging 500 of each, your YES and NO balances decrease by 500 and your USDC.e balance increases by 500. + +*** + +## Redeeming After Resolution + +Once a market resolves, redeem winning tokens for USDC.e. Each winning token is worth $1 — losing tokens redeem for $0. + +### Check Resolution Status + + + ```typescript TypeScript theme={null} + const market = await clobClient.getMarket(conditionId); + if (market.closed) { + const winningToken = market.tokens.find((t) => t.winner); + console.log("Winning outcome:", winningToken?.outcome); + } + ``` + + ```python Python theme={null} + market = clob_client.get_market(condition_id) + if market.get("closed"): + winning = next(t for t in market["tokens"] if t.get("winner")) + print("Winning outcome:", winning["outcome"]) + ``` + + +### Redeem Winning Tokens + + + ```typescript TypeScript theme={null} + const ctfInterface = new Interface([ + "function redeemPositions(address collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint[] indexSets)", + ]); + + const redeemTx: Transaction = { + to: CTF_ADDRESS, + data: ctfInterface.encodeFunctionData("redeemPositions", [ + USDCe_ADDRESS, + ethers.constants.HashZero, + conditionId, + [1, 2], // Redeem both YES and NO (only winners pay out) + ]), + value: "0", + }; + + const response = await client.execute([redeemTx], "Redeem winning tokens"); + await response.wait(); + ``` + + ```python Python theme={null} + redeem_abi = [{ + "name": "redeemPositions", + "type": "function", + "inputs": [ + {"name": "collateralToken", "type": "address"}, + {"name": "parentCollectionId", "type": "bytes32"}, + {"name": "conditionId", "type": "bytes32"}, + {"name": "indexSets", "type": "uint256[]"} + ], + "outputs": [] + }] + + redeem_tx = { + "to": CTF_ADDRESS, + "data": Web3().eth.contract( + address=CTF_ADDRESS, abi=redeem_abi + ).encode_abi( + abi_element_identifier="redeemPositions", + args=[USDCe_ADDRESS, bytes(32), condition_id, [1, 2]] + ), + "value": "0" + } + + response = client.execute([redeem_tx], "Redeem winning tokens") + response.wait() + ``` + + +*** + +## Negative Risk Markets + +Multi-outcome markets use the Neg Risk CTF Exchange. Split and merge work the same way, but use different contract addresses: + +```typescript theme={null} +const NEG_RISK_ADAPTER = "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296"; +const NEG_RISK_CTF_EXCHANGE = "0xC5d563A36AE78145C45a50134d48A1215220f80a"; +``` + +See [Negative Risk Markets](/advanced/neg-risk) for details on how multi-outcome token mechanics differ. + +*** + +## Inventory Strategies + +### Before Quoting + +1. Check market metadata via the [Gamma API](/market-data/fetching-markets) +2. Split sufficient USDC.e to cover your expected quoting size +3. Set token approvals if not already done (see [Getting Started](/market-makers/getting-started)) + +### During Trading + +* **Skew quotes** when inventory becomes imbalanced on one side +* **Merge excess tokens** to free up capital for other markets +* **Split more** when inventory on either side runs low + +### After Resolution + +1. Cancel all open orders in the market +2. Wait for resolution to complete +3. Redeem winning tokens +4. Merge any remaining YES/NO pairs + +*** + +## Batch Operations + +Execute multiple inventory operations in a single relayer call for efficiency: + +```typescript theme={null} +const transactions: Transaction[] = [ + // Split on Market A + { + to: CTF_ADDRESS, + data: ctfInterface.encodeFunctionData("splitPosition", [ + USDCe_ADDRESS, + ethers.constants.HashZero, + conditionIdA, + [1, 2], + ethers.utils.parseUnits("1000", 6), + ]), + value: "0", + }, + // Split on Market B + { + to: CTF_ADDRESS, + data: ctfInterface.encodeFunctionData("splitPosition", [ + USDCe_ADDRESS, + ethers.constants.HashZero, + conditionIdB, + [1, 2], + ethers.utils.parseUnits("1000", 6), + ]), + value: "0", + }, +]; + +const response = await client.execute(transactions, "Batch inventory setup"); +await response.wait(); +``` + +*** + +## Next Steps + + + + How the Conditional Token Framework works under the hood + + + + Detailed split function parameters and prerequisites + + + + Detailed merge function parameters + + + + Relayer Client setup and configuration + + diff --git a/docs/market-makers/liquidity-rewards.md b/docs/market-makers/liquidity-rewards.md new file mode 100644 index 0000000..54a9e01 --- /dev/null +++ b/docs/market-makers/liquidity-rewards.md @@ -0,0 +1,166 @@ +> ## 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. + +# Liquidity Rewards + +> Earn rewards for providing liquidity on Polymarket + +By posting resting limit orders, liquidity providers (makers) are automatically eligible for Polymarket's incentive program. Rewards are distributed directly to maker addresses daily at midnight UTC. + +The program is designed to: + +* Catalyze liquidity across all markets +* Encourage liquidity throughout a market's entire lifecycle +* Motivate passive, balanced quoting tight to a market's midpoint +* Encourage trading activity +* Discourage blatantly exploitative behaviors + + + 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. + + +*** + +## Methodology + +Liquidity providers are rewarded based on a formula that rewards participation in markets, boosts two-sided depth (single-sided orders still score), and tighter spread vs the size-cutoff-adjusted midpoint. Each market configures a max spread and min size cutoff within which orders are considered. The average of rewards earned is determined by the relative share of each participant's Qn in market m. + +### Variables + +| Variable | Description | +| -------------- | ---------------------------------------------------------------- | +| S | Order position scoring function | +| v | Max spread from midpoint (in cents) | +| s | Spread from size-cutoff-adjusted midpoint | +| b | In-game multiplier | +| m | Market | +| m' | Market complement (i.e. NO if m = YES) | +| n | Trader index | +| u | Sample index | +| c | Scaling factor (currently 3.0 on all markets) | +| Qne | Point total for book one for a sample | +| Qno | Point total for book two for a sample | +| Spread% | Distance from midpoint (bps or relative) for order n in market m | +| BidSize | Share-denominated quantity of bid | +| AskSize | Share-denominated quantity of ask | + +*** + +## Equations + +### 1. Order Scoring Function + +Quadratic scoring rule for an order based on position between the adjusted midpoint and the minimum qualifying spread: + +$S(v,s)= (\frac{v-s}{v})^2 \cdot b$ + +### 2. First Market Side Score (Qne) + +$Q_{one}= S(v,Spread_{m_1}) \cdot BidSize_{m_1} + S(v,Spread_{m_2}) \cdot BidSize_{m_2} + \dots $ +$ + S(v, Spread_{m^\prime_1}) \cdot AskSize_{m^\prime_1} + S(v, Spread_{m^\prime_2}) \cdot AskSize_{m^\prime_2}$ + +### 3. Second Market Side Score (Qno) + +$Q_{two}= S(v,Spread_{m_1}) \cdot AskSize_{m_1} + S(v,Spread_{m_2}) \cdot AskSize_{m_2} + \dots $ +$ + S(v, Spread_{m^\prime_1}) \cdot BidSize_{m^\prime_1} + S(v, Spread_{m^\prime_2}) \cdot BidSize_{m^\prime_2}$ + +### 4. Minimum Score (Qmin) + +Boosts two-sided liquidity by taking the minimum of Qne and Qno, while still rewarding single-sided liquidity at a reduced rate (divided by c). + +**If midpoint is in range \[0.10, 0.90]** — single-sided liquidity can score: + +$Q_{\min} = \max(\min({Q_{one}, Q_{two}}), \max(Q_{one}/c, Q_{two}/c))$ + +**If midpoint is in range \[0, 0.10) or (0.90, 1.0]** — liquidity must be double-sided to score: + +$Q_{\min} = \min({Q_{one}, Q_{two}})$ + +### 5. Normalized Score (Qnormal) + +Qmin of a market maker divided by the sum of all Qmin across market makers in a given sample: + +$Q_{normal} = \frac{Q_{min}}{\sum_{n=1}^{N}{(Q_{min})_n}}$ + +### 6. Epoch Score (Qepoch) + +Sum of all Qnormal for a trader across all samples in an epoch: + +$Q_{epoch} = \sum_{u=1}^{10,080}{(Q_{normal})_u}$ + +### 7. Final Score (Qfinal) + +Normalizes Qepoch by dividing by the sum of all market makers' Qepoch in a given epoch. This value is multiplied by the rewards available for the market to get a trader's reward: + +$Q_{final}=\frac{Q_{epoch}}{\sum_{n=1}^{N}{(Q_{epoch})_n}}$ + +*** + +## Worked Example + +Assume an adjusted market midpoint of 0.50 and a max spread config of 3 cents for both m and m'. + +### Step 2 — First Side Score + +A trader has the following open orders: + +* 100Q bid on m @ 0.49 (spread = 1 cent) +* 200Q bid on m @ 0.48 (spread = 2 cents) +* 100Q ask on m' @ 0.51 (spread = 1 cent) + +$$ +Q_{ne} = \left( \frac{(3-1)}{3} \right)^2 \cdot 100 + \left( \frac{(3-2)}{3} \right)^2 \cdot 200 + \left( \frac{(3-1)}{3} \right)^2 \cdot 100 +$$ + +Qne is calculated every minute using random sampling. + +### Step 3 — Second Side Score + +The same trader also has: + +* 100Q bid on m @ 0.485 (spread = 1.5 cents) +* 100Q bid on m' @ 0.48 (spread = 2 cents) +* 200Q ask on m' @ 0.505 (spread = 0.5 cents) + +$$ +Q_{no} = \left( \frac{(3-1.5)}{3} \right)^2 \cdot 100 + \left( \frac{(3-2)}{3} \right)^2 \cdot 100 + \left( \frac{(3-.5)}{3} \right)^2 \cdot 200 +$$ + +Qno is calculated every minute using random sampling. + +### Steps 4–7 + +4. Take the minimum of Qne and Qno (with single-sided adjustment if midpoint is in \[0.10, 0.90]) +5. Normalize against all other market makers in the sample +6. Sum across all 10,080 samples in the epoch +7. Normalize again to get final reward share + +*** + + + The minimum reward payout is **\$1**; amounts below this will not be paid. + + + + Both `min_incentive_size` and `max_incentive_spread` can be fetched alongside + full market objects via the CLOB API and [Markets + API](/market-data/fetching-markets). Reward allocations for an epoch can also + be fetched via the Markets API. + + +## Next Steps + + + + Order entry and quoting best practices + + + + Earn USDC rebates on 15-minute crypto markets + + diff --git a/docs/market-makers/maker-rebates.md b/docs/market-makers/maker-rebates.md new file mode 100644 index 0000000..2802de0 --- /dev/null +++ b/docs/market-makers/maker-rebates.md @@ -0,0 +1,219 @@ +> ## 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. + +# Maker Rebates Program + +> Earn daily USDC rebates by providing liquidity on Polymarket + +Polymarket has enabled taker fees on **15-minute crypto markets**, **5-minute crypto markets**, **NCAAB (college basketball)**, and **Serie A** markets. These fees fund a **Maker Rebates** program that pays daily USDC rebates to liquidity providers. + +*** + +## Why Maker Rebates? + +Sports markets benefit from the same dynamics as crypto markets. When liquidity is deeper: + +* Spreads tend to be tighter +* Price impact is lower +* Fills are more reliable +* Markets are more resilient during volatility + +Maker Rebates incentivize **consistent, competitive quoting** so everyone gets a better trading experience. + +*** + +## How Maker Rebates Work + +* **Paid daily in USDC:** Rebates are calculated and distributed every day. +* **Performance-based:** You earn based on the share of liquidity you provided that actually got taken. + +### Eligibility + +Place orders that add liquidity to the book and get filled (i.e., your liquidity is taken by another trader). + +### Payment + +Rebates are paid daily in USDC, directly to your wallet. + +*** + +## Funding + +Maker Rebates are funded by taker fees collected in eligible markets. A percentage of these fees are redistributed to makers who keep the markets liquid. The rebate percentage differs by market type. + +| Market Type | Period | Maker Rebate | Distribution Method | +| ----------------------- | ------------- | ------------ | ------------------- | +| 15-Min Crypto | Jan 19, 2026+ | 20% | Fee-curve weighted | +| 5-Min Crypto | Feb 12, 2026+ | 20% | Fee-curve weighted | +| Sports (NCAAB, Serie A) | Feb 18, 2026+ | 25% | Fee-curve weighted | + + + Polymarket collects taker fees in eligible markets (15-minute crypto, 5-minute + crypto, NCAAB, and Serie A). The rebate percentage is at the sole discretion + of Polymarket and may change over time. + + +*** + +## Fee-Curve Weighted Rebates + +Rebates are distributed using the **same formula as taker fees**. This ensures makers are rewarded proportionally to the fee value their liquidity generates. + +For each filled maker order: + +```text theme={null} +fee_equivalent = C × p × feeRate × (p × (1 - p))^exponent +``` + +Where **C** = number of shares traded and **p** = price of the shares. The fee parameters differ by market type: + +| Parameter | Sports (NCAAB, Serie A) | 5-Min & 15-Min Crypto | +| --------- | ----------------------- | --------------------- | +| Fee Rate | 0.0175 | 0.25 | +| Exponent | 1 | 2 | + +Your daily rebate: + +```text theme={null} +rebate = (your_fee_equivalent / total_fee_equivalent) * rebate_pool +``` + +Totals are calculated per market, so you only compete with other makers in the same market. + +*** + +## Taker Fee Structure + +Taker fees are calculated in USDC and vary based on the share price. However, fees are collected in shares on buy orders and USDC on sell orders. Fees are highest at 50% probability and lowest at the extremes (near 0% or 100%). + + +
+