Update Polymarket documentation (2026-02-19)

- Added new documentation URLs from llms.txt index
- Updated TARGET.md with 244 total documentation pages
- Scraped new pages for trading, concepts, and API reference sections
- Updated changelog and new index pages
This commit is contained in:
AI Agent
2026-02-19 14:31:02 +01:00
parent 81f77eff3c
commit b2a29fe51f
250 changed files with 33306 additions and 9659 deletions
+105
View File
@@ -0,0 +1,105 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Deposit
> Bridge assets from any supported chain to fund your Polymarket account
Polymarket uses **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.
## How It Works
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
## Create Deposit Addresses
Generate unique deposit addresses linked to your Polymarket wallet. See the [Bridge API Reference](/api-reference/introduction) for full request and response schemas.
```bash theme={null}
curl -X POST https://bridge.polymarket.com/deposit \
-H "Content-Type: application/json" \
-d '{"address": "0x56687bf447db6ffa42ffe2204a05edaa20f55839"}'
```
### Address Types
| Address | Use For |
| ------- | -------------------------------------------------------- |
| `evm` | Ethereum, Arbitrum, Base, Optimism, and other EVM chains |
| `svm` | Solana |
| `btc` | Bitcoin |
| `tvm` | Tron |
<Warning>
Each address is unique to your wallet. Only send assets from supported chains
to the correct address type.
</Warning>
## Deposit Flow
<Steps>
<Step title="Get Your Deposit Address">
Call `POST /deposit` with your Polymarket wallet address to get deposit
addresses.
</Step>
<Step title="Check Supported Assets">
Verify your token is supported and meets the minimum deposit amount via
`/supported-assets`.
</Step>
<Step title="Send Assets">
Transfer tokens to the appropriate deposit address from your source chain.
</Step>
<Step title="Track Status">
Monitor your deposit progress using `/status/{address}`.
</Step>
</Steps>
## 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/)
<Warning>
Sending unsupported tokens may cause **irrecoverable loss**. Always verify
your token is listed in [Supported Assets](/trading/bridge/supported-assets)
before depositing.
</Warning>
## Next Steps
<CardGroup cols={2}>
<Card title="Supported Assets" icon="coins" href="/trading/bridge/supported-assets">
See all supported chains and tokens with minimum amounts.
</Card>
<Card title="Check Status" icon="clock" href="/trading/bridge/status">
Track your deposit progress through completion.
</Card>
</CardGroup>
+1
View File
@@ -0,0 +1 @@
null
+117
View File
@@ -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.
# Quote
> Preview fees and estimated output for deposits and withdrawals
Get an estimated quote before executing a deposit or withdrawal. Quotes include estimated output amounts, checkout time, and a detailed fee breakdown.
## Get a Quote
```bash theme={null}
curl -X POST https://bridge.polymarket.com/quote \
-H "Content-Type: application/json" \
-d '{
"fromAmountBaseUnit": "10000000",
"fromChainId": "137",
"fromTokenAddress": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
"recipientAddress": "0x17eC161f126e82A8ba337f4022d574DBEaFef575",
"toChainId": "137",
"toTokenAddress": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"
}'
```
### Request Parameters
| Parameter | Type | Description |
| -------------------- | ------ | ------------------------------------------------------------- |
| `fromAmountBaseUnit` | string | Amount to send in base units (e.g., `"10000000"` for 10 USDC) |
| `fromChainId` | string | Source chain ID (e.g., `"137"` for Polygon) |
| `fromTokenAddress` | string | Token contract address on the source chain |
| `recipientAddress` | string | Destination wallet address to receive funds |
| `toChainId` | string | Destination chain ID |
| `toTokenAddress` | string | Token contract address on the destination chain |
### Response
The quote response includes:
| Field | Type | Description |
| -------------------- | ------ | --------------------------------------- |
| `estCheckoutTimeMs` | number | Estimated checkout time in milliseconds |
| `estInputUsd` | number | Estimated input value in USD |
| `estOutputUsd` | number | Estimated output value in USD |
| `estToTokenBaseUnit` | string | Estimated output amount in base units |
| `quoteId` | string | Unique identifier for this quote |
| `estFeeBreakdown` | object | Detailed fee breakdown (see below) |
### Fee Breakdown
The `estFeeBreakdown` object contains:
<ResponseField name="gasUsd" type="number">
Gas fee in USD
</ResponseField>
<ResponseField name="appFeeLabel" type="string">
Label of the app fee
</ResponseField>
<ResponseField name="appFeePercent" type="number">
App fee as a percentage of the total amount
</ResponseField>
<ResponseField name="appFeeUsd" type="number">
App fee in USD
</ResponseField>
<ResponseField name="fillCostPercent" type="number">
Fill cost as a percentage of the total amount
</ResponseField>
<ResponseField name="fillCostUsd" type="number">
Fill cost in USD
</ResponseField>
<ResponseField name="maxSlippage" type="number">
Maximum potential slippage as a percentage
</ResponseField>
<ResponseField name="minReceived" type="number">
Minimum amount received after slippage
</ResponseField>
<ResponseField name="swapImpact" type="number">
Swap impact as a percentage of the total amount
</ResponseField>
<ResponseField name="swapImpactUsd" type="number">
Swap impact in USD
</ResponseField>
<ResponseField name="totalImpact" type="number">
Total impact as a percentage of the total amount
</ResponseField>
<ResponseField name="totalImpactUsd" type="number">
Total impact cost in USD
</ResponseField>
<Note>
Quotes are estimates. Actual amounts may vary slightly due to market
conditions.
</Note>
## Next Steps
<CardGroup cols={2}>
<Card title="Create Deposit" icon="arrow-right-to-bracket" href="/trading/bridge/deposit">
Execute a deposit to Polymarket.
</Card>
<Card title="Withdraw" icon="arrow-right-from-bracket" href="/trading/bridge/withdraw">
Withdraw from Polymarket to another chain.
</Card>
</CardGroup>
+95
View File
@@ -0,0 +1,95 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Deposit Status
> Track the progress of your bridge deposits
After sending assets to your deposit address, use the status endpoint to track progress until funds arrive in your Polymarket wallet.
## Check Status
Query the status of all deposits to a specific deposit address.
```bash theme={null}
curl https://bridge.polymarket.com/status/0x23566f8b2E82aDfCf01846E54899d110e97AC053
```
<Note>
Use the deposit address from the `/deposit` response (EVM, SVM, or BTC), not
your Polymarket wallet address.
</Note>
## Transaction Statuses
Each deposit progresses through these statuses:
| Status | Terminal | Description |
| --------------------- | -------- | -------------------------------------------------- |
| `DEPOSIT_DETECTED` | No | Funds detected on source chain, not yet processing |
| `PROCESSING` | No | Transaction is being routed and swapped |
| `ORIGIN_TX_CONFIRMED` | No | Source chain transaction confirmed |
| `SUBMITTED` | No | Submitted to destination chain (Polygon) |
| `COMPLETED` | Yes | Funds arrived — transaction successful |
| `FAILED` | Yes | Transaction encountered an error |
## Response
A response with active deposits:
```json theme={null}
{
"transactions": [
{
"fromChainId": "1",
"fromTokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"fromAmountBaseUnit": "1000000000",
"toChainId": "137",
"toTokenAddress": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174",
"status": "COMPLETED",
"txHash": "0xabc123...",
"createdTimeMs": 1697875200000
}
]
}
```
| Field | Description |
| -------------------- | ----------------------------------------------------------------------------------------- |
| `fromChainId` | Source chain ID |
| `fromTokenAddress` | Token sent |
| `fromAmountBaseUnit` | Amount in base units |
| `toChainId` | Destination chain (137 for Polygon) |
| `toTokenAddress` | Token received |
| `status` | Current status (see table above) |
| `txHash` | Destination transaction hash (only when `COMPLETED`) |
| `createdTimeMs` | Unix timestamp in milliseconds (only present once the transaction has started processing) |
## Empty Response
An empty `transactions` array means no deposits have been detected at this address yet:
```json theme={null}
{
"transactions": []
}
```
<Tip>
Transactions typically complete within a few minutes, but may take longer
depending on network conditions. Poll every 10-30 seconds until `COMPLETED` or
`FAILED`.
</Tip>
## Next Steps
<CardGroup cols={2}>
<Card title="Create Deposit" icon="arrow-right-to-bracket" href="/trading/bridge/deposit">
Generate deposit addresses for your wallet.
</Card>
<Card title="Supported Assets" icon="coins" href="/trading/bridge/supported-assets">
Check supported chains and minimum amounts.
</Card>
</CardGroup>
+62
View File
@@ -0,0 +1,62 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Supported Assets
> Chains and tokens supported for deposits to Polymarket
The Bridge API supports deposits from multiple chains and tokens. All deposits are automatically converted to **USDC.e on Polygon**, which is used as collateral for trading on Polymarket.
## Get Supported Assets
Retrieve the full list of supported chains and tokens with their minimum deposit amounts.
```bash theme={null}
curl https://bridge.polymarket.com/supported-assets
```
## Supported Chains
The bridge supports deposits from these blockchain networks:
| Chain | Address Type | Min Deposit | Example Tokens |
| --------------- | ------------ | ----------- | ------------------------------------------- |
| Ethereum | EVM | \$7 | ETH, USDC, USDT, WBTC, DAI, LINK, UNI, AAVE |
| Polygon | EVM | \$2 | POL, USDC, USDT, DAI, WETH, SAND |
| Arbitrum | EVM | \$2 | ETH, ARB, USDC, USDT, DAI, WBTC, USDe |
| Base | EVM | \$2 | ETH, USDC, USDT, DAI, cbBTC, AERO, USDS |
| Optimism | EVM | \$2 | ETH, OP, USDC, USDT, DAI, USDe |
| BNB Smart Chain | EVM | \$2 | BNB, USDC, USDT, DAI, ETH, BTCB, BUSD |
| Solana | SVM | \$2 | SOL, USDC, USDT, USDe, TRUMP |
| Bitcoin | BTC | \$9 | BTC |
| Tron | TVM | \$9 | USDT |
| HyperEVM | EVM | \$2 | HYPE, USDC, USDe, stHYPE, UBTC, UETH |
| Abstract | EVM | \$2 | ETH, USDC, USDT |
| Monad | EVM | \$2 | MON, USDC, USDT |
| Ethereal | EVM | \$2 | USDe, WUSDe |
| Katana | EVM | \$2 | AUSD |
| Lighter | EVM | \$2 | USDC |
<Note>
Supported assets change over time. Always call `/supported-assets` for the
current list before initiating a deposit.
</Note>
## Minimum Amounts
Each asset has a `minCheckoutUsd` value—the minimum deposit amount in USD equivalent. Deposits below this threshold may fail to process.
Most L2 chains (Polygon, Arbitrum, Base, Optimism) have low minimums of $2, while Ethereum deposits require $7 minimum. Bitcoin and Tron have \$9 minimums due to higher bridging costs.
## Next Steps
<CardGroup cols={2}>
<Card title="Create Deposit" icon="arrow-right-to-bracket" href="/trading/bridge/deposit">
Generate deposit addresses for your wallet.
</Card>
<Card title="Check Status" icon="clock" href="/trading/bridge/status">
Track your deposit progress.
</Card>
</CardGroup>
+102
View File
@@ -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.
# Withdraw
> Bridge USDC.e from Polymarket to any supported chain
Withdraw USDC.e from your Polymarket wallet to any supported chain and token. Funds are automatically bridged and swapped to your desired token on the destination chain.
## How It Works
1. Specify your destination chain, token, and recipient address
2. Receive deposit addresses for each destination chain (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
<Warning>
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.
</Warning>
<Warning>
When withdrawing, USDC.e (bridged USDC) is swapped through the
[Uniswap v3 pool](https://polygonscan.com/address/0xd36ec33c8bed5a9f7b6630855f1533455b98a418)
for USDC (native). The UI enforces less than 10bp difference in output amount.
At times, this pool may be exhausted. If you are having withdraw issues, try
breaking your withdraw into smaller amounts or waiting for the pool to be
rebalanced. Alternatively, you can withdraw USDC.e directly, which does not
require Uniswap liquidity — just be aware that some exchanges no longer accept
USDC.e deposits directly.
</Warning>
<Tip>
For very large withdrawals (over \$50,000), consider breaking the withdrawal
into smaller amounts or using a third-party bridge to minimize slippage.
</Tip>
## Create Withdrawal Addresses
Generate deposit addresses configured for your withdrawal destination. See the [Bridge API Reference](/api-reference/introduction) for full request and response schemas.
```bash theme={null}
curl -X POST https://bridge.polymarket.com/withdraw \
-H "Content-Type: application/json" \
-d '{
"address": "0x9156dd10bea4c8d7e2d591b633d1694b1d764756",
"toChainId": "1",
"toTokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"recipientAddr": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
}'
```
### Address Types
| Address | Use For |
| ------- | -------------------------------------------------------- |
| `evm` | Ethereum, Arbitrum, Base, Optimism, and other EVM chains |
| `svm` | Solana |
| `btc` | Bitcoin |
| `tvm` | Tron |
Withdrawals are **instant** and **free** — Polymarket does not charge withdrawal fees.
## Withdrawal Flow
<Steps>
<Step title="Check Supported Assets">
Verify your destination chain and token are supported via
`/supported-assets`.
</Step>
<Step title="Get a Quote">
Preview fees and estimated output via `POST /quote`.
</Step>
<Step title="Create Withdrawal Addresses">
Call `POST /withdraw` with your wallet address, destination chain, token,
and recipient.
</Step>
<Step title="Send USDC.e">
Transfer USDC.e from your Polymarket wallet to the appropriate deposit
address.
</Step>
<Step title="Track Status">Monitor progress using `/status/{address}`.</Step>
</Steps>
## Next Steps
<CardGroup cols={2}>
<Card title="Get a Quote" icon="calculator" href="/trading/bridge/quote">
Preview fees and estimated output before withdrawing.
</Card>
<Card title="Check Status" icon="clock" href="/trading/bridge/status">
Track your withdrawal progress.
</Card>
</CardGroup>
+307
View File
@@ -0,0 +1,307 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Builder Methods
> These methods require builder API credentials and are only relevant for Builders Program order attribution.
## Client Initialization
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.
<Tabs>
<Tab title="Local Builder Credentials">
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient } from "@polymarket/clob-client";
import { BuilderConfig, BuilderApiKeyCreds } from "@polymarket/builder-signing-sdk";
const builderConfig = new BuilderConfig({
localBuilderCreds: new BuilderApiKeyCreds({
key: process.env.BUILDER_API_KEY,
secret: process.env.BUILDER_SECRET,
passphrase: process.env.BUILDER_PASS_PHRASE,
}),
});
const clobClient = new ClobClient(
"https://clob.polymarket.com",
137,
signer,
apiCreds, // User's API credentials from L1 authentication
signatureType,
funderAddress,
undefined,
false,
builderConfig
);
```
```python Python theme={null}
from py_clob_client.client import ClobClient
from py_builder_signing_sdk.config import BuilderConfig, BuilderApiKeyCreds
import os
builder_config = BuilderConfig(
local_builder_creds=BuilderApiKeyCreds(
key=os.getenv("BUILDER_API_KEY"),
secret=os.getenv("BUILDER_SECRET"),
passphrase=os.getenv("BUILDER_PASS_PHRASE"),
)
)
clob_client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=os.getenv("PRIVATE_KEY"),
creds=creds, # User's API credentials from L1 authentication
signature_type=signature_type,
funder=funder,
builder_config=builder_config
)
```
</CodeGroup>
</Tab>
<Tab title="Remote Builder Signing">
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient } from "@polymarket/clob-client";
import { BuilderConfig } from "@polymarket/builder-signing-sdk";
const builderConfig = new BuilderConfig({
remoteBuilderConfig: { url: "http://localhost:3000/sign" }
});
const clobClient = new ClobClient(
"https://clob.polymarket.com",
137,
signer,
apiCreds, // User's API credentials from L1 authentication
signatureType,
funder,
undefined,
false,
builderConfig
);
```
```python Python theme={null}
from py_clob_client.client import ClobClient
from py_builder_signing_sdk.config import BuilderConfig, RemoteBuilderConfig
import os
builder_config = BuilderConfig(
remote_builder_config=RemoteBuilderConfig(
url="http://localhost:3000/sign"
)
)
clob_client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=os.getenv("PRIVATE_KEY"),
creds=creds, # User's API credentials from L1 authentication
signature_type=signature_type,
funder=funder,
builder_config=builder_config
)
```
</CodeGroup>
</Tab>
</Tabs>
<Info>
See [Order Attribution](/trading/orders/attribution) for more information on builder signing.
</Info>
***
## Methods
***
### getBuilderTrades()
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(
params?: TradeParams,
): Promise<BuilderTradesPaginatedResponse>
```
**Params (`TradeParams`)**
<ResponseField name="id" type="string">
Optional. Filter trades by trade ID.
</ResponseField>
<ResponseField name="maker_address" type="string">
Optional. Filter trades by maker address.
</ResponseField>
<ResponseField name="market" type="string">
Optional. Filter trades by market condition ID.
</ResponseField>
<ResponseField name="asset_id" type="string">
Optional. Filter trades by asset (token) ID.
</ResponseField>
<ResponseField name="before" type="string">
Optional. Return trades created before this cursor value.
</ResponseField>
<ResponseField name="after" type="string">
Optional. Return trades created after this cursor value.
</ResponseField>
**Response (`BuilderTradesPaginatedResponse`)**
<ResponseField name="trades" type="BuilderTrade[]">
Array of trades attributed to the builder account.
</ResponseField>
<ResponseField name="next_cursor" type="string">
Cursor string for fetching the next page of results.
</ResponseField>
<ResponseField name="limit" type="number">
Maximum number of trades returned per page.
</ResponseField>
<ResponseField name="count" type="number">
Total number of trades returned in this response.
</ResponseField>
**`BuilderTrade` fields**
<ResponseField name="id" type="string">
Unique identifier for the trade.
</ResponseField>
<ResponseField name="tradeType" type="string">
Type of the trade.
</ResponseField>
<ResponseField name="takerOrderHash" type="string">
Hash of the taker order associated with this trade.
</ResponseField>
<ResponseField name="builder" type="string">
Address of the builder who attributed this trade.
</ResponseField>
<ResponseField name="market" type="string">
Condition ID of the market this trade belongs to.
</ResponseField>
<ResponseField name="assetId" type="string">
Token ID of the asset traded.
</ResponseField>
<ResponseField name="side" type="string">
Side of the trade (e.g. BUY or SELL).
</ResponseField>
<ResponseField name="size" type="string">
Size of the trade in shares.
</ResponseField>
<ResponseField name="sizeUsdc" type="string">
Size of the trade denominated in USDC.
</ResponseField>
<ResponseField name="price" type="string">
Price at which the trade was executed.
</ResponseField>
<ResponseField name="status" type="string">
Current status of the trade.
</ResponseField>
<ResponseField name="outcome" type="string">
Outcome label associated with the traded asset.
</ResponseField>
<ResponseField name="outcomeIndex" type="number">
Index of the outcome within the market.
</ResponseField>
<ResponseField name="owner" type="string">
Address of the order owner (taker).
</ResponseField>
<ResponseField name="maker" type="string">
Address of the maker in the trade.
</ResponseField>
<ResponseField name="transactionHash" type="string">
On-chain transaction hash for the trade.
</ResponseField>
<ResponseField name="matchTime" type="string">
Timestamp when the trade was matched.
</ResponseField>
<ResponseField name="bucketIndex" type="number">
Bucket index used for trade grouping.
</ResponseField>
<ResponseField name="fee" type="string">
Fee charged for the trade in shares.
</ResponseField>
<ResponseField name="feeUsdc" type="string">
Fee charged for the trade denominated in USDC.
</ResponseField>
<ResponseField name="err_msg" type="string | null">
Optional. Error message if the trade encountered an issue, otherwise null.
</ResponseField>
<ResponseField name="createdAt" type="string | null">
Timestamp when the trade record was created, or null if unavailable.
</ResponseField>
<ResponseField name="updatedAt" type="string | null">
Timestamp when the trade record was last updated, or null if unavailable.
</ResponseField>
***
### revokeBuilderApiKey()
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<any>
```
<ResponseField name="returns" type="any">
Response from the revocation request.
</ResponseField>
***
## See Also
<CardGroup cols={2}>
<Card title="Builders Program" icon="hammer" href="/builders/overview">
Learn about the Builders Program and its benefits.
</Card>
<Card title="Order Attribution" icon="key" href="/trading/orders/attribution">
Attribute orders to your builder account.
</Card>
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
Place and manage orders with API credentials.
</Card>
<Card title="Gasless Transactions" icon="gas-pump" href="/trading/gasless">
Execute onchain operations without paying gas.
</Card>
</CardGroup>
+405
View File
@@ -0,0 +1,405 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# L1 Methods
> These methods require a wallet signer (private key) but do not require user API credentials. Use these for initial setup.
## Client Initialization
L1 methods require the client to initialize with a signer.
<Tabs>
<Tab title="TypeScript">
```typescript theme={null}
import { ClobClient } from "@polymarket/clob-client";
import { Wallet } from "ethers";
const signer = new Wallet(process.env.PRIVATE_KEY);
const client = new ClobClient(
"https://clob.polymarket.com",
137,
signer // Signer required for L1 methods
);
// Ready to create user API credentials
const apiKey = await client.createApiKey();
```
</Tab>
<Tab title="Python">
```python theme={null}
from py_clob_client.client import ClobClient
import os
private_key = os.getenv("PRIVATE_KEY")
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=private_key # Signer required for L1 methods
)
# Ready to create user API credentials
api_key = client.create_api_key()
```
</Tab>
</Tabs>
<Warning>
Never commit private keys to version control. Always use environment variables or a secure key management system.
</Warning>
***
## API Key Management
***
### createApiKey()
Creates a new API key (L2 credentials) for the wallet signer. 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<ApiKeyCreds>
```
<ResponseField name="nonce" type="number">
Optional custom nonce for deterministic key generation. Optional.
</ResponseField>
<ResponseField name="apiKey" type="string">
The generated API key string.
</ResponseField>
<ResponseField name="secret" type="string">
The secret associated with the API key.
</ResponseField>
<ResponseField name="passphrase" type="string">
The passphrase associated with the API key.
</ResponseField>
***
### deriveApiKey()
Derives an existing API key using a specific nonce. If you've already created credentials with a particular nonce, this returns the same credentials.
```typescript Signature theme={null}
async deriveApiKey(nonce?: number): Promise<ApiKeyCreds>
```
<ResponseField name="nonce" type="number">
The nonce used when originally creating the key. Optional.
</ResponseField>
<ResponseField name="apiKey" type="string">
The derived API key string.
</ResponseField>
<ResponseField name="secret" type="string">
The secret associated with the API key.
</ResponseField>
<ResponseField name="passphrase" type="string">
The passphrase associated with the API key.
</ResponseField>
***
### createOrDeriveApiKey()
Convenience method that attempts to derive an API key with the default nonce, or creates a new one if it doesn't exist. **Recommended for initial setup.**
```typescript Signature theme={null}
async createOrDeriveApiKey(nonce?: number): Promise<ApiKeyCreds>
```
<ResponseField name="apiKey" type="string">
The API key string, either derived or newly created.
</ResponseField>
<ResponseField name="secret" type="string">
The secret associated with the API key.
</ResponseField>
<ResponseField name="passphrase" type="string">
The passphrase associated with the API key.
</ResponseField>
***
## Order Signing
### createOrder()
Create and sign a limit order locally without posting it to the CLOB. Use this when you want to sign orders in advance or implement custom submission logic. Submit via [`postOrder()`](/trading/clients/l2#postorder) or [`postOrders()`](/trading/clients/l2#postorders).
```typescript Signature theme={null}
async createOrder(
userOrder: UserOrder,
options?: Partial<CreateOrderOptions>
): Promise<SignedOrder>
```
<ResponseField name="tokenID" type="string">
The token ID of the market outcome to trade.
</ResponseField>
<ResponseField name="price" type="number">
The limit price for the order.
</ResponseField>
<ResponseField name="size" type="number">
The size (number of shares) for the order.
</ResponseField>
<ResponseField name="side" type="Side">
The side of the order (buy or sell).
</ResponseField>
<ResponseField name="feeRateBps" type="number">
Optional fee rate in basis points. Optional.
</ResponseField>
<ResponseField name="nonce" type="number">
Optional nonce for the order. Optional.
</ResponseField>
<ResponseField name="expiration" type="number">
Optional expiration timestamp for the order. Optional.
</ResponseField>
<ResponseField name="taker" type="string">
Optional taker address for the order. Optional.
</ResponseField>
<ResponseField name="tickSize" type="TickSize">
The tick size used for order validation (CreateOrderOptions).
</ResponseField>
<ResponseField name="negRisk" type="boolean">
Optional flag for negative risk markets (CreateOrderOptions). Optional.
</ResponseField>
<ResponseField name="salt" type="string">
A random salt value for the signed order.
</ResponseField>
<ResponseField name="maker" type="string">
The maker's address.
</ResponseField>
<ResponseField name="signer" type="string">
The signer's address.
</ResponseField>
<ResponseField name="taker" type="string">
The taker's address in the signed order.
</ResponseField>
<ResponseField name="tokenId" type="string">
The token ID in the signed order.
</ResponseField>
<ResponseField name="makerAmount" type="string">
The maker amount as a string.
</ResponseField>
<ResponseField name="takerAmount" type="string">
The taker amount as a string.
</ResponseField>
<ResponseField name="side" type="number">
The side of the order as a number (0 = BUY, 1 = SELL).
</ResponseField>
<ResponseField name="expiration" type="string">
The expiration timestamp as a string.
</ResponseField>
<ResponseField name="nonce" type="string">
The nonce as a string.
</ResponseField>
<ResponseField name="feeRateBps" type="string">
The fee rate in basis points as a string.
</ResponseField>
<ResponseField name="signatureType" type="number">
The type identifier for the signature scheme used.
</ResponseField>
<ResponseField name="signature" type="string">
The cryptographic signature of the order.
</ResponseField>
***
### createMarketOrder()
Create and sign a market order locally without posting it to the CLOB. Submit via [`postOrder()`](/trading/clients/l2#postorder) or [`postOrders()`](/trading/clients/l2#postorders).
```typescript Signature theme={null}
async createMarketOrder(
userMarketOrder: UserMarketOrder,
options?: Partial<CreateOrderOptions>
): Promise<SignedOrder>
```
<ResponseField name="tokenID" type="string">
The token ID of the market outcome to trade.
</ResponseField>
<ResponseField name="amount" type="number">
The order amount. For BUY orders this is a dollar amount; for SELL orders this is the number of shares.
</ResponseField>
<ResponseField name="side" type="Side">
The side of the order (buy or sell).
</ResponseField>
<ResponseField name="price" type="number">
Optional price limit for the market order. Optional.
</ResponseField>
<ResponseField name="feeRateBps" type="number">
Optional fee rate in basis points. Optional.
</ResponseField>
<ResponseField name="nonce" type="number">
Optional nonce for the order. Optional.
</ResponseField>
<ResponseField name="taker" type="string">
Optional taker address for the order. Optional.
</ResponseField>
<ResponseField name="orderType" type="OrderType.FOK | OrderType.FAK">
Optional order type, either FOK (Fill-Or-Kill) or FAK (Fill-And-Kill). Optional.
</ResponseField>
<ResponseField name="salt" type="string">
A random salt value for the signed order.
</ResponseField>
<ResponseField name="maker" type="string">
The maker's address.
</ResponseField>
<ResponseField name="signer" type="string">
The signer's address.
</ResponseField>
<ResponseField name="taker" type="string">
The taker's address in the signed order.
</ResponseField>
<ResponseField name="tokenId" type="string">
The token ID in the signed order.
</ResponseField>
<ResponseField name="makerAmount" type="string">
The maker amount as a string.
</ResponseField>
<ResponseField name="takerAmount" type="string">
The taker amount as a string.
</ResponseField>
<ResponseField name="side" type="number">
The side of the order as a number (0 = BUY, 1 = SELL).
</ResponseField>
<ResponseField name="expiration" type="string">
The expiration timestamp as a string.
</ResponseField>
<ResponseField name="nonce" type="string">
The nonce as a string.
</ResponseField>
<ResponseField name="feeRateBps" type="string">
The fee rate in basis points as a string.
</ResponseField>
<ResponseField name="signatureType" type="number">
The type identifier for the signature scheme used.
</ResponseField>
<ResponseField name="signature" type="string">
The cryptographic signature of the order.
</ResponseField>
***
## Troubleshooting
<AccordionGroup>
<Accordion title="Error: INVALID_SIGNATURE">
Your wallet's private key is incorrect or improperly formatted.
**Solution:**
* Verify your private key is a valid hex string (starts with `0x`)
* Ensure you're using the correct key for the intended address
* Check that the key has proper permissions
</Accordion>
<Accordion title="Error: NONCE_ALREADY_USED">
The nonce you provided has already been used to create an API key.
**Solution:**
* Use `deriveApiKey()` with the same nonce to retrieve existing credentials
* Or use a different nonce with `createApiKey()`
</Accordion>
<Accordion title="Error: Invalid Funder Address">
Your funder address is incorrect or doesn't match your wallet.
**Solution:** 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.
</Accordion>
<Accordion title="Lost API credentials but have nonce">
```typescript theme={null}
// Use deriveApiKey with the original nonce
const recovered = await client.deriveApiKey(originalNonce);
```
</Accordion>
<Accordion title="Lost both credentials and nonce">
There's no way to recover lost credentials without the nonce. Create new ones:
```typescript theme={null}
// Create fresh credentials with a new nonce
const newCreds = await client.createApiKey();
// Save the nonce this time!
```
</Accordion>
</AccordionGroup>
***
## See Also
<CardGroup cols={2}>
<Card title="Authentication" icon="shield" href="/api-reference/authentication">
Deep dive into L1 and L2 authentication.
</Card>
<Card title="Trading Quickstart" icon="bolt" href="/trading/quickstart">
Initialize the client and place your first order.
</Card>
<Card title="Public Methods" icon="globe" href="/trading/clients/public">
Access market data, orderbooks, and prices without auth.
</Card>
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
Place and manage orders with API credentials.
</Card>
</CardGroup>
+772
View File
@@ -0,0 +1,772 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# L2 Methods
> These methods require user API credentials (L2 headers). Use these for placing trades and managing your positions.
## Client Initialization
L2 methods require the client to initialize with a signer, signature type, API credentials, and funder address.
<Tabs>
<Tab title="TypeScript">
```typescript theme={null}
import { ClobClient } from "@polymarket/clob-client";
import { Wallet } from "ethers";
const signer = new Wallet(process.env.PRIVATE_KEY);
const apiCreds = {
apiKey: process.env.API_KEY,
secret: process.env.SECRET,
passphrase: process.env.PASSPHRASE,
};
const client = new ClobClient(
"https://clob.polymarket.com",
137,
signer,
apiCreds,
2, // GNOSIS_SAFE
process.env.FUNDER_ADDRESS
);
// Ready to send authenticated requests
const order = await client.postOrder(signedOrder);
```
</Tab>
<Tab title="Python">
```python theme={null}
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import ApiCreds
import os
api_creds = ApiCreds(
api_key=os.getenv("API_KEY"),
api_secret=os.getenv("SECRET"),
api_passphrase=os.getenv("PASSPHRASE")
)
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137,
key=os.getenv("PRIVATE_KEY"),
creds=api_creds,
signature_type=2, # GNOSIS_SAFE
funder=os.getenv("FUNDER_ADDRESS")
)
# Ready to send authenticated requests
order = client.post_order(signed_order)
```
</Tab>
</Tabs>
***
## Order Creation and Management
***
### createAndPostOrder()
Convenience method that creates, signs, and posts a limit order in a single call. Use when you want to buy or sell at a specific price.
```typescript Signature theme={null}
async createAndPostOrder(
userOrder: UserOrder,
options?: Partial<CreateOrderOptions>,
orderType?: OrderType.GTC | OrderType.GTD, // Defaults to GTC
): Promise<OrderResponse>
```
**Params**
<ResponseField name="tokenID" type="string">
The token ID of the outcome to trade.
</ResponseField>
<ResponseField name="price" type="number">
The limit price for the order.
</ResponseField>
<ResponseField name="size" type="number">
The size of the order.
</ResponseField>
<ResponseField name="side" type="Side">
The side of the order (buy or sell).
</ResponseField>
<ResponseField name="feeRateBps" type="number">
Optional fee rate in basis points.
</ResponseField>
<ResponseField name="nonce" type="number">
Optional nonce for the order.
</ResponseField>
<ResponseField name="expiration" type="number">
Optional expiration timestamp for the order.
</ResponseField>
<ResponseField name="taker" type="string">
Optional taker address.
</ResponseField>
<ResponseField name="tickSize" type="TickSize">
Tick size for the order. One of `"0.1"`, `"0.01"`, `"0.001"`, `"0.0001"`.
</ResponseField>
<ResponseField name="negRisk" type="boolean">
Optional. Whether the market uses negative risk.
</ResponseField>
**Response**
<ResponseField name="success" type="boolean">
Whether the order was successfully placed.
</ResponseField>
<ResponseField name="errorMsg" type="string">
Error message if the order was not successful.
</ResponseField>
<ResponseField name="orderID" type="string">
The ID of the placed order.
</ResponseField>
<ResponseField name="transactionsHashes" type="string[]">
Array of transaction hashes associated with the order.
</ResponseField>
<ResponseField name="status" type="string">
The current status of the order.
</ResponseField>
<ResponseField name="takingAmount" type="string">
The amount being taken in the order.
</ResponseField>
<ResponseField name="makingAmount" type="string">
The amount being made in the order.
</ResponseField>
***
### createAndPostMarketOrder()
Convenience method that creates, signs, and posts a market order in a single call. Use when you want to buy or sell at the current market price.
```typescript Signature theme={null}
async createAndPostMarketOrder(
userMarketOrder: UserMarketOrder,
options?: Partial<CreateOrderOptions>,
orderType?: OrderType.FOK | OrderType.FAK, // Defaults to FOK
): Promise<OrderResponse>
```
**Params**
<ResponseField name="tokenID" type="string">
The token ID of the outcome to trade.
</ResponseField>
<ResponseField name="amount" type="number">
The amount for the market order.
</ResponseField>
<ResponseField name="side" type="Side">
The side of the order (buy or sell).
</ResponseField>
<ResponseField name="price" type="number">
Optional price hint for the market order.
</ResponseField>
<ResponseField name="feeRateBps" type="number">
Optional fee rate in basis points.
</ResponseField>
<ResponseField name="nonce" type="number">
Optional nonce for the order.
</ResponseField>
<ResponseField name="taker" type="string">
Optional taker address.
</ResponseField>
<ResponseField name="orderType" type="OrderType.FOK | OrderType.FAK">
Optional order type override. Defaults to FOK.
</ResponseField>
**Response**
<ResponseField name="success" type="boolean">
Whether the order was successfully placed.
</ResponseField>
<ResponseField name="errorMsg" type="string">
Error message if the order was not successful.
</ResponseField>
<ResponseField name="orderID" type="string">
The ID of the placed order.
</ResponseField>
<ResponseField name="transactionsHashes" type="string[]">
Array of transaction hashes associated with the order.
</ResponseField>
<ResponseField name="status" type="string">
The current status of the order.
</ResponseField>
<ResponseField name="takingAmount" type="string">
The amount being taken in the order.
</ResponseField>
<ResponseField name="makingAmount" type="string">
The amount being made in the order.
</ResponseField>
***
### postOrder()
Posts a pre-signed order to the CLOB. Use with [`createOrder()`](/trading/clients/l1#createorder) or [`createMarketOrder()`](/trading/clients/l1#createmarketorder) from L1 methods.
```typescript Signature theme={null}
async postOrder(
order: SignedOrder,
orderType?: OrderType, // Defaults to GTC
postOnly?: boolean, // Defaults to false
): Promise<OrderResponse>
```
***
### postOrders()
Posts up to 15 pre-signed orders in a single batch.
```typescript Signature theme={null}
async postOrders(
args: PostOrdersArgs[],
): Promise<OrderResponse[]>
```
**Params**
<ResponseField name="order" type="SignedOrder">
The pre-signed order to post.
</ResponseField>
<ResponseField name="orderType" type="OrderType">
The order type (e.g. GTC, FOK, FAK).
</ResponseField>
<ResponseField name="postOnly" type="boolean">
Optional. Whether to post the order as post-only. Defaults to false.
</ResponseField>
***
### cancelOrder()
Cancels a single open order.
```typescript Signature theme={null}
async cancelOrder(orderID: string): Promise<CancelOrdersResponse>
```
**Response**
<ResponseField name="canceled" type="string[]">
Array of order IDs that were successfully canceled.
</ResponseField>
<ResponseField name="not_canceled" type="Record<string, any>">
Map of order IDs to reasons why they could not be canceled.
</ResponseField>
***
### cancelOrders()
Cancels multiple orders in a single batch.
```typescript Signature theme={null}
async cancelOrders(orderIDs: string[]): Promise<CancelOrdersResponse>
```
***
### cancelAll()
Cancels all open orders.
```typescript Signature theme={null}
async cancelAll(): Promise<CancelOrdersResponse>
```
***
### cancelMarketOrders()
Cancels all open orders for a specific market.
```typescript Signature theme={null}
async cancelMarketOrders(
payload: OrderMarketCancelParams
): Promise<CancelOrdersResponse>
```
**Params**
<ResponseField name="market" type="string">
Optional. The market condition ID to cancel orders for.
</ResponseField>
<ResponseField name="asset_id" type="string">
Optional. The token ID to cancel orders for.
</ResponseField>
***
## Order and Trade Queries
***
### getOrder()
Get details for a specific order by ID.
```typescript Signature theme={null}
async getOrder(orderID: string): Promise<OpenOrder>
```
**Response**
<ResponseField name="id" type="string">
The unique order ID.
</ResponseField>
<ResponseField name="status" type="string">
The current status of the order.
</ResponseField>
<ResponseField name="owner" type="string">
The API key of the order owner.
</ResponseField>
<ResponseField name="maker_address" type="string">
The on-chain address of the order maker.
</ResponseField>
<ResponseField name="market" type="string">
The market condition ID the order belongs to.
</ResponseField>
<ResponseField name="asset_id" type="string">
The token ID the order is for.
</ResponseField>
<ResponseField name="side" type="string">
The side of the order (BUY or SELL).
</ResponseField>
<ResponseField name="original_size" type="string">
The original size of the order when it was placed.
</ResponseField>
<ResponseField name="size_matched" type="string">
The amount of the order that has been matched so far.
</ResponseField>
<ResponseField name="price" type="string">
The limit price of the order.
</ResponseField>
<ResponseField name="associate_trades" type="string[]">
Array of trade IDs associated with this order.
</ResponseField>
<ResponseField name="outcome" type="string">
The outcome label for the order's token.
</ResponseField>
<ResponseField name="created_at" type="number">
Unix timestamp of when the order was created.
</ResponseField>
<ResponseField name="expiration" type="string">
The expiration time of the order.
</ResponseField>
<ResponseField name="order_type" type="string">
The order type (e.g. GTC, FOK, FAK, GTD).
</ResponseField>
***
### getOpenOrders()
Get all your open orders.
```typescript Signature theme={null}
async getOpenOrders(
params?: OpenOrderParams,
only_first_page?: boolean,
): Promise<OpenOrder[]>
```
**Params**
<ResponseField name="id" type="string">
Optional. Filter by order ID.
</ResponseField>
<ResponseField name="market" type="string">
Optional. Filter by market condition ID.
</ResponseField>
<ResponseField name="asset_id" type="string">
Optional. Filter by token ID.
</ResponseField>
***
### getTrades()
Get your trade history (filled orders).
```typescript Signature theme={null}
async getTrades(
params?: TradeParams,
only_first_page?: boolean,
): Promise<Trade[]>
```
**Params**
<ResponseField name="id" type="string">
Optional. Filter by trade ID.
</ResponseField>
<ResponseField name="maker_address" type="string">
Optional. Filter by maker address.
</ResponseField>
<ResponseField name="market" type="string">
Optional. Filter by market condition ID.
</ResponseField>
<ResponseField name="asset_id" type="string">
Optional. Filter by token ID.
</ResponseField>
<ResponseField name="before" type="string">
Optional. Return trades before this timestamp.
</ResponseField>
<ResponseField name="after" type="string">
Optional. Return trades after this timestamp.
</ResponseField>
**Response**
<ResponseField name="id" type="string">
The unique trade ID.
</ResponseField>
<ResponseField name="taker_order_id" type="string">
The order ID of the taker side.
</ResponseField>
<ResponseField name="market" type="string">
The market condition ID for the trade.
</ResponseField>
<ResponseField name="asset_id" type="string">
The token ID for the trade.
</ResponseField>
<ResponseField name="side" type="Side">
The side of the trade (BUY or SELL).
</ResponseField>
<ResponseField name="size" type="string">
The size of the trade.
</ResponseField>
<ResponseField name="fee_rate_bps" type="string">
The fee rate in basis points.
</ResponseField>
<ResponseField name="price" type="string">
The price at which the trade was matched.
</ResponseField>
<ResponseField name="status" type="string">
The current status of the trade.
</ResponseField>
<ResponseField name="match_time" type="string">
The time at which the trade was matched.
</ResponseField>
<ResponseField name="last_update" type="string">
The time of the last update to this trade.
</ResponseField>
<ResponseField name="outcome" type="string">
The outcome label for the traded token.
</ResponseField>
<ResponseField name="bucket_index" type="number">
The bucket index for the trade.
</ResponseField>
<ResponseField name="owner" type="string">
The API key of the trade owner.
</ResponseField>
<ResponseField name="maker_address" type="string">
The on-chain address of the maker.
</ResponseField>
<ResponseField name="maker_orders" type="MakerOrder[]">
Array of maker order objects that participated in this trade. Each `MakerOrder` contains the following fields:
</ResponseField>
<ResponseField name="maker_orders[].order_id" type="string">
The maker order ID.
</ResponseField>
<ResponseField name="maker_orders[].owner" type="string">
The API key of the maker order owner.
</ResponseField>
<ResponseField name="maker_orders[].maker_address" type="string">
The on-chain address of the maker order maker.
</ResponseField>
<ResponseField name="maker_orders[].matched_amount" type="string">
The amount matched for this maker order.
</ResponseField>
<ResponseField name="maker_orders[].price" type="string">
The price of the maker order.
</ResponseField>
<ResponseField name="maker_orders[].fee_rate_bps" type="string">
The fee rate in basis points for the maker order.
</ResponseField>
<ResponseField name="maker_orders[].asset_id" type="string">
The token ID for the maker order.
</ResponseField>
<ResponseField name="maker_orders[].outcome" type="string">
The outcome label for the maker order's token.
</ResponseField>
<ResponseField name="maker_orders[].side" type="Side">
The side of the maker order (BUY or SELL).
</ResponseField>
<ResponseField name="transaction_hash" type="string">
The on-chain transaction hash for the trade.
</ResponseField>
<ResponseField name="trader_side" type="&#x22;TAKER&#x22; | &#x22;MAKER&#x22;">
Whether the authenticated user is the taker or a maker in this trade.
</ResponseField>
***
### getTradesPaginated()
Get trade history with pagination for large result sets.
```typescript Signature theme={null}
async getTradesPaginated(
params?: TradeParams,
): Promise<TradesPaginatedResponse>
```
**Response**
<ResponseField name="trades" type="Trade[]">
Array of trade objects for the current page.
</ResponseField>
<ResponseField name="limit" type="number">
The maximum number of trades returned per page.
</ResponseField>
<ResponseField name="count" type="number">
The total number of trades matching the query.
</ResponseField>
***
## Balance and Allowances
***
### getBalanceAllowance()
Get your balance and allowance for specific tokens.
```typescript Signature theme={null}
async getBalanceAllowance(
params?: BalanceAllowanceParams
): Promise<BalanceAllowanceResponse>
```
**Params**
<ResponseField name="asset_type" type="AssetType">
The type of asset to query. One of `"COLLATERAL"` or `"CONDITIONAL"`.
</ResponseField>
<ResponseField name="token_id" type="string">
Optional. The token ID to query (required when `asset_type` is `CONDITIONAL`).
</ResponseField>
**Response**
<ResponseField name="balance" type="string">
The current balance for the specified asset.
</ResponseField>
<ResponseField name="allowance" type="string">
The current allowance for the specified asset.
</ResponseField>
***
### updateBalanceAllowance()
Updates the cached balance and allowance for specific tokens.
```typescript Signature theme={null}
async updateBalanceAllowance(
params?: BalanceAllowanceParams
): Promise<void>
```
***
## API Key Management
***
### getApiKeys()
Get all API keys associated with your account.
```typescript Signature theme={null}
async getApiKeys(): Promise<ApiKeysResponse>
```
**Response**
<ResponseField name="apiKeys" type="ApiKeyCreds[]">
Array of API key credential objects associated with the account.
</ResponseField>
***
### deleteApiKey()
Deletes (revokes) the currently authenticated API key.
```typescript Signature theme={null}
async deleteApiKey(): Promise<any>
```
***
## Notifications
***
### getNotifications()
Retrieves all event notifications for the authenticated user. Records are automatically removed after 48 hours.
```typescript Signature theme={null}
async getNotifications(): Promise<Notification[]>
```
**Response**
<ResponseField name="id" type="number">
Unique notification ID.
</ResponseField>
<ResponseField name="owner" type="string">
The user's API key, or an empty string for global notifications.
</ResponseField>
<ResponseField name="payload" type="any">
Type-specific payload data for the notification.
</ResponseField>
<ResponseField name="timestamp" type="number">
Optional Unix timestamp of when the notification was created.
</ResponseField>
<ResponseField name="type" type="number">
Notification type (see below).
</ResponseField>
| Name | Value | Description |
| ------------------ | ----- | ---------------------------------------- |
| Order Cancellation | `1` | User's order was canceled |
| Order Fill | `2` | User's order was filled (maker or taker) |
| Market Resolved | `4` | Market was resolved |
***
### dropNotifications()
Mark notifications as read/dismissed.
```typescript Signature theme={null}
async dropNotifications(params?: DropNotificationParams): Promise<void>
```
**Params**
<ResponseField name="ids" type="string[]">
Array of notification IDs to dismiss.
</ResponseField>
***
## See Also
<CardGroup cols={2}>
<Card title="Authentication" icon="shield" href="/api-reference/authentication">
Deep dive into L1 and L2 authentication.
</Card>
<Card title="L1 Methods" icon="key" href="/trading/clients/l1">
Sign orders and derive API credentials with your private key.
</Card>
<Card title="Public Methods" icon="globe" href="/trading/clients/public">
Read market data and orderbooks without auth.
</Card>
<Card title="WebSocket" icon="bolt" href="/market-data/websocket/overview">
Real-time market data streaming.
</Card>
</CardGroup>
+663
View File
@@ -0,0 +1,663 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Public Methods
> These methods can be called without a signer or user credentials. Use these for reading market data, prices, and order books.
## Client Initialization
Public methods require the client to initialize with the host URL and Polygon chain ID.
<Tabs>
<Tab title="TypeScript">
```typescript theme={null}
import { ClobClient } from "@polymarket/clob-client";
const client = new ClobClient(
"https://clob.polymarket.com",
137
);
// Ready to call public methods
const markets = await client.getMarkets();
```
</Tab>
<Tab title="Python">
```python theme={null}
from py_clob_client.client import ClobClient
client = ClobClient(
host="https://clob.polymarket.com",
chain_id=137
)
# Ready to call public methods
markets = client.get_markets()
```
</Tab>
</Tabs>
***
## Health Check
***
### getOk()
Health check endpoint to verify the CLOB service is operational.
```typescript Signature theme={null}
async getOk(): Promise<any>
```
***
## Markets
***
### getMarket()
Get details for a single market by condition ID.
```typescript Signature theme={null}
async getMarket(conditionId: string): Promise<Market>
```
<ResponseField name="accepting_order_timestamp" type="string">
Timestamp from which the market started accepting orders, or null if not set.
</ResponseField>
<ResponseField name="accepting_orders" type="boolean">
Whether the market is currently accepting orders.
</ResponseField>
<ResponseField name="active" type="boolean">
Whether the market is active.
</ResponseField>
<ResponseField name="archived" type="boolean">
Whether the market has been archived.
</ResponseField>
<ResponseField name="closed" type="boolean">
Whether the market is closed.
</ResponseField>
<ResponseField name="condition_id" type="string">
The unique condition ID for the market.
</ResponseField>
<ResponseField name="description" type="string">
Human-readable description of the market.
</ResponseField>
<ResponseField name="enable_order_book" type="boolean">
Whether the order book is enabled for this market.
</ResponseField>
<ResponseField name="end_date_iso" type="string">
ISO 8601 end date of the market.
</ResponseField>
<ResponseField name="fpmm" type="string">
Address of the Fixed Product Market Maker contract.
</ResponseField>
<ResponseField name="game_start_time" type="string">
Start time of the underlying game or event.
</ResponseField>
<ResponseField name="icon" type="string">
URL of the market icon image.
</ResponseField>
<ResponseField name="image" type="string">
URL of the market image.
</ResponseField>
<ResponseField name="is_50_50_outcome" type="boolean">
Whether the market has equal 50/50 outcomes.
</ResponseField>
<ResponseField name="maker_base_fee" type="number">
Base fee charged to makers in basis points.
</ResponseField>
<ResponseField name="market_slug" type="string">
URL-friendly slug identifier for the market.
</ResponseField>
<ResponseField name="minimum_order_size" type="number">
Minimum order size allowed in this market.
</ResponseField>
<ResponseField name="minimum_tick_size" type="number">
Minimum price increment allowed in this market.
</ResponseField>
<ResponseField name="neg_risk" type="boolean">
Whether the market uses negative risk (binary complementary tokens).
</ResponseField>
<ResponseField name="neg_risk_market_id" type="string">
Negative risk market identifier, if applicable.
</ResponseField>
<ResponseField name="neg_risk_request_id" type="string">
Negative risk request identifier, if applicable.
</ResponseField>
<ResponseField name="notifications_enabled" type="boolean">
Whether notifications are enabled for this market.
</ResponseField>
<ResponseField name="question" type="string">
The market question text.
</ResponseField>
<ResponseField name="question_id" type="string">
Unique identifier for the market question.
</ResponseField>
<ResponseField name="rewards" type="object">
Object containing reward config: `max_spread` (number), `min_size` (number), `rates` (any)
</ResponseField>
<ResponseField name="seconds_delay" type="number">
Delay in seconds before orders are processed.
</ResponseField>
<ResponseField name="tags" type="string[]">
List of tags associated with the market.
</ResponseField>
<ResponseField name="taker_base_fee" type="number">
Base fee charged to takers in basis points.
</ResponseField>
<ResponseField name="tokens" type="MarketToken[]">
Array of market tokens, each containing `outcome` (string), `price` (number), `token_id` (string), and `winner` (boolean).
</ResponseField>
***
### getMarkets()
Get details for multiple markets paginated.
```typescript Signature theme={null}
async getMarkets(): Promise<PaginationPayload>
```
<ResponseField name="limit" type="number">
Maximum number of results per page.
</ResponseField>
<ResponseField name="count" type="number">
Total number of markets returned.
</ResponseField>
<ResponseField name="data" type="Market[]">
Array of Market objects. See `getMarket()` for the full Market structure.
</ResponseField>
***
### getSimplifiedMarkets()
Get simplified market data paginated for faster loading.
```typescript Signature theme={null}
async getSimplifiedMarkets(): Promise<PaginationPayload>
```
<ResponseField name="limit" type="number">
Maximum number of results per page.
</ResponseField>
<ResponseField name="count" type="number">
Total number of markets returned.
</ResponseField>
<ResponseField name="data" type="SimplifiedMarket[]">
Array of simplified market objects, each containing `accepting_orders` (boolean), `active` (boolean), `archived` (boolean), `closed` (boolean), `condition_id` (string), `rewards` (object with `rates`, `min_size`, `max_spread`), and `tokens` (SimplifiedToken\[]) with `outcome` (string), `price` (number), `token_id` (string).
</ResponseField>
***
### getSamplingMarkets()
Get markets eligible for sampling/liquidity rewards.
```typescript Signature theme={null}
async getSamplingMarkets(): Promise<PaginationPayload>
```
***
### getSamplingSimplifiedMarkets()
Get simplified market data for markets eligible for sampling/liquidity rewards.
```typescript Signature theme={null}
async getSamplingSimplifiedMarkets(): Promise<PaginationPayload>
```
***
## Order Books and Prices
***
### calculateMarketPrice()
Calculate the estimated price for a market order of a given size.
```typescript Signature theme={null}
async calculateMarketPrice(
tokenID: string,
side: Side,
amount: number,
orderType: OrderType = OrderType.FOK
): Promise<number>
```
<ResponseField name="tokenID" type="string">
The token ID to calculate the market price for.
</ResponseField>
<ResponseField name="side" type="Side">
The side of the order. One of: `BUY`, `SELL`
</ResponseField>
<ResponseField name="amount" type="number">
The size of the order to calculate price for.
</ResponseField>
<ResponseField name="orderType" type="OrderType">
The order type. One of: `GTC` (Good Till Cancelled), `FOK` (Fill or Kill), `GTD` (Good Till Date), `FAK` (Fill and Kill). Defaults to `FOK`.
</ResponseField>
<ResponseField name="returns" type="number">
The calculated estimated market price for the given order size.
</ResponseField>
***
### getOrderBook()
Get the order book for a specific token ID.
```typescript Signature theme={null}
async getOrderBook(tokenID: string): Promise<OrderBookSummary>
```
<ResponseField name="market" type="string">
The market condition ID.
</ResponseField>
<ResponseField name="asset_id" type="string">
The token/asset ID for this order book.
</ResponseField>
<ResponseField name="timestamp" type="string">
Timestamp of the order book snapshot.
</ResponseField>
<ResponseField name="bids" type="OrderSummary[]">
Array of bid entries, each with `price` (string) and `size` (string).
</ResponseField>
<ResponseField name="asks" type="OrderSummary[]">
Array of ask entries, each with `price` (string) and `size` (string).
</ResponseField>
<ResponseField name="min_order_size" type="string">
Minimum order size for this market.
</ResponseField>
<ResponseField name="tick_size" type="string">
Minimum price increment for this market.
</ResponseField>
<ResponseField name="neg_risk" type="boolean">
Whether the market uses negative risk.
</ResponseField>
<ResponseField name="hash" type="string">
Hash of the order book state.
</ResponseField>
***
### getOrderBooks()
Get order books for multiple token IDs.
```typescript Signature theme={null}
async getOrderBooks(params: BookParams[]): Promise<OrderBookSummary[]>
```
<ResponseField name="token_id" type="string">
The token ID to fetch the order book for.
</ResponseField>
<ResponseField name="side" type="Side">
The side of the book to query. One of: `BUY`, `SELL`
</ResponseField>
<ResponseField name="returns" type="OrderBookSummary[]">
Array of OrderBookSummary objects. See `getOrderBook()` for the full structure.
</ResponseField>
***
### getPrice()
Get the current best price for buying or selling a token ID.
```typescript Signature theme={null}
async getPrice(
tokenID: string,
side: "BUY" | "SELL"
): Promise<any>
```
<ResponseField name="price" type="string">
The current best price for the requested side.
</ResponseField>
***
### getPrices()
Get the current best prices for multiple token IDs.
```typescript Signature theme={null}
async getPrices(params: BookParams[]): Promise<PricesResponse>
```
<ResponseField name="returns" type="PricesResponse">
A map of token IDs to their prices. Each entry contains an optional `BUY` (string) and/or `SELL` (string) price.
</ResponseField>
***
### getMidpoint()
Get the midpoint price (average of best bid and best ask) for a token ID.
```typescript Signature theme={null}
async getMidpoint(tokenID: string): Promise<any>
```
<ResponseField name="mid" type="string">
The midpoint price, calculated as the average of best bid and best ask.
</ResponseField>
***
### getMidpoints()
Get the midpoint prices for multiple token IDs.
```typescript Signature theme={null}
async getMidpoints(params: BookParams[]): Promise<any>
```
<ResponseField name="returns" type="object">
A map of token IDs to their midpoint price strings. Each key is a token ID and its value is the midpoint price as a string.
</ResponseField>
***
### getSpread()
Get the spread (difference between best ask and best bid) for a token ID.
```typescript Signature theme={null}
async getSpread(tokenID: string): Promise<SpreadResponse>
```
<ResponseField name="spread" type="string">
The spread value, calculated as the difference between best ask and best bid.
</ResponseField>
***
### getSpreads()
Get the spreads for multiple token IDs.
```typescript Signature theme={null}
async getSpreads(params: BookParams[]): Promise<SpreadsResponse>
```
<ResponseField name="returns" type="object">
A map of token IDs to their spread strings. Each key is a token ID and its value is the spread as a string.
</ResponseField>
***
### getPricesHistory()
Get historical price data for a token.
```typescript Signature theme={null}
async getPricesHistory(params: PriceHistoryFilterParams): Promise<MarketPrice[]>
```
<ResponseField name="market" type="string">
The token ID to fetch price history for.
</ResponseField>
<ResponseField name="startTs" type="number">
Optional start timestamp (Unix seconds) for the price history range.
</ResponseField>
<ResponseField name="endTs" type="number">
Optional end timestamp (Unix seconds) for the price history range.
</ResponseField>
<ResponseField name="fidelity" type="number">
Optional fidelity/resolution of the price history data.
</ResponseField>
<ResponseField name="interval" type="PriceHistoryInterval">
Time interval for the price history. One of: `max`, `1w`, `1d`, `6h`, `1h`
</ResponseField>
<ResponseField name="t" type="number">
Unix timestamp of the price data point.
</ResponseField>
<ResponseField name="p" type="number">
Price value at the corresponding timestamp.
</ResponseField>
***
## Trades
***
### getLastTradePrice()
Get the price of the most recent trade for a token.
```typescript Signature theme={null}
async getLastTradePrice(tokenID: string): Promise<LastTradePrice>
```
<ResponseField name="price" type="string">
The price of the most recent trade.
</ResponseField>
<ResponseField name="side" type="string">
The side of the most recent trade.
</ResponseField>
***
### getLastTradesPrices()
Get the most recent trade prices for multiple tokens.
```typescript Signature theme={null}
async getLastTradesPrices(params: BookParams[]): Promise<LastTradePriceWithToken[]>
```
<ResponseField name="price" type="string">
The price of the most recent trade for the token.
</ResponseField>
<ResponseField name="side" type="string">
The side of the most recent trade.
</ResponseField>
<ResponseField name="token_id" type="string">
The token ID this trade price corresponds to.
</ResponseField>
***
### getMarketTradesEvents()
Get recent trade events for a market.
```typescript Signature theme={null}
async getMarketTradesEvents(conditionID: string): Promise<MarketTradeEvent[]>
```
<ResponseField name="event_type" type="string">
The type of trade event.
</ResponseField>
<ResponseField name="market" type="object">
Object containing market info: `condition_id` (string), `asset_id` (string), `question` (string), `icon` (string), `slug` (string).
</ResponseField>
<ResponseField name="user" type="object">
Object containing user info: `address` (string), `username` (string), `profile_picture` (string), `optimized_profile_picture` (string), `pseudonym` (string).
</ResponseField>
<ResponseField name="side" type="Side">
The side of the trade. One of: `BUY`, `SELL`
</ResponseField>
<ResponseField name="size" type="string">
The size of the trade.
</ResponseField>
<ResponseField name="fee_rate_bps" type="string">
The fee rate in basis points for the trade.
</ResponseField>
<ResponseField name="price" type="string">
The price at which the trade was executed.
</ResponseField>
<ResponseField name="outcome" type="string">
The outcome label for the traded token.
</ResponseField>
<ResponseField name="outcome_index" type="number">
The index of the outcome in the market.
</ResponseField>
<ResponseField name="transaction_hash" type="string">
The on-chain transaction hash for the trade.
</ResponseField>
<ResponseField name="timestamp" type="string">
The timestamp of when the trade event occurred.
</ResponseField>
***
## Market Parameters
***
### getFeeRateBps()
Get the fee rate in basis points for a token.
```typescript Signature theme={null}
async getFeeRateBps(tokenID: string): Promise<number>
```
<ResponseField name="returns" type="number">
The fee rate in basis points for the specified token.
</ResponseField>
***
### getTickSize()
Get the tick size (minimum price increment) for a market.
```typescript Signature theme={null}
async getTickSize(tokenID: string): Promise<TickSize>
```
<ResponseField name="returns" type="string">
The tick size for the market. One of: `0.1`, `0.01`, `0.001`, `0.0001`
</ResponseField>
***
### getNegRisk()
Check if a market uses negative risk (binary complementary tokens).
```typescript Signature theme={null}
async getNegRisk(tokenID: string): Promise<boolean>
```
<ResponseField name="returns" type="boolean">
Whether the market uses negative risk.
</ResponseField>
***
## Time & Server Info
### getServerTime()
Get the current server timestamp.
```typescript Signature theme={null}
async getServerTime(): Promise<number>
```
<ResponseField name="returns" type="number">
Unix timestamp in seconds representing the current server time.
</ResponseField>
***
## See Also
<CardGroup cols={2}>
<Card title="L1 Methods" icon="key" href="/trading/clients/l1">
Private key authentication to create or derive API credentials.
</Card>
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
Place orders, cancel orders, and query your trades.
</Card>
<Card title="REST API Reference" icon="code" href="/api-reference/introduction">
Complete REST endpoint documentation.
</Card>
<Card title="WebSocket" icon="bolt" href="/market-data/websocket/overview">
Real-time market data streaming.
</Card>
</CardGroup>
+63
View File
@@ -0,0 +1,63 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Merge Tokens
> Convert outcome token pairs back to USDC.e
**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
<ResponseField name="collateralToken" type="IERC20">
USDC.e (Bridged USDC) contract address: `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174`
</ResponseField>
<ResponseField name="parentCollectionId" type="bytes32">
Always `0x0000...0000` (32 zero bytes) for Polymarket markets
</ResponseField>
<ResponseField name="conditionId" type="bytes32">
The market's condition ID, available from the Markets API
</ResponseField>
<ResponseField name="partition" type="uint[]">
Array of index sets: `[1, 2]` for binary markets
</ResponseField>
<ResponseField name="amount" type="uint256">
The number of full sets to merge. Also the amount of collateral to receive.
</ResponseField>
## Next Steps
<CardGroup cols={2}>
<Card title="Redeem Tokens" icon="hand-holding-dollar" href="/trading/ctf/redeem">
Exchange winning tokens for USDC.e after resolution
</Card>
<Card title="CTF Overview" icon="book" href="/trading/ctf/overview">
Learn more about the Conditional Token Framework
</Card>
</CardGroup>
+140
View File
@@ -0,0 +1,140 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Conditional Token Framework
> Onchain token mechanics powering Polymarket positions
All outcomes on Polymarket are tokenized using the **Conditional Token Framework (CTF)**, an open standard developed by Gnosis. Understanding CTF operations enables advanced trading strategies, market making, and direct smart contract interactions.
## What is CTF?
The Conditional Token Framework creates **ERC1155 tokens** representing outcomes of prediction markets. Each binary market has two tokens:
| Token | Redeems for | Condition |
| ------- | ------------- | -------------------- |
| **Yes** | \$1.00 USDC.e | Event occurs |
| **No** | \$1.00 USDC.e | Event does not occur |
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:
<CardGroup cols={3}>
<Card title="Split" icon="scissors" href="/trading/ctf/split">
Convert USDC.e into Yes + No token pairs
</Card>
<Card title="Merge" icon="merge" href="/trading/ctf/merge">
Convert Yes + No pairs back to USDC.e
</Card>
<Card title="Redeem" icon="hand-holding-dollar" href="/trading/ctf/redeem">
Exchange winning tokens for USDC.e after resolution
</Card>
</CardGroup>
## Token Flow
<Frame>
<img src="https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/core-concepts/token-flow.png?fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=36f5a57946ac2b83136e17b6c06b358c" alt="" className="dark:hidden" data-og-width="1596" width="1596" data-og-height="952" height="952" data-path="images/core-concepts/token-flow.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/core-concepts/token-flow.png?w=280&fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=abc92640ec62d9e02f2097f1c67231cb 280w, https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/core-concepts/token-flow.png?w=560&fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=0f3f010e10a5cf39e78e594cdf8e579d 560w, https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/core-concepts/token-flow.png?w=840&fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=e26855cc3aeac4b609657690df3d0086 840w, https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/core-concepts/token-flow.png?w=1100&fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=78547971ce2f750cb824d2cfdc705171 1100w, https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/core-concepts/token-flow.png?w=1650&fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=bfdcab4d02ad6fe37e0549b33b940869 1650w, https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/core-concepts/token-flow.png?w=2500&fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=78ec4b0dae7b6dc701e180fbb2e755e4 2500w" />
<img src="https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/dark/core-concepts/token-flow.png?fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=69d150ea49ffa18cd7f24689342b1bec" alt="" className="hidden dark:block" data-og-width="1596" width="1596" data-og-height="952" height="952" data-path="images/dark/core-concepts/token-flow.png" data-optimize="true" data-opv="3" srcset="https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/dark/core-concepts/token-flow.png?w=280&fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=0ef33ff2c0ab77156745d8b381dafe00 280w, https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/dark/core-concepts/token-flow.png?w=560&fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=8ab82e34078a6811fc929d3bb15ee448 560w, https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/dark/core-concepts/token-flow.png?w=840&fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=750c6e303bc8df05bbb335dd79edd2d6 840w, https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/dark/core-concepts/token-flow.png?w=1100&fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=4d5553bef579cd8b50f5be39e8e91e61 1100w, https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/dark/core-concepts/token-flow.png?w=1650&fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=d69588b8286d2a561101ffbd55364ebd 1650w, https://mintcdn.com/polymarket-292d1b1b/FOMte3ewbG-LVy3k/images/dark/core-concepts/token-flow.png?w=2500&fit=max&auto=format&n=FOMte3ewbG-LVy3k&q=85&s=633d6ce55594e89381b81b30f5f0ad45 2500w" />
</Frame>
## Token Identifiers
Each outcome token has a unique **position ID** (also called token ID or asset ID), computed onchain in three steps.
### Step 1 — Condition ID
```
getConditionId(oracle, questionId, outcomeSlotCount)
```
| Parameter | Type | Value |
| ------------------ | --------- | ---------------------------------------------------------------- |
| `oracle` | `address` | [UMA CTF Adapter](https://github.com/Polymarket/uma-ctf-adapter) |
| `questionId` | `bytes32` | Hash of the UMA ancillary data |
| `outcomeSlotCount` | `uint` | `2` for all binary markets |
### Step 2 — Collection IDs
```
getCollectionId(parentCollectionId, conditionId, indexSet)
```
| Parameter | Type | Value |
| -------------------- | --------- | --------------------------------------------------------------- |
| `parentCollectionId` | `bytes32` | `bytes32(0)` — always zero for top-level positions |
| `conditionId` | `bytes32` | The condition ID from step 1 |
| `indexSet` | `uint` | `1` (`0b01`) for the first outcome, `2` (`0b10`) for the second |
The `indexSet` is a bitmask denoting which outcome slots belong to a collection. It must be a nonempty proper subset of the condition's outcome slots. Binary markets always have exactly two collections — one per outcome.
### Step 3 — Position IDs
```
getPositionId(collateralToken, collectionId)
```
| Parameter | Type | Value |
| ----------------- | --------- | ----------------------------------------- |
| `collateralToken` | `IERC20` | 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.
<Note>
You can look up token IDs directly via the Gamma API (`GET /markets` or `GET /events`
— the `tokens` array on each market contains both outcome token IDs). Computing them
manually is only necessary for direct smart contract integration.
</Note>
## Standard vs Neg Risk Markets
Polymarket has two market types with different CTF configurations:
| Feature | Standard Markets | Neg Risk Markets |
| ----------------- | ------------------- | --------------------- |
| CTF Contract | ConditionalTokens | ConditionalTokens |
| Exchange Contract | CTF Exchange | Neg Risk CTF Exchange |
| Multi-outcome | Independent markets | Linked via conversion |
| `negRisk` flag | `false` | `true` |
For neg risk markets, an additional **conversion** operation allows exchanging a No token for Yes tokens in all other outcomes. See [Negative Risk Markets](/advanced/neg-risk) for details.
## Contract Addresses
See [Contract Addresses](/resources/contract-addresses) for all Polymarket smart contract addresses on Polygon.
## Resources
<CardGroup cols={2}>
<Card title="CTF Source Code" icon="github" href="https://github.com/gnosis/conditional-tokens-contracts">
Gnosis Conditional Tokens smart contracts
</Card>
<Card title="Code Examples" icon="code" href="https://github.com/Polymarket/examples/tree/main/examples">
Python and TypeScript examples for onchain operations
</Card>
</CardGroup>
## Next Steps
<CardGroup cols={3}>
<Card title="Split Tokens" icon="scissors" href="/trading/ctf/split">
Create outcome token pairs from USDC.e
</Card>
<Card title="Merge Tokens" icon="merge" href="/trading/ctf/merge">
Convert token pairs back to USDC.e
</Card>
<Card title="Redeem Tokens" icon="hand-holding-dollar" href="/trading/ctf/redeem">
Collect winnings after resolution
</Card>
</CardGroup>
+94
View File
@@ -0,0 +1,94 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Redeem Tokens
> Exchange winning tokens for USDC.e after market resolution
**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
<Note>
You can redeem at any time after resolution — there's no deadline. Your
winning tokens will always be redeemable.
</Note>
## How Resolution Works
1. The market's end condition is met (event occurs, date passes, etc.)
2. The UMA Adapter oracle reports the outcome via `reportPayouts()`
3. The CTF contract records the payout vector
4. Redemption becomes available for winning tokens
## Prerequisites
Before redeeming:
1. **Market must be resolved** — check the market's `resolved` status
2. **Hold winning tokens** — only the winning outcome can be redeemed
3. **Know the condition ID** — required for the redemption call
## Function Parameters
<ResponseField name="collateralToken" type="IERC20">
USDC.e (Bridged USDC) contract address: `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174`
</ResponseField>
<ResponseField name="parentCollectionId" type="bytes32">
Always `0x0000...0000` (32 zero bytes) for Polymarket markets
</ResponseField>
<ResponseField name="conditionId" type="bytes32">
The market's condition ID
</ResponseField>
<ResponseField name="indexSets" type="uint[]">
Array of index sets to redeem: `[1, 2]` redeems both outcomes (only winning
pays)
</ResponseField>
<Note>
Redemption burns your entire token balance for the condition — there is no
amount parameter.
</Note>
## Payout Mechanics
The CTF uses a **payout vector** to determine redemption values:
| Outcome | Payout Vector | Redemption |
| -------- | ------------- | ----------------- |
| Yes wins | `[1, 0]` | Yes = $1, No = $0 |
| No wins | `[0, 1]` | Yes = $0, No = $1 |
When you 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
<CardGroup cols={2}>
<Card title="CTF Overview" icon="book" href="/trading/ctf/overview">
Learn more about the Conditional Token Framework
</Card>
<Card title="Resolution Process" icon="gavel" href="/concepts/resolution">
Understand how markets are resolved
</Card>
</CardGroup>
+69
View File
@@ -0,0 +1,69 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Split Tokens
> Convert USDC.e into outcome token pairs
**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`)
<Note>
If the partition is trivial, invalid, or refers to more slots than the
condition is prepared with, the transaction will revert.
</Note>
## How It Works
1. You approve the CTF 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
<ResponseField name="collateralToken" type="IERC20">
USDC.e (Bridged USDC) contract address: `0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174`
</ResponseField>
<ResponseField name="parentCollectionId" type="bytes32">
Always `0x0000...0000` (32 zero bytes) for Polymarket markets
</ResponseField>
<ResponseField name="conditionId" type="bytes32">
The market's condition ID, available from the Markets API
</ResponseField>
<ResponseField name="partition" type="uint[]">
Array of index sets: `[1, 2]` for binary markets (Yes = 1, No = 2)
</ResponseField>
<ResponseField name="amount" type="uint256">
The amount of collateral or stake to split. Also the number of full sets to
receive.
</ResponseField>
## Next Steps
<CardGroup cols={2}>
<Card title="Merge Tokens" icon="merge" href="/trading/ctf/merge">
Convert token pairs back to USDC.e
</Card>
<Card title="Trade on Orderbook" icon="chart-line" href="/trading/orders/create">
Place orders using your newly split tokens
</Card>
</CardGroup>
+221
View File
@@ -0,0 +1,221 @@
> ## 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.
# Fees
> Understanding trading fees on Polymarket
Polymarket does not charge fees on most markets. However, certain markets have taker fees enabled to fund the [Maker Rebates Program](/market-makers/maker-rebates).
***
## Fee-Free Markets
The vast majority of Polymarket markets have **no trading fees**:
* No fees to deposit or withdraw USDC (though intermediaries like Coinbase or MoonPay may charge their own fees)
* No fees to trade shares
***
## Markets With Fees
The following market types charge a small taker fee on each trade. These fees are collected and redistributed daily to market makers as rebates, incentivizing deeper liquidity and tighter spreads.
* **15-minute crypto markets**
* **5-minute crypto markets**
* **NCAAB (college basketball) markets** (starting February 18, 2026 for new markets)
* **Serie A markets** (starting February 18, 2026 for new markets)
### Fee Structure
Fees are calculated using the following formula:
```text theme={null}
fee = 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 |
| Maker Rebate % | 25% | 20% |
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. The effective rate **peaks at 50%** probability and decreases symmetrically toward the extremes.
<Frame>
<div className="p-3 bg-white rounded-xl">
<iframe title="Fee Curves" aria-label="Line chart" id="datawrapper-chart-qTzMH" src="https://datawrapper.dwcdn.net/qTzMH/1/" scrolling="no" frameborder="0" width={700} style={{ width: "0", minWidth: "100% !important", border: "none" }} height="450" data-external="1" />
</div>
</Frame>
### Fee Table (100 shares)
<Tabs>
<Tab title="5-Min & 15-Min Crypto">
| Price | Trade Value | Fee (USDC) | Effective Rate |
| ------ | ----------- | ---------- | -------------- |
| \$0.01 | \$1 | \$0.00 | 0.00% |
| \$0.05 | \$5 | \$0.003 | 0.06% |
| \$0.10 | \$10 | \$0.02 | 0.20% |
| \$0.15 | \$15 | \$0.06 | 0.41% |
| \$0.20 | \$20 | \$0.13 | 0.64% |
| \$0.25 | \$25 | \$0.22 | 0.88% |
| \$0.30 | \$30 | \$0.33 | 1.10% |
| \$0.35 | \$35 | \$0.45 | 1.29% |
| \$0.40 | \$40 | \$0.58 | 1.44% |
| \$0.45 | \$45 | \$0.69 | 1.53% |
| \$0.50 | \$50 | \$0.78 | **1.56%** |
| \$0.55 | \$55 | \$0.84 | 1.53% |
| \$0.60 | \$60 | \$0.86 | 1.44% |
| \$0.65 | \$65 | \$0.84 | 1.29% |
| \$0.70 | \$70 | \$0.77 | 1.10% |
| \$0.75 | \$75 | \$0.66 | 0.88% |
| \$0.80 | \$80 | \$0.51 | 0.64% |
| \$0.85 | \$85 | \$0.35 | 0.41% |
| \$0.90 | \$90 | \$0.18 | 0.20% |
| \$0.95 | \$95 | \$0.05 | 0.06% |
| \$0.99 | \$99 | \$0.00 | 0.00% |
The maximum effective fee rate is **1.56%** at 50% probability. Fees decrease symmetrically toward both extremes.
</Tab>
<Tab title="Sports (NCAAB, Serie A)">
| Price | Trade Value | Fee (USDC) | Effective Rate |
| ------ | ----------- | ---------- | -------------- |
| \$0.01 | \$1 | \$0.00 | 0.02% |
| \$0.05 | \$5 | \$0.00 | 0.08% |
| \$0.10 | \$10 | \$0.02 | 0.16% |
| \$0.15 | \$15 | \$0.03 | 0.22% |
| \$0.20 | \$20 | \$0.06 | 0.28% |
| \$0.25 | \$25 | \$0.08 | 0.33% |
| \$0.30 | \$30 | \$0.11 | 0.37% |
| \$0.35 | \$35 | \$0.14 | 0.40% |
| \$0.40 | \$40 | \$0.17 | 0.42% |
| \$0.45 | \$45 | \$0.19 | 0.43% |
| \$0.50 | \$50 | \$0.22 | **0.44%** |
| \$0.55 | \$55 | \$0.24 | 0.43% |
| \$0.60 | \$60 | \$0.25 | 0.42% |
| \$0.65 | \$65 | \$0.26 | 0.40% |
| \$0.70 | \$70 | \$0.26 | 0.37% |
| \$0.75 | \$75 | \$0.25 | 0.33% |
| \$0.80 | \$80 | \$0.22 | 0.28% |
| \$0.85 | \$85 | \$0.19 | 0.22% |
| \$0.90 | \$90 | \$0.14 | 0.16% |
| \$0.95 | \$95 | \$0.08 | 0.08% |
| \$0.99 | \$99 | \$0.02 | 0.02% |
The maximum effective fee rate is **0.44%** at 50% probability. Fees decrease symmetrically toward both extremes.
</Tab>
</Tabs>
### Fee Precision
Fees are rounded to 4 decimal places. The smallest fee charged is **0.0001 USDC**. Anything smaller rounds to zero, so very small trades near the extremes may incur no fee at all.
***
## Identifying Fee-Enabled Markets
The following market types have fees enabled:
* **15-minute crypto markets**
* **5-minute crypto markets**
* **NCAAB (college basketball) markets** (starting February 18, 2026 for new markets)
* **Serie A markets** (starting February 18, 2026 for new markets)
Query the fee-rate endpoint to check any specific market. See the [API Reference](/api-reference/introduction) for full endpoint documentation.
```bash theme={null}
GET https://clob.polymarket.com/fee-rate?token_id={token_id}
```
***
## Fee Handling for API Users
### Using the SDK (Recommended)
The official CLOB clients **automatically handle fees** for you — they fetch the fee rate and include it in the signed order payload.
<CardGroup cols={3}>
<Card title="TypeScript" icon="js" href="https://github.com/Polymarket/clob-client">
npm install @polymarket/clob-client\@latest
</Card>
<Card title="Python" icon="python" href="https://github.com/Polymarket/py-clob-client">
pip install --upgrade py-clob-client
</Card>
<Card title="Rust" icon="rust" href="https://github.com/Polymarket/rs-clob-client">
cargo add polymarket-client-sdk
</Card>
</CardGroup>
**What the client does automatically:**
1. Fetches the fee rate for the market's token ID
2. Includes `feeRateBps` in the order structure
3. Signs the order with the fee rate included
**You don't need to do anything extra.** Your orders will work on fee-enabled markets.
### Using the REST API
If you're calling the REST API directly or building your own order signing, you must manually include the fee rate in your signed order payload.
**Step 1:** Fetch the fee rate for the token ID before creating your order:
```bash theme={null}
GET https://clob.polymarket.com/fee-rate?token_id={token_id}
```
See the [fee-rate API Reference](/api-reference/introduction) for full response details. Fee-enabled markets return a non-zero value; fee-free markets return `0`.
**Step 2:** Add the `feeRateBps` field to your order object. This value is part of the signed payload — the CLOB validates your signature against it.
```json theme={null}
{
"salt": "12345",
"maker": "0x...",
"signer": "0x...",
"taker": "0x...",
"tokenId": "71321045679252212594626385532706912750332728571942532289631379312455583992563",
"makerAmount": "50000000",
"takerAmount": "100000000",
"expiration": "0",
"nonce": "0",
"feeRateBps": "1000",
"side": "0",
"signatureType": 2,
"signature": "0x..."
}
```
**Step 3:** Sign and submit:
1. Include `feeRateBps` in the order object **before signing**
2. Sign the complete order
3. POST to the order endpoint
<Note>
Always fetch `fee_rate_bps` dynamically — do not hardcode. The fee rate varies
by market type and may change over time. You only need to pass `feeRateBps`.
</Note>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Maker Rebates Program" icon="coins" href="/market-makers/maker-rebates">
Learn how taker fees fund daily USDC rebates for liquidity providers.
</Card>
<Card title="Place Orders" icon="plus" href="/trading/quickstart">
Start placing orders on Polymarket.
</Card>
</CardGroup>
+555
View File
@@ -0,0 +1,555 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Gasless Transactions
> Execute onchain operations without paying gas fees
Polymarket's **Relayer Client** enables gasless transactions for your users. Instead of requiring users to hold POL for gas, Polymarket's infrastructure pays all transaction fees. This creates a seamless experience where users only need USDC.e to trade.
## How It Works
The relayer acts as a transaction sponsor:
1. Your app creates a transaction
2. The user signs it with their private key
3. Your app sends it to Polymarket's relayer
4. The relayer submits it onchain and pays the gas fee
5. The transaction executes from the user's wallet
<Note>
Gasless transactions require **Builder Program** membership. You'll need
Builder API credentials to authenticate with the relayer.
</Note>
## What's Covered
Polymarket pays gas for all operations routed through the relayer:
| 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 |
## Prerequisites
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
<CodeGroup>
```bash npm theme={null}
npm install @polymarket/builder-relayer-client @polymarket/builder-signing-sdk
```
```bash pip theme={null}
pip install py-builder-relayer-client py-builder-signing-sdk
```
</CodeGroup>
## Client Setup
Initialize the relayer client with your signing configuration:
<Tabs>
<Tab title="Local Signing">
Use local signing when your backend handles all transactions securely.
<CodeGroup>
```typescript TypeScript theme={null}
import { createWalletClient, http, Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { polygon } from "viem/chains";
import { RelayClient } from "@polymarket/builder-relayer-client";
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
)
```
</CodeGroup>
</Tab>
<Tab title="Remote Signing">
Use remote signing to keep credentials on a secure server you control.
**Your signing server** receives request details and returns authentication headers:
<CodeGroup>
```typescript Server (TypeScript) theme={null}
import {
buildHmacSignature,
BuilderApiKeyCreds,
} from "@polymarket/builder-signing-sdk";
const BUILDER_CREDENTIALS: BuilderApiKeyCreds = {
key: process.env.POLY_BUILDER_API_KEY!,
secret: process.env.POLY_BUILDER_SECRET!,
passphrase: process.env.POLY_BUILDER_PASSPHRASE!,
};
// 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,
);
return {
POLY_BUILDER_SIGNATURE: signature,
POLY_BUILDER_TIMESTAMP: timestamp,
POLY_BUILDER_API_KEY: BUILDER_CREDENTIALS.key,
POLY_BUILDER_PASSPHRASE: BUILDER_CREDENTIALS.passphrase,
};
}
```
```python Server (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 endpoint
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
)
return {
"POLY_BUILDER_SIGNATURE": signature,
"POLY_BUILDER_TIMESTAMP": timestamp,
"POLY_BUILDER_API_KEY": BUILDER_CREDENTIALS.key,
"POLY_BUILDER_PASSPHRASE": BUILDER_CREDENTIALS.passphrase,
}
```
</CodeGroup>
**Your client** points to your signing server:
<CodeGroup>
```typescript Client (TypeScript) theme={null}
import { RelayClient } from "@polymarket/builder-relayer-client";
import { BuilderConfig } from "@polymarket/builder-signing-sdk";
const builderConfig = new BuilderConfig({
remoteBuilderConfig: {
url: "https://your-server.com/sign",
},
});
const client = new RelayClient(
"https://relayer-v2.polymarket.com/",
137,
wallet,
builderConfig,
);
```
```python Client (Python) theme={null}
from py_builder_relayer_client.client import RelayClient
from py_builder_signing_sdk import BuilderConfig, RemoteBuilderConfig
builder_config = BuilderConfig(
remote_builder_config=RemoteBuilderConfig(
url="https://your-server.com/sign"
)
)
client = RelayClient(
"https://relayer-v2.polymarket.com",
137,
private_key,
builder_config
)
```
</CodeGroup>
</Tab>
</Tabs>
<Warning>
Never expose Builder API credentials in client-side code. Use environment
variables or a secrets manager.
</Warning>
### Relayer Authentication Headers
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 |
| `POLY_BUILDER_PASSPHRASE` | Your Builder passphrase |
| `POLY_BUILDER_SIGNATURE` | HMAC-SHA256 signature |
The SDKs handle header generation automatically when you provide your credentials via `BuilderConfig`.
## Wallet Types
Choose a wallet type when initializing the client:
| Type | Deployment | Best For |
| --------- | ---------------------------------------- | ------------------------- |
| **Safe** | Call `deploy()` before first transaction | Most builder integrations |
| **Proxy** | Auto-deploys on first transaction | Magic Link users |
<CodeGroup>
```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();
console.log("Safe Address:", result?.proxyAddress);
```
```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"))
```
```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
```
</CodeGroup>
## Executing Transactions
Use the `execute` method to send transactions through the relayer:
```typescript theme={null}
interface Transaction {
to: string; // Target contract address
data: string; // Encoded function call
value: string; // POL to send (usually "0")
}
const response = await client.execute(transactions, "Description");
const result = await response.wait();
```
### Token Approval
Approve contracts to spend tokens:
<CodeGroup>
```typescript TypeScript theme={null}
import { encodeFunctionData, maxUint256 } from "viem";
const USDC = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
const CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045";
const approveTx = {
to: USDC,
data: encodeFunctionData({
abi: [
{
name: "approve",
type: "function",
inputs: [
{ name: "spender", type: "address" },
{ name: "amount", type: "uint256" },
],
outputs: [{ type: "bool" }],
},
],
functionName: "approve",
args: [CTF, maxUint256],
}),
value: "0",
};
const response = await client.execute([approveTx], "Approve 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()
```
</CodeGroup>
### Redeem Positions
Exchange winning tokens for USDC.e after market resolution:
<CodeGroup>
```typescript TypeScript theme={null}
import { encodeFunctionData } from "viem";
const redeemTx = {
to: CTF_ADDRESS,
data: encodeFunctionData({
abi: [
{
name: "redeemPositions",
type: "function",
inputs: [
{ name: "collateralToken", type: "address" },
{ name: "parentCollectionId", type: "bytes32" },
{ name: "conditionId", type: "bytes32" },
{ name: "indexSets", type: "uint256[]" },
],
outputs: [],
},
],
functionName: "redeemPositions",
args: [collateralToken, parentCollectionId, conditionId, indexSets],
}),
value: "0",
};
const response = await client.execute([redeemTx], "Redeem positions");
await response.wait();
```
```python Python theme={null}
CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
redeem_tx = {
"to": CTF,
"data": Web3().eth.contract(
address=CTF,
abi=[{
"name": "redeemPositions",
"type": "function",
"inputs": [
{"name": "collateralToken", "type": "address"},
{"name": "parentCollectionId", "type": "bytes32"},
{"name": "conditionId", "type": "bytes32"},
{"name": "indexSets", "type": "uint256[]"}
],
"outputs": []
}]
).encode_abi(
abi_element_identifier="redeemPositions",
args=[collateral_token, parent_collection_id, condition_id, index_sets]
),
"value": "0"
}
response = client.execute([redeem_tx], "Redeem positions")
response.wait()
```
</CodeGroup>
### Batch Transactions
Execute multiple operations atomically in a single call:
<CodeGroup>
```typescript TypeScript theme={null}
const approveTx = {
to: 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()
```
</CodeGroup>
<Tip>
Batching reduces latency and ensures all transactions succeed or fail
together.
</Tip>
## Transaction States
Track transaction progress through these states:
| State | Terminal | Description |
| ----------------- | -------- | ------------------------------- |
| `STATE_NEW` | No | Transaction received by relayer |
| `STATE_EXECUTED` | No | Submitted onchain |
| `STATE_MINED` | No | Included in a block |
| `STATE_CONFIRMED` | Yes | Finalized successfully |
| `STATE_FAILED` | Yes | Failed permanently |
| `STATE_INVALID` | Yes | Rejected as invalid |
## Contract Addresses
See [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
<CardGroup cols={2}>
<Card title="Negative Risk Markets" icon="scale-balanced" href="/advanced/neg-risk">
Learn about capital-efficient trading for multi-outcome events.
</Card>
<Card title="Positions & Tokens" icon="coins" href="/concepts/positions-tokens">
Understand token operations like split, merge, and redeem.
</Card>
</CardGroup>
+429
View File
@@ -0,0 +1,429 @@
> ## 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.
# Orderbook
> Reading the orderbook, prices, spreads, and midpoints
The orderbook is a public endpoint — no authentication required. You can read prices and liquidity using the SDK or REST API directly.
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient } from "@polymarket/clob-client";
const client = new ClobClient("https://clob.polymarket.com", 137);
```
```python Python theme={null}
from py_clob_client.client import ClobClient
client = ClobClient("https://clob.polymarket.com", chain_id=137)
```
```bash REST theme={null}
# Base URL for all orderbook endpoints
https://clob.polymarket.com
```
</CodeGroup>
***
## Get the Orderbook
Fetch the full orderbook for a token, including all resting bid and ask levels:
<CodeGroup>
```typescript TypeScript theme={null}
const book = await client.getOrderBook("TOKEN_ID");
console.log("Best bid:", book.bids[0]);
console.log("Best ask:", book.asks[0]);
console.log("Tick size:", book.tick_size);
```
```python Python theme={null}
book = client.get_order_book("TOKEN_ID")
print("Best bid:", book["bids"][0])
print("Best ask:", book["asks"][0])
print("Tick size:", book["tick_size"])
```
```bash REST theme={null}
curl "https://clob.polymarket.com/book?token_id=TOKEN_ID"
```
</CodeGroup>
### Response
```json theme={null}
{
"market": "0xbd31dc8a...",
"asset_id": "52114319501245...",
"timestamp": "2023-10-21T08:00:00Z",
"bids": [
{ "price": "0.48", "size": "1000" },
{ "price": "0.47", "size": "2500" }
],
"asks": [
{ "price": "0.52", "size": "800" },
{ "price": "0.53", "size": "1500" }
],
"min_order_size": "5",
"tick_size": "0.01",
"neg_risk": false,
"hash": "0xabc123..."
}
```
| Field | Description |
| ---------------- | --------------------------------------------------- |
| `market` | Condition ID of the market |
| `asset_id` | Token ID |
| `bids` | Buy orders sorted by price (highest first) |
| `asks` | Sell orders sorted by price (lowest first) |
| `tick_size` | Minimum price increment for this market |
| `min_order_size` | Minimum order size for this market |
| `neg_risk` | Whether this is a multi-outcome (neg risk) market |
| `hash` | Hash of the orderbook state — use to detect changes |
***
## Prices
Get the best available price for buying or selling a token:
<CodeGroup>
```typescript TypeScript theme={null}
const buyPrice = await client.getPrice("TOKEN_ID", "BUY");
console.log("Best ask:", buyPrice.price); // Price you'd pay to buy
const sellPrice = await client.getPrice("TOKEN_ID", "SELL");
console.log("Best bid:", sellPrice.price); // Price you'd receive to sell
```
```python Python theme={null}
buy_price = client.get_price("TOKEN_ID", "BUY")
print("Best ask:", buy_price["price"])
sell_price = client.get_price("TOKEN_ID", "SELL")
print("Best bid:", sell_price["price"])
```
```bash REST theme={null}
# Best price for buying (lowest ask)
curl "https://clob.polymarket.com/price?token_id=TOKEN_ID&side=BUY"
# Best price for selling (highest bid)
curl "https://clob.polymarket.com/price?token_id=TOKEN_ID&side=SELL"
```
</CodeGroup>
***
## Midpoints
The midpoint is the average of the best bid and best ask. This is the price displayed on Polymarket as the market's implied probability.
<CodeGroup>
```typescript TypeScript theme={null}
const midpoint = await client.getMidpoint("TOKEN_ID");
console.log("Midpoint:", midpoint.mid); // e.g., "0.50"
```
```python Python theme={null}
midpoint = client.get_midpoint("TOKEN_ID")
print("Midpoint:", midpoint["mid"])
```
```bash REST theme={null}
curl "https://clob.polymarket.com/midpoint?token_id=TOKEN_ID"
```
</CodeGroup>
<Note>
If the bid-ask spread is wider than \$0.10, Polymarket displays the last traded
price instead of the midpoint.
</Note>
***
## Spreads
The spread is the difference between the best ask and the best bid. Tighter spreads indicate more liquid markets.
<CodeGroup>
```typescript TypeScript theme={null}
const spread = await client.getSpread("TOKEN_ID");
console.log("Spread:", spread.spread); // e.g., "0.04"
```
```python Python theme={null}
spread = client.get_spread("TOKEN_ID")
print("Spread:", spread["spread"])
```
```bash REST theme={null}
# Spreads use POST for batch requests
curl -X POST "https://clob.polymarket.com/spreads" \
-H "Content-Type: application/json" \
-d '[{"token_id": "TOKEN_ID"}]'
```
</CodeGroup>
***
## Price History
Fetch historical price data for a token over various time intervals:
<CodeGroup>
```typescript TypeScript theme={null}
import { PriceHistoryInterval } from "@polymarket/clob-client";
const history = await client.getPricesHistory({
market: "TOKEN_ID", // Note: this param is named "market" but takes a token ID
interval: PriceHistoryInterval.ONE_DAY,
fidelity: 60, // Data points every 60 minutes
});
// Each entry: { t: timestamp, p: price }
history.forEach((point) => {
console.log(`${new Date(point.t * 1000).toISOString()}: ${point.p}`);
});
```
```python Python theme={null}
history = client.get_prices_history(
market="TOKEN_ID", # Note: this param is named "market" but takes a token ID
interval="1d",
fidelity=60, # Data points every 60 minutes
)
for point in history:
print(f"{point['t']}: {point['p']}")
```
```bash REST theme={null}
# By interval (relative to now)
curl "https://clob.polymarket.com/prices-history?market=TOKEN_ID&interval=1d&fidelity=60"
# By timestamp range
curl "https://clob.polymarket.com/prices-history?market=TOKEN_ID&startTs=1697875200&endTs=1697961600"
```
</CodeGroup>
| Interval | Description |
| -------- | ------------------ |
| `1h` | Last hour |
| `6h` | Last 6 hours |
| `1d` | Last day |
| `1w` | Last week |
| `1m` | Last month |
| `max` | All available data |
<Note>
`interval` is relative to the current time. Use `startTs` / `endTs` for
absolute time ranges. They are mutually exclusive — don't combine them.
</Note>
***
## Estimate Fill Price
Calculate the effective price you'd pay for a market order of a given size, accounting for orderbook depth:
<CodeGroup>
```typescript TypeScript theme={null}
import { Side, OrderType } from "@polymarket/clob-client";
// What price would I pay to buy $500 worth?
const price = await client.calculateMarketPrice(
"TOKEN_ID",
Side.BUY,
500, // dollar amount
OrderType.FOK,
);
console.log("Estimated fill price:", price);
```
```python Python theme={null}
from py_clob_client.clob_types import OrderType
price = client.calculate_market_price(
token_id="TOKEN_ID",
side="BUY",
amount=500,
order_type=OrderType.FOK,
)
print("Estimated fill price:", price)
```
</CodeGroup>
This walks the orderbook to estimate slippage. Useful for sizing market orders before submitting them.
***
## Batch Requests
All orderbook queries have batch variants for fetching data across multiple tokens in a single request (up to 500 tokens):
| Single | Batch | REST |
| --------------------- | ----------------------- | ----------------- |
| `getOrderBook()` | `getOrderBooks()` | `POST /books` |
| `getPrice()` | `getPrices()` | `POST /prices` |
| `getMidpoint()` | `getMidpoints()` | `POST /midpoints` |
| `getSpread()` | `getSpreads()` | `POST /spreads` |
| `getLastTradePrice()` | `getLastTradesPrices()` | — |
<Note>
`BookParams` for batch orderbook requests accepts a `token_id` and an optional
`side` parameter to filter by bid or ask side.
</Note>
<CodeGroup>
```typescript TypeScript theme={null}
import { Side } from "@polymarket/clob-client";
// Fetch prices for multiple tokens
const prices = await client.getPrices([
{ token_id: "TOKEN_A", side: Side.BUY },
{ token_id: "TOKEN_B", side: Side.BUY },
]);
// Returns: { "TOKEN_A": { "BUY": "0.52" }, "TOKEN_B": { "BUY": "0.74" } }
```
```python Python theme={null}
prices = client.get_prices([
{"token_id": "TOKEN_A", "side": "BUY"},
{"token_id": "TOKEN_B", "side": "BUY"},
])
```
```bash REST theme={null}
curl -X POST "https://clob.polymarket.com/prices" \
-H "Content-Type: application/json" \
-d '[
{"token_id": "TOKEN_A", "side": "BUY"},
{"token_id": "TOKEN_B", "side": "BUY"}
]'
```
</CodeGroup>
***
## Last Trade Price
Get the price and side of the most recent trade for a token:
<CodeGroup>
```typescript TypeScript theme={null}
const lastTrade = await client.getLastTradePrice("TOKEN_ID");
console.log(lastTrade.price, lastTrade.side);
// e.g., "0.52", "BUY"
```
```python Python theme={null}
last_trade = client.get_last_trade_price("TOKEN_ID")
print(last_trade["price"], last_trade["side"])
```
</CodeGroup>
***
## Real-Time Updates
For live orderbook data, use the WebSocket API instead of polling. The `market` channel streams orderbook changes, price updates, and trade events in real time.
### Connecting
```typescript theme={null}
const ws = new WebSocket(
"wss://ws-subscriptions-clob.polymarket.com/ws/market",
);
ws.onopen = () => {
ws.send(
JSON.stringify({
type: "market",
assets_ids: ["TOKEN_ID"],
custom_feature_enabled: true, // enables best_bid_ask, new_market, market_resolved events
}),
);
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
switch (data.event_type) {
case "book": // full orderbook snapshot
case "price_change": // individual price level update
case "last_trade_price": // new trade executed
case "tick_size_change": // market tick size changed
case "best_bid_ask": // top-of-book update (requires custom_feature_enabled)
case "new_market": // new market created (requires custom_feature_enabled)
case "market_resolved": // market resolved (requires custom_feature_enabled)
}
};
```
### Dynamic Subscribe / Unsubscribe
After connecting, you can change your subscriptions without reconnecting:
```typescript theme={null}
// Subscribe to additional tokens
ws.send(
JSON.stringify({
assets_ids: ["NEW_TOKEN_ID"],
operation: "subscribe",
}),
);
// Unsubscribe from tokens
ws.send(
JSON.stringify({
assets_ids: ["OLD_TOKEN_ID"],
operation: "unsubscribe",
}),
);
```
### Event Types
| Event | Trigger | Key Fields |
| ------------------ | -------------------------------------------- | ---------------------------------------------------------------------- |
| `book` | On subscribe + when a trade affects the book | `bids[]`, `asks[]`, `hash`, `timestamp` |
| `price_change` | New order placed or order cancelled | `price_changes[]` with `price`, `size`, `side`, `best_bid`, `best_ask` |
| `last_trade_price` | Trade executed | `price`, `side`, `size`, `fee_rate_bps` |
| `tick_size_change` | Price hits >0.96 or \< 0.04 | `old_tick_size`, `new_tick_size` |
| `best_bid_ask` | Top-of-book changes | `best_bid`, `best_ask`, `spread` |
| `new_market` | Market created | `question`, `assets_ids`, `outcomes` |
| `market_resolved` | Market resolved | `winning_asset_id`, `winning_outcome` |
<Note>
`best_bid_ask`, `new_market`, and `market_resolved` require
`custom_feature_enabled: true` in your subscription message.
</Note>
<Warning>
The `tick_size_change` event is critical for trading bots. If the tick size
changes and you continue using the old tick size, your orders will be
rejected.
</Warning>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Place Orders" icon="plus" href="/trading/orders/create">
Create and submit orders using the orderbook data
</Card>
<Card title="Fetching Markets" icon="magnifying-glass" href="/market-data/fetching-markets">
Find token IDs for markets you want to trade
</Card>
</CardGroup>
+339
View File
@@ -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.
# Order Attribution
> Attribute orders to your builder key for volume credit
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](https://polymarket.com/settings?tab=builder):
| Credential | Description |
| ------------ | ------------------------------------ |
| `key` | Your builder API key identifier |
| `secret` | Secret key for signing requests |
| `passphrase` | Additional authentication passphrase |
<Warning>
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.
</Warning>
***
## Remote Signing (Recommended)
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.
### Server Implementation
Your signing server receives request details and returns the authentication headers:
<CodeGroup>
```typescript TypeScript theme={null}
import {
buildHmacSignature,
BuilderApiKeyCreds,
} from "@polymarket/builder-signing-sdk";
const BUILDER_CREDENTIALS: BuilderApiKeyCreds = {
key: process.env.POLY_BUILDER_API_KEY!,
secret: process.env.POLY_BUILDER_SECRET!,
passphrase: process.env.POLY_BUILDER_PASSPHRASE!,
};
// 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(
BUILDER_CREDENTIALS.secret,
parseInt(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,
};
}
```
```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,
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,
}
```
</CodeGroup>
### Client Configuration
Point the CLOB client to your signing server:
<CodeGroup>
```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
)
)
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
)
# Orders automatically include builder headers
response = client.create_and_post_order(...)
```
</CodeGroup>
***
## Local Signing
Sign orders locally when you control the entire order placement flow (e.g., your backend places orders on behalf of users):
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient } from "@polymarket/clob-client";
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 = new BuilderConfig({
localBuilderCreds: builderCreds,
});
const client = new ClobClient(
"https://clob.polymarket.com",
137,
signer,
apiCreds,
2,
funderAddress,
undefined,
false,
builderConfig,
);
// Orders automatically include builder headers
const response = await client.createAndPostOrder(/* ... */);
```
```python Python theme={null}
import os
from py_clob_client.client import ClobClient
from py_builder_signing_sdk import BuilderConfig, BuilderApiKeyCreds
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=api_creds,
signature_type=2,
funder=funder_address,
builder_config=builder_config
)
# Orders automatically include builder headers
response = client.create_and_post_order(...)
```
</CodeGroup>
***
## Authentication Headers
The SDK automatically generates and attaches these headers to each request:
| 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 |
<Info>
With **local signing**, the SDK constructs and attaches these headers
automatically. With **remote signing**, your server returns these headers and
the SDK attaches them.
</Info>
***
## Verifying Attribution
### Get Builder Trades
Query trades attributed to your builder account to verify attribution is working:
<CodeGroup>
```typescript TypeScript theme={null}
const trades = await client.getBuilderTrades();
// Filtered by market
const marketTrades = await client.getBuilderTrades({
market: "0xbd31dc8a...",
});
```
```python Python theme={null}
trades = client.get_builder_trades()
market_trades = client.get_builder_trades(
market="0xbd31dc8a..."
)
```
</CodeGroup>
Each `BuilderTrade` includes: `id`, `market`, `assetId`, `side`, `size`, `price`, `status`, `outcome`, `owner`, `maker`, `transactionHash`, `matchTime`, `fee`, and `feeUsdc`.
### Revoke Builder API Key
If your credentials are compromised, revoke them immediately:
<CodeGroup>
```typescript TypeScript theme={null}
await client.revokeBuilderApiKey();
```
```python Python theme={null}
client.revoke_builder_api_key()
```
</CodeGroup>
After revoking, generate new credentials from your [Builder Profile](https://polymarket.com/settings?tab=builder).
***
## Troubleshooting
<AccordionGroup>
<Accordion title="Invalid Signature Errors">
* 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
</Accordion>
<Accordion title="Missing Credentials">
Ensure your environment variables are set: - `POLY_BUILDER_API_KEY` -
`POLY_BUILDER_SECRET` - `POLY_BUILDER_PASSPHRASE`
</Accordion>
<Accordion title="Volume not appearing on leaderboard">
* 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
</Accordion>
</AccordionGroup>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Builder Program" icon="hammer" href="/builders/overview">
Learn about the Builder Program tiers and rewards
</Card>
<Card title="Create Orders" icon="plus" href="/trading/orders/create">
Build, sign, and submit orders
</Card>
</CardGroup>
+329
View File
@@ -0,0 +1,329 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Cancel Order
> Cancel single, multiple, or all open orders
All cancel endpoints require [L2 authentication](/trading/overview#authentication). The response always includes `canceled` (list of cancelled order IDs) and `not_canceled` (map of order IDs to failure reasons).
***
## Cancel a Single Order
<CodeGroup>
```typescript TypeScript theme={null}
const resp = await client.cancelOrder("0xb816482a...");
console.log(resp);
// { canceled: ["0xb816482a..."], not_canceled: {} }
```
```python Python theme={null}
resp = client.cancel(order_id="0xb816482a...")
print(resp)
# {"canceled": ["0xb816482a..."], "not_canceled": {}}
```
```bash REST theme={null}
curl -X DELETE "https://clob.polymarket.com/order" \
-H "Content-Type: application/json" \
-H "POLY_ADDRESS: ..." \
-H "POLY_SIGNATURE: ..." \
-H "POLY_TIMESTAMP: ..." \
-H "POLY_API_KEY: ..." \
-H "POLY_PASSPHRASE: ..." \
-d '{"orderID": "0xb816482a..."}'
```
</CodeGroup>
***
## Cancel Multiple Orders
<CodeGroup>
```typescript TypeScript theme={null}
const resp = await client.cancelOrders(["0xb816482a...", "0xc927593b..."]);
```
```python Python theme={null}
resp = client.cancel_orders([
"0xb816482a...",
"0xc927593b...",
])
```
```bash REST theme={null}
curl -X DELETE "https://clob.polymarket.com/orders" \
-H "Content-Type: application/json" \
-H "POLY_ADDRESS: ..." \
-H "POLY_SIGNATURE: ..." \
-H "POLY_TIMESTAMP: ..." \
-H "POLY_API_KEY: ..." \
-H "POLY_PASSPHRASE: ..." \
-d '["0xb816482a...", "0xc927593b..."]'
```
</CodeGroup>
***
## Cancel All Orders
Cancel every open order across all markets:
<CodeGroup>
```typescript TypeScript theme={null}
const resp = await client.cancelAll();
```
```python Python theme={null}
resp = client.cancel_all()
```
```bash REST theme={null}
curl -X DELETE "https://clob.polymarket.com/cancel-all" \
-H "POLY_ADDRESS: ..." \
-H "POLY_SIGNATURE: ..." \
-H "POLY_TIMESTAMP: ..." \
-H "POLY_API_KEY: ..." \
-H "POLY_PASSPHRASE: ..."
```
</CodeGroup>
***
## Cancel by Market
Cancel all orders for a specific market, optionally filtered to a single token. Both `market` and `asset_id` are optional — omit both to cancel all orders.
<CodeGroup>
```typescript TypeScript theme={null}
const resp = await client.cancelMarketOrders({
market: "0xbd31dc8a...", // optional: condition ID
asset_id: "52114319501245...", // optional: specific token
});
```
```python Python theme={null}
resp = client.cancel_market_orders(
market="0xbd31dc8a...",
asset_id="52114319501245...", # optional
)
```
```bash REST theme={null}
curl -X DELETE "https://clob.polymarket.com/cancel-market-orders" \
-H "Content-Type: application/json" \
-H "POLY_ADDRESS: ..." \
-H "POLY_SIGNATURE: ..." \
-H "POLY_TIMESTAMP: ..." \
-H "POLY_API_KEY: ..." \
-H "POLY_PASSPHRASE: ..." \
-d '{"market": "0xbd31dc8a...", "asset_id": "52114319501245..."}'
```
</CodeGroup>
***
## 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
<CodeGroup>
```typescript TypeScript theme={null}
const order = await client.getOrder("0xb816482a...");
console.log(order.status, order.size_matched);
```
```python Python theme={null}
order = client.get_order("0xb816482a...")
print(order["status"], order["size_matched"])
```
</CodeGroup>
### Get Open Orders
Retrieve all open orders, optionally filtered by market or token:
<CodeGroup>
```typescript TypeScript theme={null}
// All open orders
const orders = await client.getOpenOrders();
// Filtered by market
const marketOrders = await client.getOpenOrders({
market: "0xbd31dc8a...",
});
// Filtered by token
const tokenOrders = await client.getOpenOrders({
asset_id: "52114319501245...",
});
```
```python Python theme={null}
from py_clob_client.clob_types import OpenOrderParams
# All open orders
orders = client.get_orders()
# Filtered by market
market_orders = client.get_orders(
OpenOrderParams(market="0xbd31dc8a...")
)
```
</CodeGroup>
### OpenOrder Object
| Field | Type | Description |
| ------------------ | --------- | ------------------------------------------ |
| `id` | string | Order ID |
| `status` | string | Current order status |
| `market` | string | Condition ID |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `original_size` | string | Size at placement |
| `size_matched` | string | Amount filled |
| `price` | string | Limit price |
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
| `order_type` | string | Order type (GTC, GTD, FOK, FAK) |
| `maker_address` | string | Funder address |
| `owner` | string | API key of the order owner |
| `associate_trades` | string\[] | Trade IDs this order has been included in |
| `expiration` | string | Unix expiration timestamp (`0` if none) |
| `created_at` | string | Unix creation timestamp |
***
## Trade History
When an order is matched, it creates a trade. Trades progress through these statuses:
| Status | Terminal | Description |
| ----------- | -------- | --------------------------------------- |
| `MATCHED` | No | Matched and sent for onchain submission |
| `MINED` | No | Mined on the chain, no finality yet |
| `CONFIRMED` | Yes | Achieved finality — trade successful |
| `RETRYING` | No | Transaction failed — being retried |
| `FAILED` | Yes | Failed permanently |
<CodeGroup>
```typescript TypeScript theme={null}
// All trades
const trades = await client.getTrades();
// Filtered by market
const marketTrades = await client.getTrades({
market: "0xbd31dc8a...",
});
```
```python Python theme={null}
from py_clob_client.clob_types import TradeParams
trades = client.get_trades()
market_trades = client.get_trades(
TradeParams(market="0xbd31dc8a...")
)
```
</CodeGroup>
Additional filter parameters: `id`, `maker_address`, `asset_id`, `before`, `after`.
For large result sets, use the paginated variant:
<CodeGroup>
```typescript TypeScript theme={null}
const page = await client.getTradesPaginated({ market: "0xbd31dc8a..." });
console.log(page.trades, page.count); // trades array + total count
```
```python Python theme={null}
page = client.get_trades_paginated(TradeParams(market="0xbd31dc8a..."))
```
</CodeGroup>
### Trade Object
| Field | Type | Description |
| ------------------ | ------------- | ------------------------------------ |
| `id` | string | Trade ID |
| `taker_order_id` | string | Taker order hash |
| `market` | string | Condition ID |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `size` | string | Trade size |
| `price` | string | Execution price |
| `fee_rate_bps` | string | Fee rate in basis points |
| `status` | string | Trade status (see table above) |
| `match_time` | string | Unix timestamp when matched |
| `last_update` | string | Unix timestamp of last status change |
| `outcome` | string | Human-readable outcome (e.g., "Yes") |
| `maker_address` | string | Maker's funder address |
| `owner` | string | API key of the trade owner |
| `transaction_hash` | string | Onchain transaction hash |
| `bucket_index` | number | Index for trade reconciliation |
| `trader_side` | string | `TAKER` or `MAKER` |
| `maker_orders` | MakerOrder\[] | Maker orders that filled this trade |
<Note>
A single trade can be split across multiple onchain transactions due to gas
limits. Use `bucket_index` and `match_time` to reconcile related transactions
back to a single logical trade.
</Note>
***
## Order Scoring
Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:
<CodeGroup>
```typescript TypeScript theme={null}
// Single order
const scoring = await client.isOrderScoring({ orderId: "0x..." });
// Multiple orders
const batch = await client.areOrdersScoring({
orderIds: ["0x...", "0x..."],
});
```
```python Python theme={null}
from py_clob_client.clob_types import OrderScoringParams, OrdersScoringParams
scoring = client.is_order_scoring(
OrderScoringParams(orderId="0x...")
)
batch = client.are_orders_scoring(
OrdersScoringParams(orderIds=["0x...", "0x..."])
)
```
</CodeGroup>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Order Attribution" icon="tag" href="/trading/orders/attribution">
Attribute orders to your builder account for volume credit
</Card>
<Card title="Fees" icon="receipt" href="/trading/fees">
Understand fee structures and maker rebates
</Card>
</CardGroup>
+533
View File
@@ -0,0 +1,533 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Create Order
> Build, sign, and submit orders
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
<Info>
The SDK handles EIP-712 signing and submission for you. If you prefer the REST
API directly, see [Authentication](/api-reference/authentication) for constructing the
required headers and the [API Reference](/api-reference/introduction) for full endpoint
documentation including the raw order object fields and request/response schemas.
</Info>
***
## Order Types
| Type | Behavior | Use Case |
| ------- | -------------------------------------------------------------------- | ------------------------------- |
| **GTC** | Good-Til-Cancelled — rests on the book until filled or cancelled | Default for limit orders |
| **GTD** | Good-Til-Date — active until a specified expiration time | Auto-expire before known events |
| **FOK** | Fill-Or-Kill — must fill immediately and entirely, or cancel | All-or-nothing market orders |
| **FAK** | Fill-And-Kill — fills what's available immediately, cancels the rest | Partial-fill market orders |
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
* **BUY**: specify the dollar amount you want to spend
* **SELL**: specify the number of shares you want to sell
***
## Limit Orders
The simplest way to place a limit order — create, sign, and submit in one call:
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient, Side, OrderType } from "@polymarket/clob-client";
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{
tickSize: "0.01",
negRisk: false,
},
OrderType.GTC,
);
console.log("Order ID:", response.orderID);
console.log("Status:", response.status);
```
```python Python theme={null}
from py_clob_client.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
)
print("Order ID:", response["orderID"])
print("Status:", response["status"])
```
</CodeGroup>
### Two-Step: Sign Then Submit
For more control, you can separate signing from submission. This is useful for batch orders or custom submission logic:
<CodeGroup>
```typescript TypeScript theme={null}
// Step 1: Create and sign locally
const signedOrder = await client.createOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{ tickSize: "0.01", negRisk: false },
);
// Step 2: Submit to the CLOB
const response = await client.postOrder(signedOrder, OrderType.GTC);
```
```python Python theme={null}
# Step 1: Create and sign locally
signed_order = client.create_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
),
options={
"tick_size": "0.01",
"neg_risk": False,
}
)
# Step 2: Submit to the CLOB
response = client.post_order(signed_order, OrderType.GTC)
```
</CodeGroup>
***
## GTD Orders (Expiring)
GTD orders auto-expire at a specified time. Useful for quoting around known events.
<CodeGroup>
```typescript TypeScript theme={null}
// Expire in 1 hour (+ 60s security threshold buffer)
const expiration = Math.floor(Date.now() / 1000) + 60 + 3600;
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
expiration,
},
{ tickSize: "0.01", negRisk: false },
OrderType.GTD,
);
```
```python Python theme={null}
import time
# Expire in 1 hour (+ 60s security threshold buffer)
expiration = int(time.time()) + 60 + 3600
response = client.create_and_post_order(
OrderArgs(
token_id="TOKEN_ID",
price=0.50,
size=10,
side=BUY,
expiration=expiration,
),
options={
"tick_size": "0.01",
"neg_risk": False,
},
order_type=OrderType.GTD
)
```
</CodeGroup>
<Note>
There is a security threshold of one minute on GTD expiration. To set an
effective lifetime of N seconds, use `now + 60 + N`. For example, for a
30-second effective lifetime, set the expiration to `now + 60 + 30`.
</Note>
***
## Market Orders
Market orders execute immediately against resting liquidity using FOK or FAK types:
<CodeGroup>
```typescript TypeScript theme={null}
import { Side, OrderType } from "@polymarket/clob-client";
// 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)
```
</CodeGroup>
* **FOK** — fill entirely or cancel the whole order
* **FAK** — fill what's available, cancel the rest
The `price` field on market orders acts as a **worst-price limit** (slippage protection), not a target execution price.
### One-Step Market Order
For convenience, `createAndPostMarketOrder` handles creation, signing, and submission in one call:
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.createAndPostMarketOrder(
{
tokenID: "TOKEN_ID",
side: Side.BUY,
amount: 100,
price: 0.5,
},
{ tickSize: "0.01", negRisk: false },
OrderType.FOK,
);
```
```python Python theme={null}
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,
)
```
</CodeGroup>
***
## Post-Only Orders
Post-only orders guarantee you're always the maker. If the order would match immediately (cross the spread), it's rejected instead of executed.
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.postOrder(signedOrder, OrderType.GTC, true);
```
```python Python theme={null}
response = client.post_order(signed_order, OrderType.GTC, post_only=True)
```
</CodeGroup>
* Only works with **GTC** and **GTD** order types
* Rejected if combined with FOK or FAK
***
## Batch Orders
Place up to **15 orders** in a single request:
<CodeGroup>
```typescript TypeScript theme={null}
import { OrderType, Side, PostOrdersArgs } from "@polymarket/clob-client";
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,
),
])
```
</CodeGroup>
***
## Order Options
Every order requires two market-specific options: `tickSize` and `negRisk`. For details on signature types (`0` = EOA, `1` = POLY\_PROXY, `2` = GNOSIS\_SAFE), see [Authentication](/api-reference/authentication#signature-types-and-funder).
### Tick Sizes
Your order price must conform to the market's tick size, or the order is rejected.
| Tick Size | Precision | Example Prices |
| --------- | ---------- | ---------------------- |
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
<CodeGroup>
```typescript TypeScript theme={null}
const tickSize = await client.getTickSize("TOKEN_ID");
```
```python Python theme={null}
tick_size = client.get_tick_size("TOKEN_ID")
```
</CodeGroup>
### Negative Risk
Multi-outcome events (3+ outcomes) use the Neg Risk CTF Exchange. Pass `negRisk: true` for these markets.
<CodeGroup>
```typescript TypeScript theme={null}
const isNegRisk = await client.getNegRisk("TOKEN_ID");
```
```python Python theme={null}
is_neg_risk = client.get_neg_risk("TOKEN_ID")
```
</CodeGroup>
<Tip>
Both values are also available on the market object: `minimum_tick_size` and
`neg_risk`.
</Tip>
***
## 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})
$$
<Warning>
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.
</Warning>
### 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**.
<CodeGroup>
```typescript TypeScript theme={null}
let heartbeatId = "";
setInterval(async () => {
const resp = await client.postHeartbeat(heartbeatId);
heartbeatId = resp.heartbeat_id;
}, 5000);
```
```python Python theme={null}
import time
heartbeat_id = ""
while True:
resp = client.post_heartbeat(heartbeat_id)
heartbeat_id = resp["heartbeat_id"]
time.sleep(5)
```
</CodeGroup>
* Include the most recent `heartbeat_id` in each request. Use an empty string for the first request.
* If you send an expired ID, the server responds with `400` and the correct ID. Update and retry.
***
## Next Steps
<CardGroup cols={2}>
<Card title="Cancel Orders" icon="xmark" href="/trading/orders/cancel">
Cancel single, multiple, or all open orders
</Card>
<Card title="Order Attribution" icon="tag" href="/trading/orders/attribution">
Attribute orders to your builder account for volume credit
</Card>
</CardGroup>
+463
View File
@@ -0,0 +1,463 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Overview
> Order types, tick sizes, and querying orders
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
The underlying order primitive is structured, hashed, and signed using the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) standard, then executed onchain via the Exchange contract. Preparing orders manually is involved, so we recommend using the open-source [TypeScript](https://github.com/Polymarket/clob-client) or [Python](https://github.com/Polymarket/py-clob-client) SDK clients, which handle signing and submission for you.
<Info>
If you prefer to use the REST API directly, you'll need to manage order
signing yourself. See [Authentication](/api-reference/authentication) for details on
constructing the required headers.
</Info>
***
## Order Types
| Type | Behavior | Use Case |
| ---------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------- |
| **GTC** (Good-Til-Cancelled) | Rests on the book until filled or cancelled | Default for passive limit orders |
| **GTD** (Good-Til-Date) | Active until a specified expiration time (UTC seconds timestamp), unless filled or cancelled first | Auto-expire orders before known events |
| **FOK** (Fill-Or-Kill) | Must be filled immediately and entirely, or the whole order is cancelled | All-or-nothing execution |
| **FAK** (Fill-And-Kill) | Fills as many shares as available immediately, then cancels any unfilled remainder | Partial immediate execution |
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
* **BUY**: specify the dollar amount you want to spend
* **SELL**: specify the number of shares you want to sell
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
<Note>
**GTD expiration**: There is a security threshold of one minute. If you need
the order to expire in 90 seconds, the correct expiration value is `now + 1
minute + 30 seconds`.
</Note>
### Post-Only Orders
Post-only orders are limit orders that will only rest on the book and not match immediately on entry.
* If a post-only order would cross the spread (i.e., it is marketable), it will be **rejected** rather than executed.
* Post-only **cannot** be combined with market order types (FOK or FAK). If `postOnly = true` is sent with a market order type, the order will be rejected.
* Post-only can only be used with **GTC** and **GTD** order types.
***
## Tick Sizes
Markets have different minimum price increments (tick sizes). Your order price must conform to the market's tick size, or the order will be rejected.
| Tick Size | Price Precision | Example Prices |
| --------- | --------------- | ---------------------- |
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
Retrieve the tick size for a market using the SDK:
<CodeGroup>
```typescript TypeScript theme={null}
const tickSize = await client.getTickSize(tokenID);
// Returns: "0.1" | "0.01" | "0.001" | "0.0001"
```
```python Python theme={null}
tick_size = client.get_tick_size(token_id)
# Returns: "0.1" | "0.01" | "0.001" | "0.0001"
```
</CodeGroup>
<Tip>
You can also check the `minimum_tick_size` field on a market object returned
by the [Markets API](/market-data/fetching-markets).
</Tip>
***
## Negative Risk
Multi-outcome events (e.g., "Who will win the election?" with 3+ candidates) use a different exchange contract called the **Neg Risk CTF Exchange**. When placing orders on these markets, you must pass `negRisk: true` in the order options.
<CodeGroup>
```typescript TypeScript theme={null}
const response = await client.createAndPostOrder(
{
tokenID: "TOKEN_ID",
price: 0.5,
size: 10,
side: Side.BUY,
},
{
tickSize: "0.01",
negRisk: true, // Required for multi-outcome markets
},
);
```
```python Python theme={null}
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
}
)
```
</CodeGroup>
You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field:
<CodeGroup>
```typescript TypeScript theme={null}
const isNegRisk = await client.getNegRisk(tokenID);
```
```python Python theme={null}
is_neg_risk = client.get_neg_risk(token_id)
```
</CodeGroup>
***
## Allowances
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
* **Buying**: the funder must have set a **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
<Warning>
Any maker caught intentionally abusing these checks will be blacklisted.
</Warning>
There are also limits on order placement per market. You can only place orders that sum to less than or equal to your available balance for each market. For example, if you have 500 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:
<CodeGroup>
```typescript TypeScript theme={null}
const order = await client.getOrder("0xb816482a...");
console.log(order);
```
```python Python theme={null}
order = client.get_order("0xb816482a...")
print(order)
```
</CodeGroup>
### Get Open Orders
Retrieve your open orders, optionally filtered by market or asset:
<CodeGroup>
```typescript TypeScript theme={null}
// All open orders
const orders = await client.getOpenOrders();
// Filtered by market
const marketOrders = await client.getOpenOrders({
market: "0xbd31dc8a...",
});
// Filtered by asset
const assetOrders = await client.getOpenOrders({
asset_id: "52114319501245...",
});
```
```python Python theme={null}
from py_clob_client.clob_types import OpenOrderParams
# All open orders
orders = client.get_orders()
# Filtered by market
market_orders = client.get_orders(
OpenOrderParams(
market="0xbd31dc8a...",
)
)
```
</CodeGroup>
### OpenOrder Object
Each order returned contains these fields:
| Field | Type | Description |
| ------------------ | --------- | ------------------------------------------------------------ |
| `id` | string | Order ID |
| `status` | string | Current order status |
| `market` | string | Market ID (condition ID) |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `original_size` | string | Original order size at placement |
| `size_matched` | string | Amount that has been filled |
| `price` | string | Limit price |
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
| `order_type` | string | Order type (GTC, GTD, FOK, FAK) |
| `maker_address` | string | Funder address |
| `owner` | string | API key of the order owner |
| `expiration` | string | Unix timestamp when the order expires (`0` if no expiration) |
| `associate_trades` | string\[] | Trade IDs this order has been partially included in |
| `created_at` | string | Unix timestamp when the order was created |
***
## Trade History
When an order is matched, it creates a trade. Trades go through the following statuses:
| Status | Terminal? | Description |
| ----------- | --------- | -------------------------------------------------------------------- |
| `MATCHED` | No | Matched and sent to the executor service for onchain submission |
| `MINED` | No | Observed as mined on the chain, no finality threshold yet |
| `CONFIRMED` | Yes | Achieved strong probabilistic finality — trade successful |
| `RETRYING` | No | Transaction failed (revert or reorg) — being retried by the operator |
| `FAILED` | Yes | Trade failed permanently and is not being retried |
### Trade Object
Each trade contains these fields:
| Field | Type | Description |
| ------------------ | ------ | ------------------------------------------------------------ |
| `id` | string | Trade ID |
| `taker_order_id` | string | Taker order ID (hash) |
| `market` | string | Market ID (condition ID) |
| `asset_id` | string | Token ID |
| `side` | string | `BUY` or `SELL` |
| `size` | string | Trade size |
| `fee_rate_bps` | string | Fee rate in basis points |
| `price` | string | Trade price |
| `status` | string | Trade status (see table above) |
| `match_time` | string | Unix timestamp when the trade was matched |
| `last_update` | string | Unix timestamp of last status update |
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
| `owner` | string | API key ID of the trade owner |
| `maker_address` | string | Funder address |
| `trader_side` | string | Whether you were `TAKER` or `MAKER` in this trade |
| `transaction_hash` | string | Onchain transaction hash (available after mining) |
| `maker_orders` | array | Array of maker orders matched against this trade (see below) |
### MakerOrder Fields
Each entry in the `maker_orders` array contains:
| Field | Type | Description |
| ---------------- | ------ | ---------------------------- |
| `order_id` | string | Maker order ID (hash) |
| `owner` | string | Maker's API key ID |
| `maker_address` | string | Maker's funder address |
| `matched_amount` | string | Amount matched in this trade |
| `price` | string | Maker order price |
| `fee_rate_bps` | string | Maker fee rate in bps |
| `asset_id` | string | Token ID |
| `outcome` | string | Outcome name |
| `side` | string | `BUY` or `SELL` |
Retrieve your trades with the SDK:
<CodeGroup>
```typescript TypeScript theme={null}
// All trades
const trades = await client.getTrades();
// Filtered by market
const marketTrades = await client.getTrades({
market: "0xbd31dc8a...",
});
// With pagination
const paginatedTrades = await client.getTradesPaginated({
market: "0xbd31dc8a...",
});
```
```python Python theme={null}
from py_clob_client.clob_types import TradeParams
# All trades
trades = client.get_trades()
# Filtered by market
market_trades = client.get_trades(
TradeParams(
market="0xbd31dc8a...",
)
)
```
</CodeGroup>
***
## Heartbeat
The heartbeat endpoint maintains session liveness for order safety. If a valid heartbeat is not received within **10 seconds** (with up to a 5-second buffer), **all of your open orders will be cancelled**.
<CodeGroup>
```typescript TypeScript theme={null}
// Send heartbeats in a loop
let heartbeatId = "";
setInterval(async () => {
const resp = await client.postHeartbeat(heartbeatId);
heartbeatId = resp.heartbeat_id;
}, 5000);
```
```python Python theme={null}
import time
heartbeat_id = ""
while True:
resp = client.post_heartbeat(heartbeat_id)
heartbeat_id = resp["heartbeat_id"]
time.sleep(5)
```
</CodeGroup>
* On each request, include the most recent `heartbeat_id` you received. For your first request, use an empty string.
* If you send an invalid or expired `heartbeat_id`, the server responds with a `400 Bad Request` and provides the correct `heartbeat_id` in the response. Update your client and retry.
***
## Order Scoring
Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:
<CodeGroup>
```typescript TypeScript theme={null}
// Single order
const scoring = await client.isOrderScoring({ orderId: "0x..." });
console.log(scoring); // { scoring: true }
// Multiple orders
const batchScoring = await client.areOrdersScoring({
orderIds: ["0x...", "0x..."],
});
```
```python Python theme={null}
from py_clob_client.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..."])
)
```
</CodeGroup>
***
## Onchain Order Info
When a trade is settled onchain, the Exchange contract emits an `OrderFilled` event with the following fields:
| Field | Description |
| ------------------- | ----------------------------------------------------------------------------------------------- |
| `orderHash` | Unique hash for the filled order |
| `maker` | The user who generated the order and source of funds |
| `taker` | The user filling the order, or the Exchange contract if multiple limit orders are filled |
| `makerAssetId` | ID of the asset given out. If `0`, the order is a **BUY** (giving 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
<CardGroup cols={2}>
<Card title="Create Order" icon="plus" href="/trading/orders/create">
Build, sign, and submit orders
</Card>
<Card title="Cancel Order" icon="xmark" href="/trading/orders/cancel">
Cancel single, multiple, or all orders
</Card>
</CardGroup>
+200
View File
@@ -0,0 +1,200 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Overview
> Trading on the Polymarket CLOB
Polymarket's CLOB (Central Limit Order Book) is a hybrid-decentralized trading system — offchain order matching with onchain settlement via the [Exchange contract](https://github.com/Polymarket/ctf-exchange/tree/main/src) ([audited by Chainsecurity](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)). All trading is non-custodial. Orders are [EIP-712](https://eips.ethereum.org/EIPS/eip-712) signed messages, and matched trades settle atomically on Polygon. The operator cannot set prices or execute unauthorized trades — users can always cancel orders onchain independently.
We recommend using the open-source SDK clients, which handle order signing, authentication, and submission:
<CardGroup cols={2}>
<Card title="TypeScript Client" icon="github" href="https://github.com/Polymarket/clob-client">
<p className="font-mono text-[0.8rem]">
npm install @polymarket/clob-client
</p>
</Card>
<Card title="Python Client" icon="github" href="https://github.com/Polymarket/py-clob-client">
<p className="font-mono text-[0.8rem]">pip install py-clob-client</p>
</Card>
</CardGroup>
<Info>
You can also use the REST API directly, but you'll need to manage [EIP-712
order
signing](https://github.com/Polymarket/clob-client/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.
</Info>
***
## Authentication
The CLOB uses two levels of authentication:
| Level | Method | Purpose |
| ------ | ------------------------------- | ----------------------------------------- |
| **L1** | EIP-712 signature (private key) | Create or derive API credentials |
| **L2** | HMAC-SHA256 (API credentials) | Place orders, cancel orders, query trades |
You use your private key once to derive **L2 credentials** (API key, secret, passphrase), which authenticate all subsequent trading requests.
<CodeGroup>
```typescript TypeScript theme={null}
import { ClobClient } from "@polymarket/clob-client";
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()
```
</CodeGroup>
***
## Signature Types
When initializing the trading client, you must specify your wallet's **signature type** and **funder address**:
| Wallet Type | ID | When to Use | Funder Address |
| ---------------- | --- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
| **EOA** | `0` | Standalone wallet — you pay your own gas (POL for gas) | Your EOA wallet address |
| **POLY\_PROXY** | `1` | 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 |
<Note>
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.
</Note>
### Initialize the Trading Client
<CodeGroup>
```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
)
```
</CodeGroup>
***
## REST API Headers
If you're using the REST API directly (without the SDK), you need to attach authentication headers to each request.
**L1 Headers** — for creating or deriving API credentials:
| Header | Description |
| ---------------- | ------------------- |
| `POLY_ADDRESS` | Your wallet address |
| `POLY_SIGNATURE` | EIP-712 signature |
| `POLY_TIMESTAMP` | Unix timestamp |
| `POLY_NONCE` | Request nonce |
**L2 Headers** — for all trading operations (orders, cancellations, queries):
| Header | Description |
| ----------------- | ------------------------------------ |
| `POLY_ADDRESS` | Your wallet address |
| `POLY_SIGNATURE` | HMAC-SHA256 signature of the request |
| `POLY_TIMESTAMP` | Unix timestamp |
| `POLY_API_KEY` | Your API key |
| `POLY_PASSPHRASE` | Your API passphrase |
<Note>
Even with L2 authentication, methods that create orders still require the
user's private key for EIP-712 order payload signing. L2 credentials
authenticate the request, but the order itself must be signed by the key.
</Note>
***
## Client Methods
<CardGroup cols={2}>
<Card title="Public Methods" icon="globe" href="/trading/clients/public">
Market data, orderbooks, prices, and spreads — no auth required.
</Card>
<Card title="L1 Methods" icon="key" href="/trading/clients/l1">
Sign orders and derive API credentials with your private key.
</Card>
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
Place orders, cancel orders, query trades, and manage notifications.
</Card>
<Card title="Builder Methods" icon="hammer" href="/trading/clients/builder">
Track attributed trades and manage builder credentials.
</Card>
</CardGroup>
***
## What's in This Section
<CardGroup cols={2}>
<Card title="Quickstart" icon="bolt" href="/trading/quickstart">
Place your first order end-to-end
</Card>
<Card title="Orderbook" icon="chart-bar" href="/trading/orderbook">
Reading the orderbook, prices, spreads, and midpoints
</Card>
<Card title="Orders" icon="list-check" href="/trading/orders/create">
Order types, tick sizes, creating, cancelling, and querying orders
</Card>
<Card title="Fees" icon="receipt" href="/trading/fees">
Fee structure, fee-enabled markets, and maker rebates
</Card>
<Card title="Gasless Transactions" icon="gas-pump" href="/trading/gasless">
Execute onchain operations without paying gas
</Card>
<Card title="CTF Tokens" icon="coins" href="/trading/ctf/overview">
Split, merge, and redeem outcome tokens
</Card>
<Card title="Bridge" icon="bridge" href="/trading/bridge/deposit">
Deposit and withdraw funds across chains
</Card>
</CardGroup>
+227
View File
@@ -0,0 +1,227 @@
> ## Documentation Index
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
> Use this file to discover all available pages before exploring further.
# Quickstart
> Place your first order on Polymarket
This guide walks you through placing an order on Polymarket end-to-end.
<Steps>
<Step title="Install the SDK">
<CodeGroup>
```bash TypeScript theme={null}
npm install @polymarket/clob-client ethers@5
```
```bash Python theme={null}
pip install py-clob-client
```
</CodeGroup>
</Step>
<Step title="Set Up Your Client">
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:
<CodeGroup>
```typescript TypeScript theme={null}
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);
// Derive API credentials
const tempClient = new ClobClient(HOST, CHAIN_ID, signer);
const apiCreds = await tempClient.createOrDeriveApiKey();
// Initialize trading client
const client = new ClobClient(
HOST,
CHAIN_ID,
signer,
apiCreds,
0, // EOA
signer.address,
);
```
```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")
# Derive API credentials
temp_client = ClobClient(host, key=private_key, chain_id=chain_id)
api_creds = temp_client.create_or_derive_api_creds()
# Initialize trading client
client = ClobClient(
host,
key=private_key,
chain_id=chain_id,
creds=api_creds,
signature_type=0, # EOA
funder="YOUR_WALLET_ADDRESS"
)
```
</CodeGroup>
<Note>
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.
</Note>
<Warning>
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.
</Warning>
</Step>
<Step title="Place an Order">
Get a token ID from the [Markets API](/market-data/fetching-markets), then create and submit your order:
<CodeGroup>
```typescript TypeScript theme={null}
import { Side, OrderType } from "@polymarket/clob-client";
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.50,
size=10,
side=BUY,
),
options={
"tick_size": "0.01",
"neg_risk": False, # Set to True for multi-outcome markets
},
order_type=OrderType.GTC
)
print("Order ID:", response["orderID"])
print("Status:", response["status"])
```
</CodeGroup>
<Tip>
Look up a market's `tickSize` and `negRisk` values using the SDK's
`getTickSize()` and `getNegRisk()` methods, or from the market object returned
by the API.
</Tip>
</Step>
<Step title="Check Your Orders">
<CodeGroup>
```typescript TypeScript theme={null}
// View all open orders
const openOrders = await client.getOpenOrders();
console.log(`You have ${openOrders.length} open orders`);
// View your trade history
const trades = await client.getTrades();
console.log(`You've made ${trades.length} trades`);
// Cancel an order
await client.cancelOrder(response.orderID);
```
```python Python theme={null}
# View all open orders
open_orders = client.get_orders()
print(f"You have {len(open_orders)} open orders")
# View your trade history
trades = client.get_trades()
print(f"You've made {len(trades)} trades")
# Cancel an order
client.cancel(order_id=response["orderID"])
```
</CodeGroup>
</Step>
</Steps>
***
## Troubleshooting
<AccordionGroup>
<Accordion title="L2_AUTH_NOT_AVAILABLE / Invalid Signature">
Wrong private key, signature type, or funder address for the derived API credentials.
* Check that `signatureType` matches your account type (`0`, `1`, or `2`)
* Ensure `funder` is correct for your wallet type
* Re-derive credentials with `createOrDeriveApiKey()` if unsure
</Accordion>
<Accordion title="Order rejected: insufficient balance">
Your funder address doesn't have enough tokens:
* **BUY orders**: need 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
</Accordion>
<Accordion title="Order rejected: insufficient allowance">
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.
</Accordion>
<Accordion title="What's my funder address?">
Your funder address is the wallet where your funds are held:
* **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).
</Accordion>
<Accordion title="Blocked by Cloudflare / Geoblock">
You're trying to place a trade from a restricted region. See [Geographic Restrictions](/api-reference/geoblock) for details.
</Accordion>
</AccordionGroup>
***
## Next Steps
<CardGroup cols={2}>
<Card title="Create Orders" icon="plus" href="/trading/orders/create">
Order types, tick sizes, and error handling
</Card>
<Card title="Order Attribution" icon="tag" href="/trading/orders/attribution">
Attribute orders to your builder account for volume credit
</Card>
</CardGroup>