# Negative Risk Markets
Source: https://docs.polymarket.com/advanced/neg-risk

Capital-efficient trading for multi-outcome events

**Negative risk** is a mechanism for multi-outcome events where only one outcome can win. It enables capital-efficient trading by allowing positions across all outcomes within an event to be related through a **conversion** operation.

## How It Works

In a standard multi-outcome event, each market is independent. If you want to bet against one outcome, you must buy that outcome's No tokens—but those No tokens have no relationship to the other outcomes.

Negative risk changes this. In a neg risk event:

* A **No share** in any market can be converted into **1 Yes share in every other market**
* This conversion happens through the Neg Risk Adapter contract

### Example

Consider an event: "Who will win the 2024 Presidential Election?" with three outcomes:

| Outcome | Your Position |
| ------- | ------------- |
| Trump   | —             |
| Harris  | —             |
| Other   | 1 No          |

With negative risk, that 1 No on "Other" can be converted into:

| Outcome | After Conversion |
| ------- | ---------------- |
| Trump   | 1 Yes            |
| Harris  | 1 Yes            |
| Other   | —                |

This is capital-efficient because betting against one outcome is economically equivalent to betting *for* all other outcomes.

## Identifying Neg Risk Markets

The Gamma API includes a `negRisk` boolean on events and markets:

```json theme={null}
{
  "id": "123",
  "title": "Who will win the 2024 Presidential Election?",
  "negRisk": true,
  "markets": [...]
}
```

When placing orders on neg risk markets, you must specify this in your order options:

```typescript theme={null}
const response = await client.createAndPostOrder(
  {
    tokenID: "TOKEN_ID",
    price: 0.5,
    size: 100,
    side: Side.BUY,
  },
  {
    tickSize: "0.01",
    negRisk: true, // Required for neg risk markets
  },
);
```

## Contract Addresses

Neg risk markets use different contracts than standard markets:

See [Contracts](/resources/contracts) for the Neg Risk Adapter and Neg Risk CTF Exchange addresses.

## Augmented Negative Risk

Standard negative risk requires the complete set of outcomes to be known at market creation. But sometimes new outcomes emerge after trading begins (e.g., a new candidate enters a race).

**Augmented negative risk** solves this with:

| Outcome Type             | Description                                                   |
| ------------------------ | ------------------------------------------------------------- |
| **Named outcomes**       | Known outcomes (e.g., "Trump", "Harris")                      |
| **Placeholder outcomes** | Reserved slots that can be clarified later (e.g., "Person A") |
| **Explicit Other**       | Catches any outcome not explicitly named                      |

### How Placeholders Work

1. Event launches with named outcomes + placeholders + "Other"
2. When a new outcome emerges, a placeholder is clarified via the bulletin board
3. The "Other" definition narrows as placeholders are assigned

### Trading Rules for Augmented Neg Risk

<Warning>
  Only trade on **named outcomes**. Placeholder outcomes should be ignored until
  they are named or until resolution occurs. The Polymarket UI does not display
  unnamed outcomes.
</Warning>

* If the correct outcome at resolution is not named, the market resolves to "Other"
* The "Other" outcome's definition changes as placeholders are clarified—avoid trading it directly

### Identifying Augmented Neg Risk

An event is augmented neg risk when both flags are true:

```json theme={null}
{
  "enableNegRisk": true,
  "negRiskAugmented": true
}
```

<Note>
  The Gamma API includes a boolean field `negRisk` on events and markets, which indicates whether the event uses negative risk. For augmented neg risk events, an additional `enableNegRisk` field is also `true`. When placing orders, the SDK option is always `negRisk: true` / `neg_risk: True` regardless of whether the market is standard or augmented neg risk.
</Note>

## Technical Details

### Conversion Mechanics

The conversion operation is atomic and happens through the Neg Risk Adapter:

1. You hold 1 No token for Outcome A
2. Call the convert function on the adapter
3. You receive 1 Yes token for every other outcome in the event

## Resources

* [Neg Risk Adapter Source Code](https://github.com/Polymarket/neg-risk-ctf-adapter)
* [Gamma API Documentation](/market-data/overview)

## Next Steps

<CardGroup>
  <Card title="Markets & Events" icon="calendar" href="/concepts/markets-events">
    Understand how multi-market events are structured.
  </Card>

  <Card title="Positions & Tokens" icon="coins" href="/concepts/positions-tokens">
    Learn about token operations like split, merge, and redeem.
  </Card>
</CardGroup>


# Authentication
Source: https://docs.polymarket.com/api-reference/authentication

How to authenticate requests to the CLOB API

The CLOB API uses two levels of authentication: **L1 (Private Key)** and **L2 (API Key)**. Either can be accomplished using the CLOB client or REST API.

## Public vs Authenticated

<CardGroup>
  <Card title="Public (No Auth)" icon="unlock">
    The **Gamma API**, **Data API**, and CLOB read endpoints (orderbook, prices, spreads) require no authentication.
  </Card>

  <Card title="Authenticated (CLOB)" icon="lock">
    CLOB trading endpoints (placing orders, cancellations, heartbeat) require all 5 `POLY_*` L2 HTTP headers.
  </Card>
</CardGroup>

***

## Two-Level Authentication Model

The CLOB uses two levels of authentication: L1 (Private Key) and L2 (API Key). Either can be accomplished using the CLOB client or REST API

### L1 Authentication

L1 authentication uses the wallet's private key to sign an EIP-712 message used in the request header. It proves ownership and control over the private key. The private key stays in control of the user and all trading activity remains non-custodial.

**Used for:**

* Creating API credentials
* Deriving existing API credentials
* Signing and creating user's orders locally

### L2 Authentication

L2 uses API credentials (apiKey, secret, passphrase) generated from L1 authentication. These are used solely to authenticate requests made to the CLOB API. Requests are signed using HMAC-SHA256.

**Used for:**

* Cancel or get user's open orders
* Check user's balances and allowances
* Post user's signed orders

<Info>
  Even with L2 authentication headers, methods that create user orders still
  require the user to sign the order payload.
</Info>

***

## Getting API Credentials

Before making authenticated requests, you need to obtain API credentials using L1 authentication.

### Using the SDK

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { ClobClient } from "@polymarket/clob-client-v2";
    import { createWalletClient, http } from "viem";
    import { privateKeyToAccount } from "viem/accounts";

    const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
    const signer = createWalletClient({ account, transport: http() });

    const client = new ClobClient({
      host: "https://clob.polymarket.com",
      chain: 137, // Polygon mainnet
      signer,
    });

    // Creates new credentials or derives existing ones
    const credentials = await client.createOrDeriveApiKey();

    console.log(credentials);
    // {
    //   key: "550e8400-e29b-41d4-a716-446655440000",
    //   secret: "base64EncodedSecretString",
    //   passphrase: "randomPassphraseString"
    // }
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from py_clob_client_v2 import ClobClient
    import os

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

    # Creates new credentials or derives existing ones
    credentials = client.create_or_derive_api_key()

    print(credentials)
    # {
    #     "apiKey": "550e8400-e29b-41d4-a716-446655440000",
    #     "secret": "base64EncodedSecretString",
    #     "passphrase": "randomPassphraseString"
    # }
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    use std::str::FromStr;
    use polymarket_client_sdk_v2::POLYGON;
    use polymarket_client_sdk_v2::auth::{LocalSigner, Signer};
    use polymarket_client_sdk_v2::clob::{Client, Config};

    let private_key = std::env::var("POLYMARKET_PRIVATE_KEY")?;
    let signer = LocalSigner::from_str(&private_key)?
        .with_chain_id(Some(POLYGON));

    // Creates new credentials or derives existing ones,
    // then initializes the authenticated client — all in one step
    let client = Client::new("https://clob.polymarket.com", Config::default())?
        .authentication_builder(&signer)
        .authenticate()
        .await?;

    let credentials = client.credentials();
    println!("API Key: {}", credentials.key());
    ```
  </Tab>
</Tabs>

<Warning>
  **Never commit private keys to version control.** Always use environment
  variables or secure key management systems.
</Warning>

### Using the REST API

While we highly recommend using our provided clients to handle signing and authentication, the following is for developers who choose NOT to use our [Python](https://github.com/Polymarket/py-clob-client-v2) or [TypeScript](https://github.com/Polymarket/clob-client-v2) clients.

**Create API Credentials**

```bash theme={null}
POST https://clob.polymarket.com/auth/api-key
```

**Derive API Credentials**

```bash theme={null}
GET https://clob.polymarket.com/auth/derive-api-key
```

Required L1 headers:

| Header           | Description            |
| ---------------- | ---------------------- |
| `POLY_ADDRESS`   | Polygon signer address |
| `POLY_SIGNATURE` | CLOB EIP-712 signature |
| `POLY_TIMESTAMP` | Current UNIX timestamp |
| `POLY_NONCE`     | Nonce (default: 0)     |

The `POLY_SIGNATURE` is generated by signing the following EIP-712 struct:

<Accordion title="EIP-712 Signing Example">
  <CodeGroup>
    ```typescript TypeScript theme={null}
    const domain = {
      name: "ClobAuthDomain",
      version: "1",
      chainId: chainId, // Polygon Chain ID 137
    };

    const types = {
      ClobAuth: [
        { name: "address", type: "address" },
        { name: "timestamp", type: "string" },
        { name: "nonce", type: "uint256" },
        { name: "message", type: "string" },
      ],
    };

    const value = {
      address: signingAddress, // The Signing address
      timestamp: ts,            // The CLOB API server timestamp
      nonce: nonce,             // The nonce used
      message: "This message attests that I control the given wallet",
    };

    const sig = await signer._signTypedData(domain, types, value);
    ```

    ```python Python theme={null}
    domain = {
        "name": "ClobAuthDomain",
        "version": "1",
        "chainId": chainId,  # Polygon Chain ID 137
    }

    types = {
        "ClobAuth": [
            {"name": "address", "type": "address"},
            {"name": "timestamp", "type": "string"},
            {"name": "nonce", "type": "uint256"},
            {"name": "message", "type": "string"},
        ]
    }

    value = {
        "address": signingAddress,  # The signing address
        "timestamp": ts,            # The CLOB API server timestamp
        "nonce": nonce,             # The nonce used
        "message": "This message attests that I control the given wallet",
    }

    sig = signer.sign_typed_data(domain, types, value)
    ```
  </CodeGroup>
</Accordion>

Reference implementations:

* [TypeScript](https://github.com/Polymarket/clob-client-v2/blob/main/src/signing/eip712.ts)
* [Python](https://github.com/Polymarket/py-clob-client-v2/blob/main/py_clob_client_v2/signing/eip712.py)

Response:

```json theme={null}
{
  "apiKey": "550e8400-e29b-41d4-a716-446655440000",
  "secret": "base64EncodedSecretString",
  "passphrase": "randomPassphraseString"
}
```

**You'll need all three values for L2 authentication.**

***

## L2 Authentication Headers

All trading endpoints require these 5 headers:

| Header            | Description                   |
| ----------------- | ----------------------------- |
| `POLY_ADDRESS`    | Polygon signer address        |
| `POLY_SIGNATURE`  | HMAC signature for request    |
| `POLY_TIMESTAMP`  | Current UNIX timestamp        |
| `POLY_API_KEY`    | User's API `apiKey` value     |
| `POLY_PASSPHRASE` | User's API `passphrase` value |

The `POLY_SIGNATURE` for L2 is an HMAC-SHA256 signature created using the user's API credentials `secret` value. Reference implementations can be found in the [TypeScript](https://github.com/Polymarket/clob-client-v2/blob/main/src/signing/hmac.ts) and [Python](https://github.com/Polymarket/py-clob-client-v2/blob/main/py_clob_client_v2/signing/hmac.py) clients.

### CLOB Client

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { ClobClient, Side } from "@polymarket/clob-client-v2";
    import { createWalletClient, http } from "viem";
    import { privateKeyToAccount } from "viem/accounts";

    const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
    const signer = createWalletClient({ account, transport: http() });
    const depositWalletAddress = process.env.DEPOSIT_WALLET_ADDRESS!;

    const client = new ClobClient({
      host: "https://clob.polymarket.com",
      chain: 137,
      signer,
      creds: apiCreds, // Generated from L1 auth, API credentials enable L2 methods
      signatureType: 3, // POLY_1271, explained below
      funderAddress: depositWalletAddress, // deposit wallet funder
    });

    // Now you can trade!
    const order = await client.createAndPostOrder(
      { tokenID: "123456", price: 0.65, size: 100, side: Side.BUY },
      { tickSize: "0.01", negRisk: false }
    );
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from py_clob_client_v2 import ClobClient, OrderArgs, PartialCreateOrderOptions
    from py_clob_client_v2.order_builder.constants import BUY
    import os

    client = ClobClient(
        host="https://clob.polymarket.com",
        chain_id=137,
        key=os.getenv("PRIVATE_KEY"),
        creds=api_creds,  # Generated from L1 auth, API credentials enable L2 methods
        signature_type=3,  # POLY_1271, explained below
        funder=os.getenv("DEPOSIT_WALLET_ADDRESS")
    )

    # Now you can trade!
    order = client.create_and_post_order(
        OrderArgs(token_id="123456", price=0.65, size=100, side=BUY),
        options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
    )
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    use polymarket_client_sdk_v2::clob::types::{Side, SignatureType};
    use polymarket_client_sdk_v2::types::dec;

    let deposit_wallet = std::env::var("DEPOSIT_WALLET_ADDRESS")?.parse()?;

    let client = Client::new("https://clob.polymarket.com", Config::default())?
        .authentication_builder(&signer)
        .funder(deposit_wallet)
        .signature_type(SignatureType::Poly1271)
        .authenticate()
        .await?;

    // Now you can trade!
    let order = client.limit_order()
        .token_id("123456".parse()?)
        .price(dec!(0.65))
        .size(dec!(100))
        .side(Side::Buy)
        .build().await?;
    let signed = client.sign(&signer, order).await?;
    let response = client.post_order(signed).await?;
    ```
  </Tab>
</Tabs>

<Info>
  Even with L2 authentication headers, methods that create user orders still
  require the user to sign the order payload.
</Info>

***

## Signature Types and Funder

When initializing the L2 client, you must specify your wallet **signatureType** and the **funder** address which holds the funds:

| Signature Type | Value | Description                                                                                                                |
| -------------- | ----- | -------------------------------------------------------------------------------------------------------------------------- |
| EOA            | `0`   | Standard Ethereum wallet (MetaMask). Funder is the EOA address and will need POL to pay gas on transactions.               |
| POLY\_PROXY    | `1`   | Existing Polymarket proxy wallet flow, commonly used by users who logged in via Magic Link email/Google.                   |
| GNOSIS\_SAFE   | `2`   | Existing Gnosis Safe wallet flow. Existing Safe users can continue using this type.                                        |
| POLY\_1271     | `3`   | Deposit wallet flow for new API users. The funder is the deposit wallet address and orders are validated through ERC-1271. |

<Tip>
  New API users should use deposit wallets with `POLY_1271`. Existing Safe and
  Proxy users are unaffected and can keep using their current funder address and
  signature type. See the [Deposit Wallet Guide](/trading/deposit-wallets) for
  setup details.
</Tip>

***

## Security Best Practices

<AccordionGroup>
  <Accordion title="Never expose private keys">
    Store private keys in environment variables or secure key management systems. Never commit them to version control.

    ```bash theme={null}
    # .env (never commit this file)
    PRIVATE_KEY=0x...
    ```
  </Accordion>

  <Accordion title="Implement request signing on the server">
    Never expose your API secret in client-side code. All authenticated requests should originate from your backend.
  </Accordion>
</AccordionGroup>

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Error - INVALID_SIGNATURE">
    Your wallet's private key is incorrect or improperly formatted.

    **Solutions:**

    * Verify your private key is a valid hex string (starts with "0x")
    * Ensure you're using the correct key for the intended address
    * Check that the key has proper permissions
  </Accordion>

  <Accordion title="Error - NONCE_ALREADY_USED">
    The nonce you provided has already been used to create an API key.

    **Solutions:**

    * Use `deriveApiKey()` with the same nonce to retrieve existing credentials
    * Or use a different nonce with `createApiKey()`
  </Accordion>

  <Accordion title="Error - Invalid Funder Address">
    Your funder address is incorrect or doesn't match your wallet.

    **Solution:** Check your Polymarket profile address at [polymarket.com/settings](https://polymarket.com/settings).

    If it does not exist or user has never logged into Polymarket.com, deploy it first before creating L2 authentication.
  </Accordion>

  <Accordion title="Lost both credentials and nonce">
    Unfortunately, there's no way to recover lost API credentials without the nonce. You'll need to create new credentials:

    ```typescript theme={null}
    // Create fresh credentials with a new nonce
    const newCreds = await client.createApiKey();
    // Save the nonce this time!
    ```
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup>
  <Card title="Place Your First Order" icon="plus" href="/trading/quickstart">
    Learn how to create and submit orders.
  </Card>

  <Card title="Geographic Restrictions" icon="globe" href="/api-reference/geoblock">
    Check trading availability by region.
  </Card>
</CardGroup>


# Clients & SDKs
Source: https://docs.polymarket.com/api-reference/clients-sdks

Official open-source libraries for interacting with Polymarket

Polymarket provides official open-source clients in TypeScript, Python, and Rust. All three support the full CLOB API including market data, order management, and authentication.

## Installation

<CodeGroup>
  ```bash TypeScript theme={null}
  npm install @polymarket/clob-client-v2 viem
  ```

  ```bash Python theme={null}
  pip install py-clob-client-v2
  ```

  ```bash Rust theme={null}
  cargo add polymarket_client_sdk_v2 --features clob
  ```
</CodeGroup>

## Quick Example

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { ClobClient } from "@polymarket/clob-client-v2";

  const client = new ClobClient({
    host: "https://clob.polymarket.com",
    chain: 137,
    signer,
    creds: apiCreds,
  });

  const markets = await client.getMarkets();
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import ClobClient

  client = ClobClient(
      "https://clob.polymarket.com",
      key=private_key,
      chain_id=137,
      creds=api_creds,
  )

  markets = client.get_markets()
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::{Client, Config};

  let client = Client::new("https://clob.polymarket.com", Config::default())?
      .authentication_builder(&signer)
      .authenticate()
      .await?;

  let markets = client.markets(None).await?;
  ```
</CodeGroup>

## Source Code

| Language   | Package                      | Repository                                                                                 |
| ---------- | ---------------------------- | ------------------------------------------------------------------------------------------ |
| TypeScript | `@polymarket/clob-client-v2` | [github.com/Polymarket/clob-client-v2](https://github.com/Polymarket/clob-client-v2)       |
| Python     | `py-clob-client-v2`          | [github.com/Polymarket/py-clob-client-v2](https://github.com/Polymarket/py-clob-client-v2) |
| Rust       | `polymarket_client_sdk_v2`   | [github.com/Polymarket/rs-clob-client-v2](https://github.com/Polymarket/rs-clob-client-v2) |

Each repository includes working examples in the `/examples` directory.

## Relayer SDK

For [gasless transactions](/trading/gasless), the relayer client handles deposit
wallet creation and signed wallet batches for new API users. Existing Safe and
Proxy wallet flows remain supported.

| Language   | Package                              | Repository                                                                                                 |
| ---------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
| TypeScript | `@polymarket/builder-relayer-client` | [github.com/Polymarket/builder-relayer-client](https://github.com/Polymarket/builder-relayer-client)       |
| Python     | `py-builder-relayer-client`          | [github.com/Polymarket/py-builder-relayer-client](https://github.com/Polymarket/py-builder-relayer-client) |

## Next Steps

<CardGroup>
  <Card title="Quickstart" icon="rocket" href="/quickstart">
    Set up your client and place your first order.
  </Card>

  <Card title="Authentication" icon="lock" href="/api-reference/authentication">
    Understand L1/L2 auth and API credentials.
  </Card>
</CardGroup>


# Get top holders for markets
Source: https://docs.polymarket.com/api-reference/core/get-top-holders-for-markets

/api-spec/data-openapi.yaml get /holders



# Get midpoint price
Source: https://docs.polymarket.com/api-reference/data/get-midpoint-price

/api-spec/clob-openapi.yaml get /midpoint
Retrieves the midpoint price for a specific token ID.
The midpoint is calculated as the average of the best bid and best ask prices.




# Get server time
Source: https://docs.polymarket.com/api-reference/data/get-server-time

/api-spec/clob-openapi.yaml get /time
Returns the current Unix timestamp of the server.
This can be used to synchronize client time with server time.




# Get event by id
Source: https://docs.polymarket.com/api-reference/events/get-event-by-id

/api-spec/gamma-openapi.yaml get /events/{id}



# Get event by slug
Source: https://docs.polymarket.com/api-reference/events/get-event-by-slug

/api-spec/gamma-openapi.yaml get /events/slug/{slug}



# Get event tags
Source: https://docs.polymarket.com/api-reference/events/get-event-tags

/api-spec/gamma-openapi.yaml get /events/{id}/tags



# List events
Source: https://docs.polymarket.com/api-reference/events/list-events

/api-spec/gamma-openapi.yaml get /events



# List events (keyset pagination)
Source: https://docs.polymarket.com/api-reference/events/list-events-keyset-pagination

/api-spec/gamma-openapi.yaml get /events/keyset
Returns events using cursor-based (keyset) pagination for stable, efficient paging through large result sets. Use `next_cursor` from each response as `after_cursor` in the next request. The `offset` parameter is explicitly rejected; use `after_cursor` instead.




# Geographic Restrictions
Source: https://docs.polymarket.com/api-reference/geoblock

Check geographic restrictions before placing orders on the Polymarket API

Polymarket restricts order placement from certain geographic locations due to regulatory requirements and compliance with international sanctions. Before placing orders, builders should verify the location.

<Warning>
  Orders submitted from blocked regions will be rejected. Implement geoblock
  checks in your application to provide users with appropriate feedback before
  they attempt to trade.
</Warning>

***

## Geoblock Endpoint

Check the geographic eligibility of the requesting IP address:

```bash theme={null}
GET https://polymarket.com/api/geoblock
```

<Note>This endpoint is on `polymarket.com`, not the API servers.</Note>

### Response

```json theme={null}
{
  "blocked": true,
  "ip": "203.0.113.42",
  "country": "US",
  "region": "NY"
}
```

| Field     | Type    | Description                                     |
| --------- | ------- | ----------------------------------------------- |
| `blocked` | boolean | Whether the user is blocked from placing orders |
| `ip`      | string  | Detected IP address                             |
| `country` | string  | ISO 3166-1 alpha-2 country code                 |
| `region`  | string  | Region/state code                               |

***

## Blocked Countries

The following countries are restricted from placing orders on Polymarket. Countries marked as **close-only** can close existing positions but cannot open new ones. Countries marked as **frontend UI restricted** are blocked only on the Polymarket frontend; the API itself is not restricted:

| Country Code | Country Name                         | Status                 |
| ------------ | ------------------------------------ | ---------------------- |
| AU           | Australia                            | Blocked                |
| BE           | Belgium                              | Blocked                |
| BY           | Belarus                              | Blocked                |
| BI           | Burundi                              | Blocked                |
| CF           | Central African Republic             | Blocked                |
| CD           | Congo (Kinshasa)                     | Blocked                |
| CU           | Cuba                                 | Blocked                |
| DE           | Germany                              | Blocked                |
| ET           | Ethiopia                             | Blocked                |
| FR           | France                               | Blocked                |
| GB           | United Kingdom                       | Blocked                |
| IR           | Iran                                 | Blocked                |
| IQ           | Iraq                                 | Blocked                |
| IT           | Italy                                | Blocked                |
| JP           | Japan                                | Frontend UI restricted |
| KP           | North Korea                          | Blocked                |
| LB           | Lebanon                              | Blocked                |
| LY           | Libya                                | Blocked                |
| MM           | Myanmar                              | Blocked                |
| NI           | Nicaragua                            | Blocked                |
| NL           | Netherlands                          | Blocked                |
| PL           | Poland                               | Close-only             |
| RU           | Russia                               | Blocked                |
| SG           | Singapore                            | Close-only             |
| SO           | Somalia                              | Blocked                |
| SS           | South Sudan                          | Blocked                |
| SD           | Sudan                                | Blocked                |
| SY           | Syria                                | Blocked                |
| TH           | Thailand                             | Close-only             |
| TW           | Taiwan                               | Close-only             |
| UM           | United States Minor Outlying Islands | Blocked                |
| US           | United States                        | Blocked                |
| VE           | Venezuela                            | Blocked                |
| YE           | Yemen                                | Blocked                |
| ZW           | Zimbabwe                             | Blocked                |

***

## Blocked Regions

In addition to fully blocked countries, the following specific regions within otherwise accessible countries are also restricted:

| Country      | Region  | Region Code |
| ------------ | ------- | ----------- |
| Canada (CA)  | Ontario | ON          |
| Ukraine (UA) | Crimea  | 43          |
| Ukraine (UA) | Donetsk | 14          |
| Ukraine (UA) | Luhansk | 09          |

***

## Blocking Logic

The geoblocking system includes:

1. **OFAC-Sanctioned Countries**: Countries sanctioned by the U.S. Office of Foreign Assets Control (OFAC)
2. **Additional Regulatory Restrictions**: Countries added for specific regulatory compliance reasons

***

## Server Infrastructure

* **Primary Servers**: eu-west-2
* **Closest Non-Georestricted Region**: eu-west-1

***

## Usage Examples

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    interface GeoblockResponse {
      blocked: boolean;
      ip: string;
      country: string;
      region: string;
    }

    async function checkGeoblock(): Promise<GeoblockResponse> {
      const response = await fetch("https://polymarket.com/api/geoblock");
      return response.json();
    }

    // Usage
    const geo = await checkGeoblock();

    if (geo.blocked) {
      console.log(`Trading not available in ${geo.country}`);
    } else {
      console.log("Trading available");
    }
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import requests

    def check_geoblock() -> dict:
        response = requests.get("https://polymarket.com/api/geoblock")
        return response.json()

    # Usage
    geo = check_geoblock()

    if geo["blocked"]:
        print(f"Trading not available in {geo['country']}")
    else:
        print("Trading available")
    ```
  </Tab>

  <Tab title="Rust">
    ```rust theme={null}
    use polymarket_client_sdk_v2::clob::{Client, Config};

    let client = Client::new("https://clob.polymarket.com", Config::default())?;
    let geo = client.check_geoblock().await?;

    if geo.blocked {
        println!("Trading not available in {}", geo.country);
    } else {
        println!("Trading available");
    }
    ```
  </Tab>
</Tabs>

***

## Why These Restrictions

Geographic restrictions are implemented to ensure compliance with:

* International sanctions and embargoes
* Local financial regulations
* Gambling and prediction market laws
* Anti-money laundering (AML) requirements
* Know Your Customer (KYC) regulations

If you believe you are incorrectly restricted or have questions about geographic availability, please contact [Polymarket Support](https://polymarket.com/support).

***

## Next Steps

<CardGroup>
  <Card title="Authentication" icon="key" href="/api-reference/authentication">
    Learn how to authenticate trading requests.
  </Card>

  <Card title="Place Orders" icon="plus" href="/trading/quickstart">
    Start placing orders (from eligible regions).
  </Card>
</CardGroup>


# Introduction
Source: https://docs.polymarket.com/api-reference/introduction

Overview of the Polymarket APIs

The Polymarket API provides programmatic access to the world's largest prediction market. The platform is served by three separate APIs, each handling a different domain.

***

## APIs

<CardGroup>
  <Card title="Gamma API" icon="database">
    **`https://gamma-api.polymarket.com`**

    Markets, events, tags, series, comments, sports, search, and public profiles. This is the primary API for discovering and browsing market data.
  </Card>

  <Card title="Data API" icon="chart-line">
    **`https://data-api.polymarket.com`**

    User positions, trades, activity, holder data, open interest, leaderboards, and builder analytics.
  </Card>

  <Card title="CLOB API" icon="arrows-rotate">
    **`https://clob.polymarket.com`**

    Orderbook data, pricing, midpoints, spreads, and price history. Also handles order placement, cancellation, and other trading operations. Trading endpoints require [authentication](/api-reference/authentication).
  </Card>
</CardGroup>

<Info>
  A separate **Bridge API** (`https://bridge.polymarket.com`) handles deposits and withdrawals. Bridges are not handled by Polymarket, it is a proxy of fun.xyz service.
</Info>

***

## Authentication

The Gamma API and Data API are fully public — no authentication required.

The CLOB API has both public endpoints (orderbook, prices) and authenticated endpoints (order management). See [Authentication](/api-reference/authentication) for details.

***

## Next Steps

<CardGroup>
  <Card title="Authentication" icon="key" href="/api-reference/authentication">
    Learn how to authenticate requests for trading endpoints.
  </Card>

  <Card title="Clients & SDKs" icon="cube" href="/api-reference/clients-sdks">
    Official TypeScript, Python, and Rust libraries.
  </Card>
</CardGroup>


# Get fee rate
Source: https://docs.polymarket.com/api-reference/market-data/get-fee-rate

/api-spec/clob-openapi.yaml get /fee-rate
Retrieves the base fee rate for a specific token ID.
The fee rate can be provided either as a query parameter or as a path parameter.




# Get fee rate by path parameter
Source: https://docs.polymarket.com/api-reference/market-data/get-fee-rate-by-path-parameter

/api-spec/clob-openapi.yaml get /fee-rate/{token_id}
Retrieves the base fee rate for a specific token ID using the token ID as a path parameter.




# Get last trade price
Source: https://docs.polymarket.com/api-reference/market-data/get-last-trade-price

/api-spec/clob-openapi.yaml get /last-trade-price
Retrieves the last trade price and side for a specific token ID.
Returns default values of "0.5" for price and empty string for side if no trades found.




# Get last trade prices (query parameters)
Source: https://docs.polymarket.com/api-reference/market-data/get-last-trade-prices-query-parameters

/api-spec/clob-openapi.yaml get /last-trades-prices
Retrieves last trade prices for multiple token IDs using query parameters.
Maximum 500 token IDs can be requested per call.




# Get last trade prices (request body)
Source: https://docs.polymarket.com/api-reference/market-data/get-last-trade-prices-request-body

/api-spec/clob-openapi.yaml post /last-trades-prices
Retrieves last trade prices for multiple token IDs using a request body.
Maximum 500 token IDs can be requested per call.




# Get market price
Source: https://docs.polymarket.com/api-reference/market-data/get-market-price

/api-spec/clob-openapi.yaml get /price
Retrieves the best market price for a specific token ID and side (bid or ask).
Returns the best bid price for BUY side or best ask price for SELL side.




# Get market prices (query parameters)
Source: https://docs.polymarket.com/api-reference/market-data/get-market-prices-query-parameters

/api-spec/clob-openapi.yaml get /prices
Retrieves market prices for multiple token IDs and sides using query parameters.




# Get market prices (request body)
Source: https://docs.polymarket.com/api-reference/market-data/get-market-prices-request-body

/api-spec/clob-openapi.yaml post /prices
Retrieves market prices for multiple token IDs and sides using a request body.
Each request must include both token_id and side.




# Get midpoint prices (query parameters)
Source: https://docs.polymarket.com/api-reference/market-data/get-midpoint-prices-query-parameters

/api-spec/clob-openapi.yaml get /midpoints
Retrieves midpoint prices for multiple token IDs using query parameters.
The midpoint is calculated as the average of the best bid and best ask prices.




# Get midpoint prices (request body)
Source: https://docs.polymarket.com/api-reference/market-data/get-midpoint-prices-request-body

/api-spec/clob-openapi.yaml post /midpoints
Retrieves midpoint prices for multiple token IDs using a request body.
The midpoint is calculated as the average of the best bid and best ask prices.




# Get order book
Source: https://docs.polymarket.com/api-reference/market-data/get-order-book

/api-spec/clob-openapi.yaml get /book
Retrieves the order book summary for a specific token ID.
Includes bids, asks, market details, and last trade price.




# Get order books (request body)
Source: https://docs.polymarket.com/api-reference/market-data/get-order-books-request-body

/api-spec/clob-openapi.yaml post /books
Retrieves order book summaries for multiple token IDs using a request body.




# Get spread
Source: https://docs.polymarket.com/api-reference/market-data/get-spread

/api-spec/clob-openapi.yaml get /spread
Retrieves the spread for a specific token ID.
The spread is the difference between the best ask and best bid prices.




# Get spreads
Source: https://docs.polymarket.com/api-reference/market-data/get-spreads

/api-spec/clob-openapi.yaml post /spreads
Retrieves spreads for multiple token IDs.
The spread is the difference between the best ask and best bid prices.




# Get tick size
Source: https://docs.polymarket.com/api-reference/market-data/get-tick-size

/api-spec/clob-openapi.yaml get /tick-size
Retrieves the minimum tick size (price increment) for a specific token ID.
The tick size can be provided either as a query parameter or as a path parameter.




# Get tick size by path parameter
Source: https://docs.polymarket.com/api-reference/market-data/get-tick-size-by-path-parameter

/api-spec/clob-openapi.yaml get /tick-size/{token_id}
Retrieves the minimum tick size (price increment) for a specific token ID using the token ID as a path parameter.




# Get batch prices history
Source: https://docs.polymarket.com/api-reference/markets/get-batch-prices-history

/api-spec/clob-openapi.yaml post /batch-prices-history
Retrieve historical price data for multiple markets in a single request.



# Get CLOB market info
Source: https://docs.polymarket.com/api-reference/markets/get-clob-market-info

/api-spec/clob-openapi.yaml get /clob-markets/{condition_id}
Returns all CLOB-level parameters for a market in a single call —
tokens, tick size, base fees, rewards, RFQ status, and fee details.




# Get market by id
Source: https://docs.polymarket.com/api-reference/markets/get-market-by-id

/api-spec/gamma-openapi.yaml get /markets/{id}



# Get market by slug
Source: https://docs.polymarket.com/api-reference/markets/get-market-by-slug

/api-spec/gamma-openapi.yaml get /markets/slug/{slug}



# Get market by token
Source: https://docs.polymarket.com/api-reference/markets/get-market-by-token

/api-spec/clob-openapi.yaml get /markets-by-token/{token_id}
Returns the parent market for a given token ID. Useful when you have
a token ID and need to resolve its parent market without knowing the
condition ID in advance.




# Get market tags by id
Source: https://docs.polymarket.com/api-reference/markets/get-market-tags-by-id

/api-spec/gamma-openapi.yaml get /markets/{id}/tags



# Get prices history
Source: https://docs.polymarket.com/api-reference/markets/get-prices-history

/api-spec/clob-openapi.yaml get /prices-history
Retrieve historical price data for a market.



# List markets
Source: https://docs.polymarket.com/api-reference/markets/list-markets

/api-spec/gamma-openapi.yaml get /markets



# List markets (keyset pagination)
Source: https://docs.polymarket.com/api-reference/markets/list-markets-keyset-pagination

/api-spec/gamma-openapi.yaml get /markets/keyset
Returns markets using cursor-based (keyset) pagination for stable, efficient paging through large result sets. Use `next_cursor` from each response as `after_cursor` in the next request. The `offset` parameter is explicitly rejected; use `after_cursor` instead.




# Get live volume for an event
Source: https://docs.polymarket.com/api-reference/misc/get-live-volume-for-an-event

/api-spec/data-openapi.yaml get /live-volume



# Get open interest
Source: https://docs.polymarket.com/api-reference/misc/get-open-interest

/api-spec/data-openapi.yaml get /oi



# Rate Limits
Source: https://docs.polymarket.com/api-reference/rate-limits

API rate limits for all Polymarket endpoints

All API rate limits are enforced using Cloudflare's throttling system. When you exceed the limit for any endpoint, requests are throttled (delayed/queued) rather than immediately rejected. Limits reset on sliding time windows.

***

## General

| Endpoint              | Limit            |
| --------------------- | ---------------- |
| General rate limiting | 15,000 req / 10s |
| Health check (`/ok`)  | 100 req / 10s    |

***

## Gamma API

Base URL: `https://gamma-api.polymarket.com`

| Endpoint                       | Limit           |
| ------------------------------ | --------------- |
| General                        | 4,000 req / 10s |
| `/events`                      | 500 req / 10s   |
| `/markets`                     | 300 req / 10s   |
| `/markets` + `/events` listing | 900 req / 10s   |
| `/comments`                    | 200 req / 10s   |
| `/tags`                        | 200 req / 10s   |
| `/public-search`               | 350 req / 10s   |

***

## Data API

Base URL: `https://data-api.polymarket.com`

| Endpoint             | Limit           |
| -------------------- | --------------- |
| General              | 1,000 req / 10s |
| `/trades`            | 200 req / 10s   |
| `/positions`         | 150 req / 10s   |
| `/closed-positions`  | 150 req / 10s   |
| Health check (`/ok`) | 100 req / 10s   |

***

## CLOB API

Base URL: `https://clob.polymarket.com`

### General

| Endpoint                   | Limit           |
| -------------------------- | --------------- |
| General                    | 9,000 req / 10s |
| `GET` balance allowance    | 200 req / 10s   |
| `UPDATE` balance allowance | 50 req / 10s    |

### Market Data

| Endpoint          | Limit           |
| ----------------- | --------------- |
| `/book`           | 1,500 req / 10s |
| `/books`          | 500 req / 10s   |
| `/price`          | 1,500 req / 10s |
| `/prices`         | 500 req / 10s   |
| `/midpoint`       | 1,500 req / 10s |
| `/midpoints`      | 500 req / 10s   |
| `/prices-history` | 1,000 req / 10s |
| Market tick size  | 200 req / 10s   |

### Ledger

| Endpoint                                         | Limit         |
| ------------------------------------------------ | ------------- |
| `/trades`, `/orders`, `/notifications`, `/order` | 900 req / 10s |
| `/data/orders`                                   | 500 req / 10s |
| `/data/trades`                                   | 500 req / 10s |
| `/notifications`                                 | 125 req / 10s |

### Authentication

| Endpoint          | Limit         |
| ----------------- | ------------- |
| API key endpoints | 100 req / 10s |

### Trading

Trading endpoints have both **burst** limits (short spikes allowed) and **sustained** limits (longer-term average).

| Endpoint                       | Burst Limit     | Sustained Limit     |
| ------------------------------ | --------------- | ------------------- |
| `POST /order`                  | 3,500 req / 10s | 36,000 req / 10 min |
| `DELETE /order`                | 3,000 req / 10s | 30,000 req / 10 min |
| `POST /orders`                 | 1,000 req / 10s | 15,000 req / 10 min |
| `DELETE /orders`               | 1,000 req / 10s | 15,000 req / 10 min |
| `DELETE /cancel-all`           | 250 req / 10s   | 6,000 req / 10 min  |
| `DELETE /cancel-market-orders` | 1,000 req / 10s | 1,500 req / 10 min  |

***

## Other

| Endpoint          | Limit          |
| ----------------- | -------------- |
| Relayer `/submit` | 25 req / 1 min |
| User PNL API      | 200 req / 10s  |

***

## Next Steps

<CardGroup>
  <Card title="Authentication" icon="key" href="/api-reference/authentication">
    Learn how to authenticate trading requests.
  </Card>

  <Card title="Clients & SDKs" icon="cube" href="/api-reference/clients-sdks">
    Official TypeScript, Python, and Rust libraries.
  </Card>
</CardGroup>


# Cancel single order
Source: https://docs.polymarket.com/api-reference/trade/cancel-single-order

/api-spec/clob-openapi.yaml delete /order
Cancels a single order by its ID. Works even in cancel-only mode.




# Get single order by ID
Source: https://docs.polymarket.com/api-reference/trade/get-single-order-by-id

/api-spec/clob-openapi.yaml get /order/{orderID}
Retrieves a specific order by its ID (order hash) for the authenticated user.
Builder-authenticated clients can also use this endpoint to retrieve orders attributed to their builder account.




# Get user orders
Source: https://docs.polymarket.com/api-reference/trade/get-user-orders

/api-spec/clob-openapi.yaml get /data/orders
Retrieves open orders for the authenticated user. Returns paginated results.
Builder-authenticated clients can also use this endpoint to retrieve orders attributed to their builder account.




# Post a new order
Source: https://docs.polymarket.com/api-reference/trade/post-a-new-order

/api-spec/clob-openapi.yaml post /order
Creates a new order in the order book




# Post multiple orders
Source: https://docs.polymarket.com/api-reference/trade/post-multiple-orders

/api-spec/clob-openapi.yaml post /orders
Creates multiple new orders in the order book. Orders are processed in parallel.
Maximum 15 orders per request.




# Builder Code
Source: https://docs.polymarket.com/builders/api-keys

Your builder code for order attribution

Your **Builder Code** is a `bytes32` identifier that attributes orders routed through your application to your builder profile. Attach it to every order you submit — no additional authentication is required.

## Accessing Your Builder Profile

<Steps>
  <Step title="Direct Link">
    Go to
    [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder)
  </Step>

  <Step title="From Menu">Click your profile image → Select "Builders"</Step>
</Steps>

## Getting Your Builder Code

In the **Builder Code** section of your profile, copy the `bytes32` value. It looks like:

```
0x0000000000000000000000000000000000000000000000000000000000000001
```

Store it in your environment variables or a secrets manager.

<Note>
  Builder codes are public identifiers — they appear onchain in the `builder`
  field of every order you attribute. Only you control which orders include
  your code, so keep it scoped to the apps you own.
</Note>

## Profile Settings

Your builder profile includes customizable settings:

| Setting             | Description                                                             |
| ------------------- | ----------------------------------------------------------------------- |
| **Profile Picture** | Displayed on the [Builder Leaderboard](https://builders.polymarket.com) |
| **Builder Name**    | Public name shown on the leaderboard                                    |
| **Builder Address** | Your unique builder identifier (read-only)                              |
| **Builder Code**    | The `bytes32` code you attach to orders                                 |
| **Current Tier**    | Your rate limit tier: Unverified, Verified, or Partner                  |

## Environment Variables

Store your builder code as an environment variable:

<Tabs>
  <Tab title="Bash">
    ```bash .env theme={null}
    POLY_BUILDER_CODE=0x0000000000000000000000000000000000000000000000000000000000000001
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const builderCode = process.env.POLY_BUILDER_CODE!;
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import os

    builder_code = os.environ["POLY_BUILDER_CODE"]
    ```
  </Tab>
</Tabs>

## Using Your Builder Code

Pass `builderCode` on every order to attribute it to your builder profile:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const response = await client.createAndPostOrder(
    {
      tokenID: "0x...",
      price: 0.55,
      size: 100,
      side: Side.BUY,
      builderCode: process.env.POLY_BUILDER_CODE!,
    },
    { tickSize: "0.01", negRisk: false },
  );
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import OrderArgs, PartialCreateOrderOptions
  from py_clob_client_v2.order_builder.constants import BUY

  response = client.create_and_post_order(
      OrderArgs(
          token_id="0x...",
          price=0.55,
          size=100,
          side=BUY,
          builder_code=os.environ["POLY_BUILDER_CODE"],
      ),
      options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
  )
  ```
</CodeGroup>

See [Order Attribution](/trading/orders/attribution) for full details.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Rate limit exceeded">
    **Cause:** You've exceeded your tier's daily transaction limit.

    **Solution:**

    * Wait until the daily limit resets
    * [Contact Polymarket](/builders/tiers#contact) to upgrade your tier
  </Accordion>

  <Accordion title="Builder code not found">
    **Cause:** You haven't created a builder profile yet.

    **Solution:** Go to
    [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder)
    and set up your profile to get a builder code.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup>
  <Card title="Attribute Orders" icon="tag" href="/trading/orders/attribution">
    Attach your builder code to orders for volume credit.
  </Card>

  <Card title="Understand Tiers" icon="layer-group" href="/builders/tiers">
    Learn about rate limits and how to upgrade.
  </Card>
</CardGroup>


# Builder Fees
Source: https://docs.polymarket.com/builders/fees

How builders earn fees on orders routed through their applications, and how to integrate.

CLOB V2 introduces a fee layer that lets builders earn a fee on every order routed through their application. When a builder attaches their unique **builder code** to an order and that order matches, a **builder fee** is collected alongside any platform fee.

Builder fees are flat percentages of trade notional, configured by each builder within enforced limits. They're additive — they stack on top of platform fees, never replace them.

<Note>
  New to the Builder Program? Start with [Builder Program](/builders/overview). This page covers the fee layer specifically.
</Note>

***

## How it works

<Frame>
  <img alt="" />

  <img alt="" />
</Frame>

Builder fees and platform fees are independent. What the user pays depends on the market config and whether a builder code is attached:

| Market               | Builder code attached | User pays                  |
| -------------------- | --------------------- | -------------------------- |
| No platform fee      | No                    | Nothing                    |
| No platform fee      | Yes                   | Builder fee only           |
| Platform fee enabled | No                    | Platform fee only          |
| Platform fee enabled | Yes                   | Platform fee + builder fee |

Builder fees never replace platform fees — they're always additive.

<Warning>
  Polymarket reserves the right to revoke your ability to charge a builder fee in its sole discretion, for any reason or no reason, including but not limited to instances where fees are determined to have been collected through fraudulent, deceptive, misleading, automated, self-referred, or other non-bona fide trading activity.
</Warning>

***

## Registration

Register for a builder code through your Polymarket account.

<Steps>
  <Step title="Create a builder profile">
    Go to [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder) and set up your builder profile.
  </Step>

  <Step title="Set your fee rates">
    Configure two rates on your profile:

    * `builder_taker_fee_bps` — charged on taker orders routed through your app
    * `builder_maker_fee_bps` — charged on maker orders routed through your app
  </Step>

  <Step title="Copy your builder code">
    Your profile is assigned a `bytes32` builder code. Attach it to every order you submit.
  </Step>
</Steps>

### Fee rate limits

| Parameter      | Default    | Maximum       |
| -------------- | ---------- | ------------- |
| Taker fee rate | 0 bps (0%) | 100 bps (1%)  |
| Maker fee rate | 0 bps (0%) | 50 bps (0.5%) |
| Granularity    | —          | 1 bp (0.01%)  |

### Rate change policy

Fee rate changes are gated so users can see them coming:

* **Cooldown.** One rate change per 7 days.
* **Advance notice.** Changes take effect 3 days after being scheduled.
* **One pending change at a time.** You can't queue multiple changes — wait for the current one to take effect (or cancel it) before scheduling another.

***

## SDK integration

The V2 SDK handles builder codes natively — no separate signing library, no extra headers.

### Install

<CodeGroup>
  ```bash TypeScript theme={null}
  npm install @polymarket/clob-client-v2 viem
  ```

  ```bash Python theme={null}
  pip install py-clob-client-v2
  ```
</CodeGroup>

<Note>
  Coming from the old `@polymarket/builder-signing-sdk` + HMAC header flow? That's gone in V2 — see [Migrating to CLOB V2](/v2-migration#builder-program) for the full upgrade path.
</Note>

### Attach your builder code

Pass `builderCode` on every order your application submits. This is how trades are attributed to your profile.

**Limit order:**

```typescript theme={null}
const response = await client.createAndPostOrder(
  {
    tokenID: "0x123...",
    price: 0.55,
    size: 100,
    side: Side.BUY,
    expiration: 1714000000,
    builderCode: process.env.POLY_BUILDER_CODE,
  },
  { tickSize: "0.01", negRisk: false },
  OrderType.GTC,
);
```

**Market order:**

```typescript theme={null}
const response = await client.createAndPostMarketOrder(
  {
    tokenID: "0x123...",
    side: Side.BUY,
    amount: 500,
    price: 0.5, // worst-price limit (slippage protection)
    userUSDCBalance: 1000, // optional — enables fee-aware fill calculations
    builderCode: process.env.POLY_BUILDER_CODE,
  },
  { tickSize: "0.01", negRisk: false },
  OrderType.FOK,
);
```

If `builderCode` is omitted, no builder fee is charged.

<Tip>
  You can also pass `builderConfig: { builderCode }` once at client construction and every order inherits it. See [Migrating to CLOB V2](/v2-migration#builder-program) for both patterns.
</Tip>

### Query fee parameters

`getClobMarketInfo()` returns both platform and builder fee parameters for a market:

```typescript theme={null}
const info = await client.getClobMarketInfo(conditionID);

// Platform fee
// info.fd.r   — fee rate
// info.fd.e   — fee exponent
// info.fd.to  — taker-only flag

// Builder fee
// info.mbf    — builder maker fee rate
// info.tbf    — builder taker fee rate
```

***

## Fee calculation

### Platform fees

Platform fees use a dynamic per-market formula:

```
platform_fee = C × feeRate × p × (1 - p)
```

Where `C` is the trade size, `p` is the order price, and `feeRate` is a per-market parameter. Platform fees are currently taker-only and are not configurable by builders.

### Builder fees

Builder fees are a flat percentage of notional:

```
builder_fee = notional × builder_fee_rate_bps / 10000
```

**Example.** A 1,000 pUSD taker buy routed through a builder charging 100 bps (1%) taker fee:

```
builder_fee = 1000 × 100 / 10000 = 10 pUSD
```

The maker and taker sides of a single trade can have different builder codes and different rates. If Builder A (0.3% maker) posts the resting order and Builder B (0.8% taker) submits the matching order, each earns their respective fee from their respective side.

### Balance checks

The CLOB's balance checker accounts for all applicable fees (platform + builder) when validating an order. Users must have enough pUSD to cover the trade plus the maximum possible fees.

For market buy orders, pass `userUSDCBalance` and the SDK computes fee-adjusted fill amounts automatically.

***

## Onchain attribution

Builder attribution is part of the signed V2 order struct — not an offchain label. The `builder` field appears in every `OrderFilled` event emitted by the CTF Exchange V2 contract.

### V2 order struct

```
salt, maker, signer, tokenId, makerAmount, takerAmount,
side, signatureType, timestamp, metadata, builder
```

The `builder` field is a `bytes32` matching your registered builder code.

### EIP-712 domain

The Exchange domain version is `"2"` in V2 (up from `"1"`). If you construct EIP-712 typed data manually rather than via the SDK, update your domain separator — see [For API users](/v2-migration#for-api-users) in the migration guide.

***

## Fee processing and payouts

When a user places an order with your `builderCode` attached:

1. The CLOB validates the order and the builder code.
2. At match time, the Fees Service computes the platform and builder fees for each side.
3. The trade settles onchain via `CTFExchangeV2.matchOrders()`, emitting `OrderFilled` events.
4. The Builders Service indexes those events, joins onchain attribution with your builder profile, and accrues your earned fees.

Collected builder fees are distributed to the wallet associated with your builder profile.

***

## Program policies

### Disabled codes

Polymarket may disable a builder code at any time — for violations of the Builder Program terms, abusive fee practices, or platform integrity concerns. Orders carrying a disabled code will be rejected by the CLOB.

### Public visibility

Builder profiles and fee rates are publicly queryable. This is intentional — it lets users and third parties see what a builder charges before using their app.

### Existing builders

Builders with V1 integrations have builder code entities provisioned automatically. No action is required beyond upgrading to the V2 SDK and attaching your builder code to orders. See [Migrating to CLOB V2](/v2-migration) for the full upgrade path.

***

## Next steps

<CardGroup>
  <Card title="Builder Program" icon="hammer" href="/builders/overview">
    Overview of the Builder Program and benefits
  </Card>

  <Card title="Builder Methods" icon="code" href="/trading/clients/builder">
    SDK methods for querying your builder trades and orders
  </Card>

  <Card title="Order Attribution" icon="tag" href="/trading/orders/attribution">
    Details on attaching builder codes to orders
  </Card>

  <Card title="Migration Guide" icon="arrow-right" href="/v2-migration">
    Full V2 migration guide
  </Card>
</CardGroup>


# Builder Program
Source: https://docs.polymarket.com/builders/overview

Build applications that route orders through Polymarket

A **builder** is a person, group, or organization that routes orders from users to Polymarket. If you've created a platform that allows users to trade on Polymarket through your system, this program is for you.

## Program Benefits

<CardGroup>
  <Card title="Gasless Transactions" icon="gas-pump">
    All onchain operations are gas-free through our relayer
  </Card>

  <Card title="Order Attribution" icon="tag">
    Get credit for orders and compete for grants on the Builder Leaderboard
  </Card>
</CardGroup>

### What You Get

| Benefit             | Description                                                                     |
| ------------------- | ------------------------------------------------------------------------------- |
| **Relayer Access**  | Gas-free wallet deployment, approvals, order execution and CTF operations       |
| **Volume Tracking** | All orders attributed to your builder profile                                   |
| **Leaderboard**     | Public visibility on [builders.polymarket.com](https://builders.polymarket.com) |
| **Support**         | Telegram channel and engineering support (Verified+)                            |

<Warning>
  EOA wallets do not have relayer access. Users trading directly from an EOA pay
  their own gas fees.
</Warning>

## How It Works

<Steps>
  <Step title="User Places Order">
    User places an order through your application.
  </Step>

  <Step title="Attach Builder Code">
    Your app adds your `builderCode` to the order struct.
  </Step>

  <Step title="Submit to CLOB">
    Order is submitted to Polymarket's CLOB — the builder code is serialized
    onchain as part of the signed order.
  </Step>

  <Step title="Trade Execution">
    Polymarket matches the order and covers gas fees for onchain operations.
  </Step>

  <Step title="Volume Attribution">
    Volume is credited to your builder account for every matched trade where
    your code is attached.
  </Step>
</Steps>

## Getting Started

<Steps>
  <Step title="Create Builder Profile">
    Go to
    [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder)
    and copy your builder code.
  </Step>

  <Step title="Attach Your Builder Code">
    Pass `builderCode` on every order you submit — see [Order
    Attribution](/trading/orders/attribution).
  </Step>

  <Step title="Enable Gasless Transactions">
    Use the Relayer Client for gas-free wallet deployment and onchain
    operations.
  </Step>

  <Step title="Track Performance">
    Monitor your volume on the [Builder
    Leaderboard](https://builders.polymarket.com).
  </Step>
</Steps>

## SDKs and Libraries

<CardGroup>
  <Card title="CLOB Client (TypeScript)" icon="github" href="https://github.com/Polymarket/clob-client-v2">
    Place orders with builder attribution
  </Card>

  <Card title="CLOB Client (Python)" icon="github" href="https://github.com/Polymarket/py-clob-client-v2">
    Place orders with builder attribution
  </Card>

  <Card title="Relayer Client (TypeScript)" icon="github" href="https://github.com/Polymarket/builder-relayer-client">
    Gasless onchain transactions
  </Card>

  <Card title="Relayer Client (Python)" icon="github" href="https://github.com/Polymarket/py-builder-relayer-client">
    Gasless onchain transactions
  </Card>

  <Card title="CLOB Client (Rust)" icon="github" href="https://github.com/Polymarket/rs-clob-client-v2">
    Place orders with builder attribution
  </Card>
</CardGroup>

## Examples

These open-source demo applications show how to integrate Polymarket's CLOB Client and Builder Relayer Client for gasless trading with builder order attribution.

<CardGroup>
  <Card title="Authentication" icon="user-check">
    Multiple wallet providers
  </Card>

  <Card title="Gasless Trading" icon="gas-pump">
    Deposit wallet support for new API users
  </Card>

  <Card title="Full Integration" icon="puzzle-piece">
    Orders, positions, CTF ops
  </Card>
</CardGroup>

### Deposit Wallet Integrations

New API users should use deposit wallets. Use the Builder Relayer Client to
deploy deposit wallets and execute signed wallet batches, then place CLOB
orders with `POLY_1271`.

See the [Deposit Wallet Guide](/trading/deposit-wallets) for TypeScript,
Python, Rust, and direct API integration details.

### Existing Safe Wallet Examples

Existing Safe integrations can continue using Gnosis Safe wallets:

<CardGroup>
  <Card title="wagmi + Safe" icon="wallet" href="https://github.com/Polymarket/wagmi-safe-builder-example">
    MetaMask, Phantom, Rabby, and other browser wallets
  </Card>

  <Card title="Privy + Safe" icon="shield-check" href="https://github.com/Polymarket/privy-safe-builder-example">
    Privy embedded wallets
  </Card>

  <Card title="Magic Link + Safe" icon="wand-magic-sparkles" href="https://github.com/Polymarket/magic-safe-builder-example">
    Magic Link email/social authentication
  </Card>

  <Card title="Turnkey + Safe" icon="key" href="https://github.com/Polymarket/turnkey-safe-builder-example">
    Turnkey embedded wallets
  </Card>
</CardGroup>

### Existing Proxy Wallet Examples

For existing Magic Link users from Polymarket.com:

<CardGroup>
  <Card title="Magic Link + Proxy" icon="wand-magic-sparkles" href="https://github.com/Polymarket/magic-proxy-builder-example">
    Auto-deploying proxy wallets for Polymarket.com Magic users
  </Card>
</CardGroup>

### What Each Demo Covers

<Tabs>
  <Tab title="Authentication">
    <ul>
      <li>User sign-in via wallet provider</li>
      <li>User API credential derivation (L2 auth)</li>
      <li>Builder config with remote signing</li>
      <li>Signature types for Deposit Wallet, Safe, and Proxy wallets</li>
    </ul>
  </Tab>

  <Tab title="Wallet Operations">
    <ul>
      <li>Deposit wallet deployment via Relayer</li>
      <li>Batch token approvals (pUSD + outcome tokens)</li>
      <li>CTF operations (split, merge, redeem)</li>
      <li>Transaction monitoring</li>
    </ul>
  </Tab>

  <Tab title="Trading">
    <ul>
      <li>CLOB client initialization</li>
      <li>Order placement with builder attribution</li>
      <li>Position and order management</li>
      <li>Market discovery via Gamma API</li>
    </ul>
  </Tab>
</Tabs>

***

## Next Steps

<CardGroup>
  <Card title="Get API Keys" icon="key" href="/builders/api-keys">
    Create and manage your Builder API credentials.
  </Card>

  <Card title="Understand Tiers" icon="layer-group" href="/builders/tiers">
    Learn about rate limits and how to upgrade.
  </Card>

  <Card title="Attribute Orders" icon="tag" href="/trading/orders/attribution">
    Configure your client to credit trades to your account.
  </Card>

  <Card title="Gasless Guide" icon="gas-pump" href="/trading/gasless">
    Set up gasless transactions for your users.
  </Card>
</CardGroup>


# Tiers
Source: https://docs.polymarket.com/builders/tiers

Rate limits, rewards, and how to upgrade

The Builder Program uses a tiered system to manage rate limits while rewarding high-performing integrations. Higher tiers unlock increased limits, weekly rewards, and priority support.

## Feature Definitions

| Feature                     | Description                                                                                |
| --------------------------- | ------------------------------------------------------------------------------------------ |
| **Daily Relayer Txn Limit** | Maximum Relayer transactions per day for deposit wallet, Safe, and Proxy wallet operations |
| **API Rate Limits**         | Rate limits for non-relayer endpoints (CLOB, Gamma, etc.)                                  |
| **Gasless Trading**         | Gas fees subsidized for supported smart-wallet operations                                  |
| **Order Attribution**       | Orders tracked and attributed to your Builder profile                                      |
| **Builder Fees**            | Builders who route orders can charge fees and monetize on flow                             |
| **Leaderboard Visibility**  | Visibility on the [Builder Leaderboard](https://builders.polymarket.com/)                  |
| **Telegram Channel**        | Private Builders channel for announcements and support                                     |
| **Engineering Support**     | Direct access to engineering team                                                          |
| **Marketing Support**       | Promotion via official Polymarket social accounts                                          |
| **Priority Access**         | Early access to new features and products                                                  |

***

## Tier Comparison

| Feature                     | Unverified |  Verified  |  Partner  |
| --------------------------- | :--------: | :--------: | :-------: |
| **Daily Relayer Txn Limit** |   100/day  | 10,000/day | Unlimited |
| **API Rate Limits**         |  Standard  |  Standard  |  Highest  |
| **Gasless Trading\***       |     Yes    |     Yes    |    Yes    |
| **Order Attribution**       |     Yes    |     Yes    |    Yes    |
| **Builder Fees**            |     Yes    |     Yes    |    Yes    |
| **Leaderboard Visibility**  |      —     |     Yes    |    Yes    |
| **Telegram Channel**        |      —     |     Yes    |    Yes    |
| **Engineering Support**     |      —     |  Standard  |  Elevated |
| **Marketing Support**       |      —     |  Standard  |  Elevated |
| **Priority Access**         |      —     |      —     |    Yes    |

***

## Unverified

<Card title="100 Relay transactions/day" icon="seedling">
  The default tier for all new builders. Start immediately with no approval
  required.
</Card>

**How to get started:**

1. Go to [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder)
2. Create a builder profile
3. Click **"+ Create New"** to generate API keys
4. Attach your [builder code](/trading/orders/attribution) to CLOB orders for attribution; use a Relayer API key for gasless wallet operations

**What's included:**

* Gasless trading through deposit wallets for new API users and existing Safe/Proxy wallets
* Gas subsidized on all Relayer transactions up to the daily limit
* Access to all client libraries and documentation

***

## Verified

<Card title="10,000 Relay transactions/day" icon="badge-check">
  For builders who need higher throughput. Requires manual approval.
</Card>

**How to upgrade:**

Contact us at [builder@polymarket.com](mailto:builder@polymarket.com) with:

* Your Builder API Key
* Use case description
* Expected volume
* Other relevant information (links, docs, decks, etc.)

**Unlocks over Unverified:**

* 100x daily Relayer transaction limit
* Monetize with Builder fees
* Leaderboard visibility at [builders.polymarket.com](https://builders.polymarket.com)
* Private Telegram channel for announcements and support
* Weekly USDC rewards based on volume (subject to approval)
* Grants (subject to approval)

***

## Partner

<Card title="Unlimited Relay transactions/day" icon="handshake">
  Enterprise tier for high-volume integrations and strategic partners.
</Card>

**Unlocks over Verified:**

* Unlimited Relayer transactions
* Highest API rate limits
* Elevated engineering support
* Elevated and coordinated marketing support
* Priority access to new features and products

***

## How to Upgrade

<Steps>
  <Step title="Build and Launch">
    Start with the Unverified tier and build your integration.
  </Step>

  <Step title="Generate Volume">
    Route orders through Polymarket and demonstrate consistent usage.
  </Step>

  <Step title="Apply for Verification">
    Email [builder@polymarket.com](mailto:builder@polymarket.com) with your
    builder key and use case.
  </Step>

  <Step title="Get Approved">
    The Polymarket team reviews applications and responds within a few business
    days.
  </Step>
</Steps>

## Contact

Ready to upgrade or have questions?

<Card title="builder@polymarket.com" icon="envelope" href="mailto:builder@polymarket.com">
  Email us with your Builder API Key and use case details.
</Card>

## FAQ

<AccordionGroup>
  <Accordion title="How do I know if I am verified">
    Verification is displayed in your [Builder Profile](https://polymarket.com/settings?tab=builder) settings.
  </Accordion>

  <Accordion title="What happens if I exceed my daily limit">
    Relayer requests beyond your daily limit will be rate-limited and return an
    error. Consider upgrading to Verified or Partner tier if you're hitting
    limits.
  </Accordion>

  <Accordion title="What if I just need more daily Relay transaction limits for my own wallet">
    If you're not routing orders for other users (wallets), you can get unlimited
    daily Relay transactions by obtaining a [Relayer API key](https://polymarket.com/settings?tab=api-keys).
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup>
  <Card title="Get API Keys" icon="key" href="/builders/api-keys">
    Create your Builder API credentials.
  </Card>

  <Card title="Attribute Orders" icon="tag" href="/trading/orders/attribution">
    Configure your client to credit trades to your account.
  </Card>
</CardGroup>


# Markets & Events
Source: https://docs.polymarket.com/concepts/markets-events

Understanding the fundamental building blocks of Polymarket

Every prediction on Polymarket is structured around two core concepts: **markets** and **events**. Understanding how they relate is essential for building on the platform.

<Frame>
  <img alt="" />

  <img alt="" />
</Frame>

## Markets

A **market** is the fundamental tradable unit on Polymarket. Each market represents a single binary question with Yes/No outcomes.

<Frame>
  <img alt="" />

  <img alt="" />
</Frame>

Every market has:

| Identifier       | Description                                                              |
| ---------------- | ------------------------------------------------------------------------ |
| **Condition ID** | Unique identifier for the market's condition in the CTF contracts        |
| **Question ID**  | Hash of the market question used for resolution                          |
| **Token IDs**    | ERC1155 token IDs used for trading on the CLOB — one for Yes, one for No |

<Note>
  Markets can only be traded via the CLOB if `enableOrderBook` is `true`. Some
  markets may exist onchain but not be available for order book trading.
</Note>

### Market Example

A simple market might be:

> **"Will Bitcoin reach \$150,000 by December 2026?"**

This creates two outcome tokens:

* **Yes token** - Redeemable for `$1` if Bitcoin reaches `$150k`
* **No token** - Redeemable for `$1` if Bitcoin doesn't reach `$100k`

## Events

An **event** is a container that groups one or more related markets together. Events provide organizational structure and enable multi-outcome predictions.

### Single-Market Events

When an event contains just one market, it creates a simple market pair. The event and market are essentially equivalent.

```
Event: Will Bitcoin reach $100,000 by December 2024?
└── Market: Will Bitcoin reach $100,000 by December 2024? (Yes/No)
```

### Multi-Market Events

When an event contains two or more markets, it creates a grouped market pair. This enables mutually exclusive multi-outcome predictions.

```
Event: Who will win the 2024 Presidential Election?
├── Market: Donald Trump? (Yes/No)
├── Market: Joe Biden? (Yes/No)
├── Market: Kamala Harris? (Yes/No)
└── Market: Other? (Yes/No)
```

## Identifying Markets

Every market and event has a unique **slug** that appears in the Polymarket URL:

```
https://polymarket.com/event/fed-decision-in-october
                              └── slug: fed-decision-in-october
```

You can use slugs to fetch specific markets or events from the API:

```bash theme={null}
# Fetch event by slug
curl "https://gamma-api.polymarket.com/events?slug=fed-decision-in-october"
```

## Sports Markets

Specifically for sports markets, outstanding limit orders are **automatically cancelled** once the game begins, clearing the order book at the official start time. However, game start times can shift — if a game starts earlier than scheduled, orders may not be cleared in time. Always monitor your orders closely around game start times.

***

## Next Steps

<CardGroup>
  <Card title="Prices & Orderbook" icon="chart-line" href="/concepts/prices-orderbook">
    Learn how prices are determined and how the order book works.
  </Card>

  <Card title="Fetching Market Data" icon="code" href="/market-data/overview">
    Start querying markets and events from the API.
  </Card>
</CardGroup>


# Order Lifecycle
Source: https://docs.polymarket.com/concepts/order-lifecycle

Understanding how orders flow from creation to settlement

Every trade on Polymarket follows a specific lifecycle. Orders are created offchain, matched by an operator, and settled onchain through smart contracts. This hybrid approach combines the speed of centralized matching with the security of blockchain settlement.

<Frame>
  <img alt="" />

  <img alt="" />
</Frame>

## How Orders Work

All orders on Polymarket are **limit orders**. A limit order specifies the price you're willing to pay (or accept) and the quantity you want to trade.

<Note>
  "Market orders" are simply limit orders with a price set to execute
  immediately against the best available resting orders.
</Note>

Orders are **EIP712-signed messages**. When you place an order, you sign a structured message with your private key. This signature authorizes the Exchange contract to execute the trade on your behalf—without ever taking custody of your funds.

## Order Types

| Type    | Behavior                                                      | Use Case                 |
| ------- | ------------------------------------------------------------- | ------------------------ |
| **GTC** | Good Till Cancelled — rests on book until filled or cancelled | Standard limit orders    |
| **GTD** | Good Till Date — auto-expires at specified time               | Time-limited orders      |
| **FOK** | Fill Or Kill — fill entirely or cancel immediately            | All-or-nothing execution |
| **FAK** | Fill And Kill — fill what's available, cancel the rest        | Partial fills acceptable |

### Post-Only Orders

Post-only orders will only rest on the book. If a post-only order would match immediately (cross the spread), it's rejected instead of executed. This guarantees you're always the maker, never the taker.

<Steps>
  <Step title="Create and Sign">
    Your client creates an order object containing:

    * Token ID (which outcome you're trading)
    * Side (buy or sell)
    * Price and size
    * Expiration time
    * Timestamp (in milliseconds, used for order uniqueness)

    You sign this order with your private key, creating an EIP712 signature.
  </Step>

  <Step title="Submit to CLOB">
    The signed order is submitted to the Central Limit Order Book (CLOB) operator. The operator validates:

    * Signature is valid
    * You have sufficient balance
    * You have set the required allowances
    * Price meets minimum tick size requirements
  </Step>

  <Step title="Match or Rest">
    **If the order is marketable** (your buy price ≥ lowest ask, or your sell price ≤ highest bid), it matches immediately against resting orders.

    **If the order is not marketable**, it rests on the book waiting for a counterparty. It remains open until:

    * Another order matches against it
    * You cancel it
    * It expires (GTD orders only)
  </Step>

  <Step title="Settlement">
    When orders match, the operator submits the trade to the blockchain. The Exchange contract:

    * Verifies both signatures
    * Transfers tokens from seller to buyer
    * Transfers pUSD from buyer to seller

    Settlement is **atomic**—either the entire trade succeeds or nothing happens.
  </Step>

  <Step title="Confirmation">
    The trade achieves finality on Polygon. Your token balances update and the trade appears in your history.
  </Step>
</Steps>

## Order Statuses

When you place an order, it receives one of these statuses:

| Status      | Description                                                                 |
| ----------- | --------------------------------------------------------------------------- |
| `live`      | Order is resting on the book                                                |
| `matched`   | Order matched immediately                                                   |
| `delayed`   | Marketable order subject to a 1-second matching delay (sports markets)      |
| `unmatched` | Marketable order placed on the book after the delay expired without a match |

## Trade Statuses

After matching, trades progress through these statuses:

| Status      | Terminal | Description                                            |
| ----------- | -------- | ------------------------------------------------------ |
| `MATCHED`   | No       | Trade matched, sent to executor for onchain submission |
| `MINED`     | No       | Transaction mined into the blockchain                  |
| `CONFIRMED` | Yes      | Trade achieved finality, successful                    |
| `RETRYING`  | No       | Transaction failed, being retried                      |
| `FAILED`    | Yes      | Trade failed permanently                               |

## Maker vs Taker

| Role      | Description                     | When                                                  |
| --------- | ------------------------------- | ----------------------------------------------------- |
| **Maker** | Adds liquidity to the book      | Your order rests and is later matched                 |
| **Taker** | Removes liquidity from the book | Your order matches immediately against resting orders |

Price improvement always benefits the taker. If you place a buy order at `$0.55` and it matches against a resting sell at `$0.52`, you pay `$0.52`.

## Cancellation

You can cancel orders at any time before they're matched via the CLOB API.

Partial fills cannot be cancelled—only the unfilled portion of an order can be cancelled.

## Requirements

Before placing orders, ensure:

| Requirement         | Description                                        |
| ------------------- | -------------------------------------------------- |
| **Balance**         | Sufficient pUSD (for buys) or tokens (for sells)   |
| **Allowance**       | Approve the Exchange contract to spend your assets |
| **API Credentials** | Valid API key for authenticated endpoints          |

<Info>
  Order size is limited by your available balance minus any amounts reserved by existing open orders.

  $$
  \text{maxOrderSize} = \text{balance} - \sum(\text{openOrderSize} - \text{filledAmount})
  $$
</Info>

## Next Steps

<CardGroup>
  <Card title="Resolution" icon="gavel" href="/concepts/resolution">
    Learn how markets are resolved and winning tokens redeemed.
  </Card>

  <Card title="Trading Guide" icon="book" href="/trading/overview">
    Start placing orders with our step-by-step guide.
  </Card>
</CardGroup>


# Positions & Tokens
Source: https://docs.polymarket.com/concepts/positions-tokens

Understanding outcome tokens and how positions work on Polymarket

Every prediction on Polymarket is represented by **outcome tokens**. When you trade, you're buying and selling these tokens. Your **position** is simply your balance of tokens for a given market.

<Frame>
  <img alt="" />

  <img alt="" />
</Frame>

## Outcome Tokens

Each market has exactly two outcome tokens:

| Token   | Redeems for | If...                    |
| ------- | ----------- | ------------------------ |
| **Yes** | \$1.00      | The event occurs         |
| **No**  | \$1.00      | The event does not occur |

Tokens are **ERC1155** assets on Polygon, using the [Gnosis Conditional Token Framework](https://github.com/gnosis/conditional-tokens-contracts/) (CTF). This means they're fully onchain and function as standard ERC1155 tokens.

<Note>
  Outcome tokens are always fully backed. Every Yes/No pair in existence is
  backed by exactly `$1` of pUSD collateral locked in the CTF contract.
</Note>

### Split

Convert pUSD into outcome tokens. Splitting \$1 creates 1 Yes token and 1 No token.

```
$100 pUSD → 100 Yes tokens + 100 No tokens
```

Use this when you want to:

* Create inventory for market making
* Obtain both sides of a market

### Trade

Buy or sell tokens on the order book. This is how most users acquire positions.

* **Buy Yes** at `$0.60` → Pay `$0.60`, receive 1 Yes token
* **Sell Yes** at `$0.60` → Give up 1 Yes token, receive `$0.60`

You can sell your position at any time before resolution.

### Merge

Convert a complete set of tokens back into pUSD. Merging requires equal amounts of Yes and No tokens.

```
100 Yes tokens + 100 No tokens → $100 pUSD
```

Use this when you want to:

* Exit a position without trading
* Convert accumulated tokens back to collateral

### Redeem

After a market resolves, exchange winning tokens for pUSD.

| Outcome             | Yes tokens     | No tokens      |
| ------------------- | -------------- | -------------- |
| Event occurs        | Worth \$1 each | Worth \$0      |
| Event doesn't occur | Worth \$0      | Worth \$1 each |

```
100 winning tokens → $100 pUSD
```

### Position Value

The value of your position depends on the current market price:

```
Position value = Token balance × Current price
```

If you hold 100 Yes tokens and Yes is trading at \$0.75:

```
Position value = 100 × $0.75 = $75
```

## Profit and Loss

Your profit depends on how the market resolves compared to your entry price.

### Example - Buying Yes at 0.40

| Scenario            | Outcome  | Return | Profit                    |
| ------------------- | -------- | ------ | ------------------------- |
| Event occurs        | Yes wins | \$1.00 | +\$0.60 per token (150%)  |
| Event doesn't occur | No wins  | \$0.00 | -\$0.40 per token (-100%) |

### Holding Rewards

Polymarket pays a **4.00% annualized** Holding Reward based on your total position value in eligible markets. Your total position value is randomly sampled once each hour, and the reward is distributed daily. The rate is variable and subject to change at Polymarket's discretion.

### Example - Selling Before Resolution

You can lock in profits or cut losses by selling before the market resolves:

* Bought Yes at `$0.40`
* Price rises to `$0.70`
* Sell at `$0.70` → Profit of `$0.30` per token (75%)


# Prices & Orderbook
Source: https://docs.polymarket.com/concepts/prices-orderbook

How prices work and how the order book enables peer-to-peer trading

Polymarket uses a **Central Limit Order Book (CLOB)** for trading. Prices aren't set by Polymarket—they emerge from supply and demand as users trade with each other.

<Frame>
  <img alt="" />

  <img alt="" />
</Frame>

## Prices Are Probabilities

Every share on Polymarket is priced between `$0.00` and `$1.00`. The price directly represents the market's belief in the probability of that outcome.

| Price  | Implied Probability |
| ------ | ------------------- |
| \$0.25 | 25% chance          |
| \$0.50 | 50% chance          |
| \$0.75 | 75% chance          |

<Note>
  The displayed price is the **midpoint** of the bid-ask spread. If the spread
  is wider than \$0.10, the last traded price is shown instead.
</Note>

### Example

If the best bid for "Yes" is `$0.34` and the best ask is `$0.40`:

```
Displayed price = ($0.34 + $0.40) / 2 = $0.37 (37% probability)
```

You won't necessarily trade at `$0.37`—you'll pay the ask (`$0.40`) when buying or receive the bid (`$0.34`) when selling.

## The Order Book

The order book is a list of all open buy and sell orders for a market. It has two sides:

| Side | Description                                                 |
| ---- | ----------------------------------------------------------- |
| Bids | Buy orders—the highest prices traders are willing to pay    |
| Asks | Sell orders—the lowest prices traders are willing to accept |

The **spread** is the gap between the highest bid and lowest ask. Tighter spreads mean more liquid markets.

## Order Types

### Market Orders

Execute immediately at the best available price. Use when you want instant execution and are willing to pay the spread.

* **Buying**: You pay the lowest ask price
* **Selling**: You receive the highest bid price

### Limit Orders

Execute only at your specified price or better. Use when you want price control and are willing to wait.

* Your order sits in the book until someone trades against it
* Orders can **partially fill** as different traders match portions of your order
* You can cancel unfilled orders at any time

<Note>
  All orders on Polymarket are technically limit orders. A "market order" is
  simply a limit order priced to execute immediately against resting orders.
</Note>

## How Trades Work

Polymarket's CLOB is **hybrid-decentralized**:

1. **Offchain matching** — An operator matches compatible orders
2. **Onchain settlement** — Matched trades settle via smart contracts

<Frame>
  <img alt="" />

  <img alt="" />
</Frame>

This design gives you the speed of centralized matching with the security of onchain settlement. You always maintain custody of your funds.

## Price Discovery

When a new market launches, there's no initial price. The first price emerges when:

1. Someone places a limit order to buy Yes at a price (e.g., `$0.60`)
2. Someone places a limit order to buy No at the complementary price (e.g., `$0.40`)
3. Since `$0.60` + `$0.40` = `$1.00`, the orders match

When matched, `$1.00` is converted into 1 Yes token and 1 No token, each going to their respective buyers.

## Next Steps

<Note>
  Polymarket's orderbook has **no trading size limits** — it matches willing
  buyers and sellers of any amount. However, large orders may move the price
  significantly. Always check orderbook depth before trading in size.
</Note>

<CardGroup>
  <Card title="Positions & Tokens" icon="coins" href="/concepts/positions-tokens">
    Learn about outcome tokens and how positions work.
  </Card>

  <Card title="Order Lifecycle" icon="arrows-spin" href="/concepts/order-lifecycle">
    Understand what happens from order placement to settlement.
  </Card>
</CardGroup>


# Polymarket USD
Source: https://docs.polymarket.com/concepts/pusd

pUSD — the collateral token used for all trading on Polymarket

**pUSD** (Polymarket USD) is the collateral token used for all trading on Polymarket. It's a standard ERC-20 token on Polygon, backed by USDC. The smart contract — which enables the withdrawal functionality — enforces the backing. No algorithmic peg, no fractional reserve.

<Note>
  **Day to day, nothing changes.** You load funds, see a balance, trade, and
  withdraw. pUSD is the technical settlement layer underneath the same
  experience you're used to.
</Note>

***

## Why pUSD

The protocol settles all trading activity in native USDC, providing a more capital efficient, scalable, and institutionally aligned settlement standard as the platform continues to grow.

pUSD is a standard ERC-20 wrapper that represents a USDC claim. Wrapping and unwrapping are enforced onchain by the `CollateralOnramp` and `CollateralOfframp` contracts.

***

## Key facts

|                |                         |
| -------------- | ----------------------- |
| Token standard | ERC-20                  |
| Network        | Polygon mainnet         |
| Decimals       | 6                       |
| Backing        | USDC (enforced onchain) |
| Transferable   | Yes — standard ERC-20   |

pUSD is designed to function within Polymarket. There are no current plans to list it on external exchanges.

See the [Contracts](/resources/contracts) page for all collateral-related contract addresses.

***

## Wrapping — USDC.e → pUSD

Use the **CollateralOnramp** to wrap USDC.e into pUSD.

```solidity theme={null}
function wrap(address _asset, address _to, uint256 _amount) external
```

**Parameters**

* `_asset` — address of the asset being wrapped. Must be USDC.e.
* `_to` — recipient of the minted pUSD. Does not have to be `msg.sender`.
* `_amount` — amount to wrap, in USDC.e base units (6 decimals).

**Requirements**

* The caller must first approve the **CollateralOnramp** contract (not the pUSD token) to spend USDC.e.
* Reverts with `OnlyUnpaused()` if the admin has paused USDC.e.

### Example

<CodeGroup>
  ```typescript TypeScript theme={null}
  import {
    createWalletClient,
    createPublicClient,
    http,
    parseAbi,
    parseUnits,
  } from "viem";
  import { polygon } from "viem/chains";
  import { privateKeyToAccount } from "viem/accounts";

  const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
  const walletClient = createWalletClient({ account, chain: polygon, transport: http() });
  const publicClient = createPublicClient({ chain: polygon, transport: http() });

  const ONRAMP = "0x93070a847efEf7F70739046A929D47a521F5B8ee" as const;
  const USDCE = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174" as const; // USDC.e on Polygon

  const amount = parseUnits("100", 6); // 100 USDC.e

  // 1. Approve the Onramp to spend your USDC.e
  const approveHash = await walletClient.writeContract({
    address: USDCE,
    abi: parseAbi(["function approve(address spender, uint256 amount) returns (bool)"]),
    functionName: "approve",
    args: [ONRAMP, amount],
  });
  await publicClient.waitForTransactionReceipt({ hash: approveHash });

  // 2. Wrap USDC.e → pUSD
  const wrapHash = await walletClient.writeContract({
    address: ONRAMP,
    abi: parseAbi(["function wrap(address _asset, address _to, uint256 _amount)"]),
    functionName: "wrap",
    args: [USDCE, account.address, amount],
  });
  await publicClient.waitForTransactionReceipt({ hash: wrapHash });
  ```

  ```python Python theme={null}
  from web3 import Web3

  ONRAMP = "0x93070a847efEf7F70739046A929D47a521F5B8ee"
  USDCE = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"

  amount = 100 * 10**6  # 100 USDC.e

  # 1. Approve the Onramp to spend your USDC.e
  usdce = w3.eth.contract(address=USDCE, abi=[{
      "name": "approve", "type": "function",
      "inputs": [{"name": "spender", "type": "address"},
                 {"name": "amount", "type": "uint256"}],
      "outputs": [{"type": "bool"}],
  }])
  usdce.functions.approve(ONRAMP, amount).transact({"from": address})

  # 2. Wrap USDC.e → pUSD
  onramp = w3.eth.contract(address=ONRAMP, abi=[{
      "name": "wrap", "type": "function",
      "inputs": [{"name": "_asset", "type": "address"},
                 {"name": "_to", "type": "address"},
                 {"name": "_amount", "type": "uint256"}],
      "outputs": [],
  }])
  onramp.functions.wrap(USDCE, address, amount).transact({"from": address})
  ```
</CodeGroup>

***

## Unwrapping — pUSD → USDC.e

Use the **CollateralOfframp** to unwrap pUSD back into USDC.e.

```solidity theme={null}
function unwrap(address _asset, address _to, uint256 _amount) external
```

**Parameters**

* `_asset` — asset you want to receive. Must be USDC.e.
* `_to` — recipient of the underlying asset.
* `_amount` — amount of pUSD to unwrap (6 decimals).

**Requirements**

* The caller must first approve the **CollateralOfframp** contract to spend their pUSD.
* Same pause gate as the Onramp.

***

## Next steps

<CardGroup>
  <Card title="Contracts" icon="file-contract" href="/resources/contracts">
    All Polymarket contract addresses and audits
  </Card>

  <Card title="Bridge" icon="arrow-right-arrow-left" href="/trading/bridge/deposit">
    Deposit from other chains — auto-wraps to pUSD
  </Card>
</CardGroup>


# Resolution
Source: https://docs.polymarket.com/concepts/resolution

How markets are resolved and winning positions redeemed

When the outcome of an event becomes known, the market is **resolved**. Resolution determines which outcome won, allowing holders of winning tokens to redeem them for \$1 each. Losing tokens become worthless.

Polymarket uses the **UMA Optimistic Oracle** for decentralized, permissionless resolution. Anyone can propose an outcome, and anyone can dispute it if they believe it's incorrect.

<Frame>
  <img alt="" />

  <img alt="" />
</Frame>

## Resolution Rules

Every market has pre-defined resolution rules that specify:

* **Resolution source** — Where the outcome will be determined from (e.g., official announcements, specific websites)
* **End date** — When the market is eligible for resolution
* **Edge cases** — How ambiguous situations should be handled

<Warning>
  Always read the resolution rules before trading. The market title describes
  the question, but the **rules** define how it resolves.
</Warning>

<Steps>
  <Step title="Proposal">
    Anyone can propose a resolution by:

    1. Selecting the winning outcome
    2. Posting a bond (typically \$750 pUSD)
    3. Submitting the proposal to the UMA Oracle

    If the proposal is correct and undisputed, the proposer receives their bond back plus a reward.

    <Warning>
      If you propose incorrectly or too early, you lose your entire bond. Only
      propose if you're confident in the outcome and understand the process.
    </Warning>
  </Step>

  <Step title="Challenge Period">
    After a proposal, there's a **2-hour challenge period** where anyone can dispute the outcome.

    * **If no dispute**: The proposal is accepted and the market resolves
    * **If disputed**: A new proposal round begins. If the second proposal is also disputed, the resolution escalates to UMA's DVM (Data Verification Mechanism) for a token holder vote.

    There are three possible resolution flows:

    1. **No dispute** — Propose then Resolve (fastest, \~2 hours)
    2. **One dispute** — Propose, Challenge, second Propose, Resolve (second proposal accepted)
    3. **Two disputes** — Propose, Challenge, second Propose, second Challenge, Resolve via DVM vote
  </Step>

  <Step title="Dispute - If Challenged">
    To dispute a proposal:

    1. Post a counter-bond (same amount as proposer, typically \$750)
    2. The dispute triggers a new proposal round, or if already in the second round, a debate period

    During the **24-48 hour debate period**, evidence can be submitted in UMA's Discord channels (`#evidence-rationale` and `#voting-discussion`).
  </Step>

  <Step title="UMA Vote">
    After the debate period, UMA token holders vote on the correct outcome. The voting process takes approximately 48 hours.

    | Outcome           | Result                                 | Bond Distribution                                                                                        |
    | ----------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------- |
    | **Proposer wins** | Original proposal accepted             | Proposer gets bond back + half of disputer's bond                                                        |
    | **Disputer wins** | Proposal rejected, new proposal needed | Disputer gets bond back + half of proposer's bond                                                        |
    | **Too Early**     | Event hasn't concluded yet             | Disputer gets bond back + half of proposer's bond                                                        |
    | **Unknown/50-50** | Neither outcome applicable (rare)      | Market resolves 50/50 — each token redeems for \$0.50; disputer gets bond back + half of proposer's bond |
  </Step>
</Steps>

## After Resolution

Once a market resolves:

* **Trading stops** — You can no longer buy or sell tokens for this market
* **Winning tokens** become redeemable for \$1.00 each
* **Losing tokens** become worthless (\$0.00)

### Redeeming Tokens

After resolution, redeem through the CTF collateral adapter to exchange winning tokens for pUSD. The adapter burns your ERC1155 outcome tokens through the CTF contract, receives the released USDC.e collateral, wraps it into pUSD, and returns pUSD to your wallet.

```
100 winning tokens → $100 pUSD
```

## Clarifications

In rare cases, unforeseen circumstances require clarification of the rules after trading begins. Polymarket may issue an **"Additional context"** update that proposers and voters should consider during resolution.

Clarifications:

* Cannot change the fundamental intent of the question
* Are published onchain via the bulletin board contract
* Should be considered by UMA voters when resolving disputes

<Tip>
  If you believe a clarification is needed, request it in the [Polymarket
  Discord](https://discord.com/invite/polymarket) `#market-review` channel.
</Tip>

## Resolution Timeline

| Phase                       | Duration    |
| --------------------------- | ----------- |
| Challenge period            | 2 hours     |
| Debate period (if disputed) | 24-48 hours |
| UMA voting (if disputed)    | \~48 hours  |

**Undisputed resolution**: \~2 hours after proposal

**Disputed resolution**: 4-6 days total

## Contract Addresses

| Contract               | Address                                      | Network         |
| ---------------------- | -------------------------------------------- | --------------- |
| **UmaCtfAdapter v3.0** | `0x157Ce2d672854c848c9b79C49a8Cc6cc89176a49` | Polygon Mainnet |
| **UmaCtfAdapter v2.0** | `0x6A9D222616C90FcA5754cd1333cFD9b7fb6a4F74` | Polygon Mainnet |
| **UmaCtfAdapter v1.0** | `0xCB1822859cEF82Cd2Eb4E6276C7916e692995130` | Polygon Mainnet |

## Resources

* [UMA Oracle Portal](https://oracle.uma.xyz/) — View and interact with proposals
* [UMA Documentation](https://docs.uma.xyz/) — Learn more about the Optimistic Oracle
* [Polymarket Discord](https://discord.com/invite/polymarket) — Discuss resolutions and request clarifications
* [UmaCtfAdapter Source Code](https://github.com/Polymarket/uma-ctf-adapter) — Smart contract source
* [UmaCtfAdapter Audit](https://github.com/Polymarket/uma-ctf-adapter/blob/main/audit/Polymarket_UMA_Optimistic_Oracle_Adapter_Audit.pdf) — Security audit report

## Next Steps

<CardGroup>
  <Card title="Positions & Tokens" icon="coins" href="/concepts/positions-tokens">
    Learn how to redeem winning tokens after resolution.
  </Card>

  <Card title="Markets & Events" icon="calendar" href="/concepts/markets-events">
    Understand how markets are structured.
  </Card>
</CardGroup>


# Overview
Source: https://docs.polymarket.com/index

Build on the world's largest prediction market. Trade, integrate, and access real-time market data with the Polymarket API.

<a href="https://docs.polymarket.us">
  <span>🇺🇸</span>
  <span>Looking for <span>Polymarket US</span> documentation?</span>
  <span>Visit US Docs →</span>
</a>

<svg>
  <path />
</svg>

<div>
  <div>
    <h1>
      Polymarket Documentation
    </h1>

    <div>
      Build on the world's largest prediction market. APIs, SDKs, and tools for prediction market developers.
    </div>

    <div>
      <div>
        <h2>
          Developer Quickstart
        </h2>

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

        <div>
          <a href="/quickstart">
            Get Started →
          </a>
        </div>
      </div>

      <CodeGroup>
        ```typescript TypeScript theme={null}
        import { ClobClient, Side } from "@polymarket/clob-client-v2";

        const client = new ClobClient({ host, chain: chainId, signer, creds });

        const order = await client.createAndPostOrder(
          { tokenID, price: 0.50, size: 10, side: Side.BUY },
          { tickSize: "0.01", negRisk: false }
        );
        ```

        ```python Python theme={null}
        from py_clob_client_v2 import ClobClient, OrderArgs, PartialCreateOrderOptions
        from py_clob_client_v2.order_builder.constants import BUY

        client = ClobClient(host, key=key, chain_id=chain, creds=creds)
        order = client.create_and_post_order(
            OrderArgs(token_id=token_id, price=0.50, size=10, side=BUY),
            options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False)
        )
        ```

        ```rust Rust theme={null}
        use polymarket_client_sdk_v2::clob::{Client, Config};
        use polymarket_client_sdk_v2::clob::types::Side;
        use polymarket_client_sdk_v2::types::dec;

        let client = Client::new(host, Config::default())?.authentication_builder(&signer).authenticate().await?;
        let order = client.limit_order().token_id(token_id).price(dec!(0.50)).size(dec!(10)).side(Side::Buy).build().await?;
        let signed = client.sign(&signer, order).await?;
        let response = client.post_order(signed).await?;
        ```
      </CodeGroup>
    </div>
  </div>

  <div>
    <h2>
      Get Familiar with Polymarket
    </h2>

    <p>
      Learn the fundamentals, explore our APIs, and start building on the world's largest prediction market.
    </p>

    <div>
      <CardGroup>
        <Card title="Quickstart" icon="rocket" href="/quickstart">
          Set up your environment and make your first API call in minutes.
        </Card>

        <Card title="Core Concepts" icon="lightbulb" href="/concepts/markets-events">
          Understand markets, events, tokens, and how trading works.
        </Card>

        <Card title="API Reference" icon="code" href="/api-reference/introduction">
          Explore REST endpoints, WebSocket streams, and authentication.
        </Card>

        <Card title="SDKs" icon="cube" href="/api-reference/clients-sdks">
          Official Python, TypeScript, and Rust libraries for faster development.
        </Card>
      </CardGroup>
    </div>

    <div>
      <a href="https://builders.polymarket.com">
        <img alt="Banner" />
      </a>
    </div>
  </div>

  <div>
    <div>
      <IconCard icon="medal" title="Builder Program" description="Build apps on Polymarket and earn rewards for driving volume" href="https://builders.polymarket.com" />

      <IconCard icon="quiz" title="Help Desk" description="Get support, report issues, and find answers to common questions" href="https://help.polymarket.com" />

      <IconCard icon="sensor" title="Status" description="Check API uptime, service health, and incident reports" href="https://status.polymarket.com" />
    </div>
  </div>
</div>


# Fetching Markets
Source: https://docs.polymarket.com/market-data/fetching-markets

Three strategies for discovering and querying markets

<Tip>
  Both the events and markets endpoints are paginated. See
  [pagination](#pagination) for details.
</Tip>

There are three main strategies for retrieving market data, each optimized for different use cases:

1. **By Slug** — Best for fetching specific individual markets or events
2. **By Tags** — Ideal for filtering markets by category or sport
3. **Via Events Endpoint** — Most efficient for retrieving all active markets

***

## Fetch by Slug

**Use case:** When you need to retrieve a specific market or event that you already know about.

Individual markets and events are best fetched using their unique slug identifier. The slug can be found directly in the Polymarket frontend URL.

### How to Extract the Slug

From any Polymarket URL, the slug is the path segment after `/event/`:

```
https://polymarket.com/event/fed-decision-in-october
                                ↑
                      Slug: fed-decision-in-october
```

### Examples

```bash theme={null}
# Fetch an event by slug (query parameter)
curl "https://gamma-api.polymarket.com/events?slug=fed-decision-in-october"

# Or use the path endpoint
curl "https://gamma-api.polymarket.com/events/slug/fed-decision-in-october"
```

```bash theme={null}
# Fetch a market by slug (query parameter)
curl "https://gamma-api.polymarket.com/markets?slug=fed-decision-in-october"

# Or use the path endpoint
curl "https://gamma-api.polymarket.com/markets/slug/fed-decision-in-october"
```

***

## Fetch by Tags

**Use case:** When you want to filter markets by category, sport, or topic.

Tags provide a way to categorize and filter markets. You can discover available tags and then use them to filter your requests.

### Discover Available Tags

**General tags:** `GET /tags` (Gamma API)

**Sports tags and metadata:** `GET /sports` (Gamma API)

The `/sports` endpoint returns metadata for sports including tag IDs, images, resolution sources, and series information.

### Filter by Tag

Once you have tag IDs, use the `tag_id` parameter in both events and markets endpoints:

```bash theme={null}
# Fetch events for a specific tag
curl "https://gamma-api.polymarket.com/events?tag_id=100381&limit=10&active=true&closed=false"
```

### Additional Tag Filtering

You can also:

* Use `related_tags=true` to include related tag markets
* Exclude specific tags with `exclude_tag_id`

```bash theme={null}
# Include related tags
curl "https://gamma-api.polymarket.com/events?tag_id=100381&related_tags=true&active=true&closed=false"
```

***

## Fetch All Active Markets

**Use case:** When you need to retrieve all available active markets, typically for broader analysis or market discovery.

The most efficient approach is to use the events endpoint with `active=true&closed=false`, as events contain their associated markets.

```bash theme={null}
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=100"
```

### Key Parameters

| Parameter   | Description                                                                                                      |
| ----------- | ---------------------------------------------------------------------------------------------------------------- |
| `order`     | Field to order by (`volume_24hr`, `volume`, `liquidity`, `start_date`, `end_date`, `competitive`, `closed_time`) |
| `ascending` | Sort direction (`true` for ascending, `false` for descending). Default: `false`                                  |
| `active`    | Filter by active status (`true` for live tradable events)                                                        |
| `closed`    | Filter by closed status. Default: `false`                                                                        |
| `limit`     | Results per page                                                                                                 |
| `offset`    | Number of results to skip for pagination                                                                         |

```bash theme={null}
# Get the highest volume active events
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&order=volume_24hr&ascending=false&limit=100"
```

***

## Pagination

All list endpoints return paginated responses with `limit` and `offset` parameters:

```bash theme={null}
# Page 1: First 50 results
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=50&offset=0"

# Page 2: Next 50 results
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=50&offset=50"

# Page 3: Next 50 results
curl "https://gamma-api.polymarket.com/events?active=true&closed=false&limit=50&offset=100"
```

***

## Best Practices

1. **For individual markets:** Use the slug method for direct lookups
2. **For category browsing:** Use tag filtering to reduce API calls
3. **For complete market discovery:** Use the events endpoint with pagination
4. **Always include `active=true`** when fetching live markets. The `closed` parameter now defaults to `false`, so closed markets are excluded automatically — pass `closed=true` only if you need historical data
5. **Use the events endpoint** and work backwards — events contain their associated markets, reducing the number of API calls needed

***

## Next Steps

<CardGroup>
  <Card title="API Reference" icon="code" href="/api-reference/introduction">
    Full endpoint documentation with parameters and response schemas.
  </Card>
</CardGroup>


# Overview
Source: https://docs.polymarket.com/market-data/overview

Fetch market data with no authentication required

All market data is available through public REST endpoints. No API key, no authentication, no wallet required.

```bash theme={null}
curl "https://gamma-api.polymarket.com/events?limit=5"
```

***

## Data Model

Polymarket structures data using two organizational models. The most fundamental element is always markets—events simply provide additional organization.

<Steps>
  <Step title="Event">
    A top-level object representing a question (e.g., "Who will win the 2024
    Presidential Election?"). Contains one or more markets.
  </Step>

  <Step title="Market">
    A specific tradable binary outcome within an event. Maps to a pair of CLOB
    token IDs, a market address, a question ID, and a condition ID.
  </Step>
</Steps>

### Single-Market Events vs Multi-Market Events

| Type                | Example                                                                                        |
| ------------------- | ---------------------------------------------------------------------------------------------- |
| Single-market event | "Will Bitcoin reach \$100k?" → 1 market (Yes/No)                                               |
| Multi-market event  | "Where will Barron Trump attend College?" → Markets for Georgetown, NYU, UPenn, Harvard, Other |

### Outcomes and Prices

Each market has `outcomes` and `outcomePrices` arrays that map 1:1. Prices represent implied probabilities:

```json theme={null}
{
  "outcomes": "[\"Yes\", \"No\"]",
  "outcomePrices": "[\"0.20\", \"0.80\"]"
}
// Index 0: "Yes" → 0.20 (20% probability)
// Index 1: "No" → 0.80 (80% probability)
```

<Info>Markets can be traded via the CLOB if `enableOrderBook` is `true`.</Info>

***

## Available Data

Endpoints are split across three APIs. See the [API Reference](/api-reference/introduction) for full endpoint documentation with parameters and response schemas.

### Gamma API - Events Markets and Discovery

| Endpoint             | Description                                 |
| -------------------- | ------------------------------------------- |
| `GET /events`        | List events with filtering and pagination   |
| `GET /events/{id}`   | Get a single event by ID                    |
| `GET /markets`       | List markets with filtering and pagination  |
| `GET /markets/{id}`  | Get a single market by ID                   |
| `GET /public-search` | Search across events, markets, and profiles |
| `GET /tags`          | Ranked tags/categories                      |
| `GET /series`        | Series (grouped events)                     |
| `GET /sports`        | Sports metadata                             |
| `GET /teams`         | Teams                                       |

### CLOB API - Prices and Orderbooks

| Endpoint              | Description                       |
| --------------------- | --------------------------------- |
| `GET /price`          | Price for a single token          |
| `GET /prices`         | Prices for multiple tokens        |
| `GET /book`           | Order book for a token            |
| `POST /books`         | Order books for multiple tokens   |
| `GET /prices-history` | Historical price data for a token |
| `GET /midpoint`       | Midpoint price for a token        |
| `GET /spread`         | Spread for a token                |

### Data API - Positions Trades and Analytics

| Endpoint                               | Description                  |
| -------------------------------------- | ---------------------------- |
| `GET /positions?user={address}`        | Current positions for a user |
| `GET /closed-positions?user={address}` | Closed positions for a user  |
| `GET /activity?user={address}`         | Onchain activity for a user  |
| `GET /value?user={address}`            | Total position value         |
| `GET /oi`                              | Open interest for a market   |
| `GET /holders`                         | Top holders of a market      |
| `GET /trades`                          | Trade history                |

***

## Next Steps

<CardGroup>
  <Card title="Fetching Markets" icon="magnifying-glass" href="/market-data/fetching-markets">
    Three strategies for discovering and querying markets.
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference/introduction">
    Full endpoint documentation with parameters and response schemas.
  </Card>
</CardGroup>


# Market Channel
Source: https://docs.polymarket.com/market-data/websocket/market-channel

Real-time orderbook, price, and trade data

Public channel for market data updates (level 2 price data). Subscribe with asset IDs to receive orderbook snapshots, price changes, trade executions, and market events.

## Endpoint

```
wss://ws-subscriptions-clob.polymarket.com/ws/market
```

## Subscription

```json theme={null}
{
  "assets_ids": ["<token_id_1>", "<token_id_2>"],
  "type": "market",
  "custom_feature_enabled": true
}
```

Set `custom_feature_enabled: true` to receive `best_bid_ask`, `new_market`, and `market_resolved` events.

## Message Types

Each message includes an `event_type` field identifying the type.

### book

Emitted when first subscribed to a market and when there is a trade that affects the book.

```json theme={null}
{
  "event_type": "book",
  "asset_id": "65818619657568813474341868652308942079804919287380422192892211131408793125422",
  "market": "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
  "bids": [
    { "price": ".48", "size": "30" },
    { "price": ".49", "size": "20" },
    { "price": ".50", "size": "15" }
  ],
  "asks": [
    { "price": ".52", "size": "25" },
    { "price": ".53", "size": "60" },
    { "price": ".54", "size": "10" }
  ],
  "timestamp": "123456789000",
  "hash": "0x0...."
}
```

### price\_change

Emitted when a new order is placed or an order is cancelled.

```json theme={null}
{
  "market": "0x5f65177b394277fd294cd75650044e32ba009a95022d88a0c1d565897d72f8f1",
  "price_changes": [
    {
      "asset_id": "71321045679252212594626385532706912750332728571942532289631379312455583992563",
      "price": "0.5",
      "size": "200",
      "side": "BUY",
      "hash": "56621a121a47ed9333273e21c83b660cff37ae50",
      "best_bid": "0.5",
      "best_ask": "1"
    },
    {
      "asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426",
      "price": "0.5",
      "size": "200",
      "side": "SELL",
      "hash": "1895759e4df7a796bf4f1c5a5950b748306923e2",
      "best_bid": "0",
      "best_ask": "0.5"
    }
  ],
  "timestamp": "1757908892351",
  "event_type": "price_change"
}
```

A `size` of `"0"` means the price level has been removed from the book.

### tick\_size\_change

Emitted when the minimum tick size of a market changes. This happens when the book's price reaches the limits: price > 0.96 or price \< 0.04.

```json theme={null}
{
  "event_type": "tick_size_change",
  "asset_id": "65818619657568813474341868652308942079804919287380422192892211131408793125422",
  "market": "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
  "old_tick_size": "0.01",
  "new_tick_size": "0.001",
  "timestamp": "100000000"
}
```

### last\_trade\_price

Emitted when a maker and taker order is matched, creating a trade event.

```json theme={null}
{
  "asset_id": "114122071509644379678018727908709560226618148003371446110114509806601493071694",
  "event_type": "last_trade_price",
  "fee_rate_bps": "0",
  "market": "0x6a67b9d828d53862160e470329ffea5246f338ecfffdf2cab45211ec578b0347",
  "price": "0.456",
  "side": "BUY",
  "size": "219.217767",
  "timestamp": "1750428146322"
}
```

### best\_bid\_ask

<Note>Requires `custom_feature_enabled: true`.</Note>

Emitted when the best bid or ask prices for a market change.

```json theme={null}
{
  "event_type": "best_bid_ask",
  "market": "0x0005c0d312de0be897668695bae9f32b624b4a1ae8b140c49f08447fcc74f442",
  "asset_id": "85354956062430465315924116860125388538595433819574542752031640332592237464430",
  "best_bid": "0.73",
  "best_ask": "0.77",
  "spread": "0.04",
  "timestamp": "1766789469958"
}
```

### new\_market

<Note>Requires `custom_feature_enabled: true`.</Note>

Emitted when a new market is created.

The payload also includes market metadata fields such as `tags`,
`condition_id`, `active`, `clob_token_ids`, `sports_market_type`, `line`,
`game_start_time`, `order_price_min_tick_size`, `group_item_title`,
`taker_base_fee`, `fees_enabled`, and `fee_schedule`.

Where a `FeeSchedule` object is of the form:

| Name         | Type    | Description                       |
| ------------ | ------- | --------------------------------- |
| exponent     | string  | fee curve exponent                |
| rate         | string  | fee rate                          |
| taker\_only  | boolean | whether fee applies to taker only |
| rebate\_rate | string  | maker rebate rate                 |

```json theme={null}
{
  "id": "1031769",
  "question": "Will NVIDIA (NVDA) close above $240 end of January?",
  "market": "0x311d0c4b6671ab54af4970c06fcf58662516f5168997bdda209ec3db5aa6b0c1",
  "slug": "nvda-above-240-on-january-30-2026",
  "description": "This market will resolve to \"Yes\" if the official closing price...",
  "assets_ids": [
    "76043073756653678226373981964075571318267289248134717369284518995922789326425",
    "31690934263385727664202099278545688007799199447969475608906331829650099442770"
  ],
  "outcomes": ["Yes", "No"],
  "event_message": {
    "id": "125819",
    "ticker": "nvda-above-in-january-2026",
    "slug": "nvda-above-in-january-2026",
    "title": "Will NVIDIA (NVDA) close above ___ end of January?",
    "description": "This market will resolve to \"Yes\" if the official closing price..."
  },
  "timestamp": "1766790415550",
  "event_type": "new_market",
  "tags": ["stocks"],
  "condition_id": "0x311d0c4b6671ab54af4970c06fcf58662516f5168997bdda209ec3db5aa6b0c1",
  "active": true,
  "clob_token_ids": [
    "76043073756653678226373981964075571318267289248134717369284518995922789326425",
    "31690934263385727664202099278545688007799199447969475608906331829650099442770"
  ],
  "sports_market_type": "",
  "line": "",
  "game_start_time": "",
  "order_price_min_tick_size": "0.01",
  "group_item_title": "NVDA above $240",
  "taker_base_fee": "0",
  "fees_enabled": true,
  "fee_schedule": {
    "exponent": "2",
    "rate": "0.02",
    "taker_only": true,
    "rebate_rate": "0"
  }
}
```

### market\_resolved

<Note>Requires `custom_feature_enabled: true`.</Note>

Emitted when a market is resolved.

```json theme={null}
{
  "id": "1031769",
  "question": "Will NVIDIA (NVDA) close above $240 end of January?",
  "market": "0x311d0c4b6671ab54af4970c06fcf58662516f5168997bdda209ec3db5aa6b0c1",
  "slug": "nvda-above-240-on-january-30-2026",
  "description": "This market will resolve to \"Yes\" if the official closing price...",
  "assets_ids": [
    "76043073756653678226373981964075571318267289248134717369284518995922789326425",
    "31690934263385727664202099278545688007799199447969475608906331829650099442770"
  ],
  "outcomes": ["Yes", "No"],
  "winning_asset_id": "76043073756653678226373981964075571318267289248134717369284518995922789326425",
  "winning_outcome": "Yes",
  "event_message": {
    "id": "125819",
    "ticker": "nvda-above-in-january-2026",
    "slug": "nvda-above-in-january-2026",
    "title": "Will NVIDIA (NVDA) close above ___ end of January?",
    "description": "This market will resolve to \"Yes\" if the official closing price..."
  },
  "timestamp": "1766790415550",
  "event_type": "market_resolved"
}
```


# Overview
Source: https://docs.polymarket.com/market-data/websocket/overview

Real-time market data and trading updates via WebSocket

Polymarket provides WebSocket channels for near real-time streaming of orderbook data, trades, and personal order activity. There are four available channels: `market`, `user`, `sports`, and `RTDS` (Real-Time Data Socket).

## Channels

| Channel                             | Endpoint                                               | Auth     |
| ----------------------------------- | ------------------------------------------------------ | -------- |
| Market                              | `wss://ws-subscriptions-clob.polymarket.com/ws/market` | No       |
| User                                | `wss://ws-subscriptions-clob.polymarket.com/ws/user`   | Yes      |
| Sports                              | `wss://sports-api.polymarket.com/ws`                   | No       |
| [RTDS](/market-data/websocket/rtds) | `wss://ws-live-data.polymarket.com`                    | Optional |

### Market Channel

| Type               | Description             | Custom Feature |
| ------------------ | ----------------------- | -------------- |
| `book`             | Full orderbook snapshot | No             |
| `price_change`     | Price level updates     | No             |
| `tick_size_change` | Tick size changes       | No             |
| `last_trade_price` | Trade executions        | No             |
| `best_bid_ask`     | Best prices update      | Yes            |
| `new_market`       | New market created      | Yes            |
| `market_resolved`  | Market resolution       | Yes            |

Types marked "Custom Feature" require `custom_feature_enabled: true` in your subscription.

### User Channel

| Type    | Description                                   |
| ------- | --------------------------------------------- |
| `trade` | Trade lifecycle updates (MATCHED → CONFIRMED) |
| `order` | Order placements, updates, and cancellations  |

### Sports

| Type           | Description                           |
| -------------- | ------------------------------------- |
| `sport_result` | Live game scores, periods, and status |

## Subscribing

Send a subscription message after connecting to specify which data you want to receive.

### Market Channel

```json theme={null}
{
  "assets_ids": [
    "21742633143463906290569050155826241533067272736897614950488156847949938836455",
    "48331043336612883890938759509493159234755048973500640148014422747788308965732"
  ],
  "type": "market",
  "custom_feature_enabled": true
}
```

| Field                    | Type      | Description                                                       |
| ------------------------ | --------- | ----------------------------------------------------------------- |
| `assets_ids`             | string\[] | Token IDs to subscribe to                                         |
| `type`                   | string    | Channel identifier                                                |
| `custom_feature_enabled` | boolean   | Enable `best_bid_ask`, `new_market`, and `market_resolved` events |

### User Channel

```json theme={null}
{
  "auth": {
    "apiKey": "your-api-key",
    "secret": "your-api-secret",
    "passphrase": "your-passphrase"
  },
  "markets": ["0x1234...condition_id"],
  "type": "user"
}
```

<Note>
  The `auth` fields (`apiKey`, `secret`, `passphrase`) are **only required for
  the user channel**. For the market channel, these fields are optional and can
  be omitted.
</Note>

| Field     | Type      | Description                                        |
| --------- | --------- | -------------------------------------------------- |
| `auth`    | object    | API credentials (`apiKey`, `secret`, `passphrase`) |
| `markets` | string\[] | Condition IDs to receive events for                |
| `type`    | string    | Channel identifier                                 |

<Note>
  The user channel subscribes by **condition IDs** (market identifiers), not
  asset IDs. Each market has one condition ID but two asset IDs (Yes and No
  tokens).
</Note>

### Sports Channel

No subscription message required. Connect and start receiving data for all active sports events.

## Dynamic Subscription

Modify subscriptions without reconnecting.

### Subscribe to more assets

```json theme={null}
{
  "assets_ids": ["new_asset_id_1", "new_asset_id_2"],
  "operation": "subscribe",
  "custom_feature_enabled": true
}
```

### Unsubscribe from assets

```json theme={null}
{
  "assets_ids": ["asset_id_to_remove"],
  "operation": "unsubscribe"
}
```

For the user channel, use `markets` instead of `assets_ids`:

```json theme={null}
{
  "markets": ["0x1234...condition_id"],
  "operation": "subscribe"
}
```

## Heartbeats

### Market and User Channels

Send `PING` every 10 seconds. The server responds with `PONG`.

```
PING
```

### Sports Channel

The server sends `ping` every 5 seconds. Respond with `pong` within 10 seconds.

```
pong
```

<Warning>
  If you don't respond to the server's ping within 10 seconds, the connection
  will be closed.
</Warning>

## Troubleshooting

<Accordion title="Connection closes immediately after opening">
  Send a valid subscription message immediately after connecting. The server may
  close connections that don't subscribe within a timeout period.
</Accordion>

<Accordion title="Connection drops after about 10 seconds">
  You're not sending heartbeats. Send `PING` every 10 seconds for market/user
  channels, or respond to server `ping` with `pong` for the sports channel.
</Accordion>

<Accordion title="Not receiving any messages">
  1. Verify your asset IDs or condition IDs are correct 2. Check that the
     markets are active (not resolved) 3. Set `custom_feature_enabled: true` if
     expecting `best_bid_ask`, `new_market`, or `market_resolved` events
</Accordion>

<Accordion title="Authentication failed - user channel">
  Verify your API credentials are correct and haven't expired.
</Accordion>


# Real-Time Data Socket
Source: https://docs.polymarket.com/market-data/websocket/rtds

Stream comments, crypto prices, and equity prices via WebSocket

The Polymarket Real-Time Data Socket (RTDS) is a WebSocket-based streaming service that provides real-time updates for **comments**, **crypto prices**, and **equity prices**.

<Card title="TypeScript client" icon="github" href="https://github.com/Polymarket/real-time-data-client">
  Official RTDS TypeScript client (`real-time-data-client`).
</Card>

## Endpoint

```
wss://ws-live-data.polymarket.com
```

Some user-specific streams may require `gamma_auth` with your wallet address.

## Subscribing

Send a JSON message to subscribe to data streams:

```json theme={null}
{
  "action": "subscribe",
  "subscriptions": [
    {
      "topic": "topic_name",
      "type": "message_type",
      "filters": "optional_filter_string",
      "gamma_auth": {
        "address": "wallet_address"
      }
    }
  ]
}
```

To unsubscribe, send the same structure with `"action": "unsubscribe"`.

Subscriptions can be added, removed, and modified without disconnecting. Send `PING` messages every 5 seconds to maintain the connection.

<Note>Only the subscription types documented below are supported.</Note>

## Message Structure

All messages follow this structure:

```json theme={null}
{
  "topic": "string",
  "type": "string",
  "timestamp": "number",
  "payload": "object"
}
```

| Field       | Type   | Description                                                                 |
| ----------- | ------ | --------------------------------------------------------------------------- |
| `topic`     | string | The subscription topic (e.g., `crypto_prices`, `equity_prices`, `comments`) |
| `type`      | string | The message type/event (e.g., `update`, `reaction_created`)                 |
| `timestamp` | number | Unix timestamp in milliseconds when the message was sent                    |
| `payload`   | object | Event-specific data object                                                  |

## Crypto Prices

Real-time cryptocurrency price data from two sources: **Binance** and **Chainlink**. No authentication required.

### Binance Source

Subscribe to all symbols:

```json theme={null}
{
  "action": "subscribe",
  "subscriptions": [
    {
      "topic": "crypto_prices",
      "type": "update"
    }
  ]
}
```

Subscribe to specific symbols with a comma-separated filter:

```json theme={null}
{
  "action": "subscribe",
  "subscriptions": [
    {
      "topic": "crypto_prices",
      "type": "update",
      "filters": "solusdt,btcusdt,ethusdt"
    }
  ]
}
```

Symbols use lowercase concatenated format (e.g., `solusdt`, `btcusdt`).

**Solana price update:**

```json theme={null}
{
  "topic": "crypto_prices",
  "type": "update",
  "timestamp": 1753314064237,
  "payload": {
    "symbol": "solusdt",
    "timestamp": 1753314064213,
    "value": 189.55
  }
}
```

**Bitcoin price update:**

```json theme={null}
{
  "topic": "crypto_prices",
  "type": "update",
  "timestamp": 1753314088421,
  "payload": {
    "symbol": "btcusdt",
    "timestamp": 1753314088395,
    "value": 67234.50
  }
}
```

### Chainlink Source

<Tip>
  **Trading 15m Crypto Markets?** Get a sponsored Chainlink API key with onboarding support from Chainlink. Fill out [this form](https://pm-ds-request.streams.chain.link/).
</Tip>

Subscribe to all symbols:

```json theme={null}
{
  "action": "subscribe",
  "subscriptions": [
    {
      "topic": "crypto_prices_chainlink",
      "type": "*",
      "filters": ""
    }
  ]
}
```

Subscribe to a specific symbol with a JSON filter:

```json theme={null}
{
  "action": "subscribe",
  "subscriptions": [
    {
      "topic": "crypto_prices_chainlink",
      "type": "*",
      "filters": "{\"symbol\":\"eth/usd\"}"
    }
  ]
}
```

Symbols use slash-separated format (e.g., `eth/usd`, `btc/usd`).

**Ethereum price update:**

```json theme={null}
{
  "topic": "crypto_prices_chainlink",
  "type": "update",
  "timestamp": 1753314064237,
  "payload": {
    "symbol": "eth/usd",
    "timestamp": 1753314064213,
    "value": 3456.78
  }
}
```

**Bitcoin price update:**

```json theme={null}
{
  "topic": "crypto_prices_chainlink",
  "type": "update",
  "timestamp": 1753314088421,
  "payload": {
    "symbol": "btc/usd",
    "timestamp": 1753314088395,
    "value": 67234.50
  }
}
```

### Price Payload Fields

| Field       | Type   | Description                                                                                                                                        |
| ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `symbol`    | string | Trading pair symbol. **Binance**: lowercase concatenated (e.g., `solusdt`, `btcusdt`). **Chainlink**: slash-separated (e.g., `eth/usd`, `btc/usd`) |
| `timestamp` | number | When the price was recorded, in Unix milliseconds                                                                                                  |
| `value`     | number | Current price value in the quote currency                                                                                                          |

### Supported Symbols

**Binance Source** — lowercase concatenated format:

* `btcusdt` — Bitcoin to USDT
* `ethusdt` — Ethereum to USDT
* `solusdt` — Solana to USDT
* `xrpusdt` — XRP to USDT

**Chainlink Source** — slash-separated format:

* `btc/usd` — Bitcoin to USD
* `eth/usd` — Ethereum to USD
* `sol/usd` — Solana to USD
* `xrp/usd` — XRP to USD

## Equity Prices

Real-time price data for stocks, ETFs, forex pairs, precious metals, and commodities sourced from **Pyth Network**. No authentication required.

<Tip>
  **Trading Equity Markets?** Get a Pyth Network data feed - first 30 days free, then \$99/month. [Subscribe here](https://buy.stripe.com/cNi8wPeiq76FgQrbsD4ZG09).
</Tip>

All asset classes stream through a single `equity_prices` topic. When you subscribe with a symbol filter, the server sends a historical snapshot (last 2 minutes of data), then continues streaming live updates.

### Subscribe

Subscribe to a specific symbol with a JSON filter:

```json theme={null}
{
  "action": "subscribe",
  "subscriptions": [
    {
      "topic": "equity_prices",
      "type": "update",
      "filters": "{\"symbol\":\"AAPL\"}"
    }
  ]
}
```

Subscribe to multiple symbols across asset classes:

```json theme={null}
{
  "action": "subscribe",
  "subscriptions": [
    { "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"AAPL\"}" },
    { "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"EURUSD\"}" },
    { "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"XAUUSD\"}" },
    { "topic": "equity_prices", "type": "update", "filters": "{\"symbol\":\"WTI\"}" }
  ]
}
```

Use `type: "*"` to receive all message types (live updates and snapshots):

```json theme={null}
{
  "action": "subscribe",
  "subscriptions": [
    {
      "topic": "equity_prices",
      "type": "*",
      "filters": "{\"symbol\":\"GOOGL\"}"
    }
  ]
}
```

Filter values are case-insensitive on subscribe, but the `symbol` field in payloads is always returned lowercase.

<Tip>
  **Need the price-to-beat value?** Pass the market slug to the price-to-beat endpoint:

  `GET https://polymarket.com/api/equity/price-to-beat/{slug}`

  Example: `https://polymarket.com/api/equity/price-to-beat/wti-up-or-down-on-april-7-2026`
</Tip>

### Live Price Update

**Apple stock update:**

```json theme={null}
{
  "topic": "equity_prices",
  "type": "update",
  "timestamp": 1711382400000,
  "payload": {
    "symbol": "aapl",
    "value": 198.45,
    "full_accuracy_value": "198.4523",
    "timestamp": 1711382400000,
    "received_at": 1711382400005
  }
}
```

**Gold price update (market closed):**

```json theme={null}
{
  "topic": "equity_prices",
  "type": "update",
  "timestamp": 1711400000000,
  "payload": {
    "symbol": "xauusd",
    "value": 2175.30,
    "full_accuracy_value": "2175.3012",
    "timestamp": 1711399000000,
    "received_at": 1711400000002,
    "is_carried_forward": true
  }
}
```

### Historical Snapshot

On subscribe, the server delivers a backfill of the last 2 minutes of price data. Use the `type` field to distinguish: `"subscribe"` for the initial snapshot vs `"update"` for live ticks.

```json theme={null}
{
  "topic": "equity_prices",
  "type": "subscribe",
  "timestamp": 1711382400000,
  "payload": {
    "symbol": "aapl",
    "data": [
      { "timestamp": 1711382280000, "value": 198.30 },
      { "timestamp": 1711382281000, "value": 198.32 },
      { "timestamp": 1711382340000, "value": 198.41 }
    ]
  }
}
```

### Equity Price Payload Fields

| Field                 | Type    | Description                                                                                               |
| --------------------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `symbol`              | string  | Lowercase symbol identifier (e.g., `aapl`, `eurusd`, `xauusd`)                                            |
| `value`               | number  | Spot price as a float                                                                                     |
| `full_accuracy_value` | string  | Full-precision price as a string                                                                          |
| `timestamp`           | number  | Price measurement timestamp in Unix milliseconds                                                          |
| `received_at`         | number  | When the system received the price, in Unix milliseconds. Only present when non-zero.                     |
| `is_carried_forward`  | boolean | `true` when the market session is closed and the value is the last known price. Only present when `true`. |

### Supported Symbols

**Stocks:**

| Symbol  | Name           |
| ------- | -------------- |
| `AAPL`  | Apple          |
| `TSLA`  | Tesla          |
| `MSFT`  | Microsoft      |
| `GOOGL` | Alphabet       |
| `AMZN`  | Amazon         |
| `META`  | Meta Platforms |
| `NVDA`  | NVIDIA         |
| `NFLX`  | Netflix        |
| `PLTR`  | Palantir       |
| `OPEN`  | Opendoor       |
| `RKLB`  | Rocket Lab     |
| `ABNB`  | Airbnb         |
| `COIN`  | Coinbase       |
| `HOOD`  | Robinhood      |

**ETFs:**

| Symbol | Name                                 |
| ------ | ------------------------------------ |
| `QQQ`  | Invesco QQQ ETF                      |
| `SPY`  | S\&P 500 ETF                         |
| `EWY`  | iShares MSCI South Korea ETF         |
| `VXX`  | Barclays iPath Series B S\&P 500 VIX |

**Forex:**

| Symbol   | Pair                         |
| -------- | ---------------------------- |
| `EURUSD` | Euro / US Dollar             |
| `GBPUSD` | British Pound / US Dollar    |
| `USDCAD` | US Dollar / Canadian Dollar  |
| `USDJPY` | US Dollar / Japanese Yen     |
| `USDKRW` | US Dollar / South Korean Won |

**Precious Metals:**

| Symbol   | Name   |
| -------- | ------ |
| `XAUUSD` | Gold   |
| `XAGUSD` | Silver |

**Commodities** (rolling front-month futures):

| Symbol | Name            |
| ------ | --------------- |
| `WTI`  | Crude Oil (WTI) |
| `CC`   | Cocoa           |
| `NGD`  | Natural Gas     |

### Market Hours

When a market session is closed, the stream continues with the last known price and `is_carried_forward: true`. This lets you distinguish stale prices from live ticks. Update frequency is sub-second (up to 5 per second per feed) during market hours.

## Comments

Real-time comment events on the Polymarket platform, including new comments, replies, reactions, and removals. May require Gamma authentication for user-specific data.

### Subscribe

```json theme={null}
{
  "action": "subscribe",
  "subscriptions": [
    {
      "topic": "comments",
      "type": "comment_created"
    }
  ]
}
```

### Message Types

| Type               | Description                           |
| ------------------ | ------------------------------------- |
| `comment_created`  | A user creates a new comment or reply |
| `comment_removed`  | A comment is removed or deleted       |
| `reaction_created` | A user adds a reaction to a comment   |
| `reaction_removed` | A reaction is removed from a comment  |

### comment\_created

Emitted when a user posts a new comment or replies to an existing one.

```json theme={null}
{
  "topic": "comments",
  "type": "comment_created",
  "timestamp": 1753454975808,
  "payload": {
    "body": "That's a good point about the definition.",
    "createdAt": "2025-07-25T14:49:35.801298Z",
    "id": "1763355",
    "parentCommentID": "1763325",
    "parentEntityID": 18396,
    "parentEntityType": "Event",
    "profile": {
      "baseAddress": "0xce533188d53a16ed580fd5121dedf166d3482677",
      "displayUsernamePublic": true,
      "name": "salted.caramel",
      "proxyWallet": "0x4ca749dcfa93c87e5ee23e2d21ff4422c7a4c1ee",
      "pseudonym": "Adored-Disparity"
    },
    "reactionCount": 0,
    "replyAddress": "0x0bda5d16f76cd1d3485bcc7a44bc6fa7db004cdd",
    "reportCount": 0,
    "userAddress": "0xce533188d53a16ed580fd5121dedf166d3482677"
  }
}
```

A reply to the above comment — note `parentCommentID` references the parent:

```json theme={null}
{
  "topic": "comments",
  "type": "comment_created",
  "timestamp": 1753454985123,
  "payload": {
    "body": "I agree, the resolution criteria should be clearer.",
    "createdAt": "2025-07-25T14:49:45.120000Z",
    "id": "1763356",
    "parentCommentID": "1763355",
    "parentEntityID": 18396,
    "parentEntityType": "Event",
    "profile": {
      "baseAddress": "0x1234567890abcdef1234567890abcdef12345678",
      "displayUsernamePublic": true,
      "name": "trader",
      "proxyWallet": "0x9876543210fedcba9876543210fedcba98765432",
      "pseudonym": "Bright-Analysis"
    },
    "reactionCount": 0,
    "replyAddress": "0x0bda5d16f76cd1d3485bcc7a44bc6fa7db004cdd",
    "reportCount": 0,
    "userAddress": "0x1234567890abcdef1234567890abcdef12345678"
  }
}
```

### Comment Payload Fields

| Field              | Type   | Description                                                               |
| ------------------ | ------ | ------------------------------------------------------------------------- |
| `body`             | string | The text content of the comment                                           |
| `createdAt`        | string | ISO 8601 timestamp when the comment was created                           |
| `id`               | string | Unique identifier for this comment                                        |
| `parentCommentID`  | string | ID of the parent comment if this is a reply (null for top-level comments) |
| `parentEntityID`   | number | ID of the parent entity (event, market, etc.)                             |
| `parentEntityType` | string | Type of parent entity (`Event`, `Market`)                                 |
| `profile`          | object | Profile information of the comment author                                 |
| `reactionCount`    | number | Current number of reactions on this comment                               |
| `replyAddress`     | string | Polygon address for replies (may differ from userAddress)                 |
| `reportCount`      | number | Current number of reports on this comment                                 |
| `userAddress`      | string | Polygon address of the comment author                                     |

### Profile Object Fields

| Field                   | Type    | Description                                |
| ----------------------- | ------- | ------------------------------------------ |
| `baseAddress`           | string  | User profile address                       |
| `displayUsernamePublic` | boolean | Whether the username is displayed publicly |
| `name`                  | string  | User's display name                        |
| `proxyWallet`           | string  | Proxy wallet address used for transactions |
| `pseudonym`             | string  | Generated pseudonym for the user           |

### Comment Hierarchy

Comments support nested threading:

* **Top-level comments**: `parentCommentID` is null or empty
* **Reply comments**: `parentCommentID` contains the ID of the parent comment
* All comments are associated with a `parentEntityID` and `parentEntityType` (`Event` or `Market`)

## Troubleshooting

<Accordion title="Connection drops unexpectedly">
  Send `PING` messages every 5 seconds to keep the connection alive. Connection errors will trigger automatic reconnection attempts.
</Accordion>

<Accordion title="Not receiving messages after subscribing">
  Verify your subscription message is valid JSON with the correct `action`, `topic`, and `type` fields. Invalid subscription messages may result in connection closure.
</Accordion>

<Accordion title="Authentication failures">
  If subscribing to user-specific streams, ensure your `gamma_auth` object includes a valid wallet `address`. Authentication failures will prevent subscription to protected topics.
</Accordion>


# Sports WebSocket
Source: https://docs.polymarket.com/market-data/websocket/sports

Live sports scores and game state

The Sports WebSocket provides real-time sports results updates, including scores, periods, and game status. No authentication required.

## Endpoint

```
wss://sports-api.polymarket.com/ws
```

No subscription message required — connect and start receiving data for all active sports events.

## Heartbeat

The server sends `ping` every 5 seconds. Respond with `pong` within 10 seconds or the connection will close.

```javascript theme={null}
ws.onmessage = (event) => {
  if (event.data === "ping") {
    ws.send("pong");
    return;
  }

  // Handle JSON messages...
};
```

## Message Type

Each message is a JSON object with game state fields.

### sport\_result

Emitted when:

* A match goes live
* The score changes
* The period changes (e.g., halftime, overtime)
* A match ends
* Possession changes (NFL and CFB only)

**NFL (in progress):**

```json theme={null}
{
  "gameId": 19439,
  "leagueAbbreviation": "nfl",
  "slug": "nfl-lac-buf-2025-01-26",
  "homeTeam": "LAC",
  "awayTeam": "BUF",
  "status": "InProgress",
  "score": "3-16",
  "period": "Q4",
  "elapsed": "5:18",
  "live": true,
  "ended": false,
  "turn": "lac"
}
```

**Esports — CS2 (finished):**

```json theme={null}
{
  "gameId": 1317359,
  "leagueAbbreviation": "cs2",
  "slug": "cs2-arcred-the-glecs-2025-07-20",
  "homeTeam": "ARCRED",
  "awayTeam": "The glecs",
  "status": "finished",
  "score": "000-000|2-0|Bo3",
  "period": "2/3",
  "live": false,
  "ended": true,
  "finished_timestamp": "2025-07-20T18:30:00.000Z"
}
```

The `finished_timestamp` field is an ISO 8601 timestamp only present when `ended: true`.

The `slug` field follows the format `{league}-{team1}-{team2}-{date}` (e.g., `nfl-buf-kc-2025-01-26`).

## Period Values

| Period                 | Description                             |
| ---------------------- | --------------------------------------- |
| `1H`                   | First half                              |
| `2H`                   | Second half                             |
| `1Q`, `2Q`, `3Q`, `4Q` | Quarters (NFL, NBA)                     |
| `HT`                   | Halftime                                |
| `FT`                   | Full time (match ended in regulation)   |
| `FT OT`                | Full time with overtime                 |
| `FT NR`                | Full time, no result (draw or canceled) |
| `End 1`, `End 2`, ...  | End of inning (MLB)                     |
| `1/3`, `2/3`, `3/3`    | Map number in Bo3 series (Esports)      |
| `1/5`, `2/5`, ...      | Map number in Bo5 series (Esports)      |

## Game Status Values

Game status values vary by sport:

### NFL

| Status         | Description                  |
| -------------- | ---------------------------- |
| `Scheduled`    | Game not yet started         |
| `InProgress`   | Game currently playing       |
| `Final`        | Game completed in regulation |
| `F/OT`         | Final after overtime         |
| `Suspended`    | Game suspended               |
| `Postponed`    | Game postponed               |
| `Delayed`      | Game delayed                 |
| `Canceled`     | Game canceled                |
| `Forfeit`      | Game forfeited               |
| `NotNecessary` | Scheduled, but not needed    |

### NHL

| Status         | Description                  |
| -------------- | ---------------------------- |
| `Scheduled`    | Game not yet started         |
| `InProgress`   | Game currently playing       |
| `Final`        | Game completed in regulation |
| `F/OT`         | Final after overtime         |
| `F/SO`         | Final after shootout         |
| `Suspended`    | Game suspended               |
| `Postponed`    | Game postponed               |
| `Delayed`      | Game delayed                 |
| `Canceled`     | Game canceled                |
| `Forfeit`      | Game forfeited               |
| `NotNecessary` | Scheduled, but not needed    |

### MLB

| Status         | Description               |
| -------------- | ------------------------- |
| `Scheduled`    | Game not yet started      |
| `InProgress`   | Game currently playing    |
| `Final`        | Game completed            |
| `Suspended`    | Game suspended            |
| `Delayed`      | Game delayed              |
| `Postponed`    | Game postponed            |
| `Canceled`     | Game canceled             |
| `Forfeit`      | Game forfeited            |
| `NotNecessary` | Scheduled, but not needed |

### NBA and CBB

| Status         | Description               |
| -------------- | ------------------------- |
| `Scheduled`    | Game not yet started      |
| `InProgress`   | Game currently playing    |
| `Final`        | Game completed            |
| `F/OT`         | Final after overtime      |
| `Suspended`    | Game suspended            |
| `Postponed`    | Game postponed            |
| `Delayed`      | Game delayed              |
| `Canceled`     | Game canceled             |
| `Forfeit`      | Game forfeited            |
| `NotNecessary` | Scheduled, but not needed |

### CFB

| Status       | Description            |
| ------------ | ---------------------- |
| `Scheduled`  | Game not yet started   |
| `InProgress` | Game currently playing |
| `Final`      | Game completed         |
| `F/OT`       | Final after overtime   |
| `Suspended`  | Game suspended         |
| `Postponed`  | Game postponed         |
| `Delayed`    | Game delayed           |
| `Canceled`   | Game canceled          |
| `Forfeit`    | Game forfeited         |

### Soccer

| Status            | Description                          |
| ----------------- | ------------------------------------ |
| `Scheduled`       | Game not yet started                 |
| `InProgress`      | Game currently playing               |
| `Break`           | Halftime or other break              |
| `Suspended`       | Game suspended                       |
| `PenaltyShootout` | Penalty shootout in progress         |
| `Final`           | Game completed                       |
| `Awarded`         | Result awarded due to ruling/forfeit |
| `Postponed`       | Game postponed                       |
| `Canceled`        | Game canceled                        |

### Esports

| Status        | Description             |
| ------------- | ----------------------- |
| `not_started` | Match not yet started   |
| `running`     | Match currently playing |
| `finished`    | Match completed         |
| `postponed`   | Match postponed         |
| `canceled`    | Match canceled          |

### Tennis

| Status       | Description             |
| ------------ | ----------------------- |
| `scheduled`  | Match not yet started   |
| `inprogress` | Match currently playing |
| `suspended`  | Match suspended         |
| `finished`   | Match completed         |
| `postponed`  | Match postponed         |
| `cancelled`  | Match canceled          |


# User Channel
Source: https://docs.polymarket.com/market-data/websocket/user-channel

Authenticated order and trade updates

Authenticated channel for updates related to your orders and trades, filtered by API key.

## Endpoint

```
wss://ws-subscriptions-clob.polymarket.com/ws/user
```

## Authentication

Include API credentials in your subscription message:

```json theme={null}
{
  "auth": {
    "apiKey": "your-api-key",
    "secret": "your-api-secret",
    "passphrase": "your-passphrase"
  },
  "markets": ["0x1234...condition_id"],
  "type": "user"
}
```

<Warning>
  Never expose your API credentials in client-side code. Use the user channel
  only from server environments.
</Warning>

## Message Types

Each message includes a `type` field identifying the event.

### trade

Emitted when:

* A market order is matched (`MATCHED`)
* A limit order for the user is included in a trade (`MATCHED`)
* Subsequent status changes for the trade (`MINED`, `CONFIRMED`, `RETRYING`, `FAILED`)

```json theme={null}
{
  "asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426",
  "event_type": "trade",
  "id": "28c4d2eb-bbea-40e7-a9f0-b2fdb56b2c2e",
  "last_update": "1672290701",
  "maker_orders": [
    {
      "asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426",
      "matched_amount": "10",
      "order_id": "0xff354cd7ca7539dfa9c28d90943ab5779a4eac34b9b37a757d7b32bdfb11790b",
      "outcome": "YES",
      "owner": "9180014b-33c8-9240-a14b-bdca11c0a465",
      "price": "0.57"
    }
  ],
  "market": "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
  "matchtime": "1672290701",
  "outcome": "YES",
  "owner": "9180014b-33c8-9240-a14b-bdca11c0a465",
  "price": "0.57",
  "side": "BUY",
  "size": "10",
  "status": "MATCHED",
  "taker_order_id": "0x06bc63e346ed4ceddce9efd6b3af37c8f8f440c92fe7da6b2d0f9e4ccbc50c42",
  "timestamp": "1672290701",
  "trade_owner": "9180014b-33c8-9240-a14b-bdca11c0a465",
  "type": "TRADE"
}
```

#### Trade Statuses

```
MATCHED → MINED → CONFIRMED
    ↓        ↑
RETRYING ───┘
    ↓
  FAILED
```

| Status      | Terminal | Description                                                                                     |
| ----------- | -------- | ----------------------------------------------------------------------------------------------- |
| `MATCHED`   | No       | Trade has been matched and sent to the executor service by the operator                         |
| `MINED`     | No       | Trade observed to be mined into the chain, no finality threshold established                    |
| `CONFIRMED` | Yes      | Trade has achieved strong probabilistic finality and was successful                             |
| `RETRYING`  | No       | Trade transaction has failed (revert or reorg) and is being retried/resubmitted by the operator |
| `FAILED`    | Yes      | Trade has failed and is not being retried                                                       |

### order

Emitted when:

* An order is placed (`PLACEMENT`)
* An order is updated — some of it is matched (`UPDATE`)
* An order is cancelled (`CANCELLATION`)

```json theme={null}
{
  "asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426",
  "associate_trades": null,
  "event_type": "order",
  "id": "0xff354cd7ca7539dfa9c28d90943ab5779a4eac34b9b37a757d7b32bdfb11790b",
  "market": "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
  "order_owner": "9180014b-33c8-9240-a14b-bdca11c0a465",
  "original_size": "10",
  "outcome": "YES",
  "owner": "9180014b-33c8-9240-a14b-bdca11c0a465",
  "price": "0.57",
  "side": "SELL",
  "size_matched": "0",
  "timestamp": "1672290687",
  "type": "PLACEMENT"
}
```


# Getting Started
Source: https://docs.polymarket.com/market-makers/getting-started

One-time setup for market making on Polymarket

Before you can start market making, you need to complete these one-time setup steps — deposit pUSD to Polygon, deploy a wallet, approve tokens for trading, and generate API credentials.

<Steps>
  <Step title="Deposit pUSD">
    Market makers need pUSD on Polygon to fund their trading operations.

    | Method                  | Best For                             | Documentation                                        |
    | ----------------------- | ------------------------------------ | ---------------------------------------------------- |
    | Bridge API              | Automated deposits from other chains | [Bridge Deposit](/trading/bridge/deposit)            |
    | Direct Polygon transfer | Already have pUSD on Polygon         | N/A                                                  |
    | Cross-chain bridge      | Large deposits from Ethereum         | [Supported Assets](/trading/bridge/supported-assets) |

    ### Using the Bridge API

    ```typescript theme={null}
    // Get deposit addresses for your Polymarket wallet
    const deposit = await fetch("https://bridge.polymarket.com/deposit", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        address: "YOUR_POLYMARKET_WALLET_ADDRESS",
      }),
    });

    // Returns deposit addresses for EVM, SVM, and BTC networks
    const addresses = await deposit.json();
    // Send USDC to the appropriate address for your source chain
    ```
  </Step>

  <Step title="Deploy a Wallet">
    ### EOA

    Standard Ethereum wallet. You pay for all onchain transactions (approvals, splits, merges, trade execution).

    ### Deposit Wallet

    Deposit wallets are the recommended wallet path for new API users. They are
    deployed through Polymarket's relayer and use `POLY_1271` order signatures.

    See the [Deposit Wallet Guide](/trading/deposit-wallets) for the
    wallet creation, approval, balance sync, and order-signing flow.

    ### Existing Safe Wallets

    Existing Gnosis Safe users can continue using their current wallet. Safe wallets
    are deployed via Polymarket's relayer and support:

    * **Gasless transactions** — Polymarket pays gas fees for onchain operations
    * **Contract wallet** — Enables advanced features like batched transactions

    For existing Safe integrations, deploy a Safe wallet using the Relayer Client:

    <CodeGroup>
      ```typescript TypeScript theme={null}
      import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client";

      const client = new RelayClient({
        host: "https://relayer-v2.polymarket.com/",
        chain: 137,
        signer,
        relayerApiKey: process.env.RELAYER_API_KEY!,
        relayerApiKeyAddress: process.env.RELAYER_API_KEY_ADDRESS!,
        txType: RelayerTxType.SAFE,
      });

      // Deploy the Safe wallet
      const response = await client.deploy();
      const result = await response.wait();
      console.log("Safe Address:", result?.proxyAddress);
      ```

      ```python Python theme={null}
      from py_builder_relayer_client.client import RelayClient

      # client initialized with Relayer API Key credentials (see Gasless Transactions)

      # Deploy the Safe wallet
      response = client.deploy()
      result = response.wait()
      print("Safe Address:", result.get("proxyAddress"))
      ```
    </CodeGroup>

    <Info>
      See [Gasless Transactions](/trading/gasless) for full Relayer Client setup
      including local and remote signing configurations.
    </Info>
  </Step>

  <Step title="Approve Tokens">
    Before trading, you must approve the exchange contracts to spend your tokens.

    ### Required Approvals

    | Token                | Spender               | Purpose                        |
    | -------------------- | --------------------- | ------------------------------ |
    | pUSD                 | CTF Contract          | Split pUSD into outcome tokens |
    | CTF (outcome tokens) | CTF Exchange          | Trade outcome tokens           |
    | CTF (outcome tokens) | Neg Risk CTF Exchange | Trade neg-risk market tokens   |

    ### Contract Addresses

    ```typescript theme={null}
    const ADDRESSES = {
      pUSD: "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB",
      CTF: "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045",
      CTF_EXCHANGE: "0xE111180000d2663C0091e4f400237545B87B996B",
      NEG_RISK_CTF_EXCHANGE: "0xe2222d279d744050d28e00520010520000310F59",
      NEG_RISK_ADAPTER: "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296",
    };
    ```

    ### Approve via Relayer Client

    <CodeGroup>
      ```typescript TypeScript theme={null}
      import { ethers } from "ethers";
      import { Interface } from "ethers/lib/utils";

      const erc20Interface = new Interface([
        "function approve(address spender, uint256 amount) returns (bool)",
      ]);

      // Approve pUSD for CTF contract
      const approveTx = {
        to: ADDRESSES.pUSD,
        data: erc20Interface.encodeFunctionData("approve", [
          ADDRESSES.CTF,
          ethers.constants.MaxUint256,
        ]),
        value: "0",
      };

      const response = await client.execute([approveTx], "Approve pUSD for CTF");
      await response.wait();
      ```

      ```python Python theme={null}
      from web3 import Web3

      pUSD = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"
      CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
      MAX_UINT256 = 2**256 - 1

      approve_tx = {
          "to": pUSD,
          "data": Web3().eth.contract(
              address=pUSD,
              abi=[{
                  "name": "approve",
                  "type": "function",
                  "inputs": [
                      {"name": "spender", "type": "address"},
                      {"name": "amount", "type": "uint256"}
                  ],
                  "outputs": [{"type": "bool"}]
              }]
          ).encode_abi(abi_element_identifier="approve", args=[CTF, MAX_UINT256]),
          "value": "0"
      }

      response = client.execute([approve_tx], "Approve pUSD for CTF")
      response.wait()
      ```
    </CodeGroup>
  </Step>

  <Step title="Generate API Credentials">
    To place orders and access authenticated endpoints, you need L2 API credentials derived from your wallet.

    <CodeGroup>
      ```typescript TypeScript theme={null}
      import { ClobClient } from "@polymarket/clob-client-v2";

      const client = new ClobClient({
        host: "https://clob.polymarket.com",
        chain: 137,
        signer,
      });

      // Derive API credentials from your wallet
      const credentials = await client.createOrDeriveApiKey();
      console.log("API Key:", credentials.key);
      console.log("Secret:", credentials.secret);
      console.log("Passphrase:", credentials.passphrase);
      ```

      ```python Python theme={null}
      from py_clob_client_v2 import ClobClient
      import os

      private_key = os.getenv("PRIVATE_KEY")

      temp_client = ClobClient("https://clob.polymarket.com", key=private_key, chain_id=137)
      credentials = temp_client.create_or_derive_api_key()
      ```

      ```rust Rust theme={null}
      use std::str::FromStr;
      use polymarket_client_sdk_v2::POLYGON;
      use polymarket_client_sdk_v2::auth::{LocalSigner, Signer};
      use polymarket_client_sdk_v2::clob::{Client, Config};

      let private_key = std::env::var("POLYMARKET_PRIVATE_KEY")?;
      let signer = LocalSigner::from_str(&private_key)?
          .with_chain_id(Some(POLYGON));

      // The Rust SDK derives credentials and initializes in one step
      let client = Client::new("https://clob.polymarket.com", Config::default())?
          .authentication_builder(&signer)
          .authenticate()
          .await?;
      ```
    </CodeGroup>

    See [Authentication](/trading/overview#authentication) for full details on signature types and REST API headers.
  </Step>
</Steps>

***

## Next Steps

<CardGroup>
  <Card title="Trading" icon="chart-line" href="/market-makers/trading">
    Post limit orders and manage quotes
  </Card>

  <Card title="Market Data" icon="database" href="/market-data/overview">
    Connect to real-time market data
  </Card>
</CardGroup>


# Inventory Management
Source: https://docs.polymarket.com/market-makers/inventory

Managing outcome token inventory for market making

Market makers need outcome tokens on both sides to quote a market. The three core inventory operations are **splitting** pUSD into YES/NO token pairs, **merging** pairs back into pUSD, and **redeeming** winning tokens after resolution — all executed gaslessly through the Relayer Client.

<Info>
  For a full breakdown of how the Conditional Token Framework works, see [CTF
  Overview](/trading/ctf/overview). This page focuses on the MM workflow using
  the Relayer Client.
</Info>

***

## Splitting pUSD into Tokens

Split converts pUSD into equal amounts of YES and NO tokens — creating the inventory you need to quote both sides of a market.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { ethers } from "ethers";
  import { Interface } from "ethers/lib/utils";
  import { RelayClient, Transaction } from "@polymarket/builder-relayer-client";

  const CTF_ADDRESS = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045";
  const pUSD_ADDRESS = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB";

  const ctfInterface = new Interface([
    "function splitPosition(address collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint[] partition, uint amount)",
  ]);

  // Split $1000 pUSD into YES/NO tokens
  const amount = ethers.utils.parseUnits("1000", 6); // pUSD has 6 decimals

  const splitTx: Transaction = {
    to: CTF_ADDRESS,
    data: ctfInterface.encodeFunctionData("splitPosition", [
      pUSD_ADDRESS, // collateralToken
      ethers.constants.HashZero, // parentCollectionId (always zero for Polymarket)
      conditionId, // conditionId from market
      [1, 2], // partition: [YES, NO]
      amount,
    ]),
    value: "0",
  };

  const response = await client.execute([splitTx], "Split pUSD into tokens");
  const result = await response.wait();
  console.log("Split completed:", result?.transactionHash);
  ```

  ```python Python theme={null}
  from web3 import Web3

  CTF_ADDRESS = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
  pUSD_ADDRESS = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"

  ctf_abi = [{
      "name": "splitPosition",
      "type": "function",
      "inputs": [
          {"name": "collateralToken", "type": "address"},
          {"name": "parentCollectionId", "type": "bytes32"},
          {"name": "conditionId", "type": "bytes32"},
          {"name": "partition", "type": "uint256[]"},
          {"name": "amount", "type": "uint256"}
      ],
      "outputs": []
  }]

  # Split $1000 pUSD into YES/NO tokens
  amount = 1000 * 10**6  # pUSD has 6 decimals

  split_tx = {
      "to": CTF_ADDRESS,
      "data": Web3().eth.contract(
          address=CTF_ADDRESS, abi=ctf_abi
      ).encode_abi(
          abi_element_identifier="splitPosition",
          args=[
              pUSD_ADDRESS,
              bytes(32),          # parentCollectionId (always zero)
              condition_id,       # conditionId from market
              [1, 2],             # partition: [YES, NO]
              amount,
          ]
      ),
      "value": "0"
  }

  response = client.execute([split_tx], "Split pUSD into tokens")
  response.wait()
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::ctf::Client as CtfClient;
  use polymarket_client_sdk_v2::ctf::types::SplitPositionRequest;
  use polymarket_client_sdk_v2::types::{U256, address};

  let ctf_client = CtfClient::new(provider, 137)?;

  // Split $1000 pUSD into YES/NO tokens
  let request = SplitPositionRequest::builder()
      .collateral_token(address!("0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"))
      .condition_id(condition_id)
      .partition(vec![U256::from(1), U256::from(2)])
      .amount(U256::from(1000_000_000u64)) // 1000 pUSD (6 decimals)
      .build();
  let result = ctf_client.split_position(&request).await?;
  println!("Split tx: {:?}", result.transaction_hash);
  ```
</CodeGroup>

After splitting 1000 pUSD, you receive 1000 YES tokens and 1000 NO tokens. Your pUSD balance decreases by 1000.

***

## Merging Tokens to pUSD

Merge converts equal amounts of YES and NO tokens back into pUSD — useful for reducing exposure, exiting a market, or freeing up capital.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const ctfInterface = new Interface([
    "function mergePositions(address collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint[] partition, uint amount)",
  ]);

  // Merge 500 YES + 500 NO back to 500 pUSD
  const amount = ethers.utils.parseUnits("500", 6);

  const mergeTx: Transaction = {
    to: CTF_ADDRESS,
    data: ctfInterface.encodeFunctionData("mergePositions", [
      pUSD_ADDRESS,
      ethers.constants.HashZero,
      conditionId,
      [1, 2],
      amount,
    ]),
    value: "0",
  };

  const response = await client.execute([mergeTx], "Merge tokens to pUSD");
  await response.wait();
  ```

  ```python Python theme={null}
  merge_abi = [{
      "name": "mergePositions",
      "type": "function",
      "inputs": [
          {"name": "collateralToken", "type": "address"},
          {"name": "parentCollectionId", "type": "bytes32"},
          {"name": "conditionId", "type": "bytes32"},
          {"name": "partition", "type": "uint256[]"},
          {"name": "amount", "type": "uint256"}
      ],
      "outputs": []
  }]

  # Merge 500 YES + 500 NO back to 500 pUSD
  amount = 500 * 10**6

  merge_tx = {
      "to": CTF_ADDRESS,
      "data": Web3().eth.contract(
          address=CTF_ADDRESS, abi=merge_abi
      ).encode_abi(
          abi_element_identifier="mergePositions",
          args=[pUSD_ADDRESS, bytes(32), condition_id, [1, 2], amount]
      ),
      "value": "0"
  }

  response = client.execute([merge_tx], "Merge tokens to pUSD")
  response.wait()
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::ctf::types::MergePositionsRequest;

  // Merge 500 YES + 500 NO back to 500 pUSD
  let request = MergePositionsRequest::builder()
      .collateral_token(address!("0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"))
      .condition_id(condition_id)
      .partition(vec![U256::from(1), U256::from(2)])
      .amount(U256::from(500_000_000u64)) // 500 pUSD (6 decimals)
      .build();
  let result = ctf_client.merge_positions(&request).await?;
  ```
</CodeGroup>

After merging 500 of each, your YES and NO balances decrease by 500 and your pUSD balance increases by 500.

***

## Redeeming After Resolution

Once a market resolves, redeem winning tokens for pUSD. Each winning token is worth $1 — losing tokens redeem for $0.

### Check Resolution Status

<CodeGroup>
  ```typescript TypeScript theme={null}
  const market = await clobClient.getMarket(conditionId);
  if (market.closed) {
    const winningToken = market.tokens.find((t) => t.winner);
    console.log("Winning outcome:", winningToken?.outcome);
  }
  ```

  ```python Python theme={null}
  market = clob_client.get_market(condition_id)
  if market.get("closed"):
      winning = next(t for t in market["tokens"] if t.get("winner"))
      print("Winning outcome:", winning["outcome"])
  ```

  ```rust Rust theme={null}
  let market = clob_client.market(condition_id).await?;
  if market.closed {
      if let Some(winner) = market.tokens.iter().find(|t| t.winner) {
          println!("Winning outcome: {}", winner.outcome);
      }
  }
  ```
</CodeGroup>

### Redeem Winning Tokens

<CodeGroup>
  ```typescript TypeScript theme={null}
  const ctfInterface = new Interface([
    "function redeemPositions(address collateralToken, bytes32 parentCollectionId, bytes32 conditionId, uint[] indexSets)",
  ]);

  const redeemTx: Transaction = {
    to: CTF_ADDRESS,
    data: ctfInterface.encodeFunctionData("redeemPositions", [
      pUSD_ADDRESS,
      ethers.constants.HashZero,
      conditionId,
      [1, 2], // Redeem both YES and NO (only winners pay out)
    ]),
    value: "0",
  };

  const response = await client.execute([redeemTx], "Redeem winning tokens");
  await response.wait();
  ```

  ```python Python theme={null}
  redeem_abi = [{
      "name": "redeemPositions",
      "type": "function",
      "inputs": [
          {"name": "collateralToken", "type": "address"},
          {"name": "parentCollectionId", "type": "bytes32"},
          {"name": "conditionId", "type": "bytes32"},
          {"name": "indexSets", "type": "uint256[]"}
      ],
      "outputs": []
  }]

  redeem_tx = {
      "to": CTF_ADDRESS,
      "data": Web3().eth.contract(
          address=CTF_ADDRESS, abi=redeem_abi
      ).encode_abi(
          abi_element_identifier="redeemPositions",
          args=[pUSD_ADDRESS, bytes(32), condition_id, [1, 2]]
      ),
      "value": "0"
  }

  response = client.execute([redeem_tx], "Redeem winning tokens")
  response.wait()
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::ctf::types::RedeemPositionsRequest;

  let request = RedeemPositionsRequest::builder()
      .collateral_token(address!("0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"))
      .condition_id(condition_id)
      .index_sets(vec![U256::from(1), U256::from(2)]) // Redeem both (only winners pay)
      .build();
  let result = ctf_client.redeem_positions(&request).await?;
  ```
</CodeGroup>

***

## Negative Risk Markets

Multi-outcome markets use the Neg Risk CTF Exchange and Neg Risk Adapter. Split and merge work the same way, but use different contract addresses:

```typescript theme={null}
const NEG_RISK_CTF_EXCHANGE = "0xe2222d279d744050d28e00520010520000310F59";
const NEG_RISK_ADAPTER = "0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296";
```

See [Negative Risk Markets](/advanced/neg-risk) for details on how multi-outcome token mechanics differ.

***

## Inventory Strategies

### Before Quoting

1. Check market metadata via the [Gamma API](/market-data/fetching-markets)
2. Split sufficient pUSD to cover your expected quoting size
3. Set token approvals if not already done (see [Getting Started](/market-makers/getting-started))

### During Trading

* **Skew quotes** when inventory becomes imbalanced on one side
* **Merge excess tokens** to free up capital for other markets
* **Split more** when inventory on either side runs low

### After Resolution

1. Cancel all open orders in the market
2. Wait for resolution to complete
3. Redeem winning tokens
4. Merge any remaining YES/NO pairs

***

## Batch Operations

Execute multiple inventory operations in a single relayer call for efficiency:

```typescript theme={null}
const transactions: Transaction[] = [
  // Split on Market A
  {
    to: CTF_ADDRESS,
    data: ctfInterface.encodeFunctionData("splitPosition", [
      pUSD_ADDRESS,
      ethers.constants.HashZero,
      conditionIdA,
      [1, 2],
      ethers.utils.parseUnits("1000", 6),
    ]),
    value: "0",
  },
  // Split on Market B
  {
    to: CTF_ADDRESS,
    data: ctfInterface.encodeFunctionData("splitPosition", [
      pUSD_ADDRESS,
      ethers.constants.HashZero,
      conditionIdB,
      [1, 2],
      ethers.utils.parseUnits("1000", 6),
    ]),
    value: "0",
  },
];

const response = await client.execute(transactions, "Batch inventory setup");
await response.wait();
```

***

## Next Steps

<CardGroup>
  <Card title="CTF Overview" icon="coins" href="/trading/ctf/overview">
    How the Conditional Token Framework works under the hood
  </Card>

  <Card title="Split Tokens" icon="scissors" href="/trading/ctf/split">
    Detailed split function parameters and prerequisites
  </Card>

  <Card title="Merge Tokens" icon="merge" href="/trading/ctf/merge">
    Detailed merge function parameters
  </Card>

  <Card title="Gasless Transactions" icon="gas-pump" href="/trading/gasless">
    Relayer Client setup and configuration
  </Card>
</CardGroup>


# Liquidity Rewards
Source: https://docs.polymarket.com/market-makers/liquidity-rewards

Earn rewards for providing liquidity on Polymarket

By posting resting limit orders, liquidity providers (makers) are automatically eligible for Polymarket's incentive program. Rewards are distributed directly to maker addresses daily at midnight UTC.

The program is designed to:

* Catalyze liquidity across all markets
* Encourage liquidity throughout a market's entire lifecycle
* Motivate passive, balanced quoting tight to a market's midpoint
* Encourage trading activity
* Discourage blatantly exploitative behaviors

<Info>
  This program is heavily inspired by [dYdX's liquidity provider
  rewards](https://www.dydx.foundation/blog/liquidity-provider-rewards). The
  methodology is essentially a copy of dYdX's approach with adjustments for
  binary contract markets — distinct books, no staking mechanic, a modified
  order utility-relative depth function, and reward amounts isolated per market.
</Info>

***

<Note>
  The minimum reward payout is **\$1**; amounts below this will not be paid.
</Note>

<Tip>
  Both `min_incentive_size` and `max_incentive_spread` can be fetched alongside
  full market objects via the CLOB API and [Markets
  API](/market-data/fetching-markets). Reward allocations for an epoch can also
  be fetched via the Markets API.
</Tip>

***

## Methodology

Liquidity providers are rewarded based on a formula that rewards participation in markets, boosts two-sided depth (single-sided orders still score), and tighter spread vs the size-cutoff-adjusted midpoint. Each market configures a max spread and min size cutoff within which orders are considered. The average of rewards earned is determined by the relative share of each participant's Q<sub>n</sub> in market m.

### Variables

| Variable       | Description                                                      |
| -------------- | ---------------------------------------------------------------- |
| S              | Order position scoring function                                  |
| v              | Max spread from midpoint (in cents)                              |
| s              | Spread from size-cutoff-adjusted midpoint                        |
| b              | In-game multiplier                                               |
| m              | Market                                                           |
| m'             | Market complement (i.e. NO if m = YES)                           |
| n              | Trader index                                                     |
| u              | Sample index                                                     |
| c              | Scaling factor (currently 3.0 on all markets)                    |
| Q<sub>ne</sub> | Point total for book one for a sample                            |
| Q<sub>no</sub> | Point total for book two for a sample                            |
| Spread%        | Distance from midpoint (bps or relative) for order n in market m |
| BidSize        | Share-denominated quantity of bid                                |
| AskSize        | Share-denominated quantity of ask                                |

***

## Equations

### 1. Order Scoring Function

Quadratic scoring rule for an order based on position between the adjusted midpoint and the minimum qualifying spread:

$S(v,s)= (\frac{v-s}{v})^2 \cdot b$

### 2. First Market Side Score

$Q_{one}= S(v,Spread_{m_1}) \cdot BidSize_{m_1} + S(v,Spread_{m_2}) \cdot BidSize_{m_2} + \dots $
$ + S(v, Spread_{m^\prime_1}) \cdot AskSize_{m^\prime_1} + S(v, Spread_{m^\prime_2}) \cdot AskSize_{m^\prime_2}$

### 3. Second Market Side Score

$Q_{two}= S(v,Spread_{m_1}) \cdot AskSize_{m_1} + S(v,Spread_{m_2}) \cdot AskSize_{m_2} + \dots $
$ + S(v, Spread_{m^\prime_1}) \cdot BidSize_{m^\prime_1} + S(v, Spread_{m^\prime_2}) \cdot BidSize_{m^\prime_2}$

### 4. Minimum Score

Boosts two-sided liquidity by taking the minimum of Q<sub>ne</sub> and Q<sub>no</sub>, while still rewarding single-sided liquidity at a reduced rate (divided by c).

**If midpoint is in range \[0.10, 0.90]** — single-sided liquidity can score:

$Q_{\min} = \max(\min({Q_{one}, Q_{two}}), \max(Q_{one}/c, Q_{two}/c))$

**If midpoint is in range \[0, 0.10) or (0.90, 1.0]** — liquidity must be double-sided to score:

$Q_{\min} = \min({Q_{one}, Q_{two}})$

### 5. Normalized Score

Q<sub>min</sub> of a market maker divided by the sum of all Q<sub>min</sub> across market makers in a given sample:

$Q_{normal} = \frac{Q_{min}}{\sum_{n=1}^{N}{(Q_{min})_n}}$

### 6. Epoch Score

Sum of all Q<sub>normal</sub> for a trader across all samples in an epoch:

$Q_{epoch} = \sum_{u=1}^{10,080}{(Q_{normal})_u}$

### 7. Final Score

Normalizes Q<sub>epoch</sub> by dividing by the sum of all market makers' Q<sub>epoch</sub> in a given epoch. This value is multiplied by the rewards available for the market to get a trader's reward:

$Q_{final}=\frac{Q_{epoch}}{\sum_{n=1}^{N}{(Q_{epoch})_n}}$

***

## Worked Example

Assume an adjusted market midpoint of 0.50 and a max spread config of 3 cents for both m and m'.

### Step 2 - First Side Score

A trader has the following open orders:

* 100Q bid on m @ 0.49 (spread = 1 cent)
* 200Q bid on m @ 0.48 (spread = 2 cents)
* 100Q ask on m' @ 0.51 (spread = 1 cent)

$$
Q_{ne} = \left( \frac{(3-1)}{3} \right)^2 \cdot 100 + \left( \frac{(3-2)}{3} \right)^2 \cdot 200 + \left( \frac{(3-1)}{3} \right)^2 \cdot 100
$$

Q<sub>ne</sub> is calculated every minute using random sampling.

### Step 3 - Second Side Score

The same trader also has:

* 100Q bid on m @ 0.485 (spread = 1.5 cents)
* 100Q bid on m' @ 0.48 (spread = 2 cents)
* 200Q ask on m' @ 0.505 (spread = 0.5 cents)

$$
Q_{no} = \left( \frac{(3-1.5)}{3} \right)^2 \cdot 100 + \left( \frac{(3-2)}{3} \right)^2 \cdot 100 + \left( \frac{(3-.5)}{3} \right)^2 \cdot 200
$$

Q<sub>no</sub> is calculated every minute using random sampling.

### Steps 4-7

4. Take the minimum of Q<sub>ne</sub> and Q<sub>no</sub> (with single-sided adjustment if midpoint is in \[0.10, 0.90])
5. Normalize against all other market makers in the sample
6. Sum across all 10,080 samples in the epoch
7. Normalize again to get final reward share

***

## April 2026 — Liquidity Incentive Program

Polymarket is distributing over **\$5M** in liquidity incentives for April 2026 across sports and esports markets. The reward pool is split into **Pre** (pre-game) and **Live** (in-play) periods per game. Rewards are distributed pro-rata across all eligible markets within each game.

<Note>
  This covers April 2026 sports markets. Additional categories will be added soon.
</Note>

### Soccer — Top 5 Leagues + UEFA

Every game in these leagues has liquidity rewards split across pre-game and live periods.

| League                  | Pre \$/Game | Live \$/Game | Total \$/Game |
| ----------------------- | ----------- | ------------ | ------------- |
| English Premier League  | \$2,800     | \$7,200      | \$10,000      |
| La Liga                 | \$900       | \$2,400      | \$3,300       |
| Serie A                 | \$900       | \$2,400      | \$3,300       |
| Bundesliga              | \$850       | \$2,150      | \$3,000       |
| Ligue 1                 | \$600       | \$1,500      | \$2,100       |
| Champions League (QFs)  | \$6,750     | \$17,250     | \$24,000      |
| Europa League (QFs)     | \$1,350     | \$3,400      | \$4,750       |
| Conference League (QFs) | \$400       | \$1,100      | \$1,500       |

### Soccer — Americas

| League                     | Pre \$/Game | Live \$/Game | Total \$/Game |
| -------------------------- | ----------- | ------------ | ------------- |
| MLS                        | \$450       | \$1,200      | \$1,650       |
| Liga MX                    | \$450       | \$1,200      | \$1,650       |
| Copa Libertadores (Groups) | \$750       | \$1,900      | \$2,650       |
| Copa Sudamericana (Groups) | \$225       | \$575        | \$800         |
| Argentine Primera Division | \$150       | \$400        | \$550         |
| Brasileirao Serie A        | \$150       | \$400        | \$550         |
| Colombian Primera A        | \$100       | \$200        | \$300         |
| Chilean Primera Division   | \$75        | \$175        | \$250         |
| Peruvian Primera Division  | \$75        | \$175        | \$250         |
| Bolivian Primera           | \$25        | \$50         | \$75          |
| Brasileirao Serie B        | \$25        | \$50         | \$75          |

### Soccer — Other Europe

| League                   | Pre \$/Game | Live \$/Game | Total \$/Game |
| ------------------------ | ----------- | ------------ | ------------- |
| Turkish Super Lig        | \$550       | \$1,450      | \$2,000       |
| Eredivisie               | \$250       | \$650        | \$900         |
| Liga Portugal            | \$200       | \$550        | \$750         |
| EFL Championship         | \$150       | \$350        | \$500         |
| Russian Premier League   | \$100       | \$275        | \$375         |
| Danish Superliga         | \$75        | \$150        | \$225         |
| Czech First League       | \$25        | \$75         | \$100         |
| Romanian Liga I          | \$25        | \$75         | \$100         |
| Ukrainian Premier League | \$25        | \$75         | \$100         |

### Soccer — Asia / Middle East / Africa

| League                  | Pre \$/Game | Live \$/Game | Total \$/Game |
| ----------------------- | ----------- | ------------ | ------------- |
| Saudi Pro League        | \$450       | \$1,200      | \$1,650       |
| J1 League (Japan)       | \$300       | \$800        | \$1,100       |
| K League 1 (Korea)      | \$200       | \$550        | \$750         |
| Chinese Super League    | \$100       | \$250        | \$350         |
| A-League (Australia)    | \$100       | \$250        | \$350         |
| Indian Super League     | \$75        | \$175        | \$250         |
| J2 League (Japan)       | \$25        | \$75         | \$100         |
| Egyptian Premier League | \$25        | \$75         | \$100         |
| Moroccan League         | \$25        | \$75         | \$100         |
| Norwegian Eliteserien   | \$25        | \$75         | \$100         |

### Soccer — Domestic Cups

| League                        | Pre \$/Game | Live \$/Game | Total \$/Game |
| ----------------------------- | ----------- | ------------ | ------------- |
| FA Cup (Semi-Finals)          | \$850       | \$2,000      | \$2,850       |
| DFB-Pokal (Semi-Finals)       | \$450       | \$950        | \$1,400       |
| Coppa Italia (Semi-Finals)    | \$450       | \$950        | \$1,400       |
| Coupe de France (Semi-Finals) | \$275       | \$675        | \$950         |

### Esports — CS2

| Tier                                | Pre \$/Game | Live \$/Game | Total \$/Game |
| ----------------------------------- | ----------- | ------------ | ------------- |
| A Tier (ESL Pro League, BLAST)      | \$1,550     | \$3,950      | \$5,500       |
| B Tier (RMRs, Large Regional)       | \$1,550     | \$3,950      | \$5,500       |
| C Tier (Small Regional, Qualifiers) | \$150       | \$350        | \$500         |

### Esports — League of Legends

| Tier                            | Pre \$/Game | Live \$/Game | Total \$/Game |
| ------------------------------- | ----------- | ------------ | ------------- |
| A Tier (LCK, LPL, LEC Playoffs) | \$1,550     | \$3,950      | \$5,500       |
| B Tier (LCS, Other Regional)    | \$1,550     | \$3,950      | \$5,500       |
| C Tier (ERLs, National Leagues) | \$150       | \$350        | \$500         |

### Esports — Dota 2

| Tier                       | Pre \$/Game | Live \$/Game | Total \$/Game |
| -------------------------- | ----------- | ------------ | ------------- |
| A/B Tier (DPC, Qualifiers) | \$1,000     | \$2,500      | \$3,500       |
| C Tier (Regional)          | \$150       | \$350        | \$500         |

### Esports — Valorant

| Tier                  | Pre \$/Game | Live \$/Game | Total \$/Game |
| --------------------- | ----------- | ------------ | ------------- |
| A/B Tier (VCT Stages) | \$1,000     | \$2,500      | \$3,500       |
| C Tier (Regional)     | \$150       | \$350        | \$500         |

### Esports — Other Titles

| Game                      | Pre \$/Game | Live \$/Game | Total \$/Game |
| ------------------------- | ----------- | ------------ | ------------- |
| Call of Duty (CDL)        | \$50        | \$100        | \$150         |
| Rocket League (RLCS)      | \$50        | \$100        | \$150         |
| Mobile Legends: Bang Bang | \$50        | \$100        | \$150         |
| Honor of Kings            | \$50        | \$100        | \$150         |

### Basketball

| League                                | Pre \$/Game | Live \$/Game | Total \$/Game |
| ------------------------------------- | ----------- | ------------ | ------------- |
| NBA (Reg Season + Play-In + Playoffs) | \$2,150     | \$5,550      | \$7,700       |
| EuroLeague (Playoffs)                 | \$150       | \$350        | \$500         |
| ACB Spain                             | \$75        | \$200        | \$275         |
| Lega Basket Serie A (Italy)           | \$75        | \$200        | \$275         |
| Basketball Champions League           | \$75        | \$200        | \$275         |
| CBA (China)                           | \$50        | \$150        | \$200         |
| LNB Pro A (France)                    | \$50        | \$150        | \$200         |
| KBL (Korea)                           | \$25        | \$50         | \$75          |
| NBL (Australia)                       | \$25        | \$50         | \$75          |
| B.League (Japan)                      | \$25        | \$50         | \$75          |
| BBL (Germany)                         | \$25        | \$50         | \$75          |
| ABA League                            | \$25        | \$50         | \$75          |
| BSL (Turkey)                          | \$25        | \$50         | \$75          |
| Greek A1                              | \$25        | \$50         | \$75          |
| LNB Argentina                         | \$0         | \$25         | \$25          |
| VTB United League                     | \$0         | \$25         | \$25          |

### Baseball

| League      | Pre \$/Game | Live \$/Game | Total \$/Game |
| ----------- | ----------- | ------------ | ------------- |
| MLB         | \$465       | \$1,185      | \$1,650       |
| KBO (Korea) | \$75        | \$225        | \$300         |

### Hockey

| League                      | Pre \$/Game | Live \$/Game | Total \$/Game |
| --------------------------- | ----------- | ------------ | ------------- |
| NHL (Reg Season + Playoffs) | \$400       | \$1,100      | \$1,500       |
| KHL (Playoffs)              | \$75        | \$200        | \$275         |
| SHL (Playoffs)              | \$25        | \$150        | \$175         |
| AHL                         | \$0         | \$25         | \$25          |
| Czech Extraliga (Playoffs)  | \$0         | \$25         | \$25          |
| DEL Germany (Playoffs)      | \$0         | \$25         | \$25          |

### Tennis

| Tour     | Pre \$/Game | Live \$/Game | Total \$/Game |
| -------- | ----------- | ------------ | ------------- |
| ATP Tour | \$450       | \$1,000      | \$1,450       |
| WTA Tour | \$300       | \$750        | \$1,050       |

### UFC / MMA

| Event Type    | Pre \$/Game | Live \$/Game | Total \$/Game |
| ------------- | ----------- | ------------ | ------------- |
| UFC Main Card | \$1,200     | \$3,050      | \$4,250       |
| UFC Prelims   | \$250       | \$700        | \$950         |

### Cricket

| League                       | Pre \$/Game | Live \$/Game | Total \$/Game |
| ---------------------------- | ----------- | ------------ | ------------- |
| IPL (Indian Premier League)  | \$1,250     | \$3,250      | \$4,500       |
| ICC ODI Internationals       | \$0         | \$50         | \$50          |
| ICC T20 Internationals       | \$0         | \$50         | \$50          |
| Other Cricket Internationals | \$0         | \$25         | \$25          |
| Test Cricket                 | \$0         | \$25         | \$25          |

### Rugby

| League                       | Pre \$/Game | Live \$/Game | Total \$/Game |
| ---------------------------- | ----------- | ------------ | ------------- |
| Top 14 (France)              | \$75        | \$175        | \$250         |
| Premiership Rugby (England)  | \$75        | \$175        | \$250         |
| Super Rugby Pacific          | \$75        | \$175        | \$250         |
| United Rugby Championship    | \$50        | \$125        | \$175         |
| European Champions Cup (QFs) | \$100       | \$300        | \$400         |

### Other

| Event            | Pre \$/Game | Live \$/Game | Total \$/Game |
| ---------------- | ----------- | ------------ | ------------- |
| WTT Table Tennis | \$0         | \$25         | \$25          |
| Chess            | \$25        | \$75         | \$100         |
| PLL Lacrosse     | \$25        | \$75         | \$100         |

***

## Next Steps

<CardGroup>
  <Card title="Trading" icon="chart-line" href="/market-makers/trading">
    Order entry and quoting best practices
  </Card>

  <Card title="Maker Rebates" icon="receipt" href="/market-makers/maker-rebates">
    Earn USDC rebates on eligible crypto and sports markets
  </Card>
</CardGroup>


# Maker Rebates Program
Source: https://docs.polymarket.com/market-makers/maker-rebates

Earn daily USDC rebates by providing liquidity on Polymarket

Polymarket charges taker fees across multiple market categories. Fees are determined by the protocol at match time and fund a **Maker Rebates** program that pays daily USDC rebates to liquidity providers.

***

## Why Maker Rebates

Deeper liquidity means tighter spreads, lower price impact, more reliable fills, and greater resilience during volatility. Maker Rebates incentivize **consistent, competitive quoting** so everyone gets a better trading experience.

***

## How Maker Rebates Work

* **Paid daily in USDC:** Rebates are calculated and distributed every day.
* **Performance-based:** You earn based on the share of liquidity you provided that actually got taken.

### Eligibility

Place orders that add liquidity to the book and get filled (i.e., your liquidity is taken by another trader).

### Payment

Rebates are paid daily in USDC, directly to your wallet. A minimum accrued rebate of **\$1 USDC** is required for a payout.

***

## Funding

Maker Rebates are funded by taker fees collected in eligible markets. A percentage of these fees are redistributed to makers who keep the markets liquid. The rebate percentage differs by market type.

| Category        | Maker Rebate | Distribution Method |
| --------------- | ------------ | ------------------- |
| Crypto          | 20%          | Fee-curve weighted  |
| Sports          | 25%          | Fee-curve weighted  |
| Finance         | 25%          | Fee-curve weighted  |
| Politics        | 25%          | Fee-curve weighted  |
| Economics       | 25%          | Fee-curve weighted  |
| Culture         | 25%          | Fee-curve weighted  |
| Weather         | 25%          | Fee-curve weighted  |
| Other / General | 25%          | Fee-curve weighted  |
| Mentions        | 25%          | Fee-curve weighted  |
| Tech            | 25%          | Fee-curve weighted  |
| Geopolitics     | —            | Fee-free            |

<Note>
  Polymarket collects taker fees in eligible markets across all fee-enabled categories.
  The rebate percentage is at the sole discretion of Polymarket
  and may change over time.
</Note>

***

## Fee-Curve Weighted Rebates

Rebates are distributed using the **same formula as taker fees**. This ensures makers are rewarded proportionally to the fee value their liquidity generates.

For each filled maker order:

```text theme={null}
fee_equivalent = C × feeRate × p × (1 - p)
```

Where **C** = number of shares traded and **p** = price of the shares. The fee parameters differ by market type:

| Category        | Taker Fee Rate | Maker Fee Rate |
| --------------- | -------------- | -------------- |
| Crypto          | 0.07           | 0              |
| Sports          | 0.03           | 0              |
| Finance         | 0.04           | 0              |
| Politics        | 0.04           | 0              |
| Economics       | 0.05           | 0              |
| Culture         | 0.05           | 0              |
| Weather         | 0.05           | 0              |
| Other / General | 0.05           | 0              |
| Mentions        | 0.04           | 0              |
| Tech            | 0.04           | 0              |
| Geopolitics     | 0              | 0              |

Your daily rebate:

```text theme={null}
rebate = (your_fee_equivalent / total_fee_equivalent) * rebate_pool
```

Totals are calculated per market, so you only compete with other makers in the same market.

***

## Taker Fee Structure

Taker fees are calculated in USDC and vary based on the share price. The fee amount in USDC is symmetric around 50% probability — a trade at 30¢ incurs the same dollar fee as a trade at 70¢.

<Frame>
  <div>
    <iframe title="Fee Curves" aria-label="Line chart" />
  </div>
</Frame>

### Fee Tables (100 Shares)

For detailed fee tables for each market category, see the [Fees](/trading/fees) page.

### Fee Precision

Fees are rounded to 5 decimal places. The smallest fee charged is 0.00001 USDC. Anything smaller rounds to zero, so very small trades near the extremes may incur no fee at all.

***

## Which Markets Are Eligible

The following market categories have taker fees enabled and are eligible for maker rebates: Crypto, Sports, Finance, Politics, Economics, Culture, Weather, Tech, Mentions, and Other / General.

<Note>
  Markets with fees enabled have `feesEnabled` set to `true` on the market
  object. Query per-market fee parameters via `getClobMarketInfo(conditionID)`.
</Note>

***

## FAQ

<AccordionGroup>
  <Accordion title="How do I qualify for maker rebates">
    Place orders that add liquidity to the book and get filled (i.e., your
    liquidity is taken by another trader).
  </Accordion>

  <Accordion title="When are rebates paid">Daily, in USDC. You must accrue at least \$1 in rebates before a payout is issued.</Accordion>

  <Accordion title="How are rebates calculated">
    Rebates are proportional to your share of executed maker liquidity in each
    eligible market. Totals are calculated per market, so you only compete with
    other makers in the same market.
  </Accordion>

  <Accordion title="Where does the rebate pool come from">
    Taker fees collected in eligible markets are allocated to the maker rebate
    pool and distributed daily.
  </Accordion>

  <Accordion title="Which markets have fees enabled">
    Crypto, Sports, Finance, Politics, Economics, Culture, Weather, Tech, Mentions, and Other / General markets.
  </Accordion>

  <Accordion title="Is Polymarket charging fees on all markets">
    Fees apply to markets in fee-enabled categories. Markets with fees enabled have `feesEnabled` set to `true` on the market object — check it per-market via `getClobMarketInfo(conditionID)`.
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup>
  <Card title="Fee Structure" icon="receipt" href="/trading/fees">
    Full fee handling guide for SDK and REST API users.
  </Card>

  <Card title="Place Orders" icon="plus" href="/trading/quickstart">
    Start placing orders on Polymarket.
  </Card>
</CardGroup>


# Overview
Source: https://docs.polymarket.com/market-makers/overview

Market making on Polymarket

A Market Maker (MM) on Polymarket is a trader who provides liquidity to prediction markets by continuously posting bid and ask orders. By laying the spread, market makers enable other users to trade efficiently while earning the spread as compensation for the risk they take.

Market makers are essential to Polymarket's ecosystem — they provide liquidity across markets, tighten spreads for better user experience, enable price discovery through continuous quoting, and absorb trading flow from retail and institutional users.

<Note>
  **Not a Market Maker?** If you're building an application that routes orders
  for your users, see the [Builder Program](/builders/overview) instead.
</Note>

***

## Getting Started

<Steps>
  <Step title="Complete Setup">
    Deploy wallets, fund with pUSD, and set token approvals. See the [Getting
    Started](/market-makers/getting-started) guide.
  </Step>

  <Step title="Connect to Data Feeds">
    WebSocket for real-time orderbook updates, Gamma API for market metadata.
    See [Market Data](/market-data/overview).
  </Step>

  <Step title="Start Quoting">
    Post orders via the CLOB REST API. See [Trading ](/market-makers/trading).
  </Step>
</Steps>

***

## Quick Reference

| Action               | Tool           | Documentation                                     |
| -------------------- | -------------- | ------------------------------------------------- |
| Deposit pUSD         | Bridge API     | [Bridge](/trading/bridge/deposit)                 |
| Approve tokens       | Relayer Client | [Getting Started](/market-makers/getting-started) |
| Post limit orders    | CLOB REST API  | [Create Orders](/trading/orders/create)           |
| Monitor orderbook    | WebSocket      | [WebSocket](/market-data/websocket/overview)      |
| Split pUSD to tokens | CTF / Relayer  | [Inventory](/market-makers/inventory)             |
| Merge tokens to pUSD | CTF / Relayer  | [Inventory](/market-makers/inventory)             |

***

## What Is in This Section

<CardGroup>
  <Card title="Getting Started" icon="gear" href="/market-makers/getting-started">
    Deposits, token approvals, wallet deployment, API keys
  </Card>

  <Card title="Trading" icon="chart-line" href="/market-makers/trading">
    Quoting best practices, strategies, and risk controls
  </Card>

  <Card title="Inventory Management" icon="boxes-stacked" href="/market-makers/inventory">
    Split, merge, and redeem outcome tokens
  </Card>

  <Card title="Liquidity Rewards" icon="gift" href="/market-makers/liquidity-rewards">
    Earn rewards for providing liquidity
  </Card>
</CardGroup>

## Risks

<Warning>
  Be careful with spread management — if your bid price is higher than your ask
  price (a "negative spread" or "crossed market"), you will lose money on every
  fill. Always validate your quote prices before submission.
</Warning>

## Support

For market maker onboarding and support, contact [support@polymarket.com](mailto:support@polymarket.com).


# Trading
Source: https://docs.polymarket.com/market-makers/trading

Order entry, management, and best practices for market makers

Market makers interact with Polymarket through the CLOB API — posting two-sided quotes, managing inventory across markets, and rebalancing positions. The SDK clients handle order signing and submission, so you can focus on strategy.

<Info>
  This page covers MM-specific workflows and best practices. For full order
  mechanics, see [Create Orders](/trading/orders/create) and [Cancel
  Orders](/trading/orders/cancel).
</Info>

***

## Two-Sided Quoting

The core market making workflow is posting a bid and ask around your fair value. Use `createAndPostOrder` to place each side:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { ClobClient, Side, OrderType } from "@polymarket/clob-client-v2";

  const client = new ClobClient({
    host: "https://clob.polymarket.com",
    chain: 137,
    signer: wallet,
    creds: credentials,
    signatureType,
    funderAddress: funder,
  });

  // Bid at 0.48
  const bid = await client.createAndPostOrder({
    tokenID: "3409705850427531082723332342151729...",
    side: Side.BUY,
    price: 0.48,
    size: 1000,
  });

  // Ask at 0.52
  const ask = await client.createAndPostOrder({
    tokenID: "3409705850427531082723332342151729...",
    side: Side.SELL,
    price: 0.52,
    size: 1000,
  });
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import OrderArgs, OrderType
  from py_clob_client_v2.order_builder.constants import BUY, SELL

  token_id = "3409705850427531082723332342151729..."

  # Bid at 0.48
  bid = client.create_and_post_order(
      OrderArgs(token_id=token_id, side=BUY, price=0.48, size=1000),
      order_type=OrderType.GTC,
  )

  # Ask at 0.52
  ask = client.create_and_post_order(
      OrderArgs(token_id=token_id, side=SELL, price=0.52, size=1000),
      order_type=OrderType.GTC,
  )
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::Side;
  use polymarket_client_sdk_v2::types::dec;

  let token_id = "3409705850427531082723332342151729...".parse()?;

  // Bid at 0.48
  let bid = client.limit_order()
      .token_id(token_id).price(dec!(0.48)).size(dec!(1000)).side(Side::Buy)
      .build().await?;
  let signed = client.sign(&signer, bid).await?;
  client.post_order(signed).await?;

  // Ask at 0.52
  let ask = client.limit_order()
      .token_id(token_id).price(dec!(0.52)).size(dec!(1000)).side(Side::Sell)
      .build().await?;
  let signed = client.sign(&signer, ask).await?;
  client.post_order(signed).await?;
  ```
</CodeGroup>

### Batch Orders

For tighter spreads across multiple levels, use `postOrders` to submit up to 15 orders in a single request:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const orders = await Promise.all([
    client.createOrder({ tokenID, side: Side.BUY, price: 0.48, size: 500 }),
    client.createOrder({ tokenID, side: Side.BUY, price: 0.47, size: 500 }),
    client.createOrder({ tokenID, side: Side.SELL, price: 0.52, size: 500 }),
    client.createOrder({ tokenID, side: Side.SELL, price: 0.53, size: 500 }),
  ]);

  const response = await client.postOrders(
    orders.map((order) => ({ order, orderType: OrderType.GTC })),
  );
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import OrderArgs, OrderType, PostOrdersV2Args
  from py_clob_client_v2.order_builder.constants import BUY, SELL

  response = client.post_orders([
      PostOrdersV2Args(
          order=client.create_order(OrderArgs(
              price=0.48, size=500, side=BUY, token_id=token_id,
          )),
          orderType=OrderType.GTC,
      ),
      PostOrdersV2Args(
          order=client.create_order(OrderArgs(
              price=0.47, size=500, side=BUY, token_id=token_id,
          )),
          orderType=OrderType.GTC,
      ),
      PostOrdersV2Args(
          order=client.create_order(OrderArgs(
              price=0.52, size=500, side=SELL, token_id=token_id,
          )),
          orderType=OrderType.GTC,
      ),
      PostOrdersV2Args(
          order=client.create_order(OrderArgs(
              price=0.53, size=500, side=SELL, token_id=token_id,
          )),
          orderType=OrderType.GTC,
      ),
  ])
  ```

  ```rust Rust theme={null}
  let mut signed_orders = Vec::new();
  for (price, side) in [
      (dec!(0.48), Side::Buy), (dec!(0.47), Side::Buy),
      (dec!(0.52), Side::Sell), (dec!(0.53), Side::Sell),
  ] {
      let order = client.limit_order()
          .token_id(token_id).price(price).size(dec!(500)).side(side)
          .build().await?;
      signed_orders.push(client.sign(&signer, order).await?);
  }
  let response = client.post_orders(signed_orders).await?;
  ```
</CodeGroup>

<Tip>
  Batching reduces latency by submitting multiple quotes in a single request.
  Always prefer `postOrders()` over multiple individual `createAndPostOrder()`
  calls.
</Tip>

***

## Choosing Order Types

| Type    | Behavior                                         | When to Use                             |
| ------- | ------------------------------------------------ | --------------------------------------- |
| **GTC** | Rests on the book until filled or cancelled      | Default for passive quoting             |
| **GTD** | Auto-expires at a specified time                 | Expire quotes before known events       |
| **FOK** | Must fill entirely and immediately, or cancel    | Aggressive rebalancing — all or nothing |
| **FAK** | Fills what's available immediately, cancels rest | Rebalancing where partial fills are OK  |

**GTC** and **GTD** are your primary tools for passive market making — they rest on the book at your specified price. **FOK** and **FAK** are for rebalancing inventory against resting liquidity.

### Time-Limited Quotes with GTD

Auto-expire quotes before known events like market close or resolution:

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Expire in 1 hour
  const expiringOrder = await client.createAndPostOrder(
    {
      tokenID,
      side: Side.BUY,
      price: 0.5,
      size: 1000,
      expiration: Math.floor(Date.now() / 1000) + 3600,
    },
    undefined,
    OrderType.GTD,
  );
  ```

  ```python Python theme={null}
  import time
  from py_clob_client_v2 import OrderArgs, OrderType
  from py_clob_client_v2.order_builder.constants import BUY

  # Expire in 1 hour
  expiring_order = client.create_and_post_order(
      OrderArgs(
          token_id=token_id,
          side=BUY,
          price=0.50,
          size=1000,
          expiration=int(time.time()) + 3600,
      ),
      order_type=OrderType.GTD,
  )
  ```

  ```rust Rust theme={null}
  use chrono::{TimeDelta, Utc};
  use polymarket_client_sdk_v2::clob::types::OrderType;

  // Expire in 1 hour
  let order = client.limit_order()
      .token_id(token_id)
      .price(dec!(0.50))
      .size(dec!(1000))
      .side(Side::Buy)
      .order_type(OrderType::GTD)
      .expiration(Utc::now() + TimeDelta::hours(1))
      .build().await?;
  let signed = client.sign(&signer, order).await?;
  client.post_order(signed).await?;
  ```
</CodeGroup>

***

## Managing Orders

### Cancelling

Cancel individual orders, by market, or everything at once:

<CodeGroup>
  ```typescript TypeScript theme={null}
  await client.cancelOrder(orderId); // Single order
  await client.cancelOrders(orderIds); // Multiple orders
  await client.cancelMarketOrders(conditionId); // All orders in a market
  await client.cancelAll(); // Everything
  ```

  ```python Python theme={null}
  client.cancel(order_id=order_id)                  # Single order
  client.cancel_market_orders(market=condition_id)  # All orders in a market
  client.cancel_all()                               # Everything
  ```

  ```rust Rust theme={null}
  client.cancel_order(order_id).await?;           // Single order
  client.cancel_market_orders(&request).await?;   // All orders in a market
  client.cancel_all_orders().await?;              // Everything
  ```
</CodeGroup>

See [Cancel Orders](/trading/orders/cancel) for full details.

### Monitoring Open Orders

<CodeGroup>
  ```typescript TypeScript theme={null}
  const order = await client.getOrder(orderId);

  const orders = await client.getOpenOrders({
    market: "0xbd31dc8a...",
    asset_id: "52114319501245...",
  });
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import OpenOrderParams

  order = client.get_order(order_id)

  orders = client.get_orders(
      OpenOrderParams(market="0xbd31dc8a...")
  )
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::request::OrdersRequest;

  let order = client.order(order_id).await?;

  let request = OrdersRequest::builder()
      .market("0xbd31dc8a...".parse()?)
      .build();
  let orders = client.orders(&request, None).await?;
  ```
</CodeGroup>

***

## Tick Sizes

Your order price must conform to the market's tick size, or it will be rejected. Look it up with the SDK before quoting:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const tickSize = await client.getTickSize(tokenID);
  // Returns: "0.1" | "0.01" | "0.001" | "0.0001"
  ```

  ```python Python theme={null}
  tick_size = client.get_tick_size(token_id)
  # Returns: "0.1" | "0.01" | "0.001" | "0.0001"
  ```

  ```rust Rust theme={null}
  let resp = client.tick_size(token_id).await?;
  // resp.minimum_tick_size: TickSize::Tenth | Hundredth | Thousandth | TenThousandth
  ```
</CodeGroup>

***

## Fees

Most markets charge a small taker fee. Makers are never charged fees. **Geopolitical and world events markets are fee-free.**

Taker fees fund the [Maker Rebates Program](/market-makers/maker-rebates), which pays daily USDC rebates to liquidity providers.

<Note>
  Fees apply only to markets deployed on or after the activation date. Pre-existing markets are unaffected. Markets with fees enabled have `feesEnabled` set to `true` on the market object.
</Note>

See [Fees](/trading/fees) for the full fee schedule, rates by category, and calculation details.

***

## Best Practices

### Quote Management

* **Quote both sides** — Post bids and asks to earn maximum [liquidity rewards](/market-makers/liquidity-rewards)
* **Skew on inventory** — Adjust quote prices based on your current position to manage exposure
* **Cancel stale quotes** — Pull orders immediately when market conditions change
* **Use GTD for events** — Auto-expire quotes before known catalysts to avoid stale exposure

### Latency

* **Batch orders** — Use `postOrders()` to submit multiple quotes in a single request
* **WebSocket for data** — Subscribe to real-time feeds instead of polling REST endpoints

### Risk Controls

* **Size limits** — Check token balances before quoting and don't exceed your available inventory
* **Price guards** — Validate prices against the book midpoint and reject outliers
* **Kill switch** — Call `cancelAll()` immediately on errors or position breaches
* **Monitor fills** — Subscribe to the WebSocket user channel for real-time fill notifications

***

## Next Steps

<CardGroup>
  <Card title="Inventory" icon="boxes-stacked" href="/market-makers/inventory">
    Split, merge, and redeem outcome tokens
  </Card>

  <Card title="Liquidity Rewards" icon="gift" href="/market-makers/liquidity-rewards">
    Earn rewards for providing two-sided liquidity
  </Card>

  <Card title="Create Orders" icon="plus" href="/trading/orders/create">
    Full order creation reference with all options
  </Card>
</CardGroup>


# Polymarket 101
Source: https://docs.polymarket.com/polymarket-101

An intro to Polymarket - the world's largest prediction market

Polymarket is a prediction market platform where users trade on the outcomes of real-world events. Instead of betting against a house, you trade shares with other users in an open, peer-to-peer market. Prices reflect the market's collective belief in the probability of an event occurring.

The platform is non-custodial, meaning you always control your funds. All trades are settled through smart contracts on the blockchain, ensuring transparent and trustless operation.

## Self-Custody

Polymarket operates on a non-custodial model. You maintain full control of your funds at all times.

* **You control your funds** - Assets are held in your wallet, secured by your private key
* **Smart contract enforcement** - Trades execute automatically through audited smart contracts
* **No intermediary risk** - Polymarket never takes possession of your funds — you maintain full control through your private key
* **Full transparency** - All trades and positions are recorded onchain and publicly verifiable
* **Trustless execution** - Settlement happens automatically based on market resolution

<Warning>
  Keep your private key safe and never share it with anyone. If you lose your
  private key, you lose access to your funds. If you signed up via Magic Link or
  have a proxy wallet, recovery may be possible through
  [recovery.polymarket.com](https://recovery.polymarket.com).
</Warning>

## How Polymarket Works

<Frame>
  <img alt="Polymarket Overview" />

  <img alt="Polymarket Overview" />
</Frame>

### Prices Are Probabilities

Every share on Polymarket is priced between `$0.00` and `$1.00`. The price represents the market's belief in the probability of that outcome occurring.

For example, if "Yes" shares for an event are trading at `$0.65`, the market believes there's approximately a `65%` chance the event will happen.

### Collateral and Tokens

Polymarket uses pUSD (Polymarket USD) as collateral. Every Yes/No pair is fully backed:

* `$1 pUSD` creates one Yes share and one No share
* Winning shares are redeemable for `$1.00`
* Losing shares are worth `$0.00`

Shares are represented as tokens using the [Gnosis Conditional Token Framework](https://github.com/gnosis/conditional-tokens-contracts/) (ERC1155 standard), enabling seamless onchain trading and settlement.

### Trading

Polymarket uses a peer-to-peer order book (CLOB) for trading. You trade directly with other users, not against the house.

* **Buy shares** when you think the market underestimates the probability
* **Sell shares** when you think the market overestimates the probability
* **Exit anytime** - Sell your position before resolution to lock in profits or cut losses

| Action  | When to Use                           | Profit Scenario           |
| ------- | ------------------------------------- | ------------------------- |
| Buy Yes | You think the probability is too low  | Event occurs              |
| Buy No  | You think the probability is too high | Event does not occur      |
| Sell    | Lock in gains or limit losses         | Price moves in your favor |

### Resolution

When an event concludes, markets are resolved through the **UMA Optimistic Oracle**:

1. A proposer submits the outcome with a bond
2. There's a challenge period where anyone can dispute
3. If disputed, UMA token holders vote on the correct resolution
4. Winning tokens become redeemable for \$1 pUSD

This community-driven process ensures fair and accurate market resolution.

## Why Blockchain

Polymarket is built on **Polygon**, a blockchain network, for several key reasons:

* **Global accessibility** - Anyone with an internet connection can participate
* **Non-custodial** - You control your funds, not a centralized entity
* **Transparent** - All activity is publicly verifiable onchain
* **Fast and affordable** - Polygon enables quick, low-cost transactions
* **Stable value** - pUSD is a standard ERC-20 backed by USDC, with backing enforced onchain by the smart contract — avoiding crypto volatility

## Smart Wallets

Polymarket uses smart wallets so users can trade without manually submitting
every onchain transaction. New API users use deposit wallets. Existing Safe and
Proxy users can continue using their current wallet.

Deposit wallets hold the user's pUSD and outcome tokens on Polygon and validate
orders through ERC-1271. Safe and Proxy wallets remain supported for existing
users and integrations.

Using smart wallets allows Polymarket to provide an improved UX where multi-step
transactions can be executed atomically and transactions can be relayed by
Polymarket's relayer. If you are a developer looking to programmatically access
positions accumulated through an existing Polymarket account, continue using
that account's current smart wallet type.

### Deployments

Each smart-wallet user has their own wallet address. See
[Contracts](/resources/contracts) for all deployed factory and trading contract
addresses on Polygon.

<Tip>
  For details on signature types (`EOA`, `POLY_PROXY`, `GNOSIS_SAFE`,
  `POLY_1271`) and how to configure your trading client for each wallet type,
  see [Signature Types](/trading/overview#signature-types).
</Tip>

***

## Getting Started

Ready to start trading?

<CardGroup>
  <Card title="Quickstart Guide" icon="rocket" href="/quickstart">
    Set up your account and make your first trade.
  </Card>

  <Card title="Explore Markets" icon="chart-line" href="https://polymarket.com">
    Browse active prediction markets on Polymarket.
  </Card>
</CardGroup>


# Quickstart
Source: https://docs.polymarket.com/quickstart

Fetch a market and place your first order

Get up and running with the Polymarket API in minutes — fetch market data and place your first order.

<Steps>
  <Step title="Fetch a Market">
    All data endpoints are public — no API key or authentication needed. Use the markets endpoint to find a market and get its token IDs:

    <Tabs>
      <Tab title="cURL">
        ```bash theme={null}
        curl "https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=1"
        ```
      </Tab>

      <Tab title="TypeScript">
        ```typescript theme={null}
        const response = await fetch(
          "https://gamma-api.polymarket.com/markets?active=true&closed=false&limit=1"
        );
        const markets = await response.json();

        const market = markets[0];
        console.log(market.question);
        console.log(market.clobTokenIds);
        // ["123456...", "789012..."]  — [Yes token ID, No token ID]
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={null}
        import requests

        response = requests.get(
            "https://gamma-api.polymarket.com/markets",
            params={"active": "true", "closed": "false", "limit": 1}
        )
        markets = response.json()

        market = markets[0]
        print(market["question"])
        print(market["clobTokenIds"])
        # ["123456...", "789012..."]  — [Yes token ID, No token ID]
        ```
      </Tab>

      <Tab title="Rust">
        ```rust theme={null}
        use polymarket_client_sdk_v2::gamma::Client;
        use polymarket_client_sdk_v2::gamma::types::request::MarketsRequest;

        let client = Client::default();

        let request = MarketsRequest::builder()
            .closed(false)
            .limit(1)
            .build();
        let markets = client.markets(&request).await?;

        let market = &markets[0];
        println!("{:?}", market.question);
        println!("{:?}", market.clob_token_ids);
        // Some(["123456...", "789012..."])  — [Yes token ID, No token ID]
        ```
      </Tab>
    </Tabs>

    Save a token ID from `clobTokenIds` — you'll need it to place an order. The first ID is the Yes token, the second is the No token. See [Fetching Markets](/market-data/fetching-markets) for more strategies like fetching by slug, tag, or event.
  </Step>

  <Step title="Install the SDK">
    <CodeGroup>
      ```bash TypeScript theme={null}
      npm install @polymarket/clob-client-v2 viem
      ```

      ```bash Python theme={null}
      pip install py-clob-client-v2
      ```

      ```bash Rust theme={null}
      cargo add polymarket_client_sdk_v2 --features gamma,clob
      ```
    </CodeGroup>
  </Step>

  <Step title="Set Up Your Client">
    Derive API credentials and initialize the trading client:

    <Tabs>
      <Tab title="TypeScript">
        ```typescript theme={null}
        import { ClobClient } from "@polymarket/clob-client-v2";
        import { createWalletClient, http } from "viem";
        import { privateKeyToAccount } from "viem/accounts";

        const HOST = "https://clob.polymarket.com";
        const CHAIN_ID = 137; // Polygon mainnet
        const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
        const signer = createWalletClient({ account, transport: http() });

        // Derive API credentials (L1 → L2 auth)
        const tempClient = new ClobClient({ host: HOST, chain: CHAIN_ID, signer });
        const apiCreds = await tempClient.createOrDeriveApiKey();

        // Initialize trading client
        const client = new ClobClient({
          host: HOST,
          chain: CHAIN_ID,
          signer,
          creds: apiCreds,
          signatureType: 0, // Signature type: 0 = EOA
          funderAddress: account.address, // Funder address
        });
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={null}
        from py_clob_client_v2 import ClobClient
        import os

        host = "https://clob.polymarket.com"
        chain = 137  # Polygon mainnet
        private_key = os.getenv("PRIVATE_KEY")

        # Derive API credentials (L1 → L2 auth)
        temp_client = ClobClient(host, key=private_key, chain_id=chain)
        api_creds = temp_client.create_or_derive_api_key()

        # Initialize trading client
        client = ClobClient(
            host,
            key=private_key,
            chain_id=chain,
            creds=api_creds,
            signature_type=0,  # Signature type: 0 = EOA
            funder="YOUR_WALLET_ADDRESS",  # Funder address
        )
        ```
      </Tab>

      <Tab title="Rust">
        ```rust theme={null}
        use std::str::FromStr;
        use polymarket_client_sdk_v2::POLYGON;
        use polymarket_client_sdk_v2::auth::{LocalSigner, Signer};
        use polymarket_client_sdk_v2::clob::{Client, Config};

        let private_key = std::env::var("POLYMARKET_PRIVATE_KEY")?;
        let signer = LocalSigner::from_str(&private_key)?
            .with_chain_id(Some(POLYGON));

        // Derive API credentials and initialize trading client (L1 → L2 auth)
        // Signature type defaults to EOA (0)
        let client = Client::new("https://clob.polymarket.com", Config::default())?
            .authentication_builder(&signer)
            .authenticate()
            .await?;
        ```
      </Tab>
    </Tabs>

    <Note>
      This example uses an EOA wallet (signature type `0`) — your wallet pays its
      own gas. New API users should use deposit wallets with signature type `3`.
      Existing Proxy and Safe users can keep using signature types `1` and `2`. See
      [Authentication](/api-reference/authentication) for details on signature
      types.
    </Note>

    <Warning>
      Before trading, your funder address needs **pUSD** (for buying outcome tokens)
      and **POL** (for gas, if using EOA type `0`).
    </Warning>
  </Step>

  <Step title="Place an Order">
    Use the `token_id` from Step 1 to place a limit order:

    <Tabs>
      <Tab title="TypeScript">
        ```typescript theme={null}
        import { Side, OrderType } from "@polymarket/clob-client-v2";

        // Fetch market details to get tick size and neg risk
        const market = await client.getMarket("YOUR_CONDITION_ID");
        const tickSize = String(market.minimum_tick_size);   // e.g., "0.01"
        const negRisk = market.neg_risk;             // e.g., false

        const response = await client.createAndPostOrder(
          {
            tokenID: "YOUR_TOKEN_ID", // From Step 1
            price: 0.50,
            size: 10,
            side: Side.BUY,
          },
          {
            tickSize,
            negRisk,
          },
        );

        console.log("Order ID:", response.orderID);
        console.log("Status:", response.status);
        ```
      </Tab>

      <Tab title="Python">
        ```python theme={null}
        from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions
        from py_clob_client_v2.order_builder.constants import BUY

        # Fetch market details to get tick size and neg risk
        market = client.get_market("YOUR_CONDITION_ID")
        tick_size = str(market["minimum_tick_size"])   # e.g., "0.01"
        neg_risk = market["neg_risk"]             # e.g., False

        response = client.create_and_post_order(
            OrderArgs(
                token_id="YOUR_TOKEN_ID",  # From Step 1
                price=0.50,
                size=10,
                side=BUY,
            ),
            options=PartialCreateOrderOptions(tick_size=tick_size, neg_risk=neg_risk),
            order_type=OrderType.GTC,
        )

        print("Order ID:", response["orderID"])
        print("Status:", response["status"])
        ```
      </Tab>

      <Tab title="Rust">
        ```rust theme={null}
        use polymarket_client_sdk_v2::clob::types::Side;
        use polymarket_client_sdk_v2::types::dec;

        // token_id is a U256 — parse from the string returned in Step 1
        let token_id = "YOUR_TOKEN_ID".parse()?;

        // The Rust SDK auto-fetches tick size, neg risk, and fee rate
        // No need to manually look them up — the order builder handles it
        let order = client
            .limit_order()
            .token_id(token_id)
            .price(dec!(0.50))
            .size(dec!(10))
            .side(Side::Buy)
            .build()
            .await?;
        let signed_order = client.sign(&signer, order).await?;
        let response = client.post_order(signed_order).await?;

        println!("Order ID: {}", response.order_id);
        println!("Status: {:?}", response.status);
        ```
      </Tab>
    </Tabs>
  </Step>
</Steps>

***

## Next Steps

<CardGroup>
  <Card title="Authentication" icon="lock" href="/api-reference/authentication">
    Understand L1/L2 auth, signature types, and API credentials.
  </Card>

  <Card title="Trading Quickstart" icon="bolt" href="/trading/quickstart">
    Detailed trading guide with order management and troubleshooting.
  </Card>

  <Card title="Fetching Markets" icon="magnifying-glass" href="/market-data/fetching-markets">
    Strategies for discovering markets by slug, tag, or category.
  </Card>

  <Card title="Core Concepts" icon="book" href="/concepts/markets-events">
    Understand markets, events, prices, and positions.
  </Card>
</CardGroup>


# Data Resources
Source: https://docs.polymarket.com/resources/blockchain-data

Access Polymarket on-chain activity for data & analytics

Polymarket data that lands on the blockchain, such as trades, balances, positions, and redeems, is available through various on-chain analytics platforms and blockchain data providers. Polymarket also provides its own APIs and WebSockets. See the [API Endpoints reference](/quickstart/reference/endpoints) for more information.

The purpose of this page is to serve as a public good for Polymarket builders, researches, and analysts alike.

***

## Data

### Goldsky

[Goldsky](https://docs.goldsky.com/chains/polymarket) provides real-time streaming pipelines for Polymarket on-chain activity (i.e. trades, balances, positions, etc...) into your own database/data warehouse.

Goldsky also partnered with [ClickHouse](https://clickhouse.com) to create [CryptoHouse](https://crypto.clickhouse.com), where you can query Polymarket on-chain data using SQL.

### Dune

[Dune](https://dune.com) is a blockchain analytics platform that has Polymarket on-chain activity (i.e. trades, balances, positions, etc...). Query Polymarket data using SQL, create custom dashboards, and more.

Here are a few simple queries to get started:

| Query         | Description                                   | Link                                                |
| ------------- | --------------------------------------------- | --------------------------------------------------- |
| Volume        | Notional Volume and Maker & Taker USDC Volume | [View Dune Query](https://dune.com/queries/6545441) |
| TVL           | USDC locked in Polymarket smart contracts     | [View Dune Query](https://dune.com/queries/6588784) |
| Open Interest | Estimated market open interest, and over time | [View Dune Query](https://dune.com/queries/6555478) |

### Allium

[Allium](https://docs.allium.so/historical-data/predictions) is a blockchain analytics platform that has Polymarket on-chain activity (i.e. trades, balances, positions, etc...). Query Polymarket data using SQL, create custom dashboards, and more.

\--

## Dashboards

Third-party blockchain analytics platforms that aggregate and visualize Polymarket data:

<CardGroup>
  <Card title="Blockworks" href="https://blockworks.com/analytics/polymarket" />

  <Card title="Artemis" href="https://app.artemisanalytics.com/asset/polymarket?from=assets" />

  <Card title="Dune" href="https://dune.com/discover/content/popular?q=polymarket&resource-type=dashboards" />

  <Card title="DeFiLlama" href="https://defillama.com/protocol/polymarket" />

  <Card title="The Block" href="https://www.theblock.co/data/decentralized-finance/prediction-markets-and-betting" />

  <Card title="Token Terminal" href="https://tokenterminal.com/explorer/projects/polymarket" />

  <Card title="Allium" href="https://predictions.allium.so" />
</CardGroup>

### Community Dashboards

Community-created Dune dashboards of Polymarket on-chain analytics:

| Dashboard                                         | Created By                                      | Link                                                                         |
| ------------------------------------------------- | ----------------------------------------------- | ---------------------------------------------------------------------------- |
| Polymarket Overview                               | [@datadashboards](https://x.com/datadashboards) | [View Dashboard](https://dune.com/datadashboards/polymarket-overview)        |
| Polymarket Volume, OI, Markets, Addresses and TVL | [@hildobby](https://x.com/hildobby)             | [View Dashboard](https://dune.com/hildobby/polymarket)                       |
| Polymarket Historical Accuracy                    | [@alexmccullaaa](https://x.com/alexmccullaaa)   | [View Dashboard](https://dune.com/alexmccullough/how-accurate-is-polymarket) |
| Polymarket Builders Dashboard                     | [@defioasis](https://x.com/defioasis)           | [View Dashboard](https://dune.com/gateresearch/pmbuilders)                   |


# Contracts
Source: https://docs.polymarket.com/resources/contracts

All Polymarket smart contract addresses, audits, and security resources

All Polymarket contracts are deployed on **Polygon mainnet** (Chain ID: 137). This is the single source of truth for all contract addresses used across the platform.

***

## Core Trading Contracts

| Contract                 | Address                                                                                                                    |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| CTF Exchange             | [`0xE111180000d2663C0091e4f400237545B87B996B`](https://polygonscan.com/address/0xE111180000d2663C0091e4f400237545B87B996B) |
| Neg Risk CTF Exchange    | [`0xe2222d279d744050d28e00520010520000310F59`](https://polygonscan.com/address/0xe2222d279d744050d28e00520010520000310F59) |
| Neg Risk Adapter         | [`0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296`](https://polygonscan.com/address/0xd91E80cF2E7be2e162c6513ceD06f1dD0dA35296) |
| Conditional Tokens (CTF) | [`0x4D97DCd97eC945f40cF65F87097ACe5EA0476045`](https://polygonscan.com/address/0x4D97DCd97eC945f40cF65F87097ACe5EA0476045) |

***

## Collateral Contracts

| Contract                       | Address                                                                                                                    |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| pUSD — CollateralToken (proxy) | [`0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB`](https://polygonscan.com/address/0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB) |
| pUSD — CollateralToken (impl)  | [`0x6bBCef9f7ef3B6C592c99e0f206a0DE94Ad0925f`](https://polygonscan.com/address/0x6bBCef9f7ef3B6C592c99e0f206a0DE94Ad0925f) |
| CollateralOnramp               | [`0x93070a847efEf7F70739046A929D47a521F5B8ee`](https://polygonscan.com/address/0x93070a847efEf7F70739046A929D47a521F5B8ee) |
| CollateralOfframp              | [`0x2957922Eb93258b93368531d39fAcCA3B4dC5854`](https://polygonscan.com/address/0x2957922Eb93258b93368531d39fAcCA3B4dC5854) |
| PermissionedRamp               | [`0xebC2459Ec962869ca4c0bd1E06368272732BCb08`](https://polygonscan.com/address/0xebC2459Ec962869ca4c0bd1E06368272732BCb08) |
| CtfCollateralAdapter           | [`0xAdA100Db00Ca00073811820692005400218FcE1f`](https://polygonscan.com/address/0xAdA100Db00Ca00073811820692005400218FcE1f) |
| NegRiskCtfCollateralAdapter    | [`0xadA2005600Dec949baf300f4C6120000bDB6eAab`](https://polygonscan.com/address/0xadA2005600Dec949baf300f4C6120000bDB6eAab) |

***

## Wallet Factory Contracts

| Contract                 | Address                                                                                                                    |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------- |
| Deposit Wallet Factory   | [`0x00000000000Fb5C9ADea0298D729A0CB3823Cc07`](https://polygonscan.com/address/0x00000000000Fb5C9ADea0298D729A0CB3823Cc07) |
| Gnosis Safe Factory      | [`0xaacfeea03eb1561c4e67d661e40682bd20e3541b`](https://polygonscan.com/address/0xaacfeea03eb1561c4e67d661e40682bd20e3541b) |
| Polymarket Proxy Factory | [`0xaB45c5A4B0c941a2F231C04C3f49182e1A254052`](https://polygonscan.com/address/0xaB45c5A4B0c941a2F231C04C3f49182e1A254052) |

***

## Resolution Contracts

| Contract              | Address                                                                                                                    |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| UMA Adapter           | [`0x6A9D222616C90FcA5754cd1333cFD9b7fb6a4F74`](https://polygonscan.com/address/0x6A9D222616C90FcA5754cd1333cFD9b7fb6a4F74) |
| UMA Optimistic Oracle | [`0xCB1822859cEF82Cd2Eb4E6276C7916e692995130`](https://polygonscan.com/address/0xCB1822859cEF82Cd2Eb4E6276C7916e692995130) |

***

## Security

### Audits

CTF Exchange V2 has been audited by two independent firms:

| Auditor    | Report                                                                                                                                                                  |
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Quantstamp | [CTF Exchange V2 — Quantstamp — March 2026](https://github.com/Polymarket/ctf-exchange-v2/blob/main/audits/CTF%20Exchange%20V2%20-%20Quantstamp%20-%20March%202026.pdf) |
| Cantina    | [CTF Exchange V2 — Cantina — March 2026](https://github.com/Polymarket/ctf-exchange-v2/blob/main/audits/CTF%20Exchange%20V2%20-%20Cantina%20-%20March%202026.pdf)       |

### Bug Bounty

Security vulnerabilities can be reported through the [Cantina bug bounty program](https://cantina.xyz/bounties/ff945ca2-2a6e-4b83-b1b6-7a0cd3b94bea).

***

## Source Code

<CardGroup>
  <Card title="CTF Exchange V2" icon="github" href="https://github.com/Polymarket/ctf-exchange-v2">
    Order matching and settlement contracts
  </Card>
</CardGroup>


# Error Codes
Source: https://docs.polymarket.com/resources/error-codes

Complete reference for CLOB API error responses

All CLOB API errors return a JSON object with a single `error` field:

```json theme={null}
{
  "error": "<message>"
}
```

***

## Global Errors

These errors can occur on **any authenticated endpoint**.

<ResponseField name="401" type="Unauthorized">
  `Unauthorized/Invalid api key` — Your API key is missing, expired, or invalid. Ensure you're sending all required [authentication headers](/trading/overview#authentication).
</ResponseField>

<ResponseField name="401" type="Unauthorized">
  `Invalid L1 Request headers` — Your L1 authentication headers (HMAC signature) are malformed or the signature doesn't match. See [Authentication](/api-reference/authentication).
</ResponseField>

<ResponseField name="503" type="Service Unavailable">
  `Trading is currently disabled. Check polymarket.com for updates` — The exchange is temporarily paused. No orders (including cancels) are accepted.
</ResponseField>

<ResponseField name="503" type="Service Unavailable">
  `Trading is currently cancel-only. New orders are not accepted, but cancels are allowed.` — The exchange is in cancel-only mode. You can cancel existing orders but cannot place new ones.
</ResponseField>

<ResponseField name="429" type="Too Many Requests">
  `Too Many Requests` — You've exceeded the [rate limit](/api-reference/rate-limits). Back off and retry with exponential backoff.
</ResponseField>

***

## Order Book

Errors from the order book endpoints.

### GET book

<ResponseField name="400" type="Bad Request">
  `Invalid token id` — The `token_id` query parameter is missing or not a valid token ID.
</ResponseField>

<ResponseField name="404" type="Not Found">
  `No orderbook exists for the requested token id`
</ResponseField>

### POST books

<ResponseField name="400" type="Bad Request">
  `Invalid payload` — The request body is malformed or missing required fields.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `Payload exceeds the limit` — Too many token IDs in a single request. Reduce the batch size.
</ResponseField>

***

## Pricing

Errors from price, midpoint, and spread endpoints.

### GET price

<ResponseField name="400" type="Bad Request">
  `Invalid token id` — The `token_id` parameter is missing or invalid.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `Invalid side` — The `side` parameter must be `BUY` or `SELL`.
</ResponseField>

<ResponseField name="404" type="Not Found">
  `No orderbook exists for the requested token id`
</ResponseField>

### POST prices

<ResponseField name="400" type="Bad Request">
  `Invalid payload` — The request body is malformed or missing required fields.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `Invalid side` — The `side` field must be `BUY` or `SELL`.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `Payload exceeds the limit` — Too many token IDs in a single request.
</ResponseField>

### GET midpoint

<ResponseField name="400" type="Bad Request">
  `Invalid token id` — The `token_id` parameter is missing or invalid.
</ResponseField>

<ResponseField name="404" type="Not Found">
  `No orderbook exists for the requested token id`
</ResponseField>

### POST midpoints

<ResponseField name="400" type="Bad Request">
  `Invalid payload` — The request body is malformed or missing required fields.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `Payload exceeds the limit` — Too many token IDs in a single request.
</ResponseField>

### GET spread

<ResponseField name="400" type="Bad Request">
  `Invalid token id` — The `token_id` parameter is missing or invalid.
</ResponseField>

<ResponseField name="404" type="Not Found">
  `No orderbook exists for the requested token id`
</ResponseField>

### POST spreads

<ResponseField name="400" type="Bad Request">
  `Invalid payload` — The request body is malformed or missing required fields.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `Payload exceeds the limit` — Too many token IDs in a single request.
</ResponseField>

***

## Place Orders

Errors from order placement endpoints.

### POST order

<ResponseField name="400" type="Bad Request">
  `Invalid order payload` — The request body is malformed, missing required fields, or contains invalid values.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `the order owner has to be the owner of the API KEY` — The `maker` address in the order doesn't match the address associated with your API key.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `the order signer address has to be the address of the API KEY`
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `'{address}' address banned` — This address has been banned from trading.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `'{address}' address in closed only mode`
</ResponseField>

### POST orders

All errors from `POST /order` apply, plus:

<ResponseField name="400" type="Bad Request">
  `Too many orders in payload: {N}, max allowed: {M}` — The batch contains more orders than the maximum allowed per request.
</ResponseField>

Per-order errors are returned in the `200` response array, with individual error messages for each failed order.

***

## Order Processing Errors

These errors are returned when an order passes initial validation but fails during processing. They appear in the response body of `POST /order` and `POST /orders`.

<ResponseField name="400" type="Bad Request">
  `invalid post-only order: order crosses book` — A post-only (maker) order would immediately match. Adjust the price so it rests on the book.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `order {id} is invalid. Price ({price}) breaks minimum tick size rule: {tick}` — The order price doesn't align with the market's tick size. Use [`GET /tick-size`](/api-reference/clob#get-tick-size) to check the valid tick size.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `order {id} is invalid. Size ({size}) lower than the minimum: {min}` — The order size is below the market minimum.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `order {id} is invalid. Duplicated.`
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `order {id} crosses the book`
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `not enough balance / allowance` — Insufficient pUSD balance or token allowance. Check your balance with [`GET /balance-allowance`](/api-reference/clob#get-balance-allowance) and approve the exchange contract if needed.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `invalid expiration` — The order expiration timestamp is in the past or invalid.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `order canceled in the CTF exchange contract`
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `order match delayed due to market conditions`
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `order couldn't be fully filled. FOK orders are fully filled or killed.` — A Fill-or-Kill order could not be completely filled by available liquidity. The entire order is rejected.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `no orders found to match with FAK order. FAK orders are partially filled or killed if no match is found.` — A Fill-and-Kill order found no matching orders at all. At least one match is required.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `the market is not yet ready to process new orders`
</ResponseField>

***

## Matching Engine Errors

Internal matching engine errors that may surface during order execution.

<ResponseField name="425" type="Too Early">
  The matching engine is restarting. Retry with exponential backoff. See [Matching Engine](/trading/matching-engine) for details on restart schedule and handling.
</ResponseField>

<ResponseField name="500" type="Internal Server Error">
  `there are no matching orders`
</ResponseField>

<ResponseField name="500" type="Internal Server Error">
  `FOK orders are filled or killed` — A Fill-or-Kill order could not be fully satisfied.
</ResponseField>

<ResponseField name="500" type="Internal Server Error">
  `the trade contains rounding issues`
</ResponseField>

<ResponseField name="500" type="Internal Server Error">
  `the price of the taker's order has a discrepancy greater than allowed with the worst maker order`
</ResponseField>

***

## Cancel Orders

Errors from order cancellation endpoints.

### DELETE order

<ResponseField name="400" type="Bad Request">
  `Invalid order payload` — The request body is malformed.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `Invalid orderID` — The provided order ID is not a valid format.
</ResponseField>

### DELETE orders

<ResponseField name="400" type="Bad Request">
  `Invalid order payload` — The request body is malformed.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `Too many orders in payload, max allowed: {N}` — Too many order IDs in a single cancellation request.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `Invalid orderID` — One or more order IDs are not valid.
</ResponseField>

### DELETE cancel-market-orders

<ResponseField name="400" type="Bad Request">
  `Invalid order payload` — The request body is malformed or contains invalid filter parameters.
</ResponseField>

***

## Query Orders

Errors from order query endpoints.

### GET order by ID

<ResponseField name="400" type="Bad Request">
  `Invalid orderID` — The order ID in the URL path is not valid.
</ResponseField>

<ResponseField name="500" type="Internal Server Error">
  `Internal server error` — An unexpected error occurred while fetching the order.
</ResponseField>

### GET orders

<ResponseField name="400" type="Bad Request">
  `invalid order params payload` — The query parameters are malformed or contain invalid values.
</ResponseField>

<ResponseField name="500" type="Internal Server Error">
  `Internal server error` — An unexpected error occurred while fetching orders.
</ResponseField>

***

## Trades

### GET trades

<ResponseField name="400" type="Bad Request">
  `Invalid trade params payload` — The query parameters are malformed or contain invalid values.
</ResponseField>

<ResponseField name="500" type="Internal Server Error">
  `Internal server error` — An unexpected error occurred while fetching trades.
</ResponseField>

### GET last-trade-price

<ResponseField name="400" type="Bad Request">
  `Invalid token id` — The `token_id` parameter is missing or invalid.
</ResponseField>

<ResponseField name="500" type="Internal Server Error">
  `Internal server error` — An unexpected error occurred while fetching the last trade price.
</ResponseField>

### POST last-trades-prices

<ResponseField name="400" type="Bad Request">
  `Invalid payload` — The request body is malformed or missing required fields.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `Payload exceeds the limit` — Too many token IDs in a single request.
</ResponseField>

***

## Markets

### GET market by condition ID

<ResponseField name="400" type="Bad Request">
  `Invalid market` — The condition ID is not a valid format.
</ResponseField>

<ResponseField name="404" type="Not Found">
  `market not found` — No market exists with this condition ID.
</ResponseField>

### GET tick-size

<ResponseField name="400" type="Bad Request">
  `Invalid token id` — The token ID is not valid.
</ResponseField>

<ResponseField name="404" type="Not Found">
  `market not found` — No market found for this token ID.
</ResponseField>

### GET neg-risk

<ResponseField name="400" type="Bad Request">
  `Invalid token id` — The token ID is not valid.
</ResponseField>

<ResponseField name="404" type="Not Found">
  `market not found` — No market found for this token ID.
</ResponseField>

***

## Price History

### GET prices-history

<ResponseField name="400" type="Bad Request">
  Filter validation errors — One or more query parameters (`market`, `startTs`, `endTs`, `fidelity`) are invalid.
</ResponseField>

### GET ohlc

<ResponseField name="400" type="Bad Request">
  `startTs is required` — The `startTs` query parameter is missing.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `asset_id is required` — The `asset_id` query parameter is missing.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `invalid fidelity: {val}` — The `fidelity` parameter must be one of: `1m`, `5m`, `15m`, `30m`, `1h`, `4h`, `1d`, `1w`.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `limit cannot exceed 1000` — Reduce the `limit` parameter to 1000 or below.
</ResponseField>

### GET orderbook-history

<ResponseField name="400" type="Bad Request">
  `startTs is required` — The `startTs` query parameter is missing.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `either market or asset_id must be provided` — You must specify either a `market` (condition ID) or `asset_id` (token ID).
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `limit cannot exceed 1000` — Reduce the `limit` parameter to 1000 or below.
</ResponseField>

***

## Authentication and API Keys

### POST auth api-key

<ResponseField name="401" type="Unauthorized">
  `Invalid L1 Request headers` — L1 authentication headers are missing or invalid.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `Could not create api key`
</ResponseField>

### GET auth api-keys

<ResponseField name="500" type="Internal Server Error">
  `Could not retrieve API keys` — An unexpected error occurred while fetching your API keys.
</ResponseField>

### DELETE auth api-key

<ResponseField name="500" type="Internal Server Error">
  `Could not delete API key` — An unexpected error occurred while deleting the API key.
</ResponseField>

### GET auth derive-api-key

<ResponseField name="401" type="Unauthorized">
  `Invalid L1 Request headers` — L1 authentication headers are missing or invalid.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `Could not derive api key!`
</ResponseField>

***

## Builder API Keys

### POST auth builder-api-key

<ResponseField name="500" type="Internal Server Error">
  `could not create builder api key` — Builder API key creation failed.
</ResponseField>

### GET auth builder-api-key

<ResponseField name="500" type="Internal Server Error">
  `could not get builder api keys` — An unexpected error occurred while fetching builder API keys.
</ResponseField>

### DELETE auth builder-api-key

<ResponseField name="400" type="Bad Request">
  `invalid revoke builder api key body` — The request body is malformed.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `invalid revoke builder api key headers` — Required authentication headers are missing.
</ResponseField>

<ResponseField name="500" type="Internal Server Error">
  `could not revoke the builder api key: {key}` — An unexpected error occurred while revoking the key.
</ResponseField>

***

## Builder Trades

### GET builder trades

<ResponseField name="400" type="Bad Request">
  `invalid builder trade params` — The query parameters are malformed or contain invalid values.
</ResponseField>

<ResponseField name="500" type="Internal Server Error">
  `could not fetch builder trades` — An unexpected error occurred while fetching builder trades.
</ResponseField>

***

## Balance and Allowance

### GET balance-allowance

<ResponseField name="400" type="Bad Request">
  `Invalid asset type` — The `asset_type` parameter is not a recognized asset type.
</ResponseField>

<ResponseField name="400" type="Bad Request">
  `Invalid signature_type` — The `signature_type` parameter must be `EOA`, `POLY_PROXY`, or `GNOSIS_SAFE`.
</ResponseField>

***

## Status Code Reference

| Status | Meaning               | Common Causes                                                                                       |
| ------ | --------------------- | --------------------------------------------------------------------------------------------------- |
| `400`  | Bad Request           | Invalid parameters, malformed payload, business logic violation                                     |
| `401`  | Unauthorized          | Missing or invalid API key, bad HMAC signature, expired timestamp                                   |
| `404`  | Not Found             | Market doesn't exist, order not found, token ID not recognized                                      |
| `425`  | Too Early             | Matching engine is restarting — retry with backoff. See [Matching Engine](/trading/matching-engine) |
| `429`  | Too Many Requests     | Rate limit exceeded — implement exponential backoff                                                 |
| `500`  | Internal Server Error | Unexpected server error — retry with backoff                                                        |
| `503`  | Service Unavailable   | Exchange paused or in cancel-only mode                                                              |

<Note>
  The CLOB API has an internal override: any error message containing `"not found"` returns `404`, `"unauthorized"` returns `401`, and `"context canceled"` returns `400`, regardless of the original status code.
</Note>


# Referral Program
Source: https://docs.polymarket.com/resources/referral-program

Earn rewards by referring users to Polymarket

We're excited to announce Polymarket's referral program. Existing users who have traded at least \$10,000 in volume are eligible to sign up. Get paid to refer users to Polymarket, and be eligible for future Polymarket rewards.

## Referral Link

You can create a referral link at [polymarket.com/refer](http://polymarket.com/refer). When someone signs up using your link, you'll earn a percentage of the fees generated from their trades. Instead of manually creating referral links, you can also find a unique referral link on each market page when signed in to your Polymarket account.

The referral rewards are unlimited. The more that users you refer trade, the more you'll earn — also increasing your allocation in all future rewards.

## Boosted Rebate Period

For a limited time, you'll earn:

* 30% of fees generated from direct referrals
* 10% of fees generated from indirect referrals

Direct referrals are those you personally refer, and indirect referrals are those referred by someone you've referred (i.e. if you refer Alice and Alice refers Bob, you'll earn 10% of trading fees generated from Bob's trading volume as well).

These rewards will be for the first 180 days after a user has signed up to Polymarket, and this period is subject to change without notice.

## Notes

* You will earn referral rewards based on the gross trading fee that a user pays on polymarkets.
* Not all polymarkets have fees, so you won't make \$ from volume on every polymarket.
* Rewards are paid out once a day at midnight UTC.
* Rewards are unlimited. You will earn more money the more the users you refer trade on the platform.
* Polymarket reserves the right, in its sole discretion, to disqualify referrals that violate our Terms of Service — including but not limited to self-referrals or inauthentic trading.


# Deposit
Source: https://docs.polymarket.com/trading/bridge/deposit

Bridge assets from any supported chain to fund your Polymarket account

Polymarket uses **pUSD** (Polymarket USD) on Polygon as collateral for all trading. The Bridge API lets you deposit assets from Ethereum, Solana, Bitcoin, and other chains—they're automatically converted to pUSD on Polygon.

## How It Works

1. Request deposit addresses for your Polymarket wallet
2. Send assets to the appropriate address for your source chain
3. Assets are bridged and swapped to pUSD automatically
4. pUSD is credited to your wallet for trading

## Create 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 pUSD

You can deposit either USDC (native) or USDC.e (bridged) as the source asset to your Polymarket wallet. Either way, the incoming USDC or USDC.e is wrapped into pUSD via the Collateral Onramp, and pUSD is what you hold and trade with on Polymarket.

## Large Deposits

For deposits over \$50,000 originating from a chain other than Polygon, we recommend using a third-party bridge to minimize slippage:

* [DeBridge](https://app.debridge.finance/)
* [Across](https://app.across.to/bridge)
* [Portal](https://portalbridge.com/)

Bridge directly to your Polymarket USDC (Polygon) 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, use this tool to recover your funds:

[recovery.polymarket.com](https://recovery.polymarket.com/)

<Warning>
  Sending unsupported tokens may cause **irrecoverable loss**. Always verify
  your token is listed in [Supported Assets](/trading/bridge/supported-assets)
  before depositing.
</Warning>

## Next Steps

<CardGroup>
  <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>


# Quote
Source: https://docs.polymarket.com/trading/bridge/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": "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"
  }'
```

### 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>
  <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>


# Deposit Status
Source: https://docs.polymarket.com/trading/bridge/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                   |

<Note>
  If a bridge transaction fails, remains stuck, or funds are held due to a
  compliance check, direct users to
  [our Bridge API provider's support](https://intercom.help/funxyz/en/articles/10732578-contact-us)
  to resolve the issue.
</Note>

## Response

A response with active deposits:

```json theme={null}
{
  "transactions": [
    {
      "fromChainId": "1",
      "fromTokenAddress": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
      "fromAmountBaseUnit": "1000000000",
      "toChainId": "137",
      "toTokenAddress": "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB",
      "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>
  <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>


# Supported Assets
Source: https://docs.polymarket.com/trading/bridge/supported-assets

Chains and tokens supported for deposits to Polymarket

The Bridge API supports deposits from multiple chains and tokens. All deposits are automatically converted to **pUSD on Polygon**, which is used as collateral for trading on Polymarket.

## Get Supported Assets

Retrieve the full list of supported chains and tokens with their minimum deposit amounts.

```bash theme={null}
curl https://bridge.polymarket.com/supported-assets
```

## Supported Chains

The bridge supports deposits from these blockchain networks:

| Chain           | Address Type | Min Deposit | Example Tokens                              |
| --------------- | ------------ | ----------- | ------------------------------------------- |
| Ethereum        | EVM          | \$7         | ETH, USDC, USDT, WBTC, DAI, LINK, UNI, AAVE |
| Polygon         | EVM          | \$2         | POL, USDC, USDT, DAI, WETH, SAND            |
| Arbitrum        | EVM          | \$2         | ETH, ARB, USDC, USDT, DAI, WBTC, USDe       |
| Base            | EVM          | \$2         | ETH, USDC, USDT, DAI, cbBTC, AERO, USDS     |
| Optimism        | EVM          | \$2         | ETH, OP, USDC, USDT, DAI, USDe              |
| BNB Smart Chain | EVM          | \$2         | BNB, USDC, USDT, DAI, ETH, BTCB, BUSD       |
| Solana          | SVM          | \$2         | SOL, USDC, USDT, USDe, TRUMP                |
| Bitcoin         | BTC          | \$9         | BTC                                         |
| Tron            | TVM          | \$9         | USDT                                        |
| HyperEVM        | EVM          | \$2         | HYPE, USDC, USDe, stHYPE, UBTC, UETH        |
| Abstract        | EVM          | \$2         | ETH, USDC, USDT                             |
| Monad           | EVM          | \$2         | MON, USDC, USDT                             |
| Ethereal        | EVM          | \$2         | USDe, WUSDe                                 |
| Katana          | EVM          | \$2         | AUSD                                        |
| Lighter         | EVM          | \$2         | USDC                                        |

<Note>
  Supported assets change over time. Always call `/supported-assets` for the
  current list before initiating a deposit.
</Note>

## Minimum Amounts

Each asset has a `minCheckoutUsd` value—the minimum deposit amount in USD equivalent. Deposits below this threshold may fail to process.

Most L2 chains (Polygon, Arbitrum, Base, Optimism) have low minimums of $2, while Ethereum deposits require $7 minimum. Bitcoin and Tron have \$9 minimums due to higher bridging costs.

## Next Steps

<CardGroup>
  <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>


# Withdraw
Source: https://docs.polymarket.com/trading/bridge/withdraw

Bridge pUSD from Polymarket to any supported chain

Withdraw pUSD 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 pUSD 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, pUSD is unwrapped to USDC via the Collateral Offramp and 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 pUSD directly, which does not
  require Uniswap liquidity — just be aware that some exchanges no longer accept
  pUSD 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 pUSD">
    Transfer pUSD from your Polymarket wallet to the appropriate deposit
    address.
  </Step>

  <Step title="Track Status">Monitor progress using `/status/{address}`.</Step>
</Steps>

## Next Steps

<CardGroup>
  <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>


# Builder Methods
Source: https://docs.polymarket.com/trading/clients/builder

Methods for querying orders and trades attributed to your builder code.

## Overview

Builder attribution in V2 is handled natively through the order struct — you attach your **builder code** (a `bytes32` identifier from your [Builder Profile](https://polymarket.com/settings?tab=builder)) to every order you submit. No separate client configuration is required.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { ClobClient } from "@polymarket/clob-client-v2";

  const client = new ClobClient({
    host: "https://clob.polymarket.com",
    chain: 137,
    signer,
    creds: apiCreds,
    signatureType,
    funderAddress,
  });

  // Attach your builder code on every order
  const response = await client.createAndPostOrder(
    {
      tokenID: "0x...",
      price: 0.55,
      size: 100,
      side: Side.BUY,
      builderCode: process.env.POLY_BUILDER_CODE!,
    },
    { tickSize: "0.01", negRisk: false },
  );
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import ClobClient
  from py_clob_client_v2 import OrderArgs, PartialCreateOrderOptions
  from py_clob_client_v2.order_builder.constants import BUY
  import os

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

  # Attach your builder code on every order
  response = client.create_and_post_order(
      OrderArgs(
          token_id="0x...",
          price=0.55,
          size=100,
          side=BUY,
          builder_code=os.environ["POLY_BUILDER_CODE"],
      ),
      options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
  )
  ```
</CodeGroup>

<Info>
  See [Order Attribution](/trading/orders/attribution) for the full attribution flow.
</Info>

***

## Methods

***

### getOrder

Get details for a specific order by ID.

```typescript Signature theme={null}
async getOrder(orderID: string): Promise<OpenOrder>
```

<CodeGroup>
  ```typescript TypeScript theme={null}
  const order = await client.getOrder("0xb816482a...");
  console.log(order);
  ```

  ```python Python theme={null}
  order = client.get_order("0xb816482a...")
  print(order)
  ```
</CodeGroup>

***

### getOpenOrders

Get all open orders attributed to your builder code.

```typescript Signature theme={null}
async getOpenOrders(
  params?: OpenOrderParams,
  only_first_page?: boolean,
): Promise<OpenOrder[]>
```

**Params**

<ResponseField name="id" type="string">
  Optional. Filter by order ID.
</ResponseField>

<ResponseField name="market" type="string">
  Optional. Filter by market condition ID.
</ResponseField>

<ResponseField name="asset_id" type="string">
  Optional. Filter by token ID.
</ResponseField>

```typescript TypeScript theme={null}
// All open orders for this builder
const orders = await client.getOpenOrders();

// Filtered by market
const marketOrders = await client.getOpenOrders({
  market: "0xbd31dc8a...",
});
```

***

### getBuilderTrades

Retrieves all trades attributed to your builder code. Use this to track which trades were routed through your platform.

```typescript Signature theme={null}
async getBuilderTrades(
  params?: TradeParams,
): Promise<BuilderTradesPaginatedResponse>
```

**Params (`TradeParams`)**

<ResponseField name="id" type="string">
  Optional. Filter trades by trade ID.
</ResponseField>

<ResponseField name="maker_address" type="string">
  Optional. Filter trades by maker address.
</ResponseField>

<ResponseField name="market" type="string">
  Optional. Filter trades by market condition ID.
</ResponseField>

<ResponseField name="asset_id" type="string">
  Optional. Filter trades by asset (token) ID.
</ResponseField>

<ResponseField name="before" type="string">
  Optional. Return trades created before this cursor value.
</ResponseField>

<ResponseField name="after" type="string">
  Optional. Return trades created after this cursor value.
</ResponseField>

**Response (`BuilderTradesPaginatedResponse`)**

<ResponseField name="trades" type="BuilderTrade[]">
  Array of trades attributed to the builder account.
</ResponseField>

<ResponseField name="next_cursor" type="string">
  Cursor string for fetching the next page of results.
</ResponseField>

<ResponseField name="limit" type="number">
  Maximum number of trades returned per page.
</ResponseField>

<ResponseField name="count" type="number">
  Total number of trades returned in this response.
</ResponseField>

**`BuilderTrade` fields**

<ResponseField name="id" type="string">
  Unique identifier for the trade.
</ResponseField>

<ResponseField name="tradeType" type="string">
  Type of the trade.
</ResponseField>

<ResponseField name="takerOrderHash" type="string">
  Hash of the taker order associated with this trade.
</ResponseField>

<ResponseField name="builder" type="string">
  Builder code attributed to this trade.
</ResponseField>

<ResponseField name="market" type="string">
  Condition ID of the market this trade belongs to.
</ResponseField>

<ResponseField name="assetId" type="string">
  Token ID of the asset traded.
</ResponseField>

<ResponseField name="side" type="string">
  Side of the trade (e.g. BUY or SELL).
</ResponseField>

<ResponseField name="size" type="string">
  Size of the trade in shares.
</ResponseField>

<ResponseField name="sizeUsdc" type="string">
  Size of the trade denominated in USDC.
</ResponseField>

<ResponseField name="price" type="string">
  Price at which the trade was executed.
</ResponseField>

<ResponseField name="status" type="string">
  Current status of the trade.
</ResponseField>

<ResponseField name="outcome" type="string">
  Outcome label associated with the traded asset.
</ResponseField>

<ResponseField name="outcomeIndex" type="number">
  Index of the outcome within the market.
</ResponseField>

<ResponseField name="owner" type="string">
  Address of the order owner (taker).
</ResponseField>

<ResponseField name="maker" type="string">
  Address of the maker in the trade.
</ResponseField>

<ResponseField name="transactionHash" type="string">
  On-chain transaction hash for the trade.
</ResponseField>

<ResponseField name="matchTime" type="string">
  Timestamp when the trade was matched.
</ResponseField>

<ResponseField name="bucketIndex" type="number">
  Bucket index used for trade grouping.
</ResponseField>

<ResponseField name="fee" type="string">
  Fee charged for the trade in shares.
</ResponseField>

<ResponseField name="feeUsdc" type="string">
  Fee charged for the trade denominated in USDC.
</ResponseField>

<ResponseField name="err_msg" type="string | null">
  Optional. Error message if the trade encountered an issue, otherwise null.
</ResponseField>

<ResponseField name="createdAt" type="string | null">
  Timestamp when the trade record was created, or null if unavailable.
</ResponseField>

<ResponseField name="updatedAt" type="string | null">
  Timestamp when the trade record was last updated, or null if unavailable.
</ResponseField>

***

## See Also

<CardGroup>
  <Card title="Builders Program" icon="hammer" href="/builders/overview">
    Learn about the Builders Program and its benefits.
  </Card>

  <Card title="Order Attribution" icon="key" href="/trading/orders/attribution">
    Attach your builder code to orders for volume credit.
  </Card>

  <Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
    Place and manage orders with API credentials.
  </Card>

  <Card title="Gasless Transactions" icon="gas-pump" href="/trading/gasless">
    Execute onchain operations without paying gas.
  </Card>
</CardGroup>


# L1 Methods
Source: https://docs.polymarket.com/trading/clients/l1

These methods require a wallet signer (private key) but do not require user API credentials. Use these for initial setup.

## Client Initialization

L1 methods require the client to initialize with a signer.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { ClobClient } from "@polymarket/clob-client-v2";
    import { createWalletClient, http } from "viem";
    import { privateKeyToAccount } from "viem/accounts";

    const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
    const signer = createWalletClient({ account, transport: http() });

    const client = new ClobClient({
      host: "https://clob.polymarket.com",
      chain: 137,
      signer, // Signer required for L1 methods
    });

    // Ready to create user API credentials
    const apiKey = await client.createApiKey();
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from py_clob_client_v2 import ClobClient
    import os

    private_key = os.getenv("PRIVATE_KEY")

    client = ClobClient(
        host="https://clob.polymarket.com",
        chain_id=137,
        key=private_key  # Signer required for L1 methods
    )

    # Ready to create user API credentials
    api_key = client.create_api_key()
    ```
  </Tab>
</Tabs>

<Warning>
  Never commit private keys to version control. Always use environment variables
  or a secure key management system.
</Warning>

***

## API Key Management

***

### createApiKey

Creates a new API key (L2 credentials) for the wallet signer. 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

<Note>
  In CLOB V2, `expiration` is still accepted in order payloads for GTD/order
  expiry handling, but it is not part of the EIP-712 signed order struct. The
  signed struct uses `timestamp`, `metadata`, and `builder` instead of the V1
  `expiration`, `nonce`, `feeRateBps`, and `taker` fields.
</Note>

### createOrder

Create and sign a limit order locally without posting it to the CLOB. Use this when you want to sign orders in advance or implement custom submission logic. Submit via [`postOrder()`](/trading/clients/l2#postorder) or [`postOrders()`](/trading/clients/l2#postorders).

```typescript Signature theme={null}
async createOrder(
  userOrder: UserOrder,
  options?: Partial<CreateOrderOptions>
): Promise<SignedOrder>
```

<ResponseField name="tokenID" type="string">
  The token ID of the market outcome to trade.
</ResponseField>

<ResponseField name="price" type="number">
  The limit price for the order.
</ResponseField>

<ResponseField name="size" type="number">
  The size (number of shares) for the order.
</ResponseField>

<ResponseField name="side" type="Side">
  The side of the order (buy or sell).
</ResponseField>

<ResponseField name="expiration" type="number">
  Optional expiration timestamp included in the order payload for GTD/order
  expiry handling. This is not part of the CLOB V2 EIP-712 signed order struct.
</ResponseField>

<ResponseField name="tickSize" type="TickSize">
  The tick size used for order validation (CreateOrderOptions).
</ResponseField>

<ResponseField name="negRisk" type="boolean">
  Optional flag for negative risk markets (CreateOrderOptions). Optional.
</ResponseField>

<ResponseField name="salt" type="string">
  A random salt value for the signed order.
</ResponseField>

<ResponseField name="maker" type="string">
  The maker's address.
</ResponseField>

<ResponseField name="signer" type="string">
  The signer's address.
</ResponseField>

<ResponseField name="tokenId" type="string">
  The token ID in the signed order.
</ResponseField>

<ResponseField name="makerAmount" type="string">
  The maker amount as a string.
</ResponseField>

<ResponseField name="takerAmount" type="string">
  The taker amount as a string.
</ResponseField>

<ResponseField name="side" type="number">
  The side of the order as a number (0 = BUY, 1 = SELL).
</ResponseField>

<ResponseField name="expiration" type="string">
  The expiration timestamp included in the order payload. This is not part of
  the CLOB V2 EIP-712 signed order struct.
</ResponseField>

<ResponseField name="timestamp" type="string">
  Order creation timestamp in milliseconds, used for order uniqueness in CLOB
  V2.
</ResponseField>

<ResponseField name="metadata" type="string">
  Reserved `bytes32` metadata field.
</ResponseField>

<ResponseField name="builder" type="string">
  Builder code (`bytes32`) for attribution, or zero if no builder code is
  attached.
</ResponseField>

<ResponseField name="signatureType" type="number">
  The type identifier for the signature scheme used.
</ResponseField>

<ResponseField name="signature" type="string">
  The cryptographic signature of the order.
</ResponseField>

***

### createMarketOrder

Create and sign a market order locally without posting it to the CLOB. Submit via [`postOrder()`](/trading/clients/l2#postorder) or [`postOrders()`](/trading/clients/l2#postorders).

```typescript Signature theme={null}
async createMarketOrder(
  userMarketOrder: UserMarketOrder,
  options?: Partial<CreateOrderOptions>
): Promise<SignedOrder>
```

<ResponseField name="tokenID" type="string">
  The token ID of the market outcome to trade.
</ResponseField>

<ResponseField name="amount" type="number">
  The order amount. For BUY orders this is a dollar amount; for SELL orders this
  is the number of shares.
</ResponseField>

<ResponseField name="side" type="Side">
  The side of the order (buy or sell).
</ResponseField>

<ResponseField name="price" type="number">
  Optional price limit for the market order. Optional.
</ResponseField>

<ResponseField name="orderType" type="OrderType.FOK | OrderType.FAK">
  Optional order type, either FOK (Fill-Or-Kill) or FAK (Fill-And-Kill).
  Optional.
</ResponseField>

<ResponseField name="salt" type="string">
  A random salt value for the signed order.
</ResponseField>

<ResponseField name="maker" type="string">
  The maker's address.
</ResponseField>

<ResponseField name="signer" type="string">
  The signer's address.
</ResponseField>

<ResponseField name="tokenId" type="string">
  The token ID in the signed order.
</ResponseField>

<ResponseField name="makerAmount" type="string">
  The maker amount as a string.
</ResponseField>

<ResponseField name="takerAmount" type="string">
  The taker amount as a string.
</ResponseField>

<ResponseField name="side" type="number">
  The side of the order as a number (0 = BUY, 1 = SELL).
</ResponseField>

<ResponseField name="expiration" type="string">
  The expiration timestamp included in the order payload. This is not part of
  the CLOB V2 EIP-712 signed order struct.
</ResponseField>

<ResponseField name="timestamp" type="string">
  Order creation timestamp in milliseconds, used for order uniqueness in CLOB
  V2.
</ResponseField>

<ResponseField name="metadata" type="string">
  Reserved `bytes32` metadata field.
</ResponseField>

<ResponseField name="builder" type="string">
  Builder code (`bytes32`) for attribution, or zero if no builder code is
  attached.
</ResponseField>

<ResponseField name="signatureType" type="number">
  The type identifier for the signature scheme used.
</ResponseField>

<ResponseField name="signature" type="string">
  The cryptographic signature of the order.
</ResponseField>

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Error - INVALID_SIGNATURE">
    Your wallet's private key is incorrect or improperly formatted.

    **Solution:**

    * Verify your private key is a valid hex string (starts with `0x`)
    * Ensure you're using the correct key for the intended address
    * Check that the key has proper permissions
  </Accordion>

  <Accordion title="Error - NONCE_ALREADY_USED">
    The nonce you provided has already been used to create an API key.

    **Solution:**

    * Use `deriveApiKey()` with the same nonce to retrieve existing credentials
    * Or use a different nonce with `createApiKey()`
  </Accordion>

  <Accordion title="Error - Invalid Funder Address">
    Your funder address is incorrect or doesn't match your wallet.

    **Solution:** New API users should use the deposit wallet address as the
    funder with signature type `3`. Existing Safe and Proxy users should use
    their current smart-wallet address.
  </Accordion>

  <Accordion title="Lost API credentials but have nonce">
    Use `deriveApiKey()` with the original nonce:

    ```typescript theme={null}
    const recovered = await client.deriveApiKey(originalNonce);
    ```
  </Accordion>

  <Accordion title="Lost both credentials and nonce">
    There's no way to recover lost credentials without the nonce. Create new ones:

    ```typescript theme={null}
    // Create fresh credentials with a new nonce
    const newCreds = await client.createApiKey();
    // Save the nonce this time!
    ```
  </Accordion>
</AccordionGroup>

***

## See Also

<CardGroup>
  <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>


# L2 Methods
Source: https://docs.polymarket.com/trading/clients/l2

These methods require user API credentials (L2 headers). Use these for placing trades and managing your positions.

## Client Initialization

L2 methods require the client to initialize with a signer, signature type, API credentials, and funder address.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { ClobClient } from "@polymarket/clob-client-v2";
    import { createWalletClient, http } from "viem";
    import { privateKeyToAccount } from "viem/accounts";

    const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
    const signer = createWalletClient({ account, transport: http() });

    const apiCreds = {
      key: process.env.API_KEY,
      secret: process.env.SECRET,
      passphrase: process.env.PASSPHRASE,
    };
    const depositWalletAddress = process.env.DEPOSIT_WALLET_ADDRESS!;

    const client = new ClobClient({
      host: "https://clob.polymarket.com",
      chain: 137,
      signer,
      creds: apiCreds,
      signatureType: 3, // POLY_1271
      funderAddress: depositWalletAddress,
    });

    // Ready to send authenticated requests
    const order = await client.postOrder(signedOrder);
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from py_clob_client_v2 import ClobClient
    from py_clob_client_v2 import ApiCreds
    import os

    api_creds = ApiCreds(
        api_key=os.getenv("API_KEY"),
        api_secret=os.getenv("SECRET"),
        api_passphrase=os.getenv("PASSPHRASE")
    )

    client = ClobClient(
        host="https://clob.polymarket.com",
        chain_id=137,
        key=os.getenv("PRIVATE_KEY"),
        creds=api_creds,
        signature_type=3,  # POLY_1271
        funder=os.getenv("DEPOSIT_WALLET_ADDRESS")
    )

    # Ready to send authenticated requests
    order = client.post_order(signed_order)
    ```
  </Tab>
</Tabs>

***

## Order Creation and Management

***

### createAndPostOrder

Convenience method that creates, signs, and posts a limit order in a single call. Use when you want to buy or sell at a specific price.

```typescript Signature theme={null}
async createAndPostOrder(
  userOrder: UserOrder,
  options?: Partial<CreateOrderOptions>,
  orderType?: OrderType.GTC | OrderType.GTD, // Defaults to GTC
): Promise<OrderResponse>
```

**Params**

<ResponseField name="tokenID" type="string">
  The token ID of the outcome to trade.
</ResponseField>

<ResponseField name="price" type="number">
  The limit price for the order.
</ResponseField>

<ResponseField name="size" type="number">
  The size of the order.
</ResponseField>

<ResponseField name="side" type="Side">
  The side of the order (buy or sell).
</ResponseField>

<ResponseField name="expiration" type="number">
  Optional expiration timestamp for the order.
</ResponseField>

<ResponseField name="tickSize" type="TickSize">
  Tick size for the order. One of `"0.1"`, `"0.01"`, `"0.001"`, `"0.0001"`.
</ResponseField>

<ResponseField name="negRisk" type="boolean">
  Optional. Whether the market uses negative risk.
</ResponseField>

**Response**

<ResponseField name="success" type="boolean">
  Whether the order was successfully placed.
</ResponseField>

<ResponseField name="errorMsg" type="string">
  Error message if the order was not successful.
</ResponseField>

<ResponseField name="orderID" type="string">
  The ID of the placed order.
</ResponseField>

<ResponseField name="transactionsHashes" type="string[]">
  Array of transaction hashes associated with the order.
</ResponseField>

<ResponseField name="status" type="string">
  The current status of the order.
</ResponseField>

<ResponseField name="takingAmount" type="string">
  The amount being taken in the order.
</ResponseField>

<ResponseField name="makingAmount" type="string">
  The amount being made in the order.
</ResponseField>

***

### createAndPostMarketOrder

Convenience method that creates, signs, and posts a market order in a single call. Use when you want to buy or sell at the current market price.

```typescript Signature theme={null}
async createAndPostMarketOrder(
  userMarketOrder: UserMarketOrder,
  options?: Partial<CreateOrderOptions>,
  orderType?: OrderType.FOK | OrderType.FAK, // Defaults to FOK
): Promise<OrderResponse>
```

**Params**

<ResponseField name="tokenID" type="string">
  The token ID of the outcome to trade.
</ResponseField>

<ResponseField name="amount" type="number">
  The amount for the market order.
</ResponseField>

<ResponseField name="side" type="Side">
  The side of the order (buy or sell).
</ResponseField>

<ResponseField name="price" type="number">
  Optional price hint for the market order.
</ResponseField>

<ResponseField name="orderType" type="OrderType.FOK | OrderType.FAK">
  Optional order type override. Defaults to FOK.
</ResponseField>

**Response**

<ResponseField name="success" type="boolean">
  Whether the order was successfully placed.
</ResponseField>

<ResponseField name="errorMsg" type="string">
  Error message if the order was not successful.
</ResponseField>

<ResponseField name="orderID" type="string">
  The ID of the placed order.
</ResponseField>

<ResponseField name="transactionsHashes" type="string[]">
  Array of transaction hashes associated with the order.
</ResponseField>

<ResponseField name="status" type="string">
  The current status of the order.
</ResponseField>

<ResponseField name="takingAmount" type="string">
  The amount being taken in the order.
</ResponseField>

<ResponseField name="makingAmount" type="string">
  The amount being made in the order.
</ResponseField>

***

### postOrder

Posts a pre-signed order to the CLOB. Use with [`createOrder()`](/trading/clients/l1#createorder) or [`createMarketOrder()`](/trading/clients/l1#createmarketorder) from L1 methods.

```typescript Signature theme={null}
async postOrder(
  order: SignedOrder,
  orderType?: OrderType, // Defaults to GTC
  postOnly?: boolean,    // Defaults to false
): Promise<OrderResponse>
```

***

### postOrders

Posts up to 15 pre-signed orders in a single batch.

```typescript Signature theme={null}
async postOrders(
  args: PostOrdersArgs[],
): Promise<OrderResponse[]>
```

**Params**

<ResponseField name="order" type="SignedOrder">
  The pre-signed order to post.
</ResponseField>

<ResponseField name="orderType" type="OrderType">
  The order type (e.g. GTC, FOK, FAK).
</ResponseField>

<ResponseField name="postOnly" type="boolean">
  Optional. Whether to post the order as post-only. Defaults to false.
</ResponseField>

***

### cancelOrder

Cancels a single open order.

```typescript Signature theme={null}
async cancelOrder(orderID: string): Promise<CancelOrdersResponse>
```

**Response**

<ResponseField name="canceled" type="string[]">
  Array of order IDs that were successfully canceled.
</ResponseField>

<ResponseField name="not_canceled" type="Record<string, any>">
  Map of order IDs to reasons why they could not be canceled.
</ResponseField>

***

### cancelOrders

Cancels multiple orders in a single batch.

```typescript Signature theme={null}
async cancelOrders(orderIDs: string[]): Promise<CancelOrdersResponse>
```

***

### cancelAll

Cancels all open orders.

```typescript Signature theme={null}
async cancelAll(): Promise<CancelOrdersResponse>
```

***

### cancelMarketOrders

Cancels all open orders for a specific market.

```typescript Signature theme={null}
async cancelMarketOrders(
  payload: OrderMarketCancelParams
): Promise<CancelOrdersResponse>
```

**Params**

<ResponseField name="market" type="string">
  Optional. The market condition ID to cancel orders for.
</ResponseField>

<ResponseField name="asset_id" type="string">
  Optional. The token ID to cancel orders for.
</ResponseField>

***

## Order and Trade Queries

***

### getOrder

Get details for a specific order by ID.

```typescript Signature theme={null}
async getOrder(orderID: string): Promise<OpenOrder>
```

**Response**

<ResponseField name="id" type="string">
  The unique order ID.
</ResponseField>

<ResponseField name="status" type="string">
  The current status of the order.
</ResponseField>

<ResponseField name="owner" type="string">
  The API key of the order owner.
</ResponseField>

<ResponseField name="maker_address" type="string">
  The on-chain address of the order maker.
</ResponseField>

<ResponseField name="market" type="string">
  The market condition ID the order belongs to.
</ResponseField>

<ResponseField name="asset_id" type="string">
  The token ID the order is for.
</ResponseField>

<ResponseField name="side" type="string">
  The side of the order (BUY or SELL).
</ResponseField>

<ResponseField name="original_size" type="string">
  The original size of the order when it was placed.
</ResponseField>

<ResponseField name="size_matched" type="string">
  The amount of the order that has been matched so far.
</ResponseField>

<ResponseField name="price" type="string">
  The limit price of the order.
</ResponseField>

<ResponseField name="associate_trades" type="string[]">
  Array of trade IDs associated with this order.
</ResponseField>

<ResponseField name="outcome" type="string">
  The outcome label for the order's token.
</ResponseField>

<ResponseField name="created_at" type="number">
  Unix timestamp of when the order was created.
</ResponseField>

<ResponseField name="expiration" type="string">
  The expiration time of the order.
</ResponseField>

<ResponseField name="order_type" type="string">
  The order type (e.g. GTC, FOK, FAK, GTD).
</ResponseField>

***

### getOpenOrders

Get all your open orders.

```typescript Signature theme={null}
async getOpenOrders(
  params?: OpenOrderParams,
  only_first_page?: boolean,
): Promise<OpenOrder[]>
```

**Params**

<ResponseField name="id" type="string">
  Optional. Filter by order ID.
</ResponseField>

<ResponseField name="market" type="string">
  Optional. Filter by market condition ID.
</ResponseField>

<ResponseField name="asset_id" type="string">
  Optional. Filter by token ID.
</ResponseField>

***

### getTrades

Get your trade history (filled orders).

```typescript Signature theme={null}
async getTrades(
  params?: TradeParams,
  only_first_page?: boolean,
): Promise<Trade[]>
```

**Params**

<ResponseField name="id" type="string">
  Optional. Filter by trade ID.
</ResponseField>

<ResponseField name="maker_address" type="string">
  Optional. Filter by maker address.
</ResponseField>

<ResponseField name="market" type="string">
  Optional. Filter by market condition ID.
</ResponseField>

<ResponseField name="asset_id" type="string">
  Optional. Filter by token ID.
</ResponseField>

<ResponseField name="before" type="string">
  Optional. Return trades before this timestamp.
</ResponseField>

<ResponseField name="after" type="string">
  Optional. Return trades after this timestamp.
</ResponseField>

**Response**

<ResponseField name="id" type="string">
  The unique trade ID.
</ResponseField>

<ResponseField name="taker_order_id" type="string">
  The order ID of the taker side.
</ResponseField>

<ResponseField name="market" type="string">
  The market condition ID for the trade.
</ResponseField>

<ResponseField name="asset_id" type="string">
  The token ID for the trade.
</ResponseField>

<ResponseField name="side" type="Side">
  The side of the trade (BUY or SELL).
</ResponseField>

<ResponseField name="size" type="string">
  The size of the trade.
</ResponseField>

<ResponseField name="fee_rate_bps" type="string">
  The fee rate in basis points.
</ResponseField>

<ResponseField name="price" type="string">
  The price at which the trade was matched.
</ResponseField>

<ResponseField name="status" type="string">
  The current status of the trade.
</ResponseField>

<ResponseField name="match_time" type="string">
  The time at which the trade was matched.
</ResponseField>

<ResponseField name="last_update" type="string">
  The time of the last update to this trade.
</ResponseField>

<ResponseField name="outcome" type="string">
  The outcome label for the traded token.
</ResponseField>

<ResponseField name="bucket_index" type="number">
  The bucket index for the trade.
</ResponseField>

<ResponseField name="owner" type="string">
  The API key of the trade owner.
</ResponseField>

<ResponseField name="maker_address" type="string">
  The on-chain address of the maker.
</ResponseField>

<ResponseField name="maker_orders" type="MakerOrder[]">
  Array of maker order objects that participated in this trade. Each
  `MakerOrder` contains the following fields:
</ResponseField>

<ResponseField name="maker_orders[].order_id" type="string">
  The maker order ID.
</ResponseField>

<ResponseField name="maker_orders[].owner" type="string">
  The API key of the maker order owner.
</ResponseField>

<ResponseField name="maker_orders[].maker_address" type="string">
  The on-chain address of the maker order maker.
</ResponseField>

<ResponseField name="maker_orders[].matched_amount" type="string">
  The amount matched for this maker order.
</ResponseField>

<ResponseField name="maker_orders[].price" type="string">
  The price of the maker order.
</ResponseField>

<ResponseField name="maker_orders[].fee_rate_bps" type="string">
  The fee rate in basis points for the maker order.
</ResponseField>

<ResponseField name="maker_orders[].asset_id" type="string">
  The token ID for the maker order.
</ResponseField>

<ResponseField name="maker_orders[].outcome" type="string">
  The outcome label for the maker order's token.
</ResponseField>

<ResponseField name="maker_orders[].side" type="Side">
  The side of the maker order (BUY or SELL).
</ResponseField>

<ResponseField name="transaction_hash" type="string">
  The on-chain transaction hash for the trade.
</ResponseField>

<ResponseField name="trader_side" type="&#x22;TAKER&#x22; | &#x22;MAKER&#x22;">
  Whether the authenticated user is the taker or a maker in this trade.
</ResponseField>

***

### getTradesPaginated

Get trade history with pagination for large result sets.

```typescript Signature theme={null}
async getTradesPaginated(
  params?: TradeParams,
): Promise<TradesPaginatedResponse>
```

**Response**

<ResponseField name="trades" type="Trade[]">
  Array of trade objects for the current page.
</ResponseField>

<ResponseField name="limit" type="number">
  The maximum number of trades returned per page.
</ResponseField>

<ResponseField name="count" type="number">
  The total number of trades matching the query.
</ResponseField>

***

## Balance and Allowances

***

### getBalanceAllowance

Get your balance and allowance for specific tokens.

```typescript Signature theme={null}
async getBalanceAllowance(
  params?: BalanceAllowanceParams
): Promise<BalanceAllowanceResponse>
```

**Params**

<ResponseField name="asset_type" type="AssetType">
  The type of asset to query. One of `"COLLATERAL"` or `"CONDITIONAL"`.
</ResponseField>

<ResponseField name="token_id" type="string">
  Optional. The token ID to query (required when `asset_type` is `CONDITIONAL`).
</ResponseField>

**Response**

<ResponseField name="balance" type="string">
  The current balance for the specified asset.
</ResponseField>

<ResponseField name="allowance" type="string">
  The current allowance for the specified asset.
</ResponseField>

***

### updateBalanceAllowance

Updates the cached balance and allowance for specific tokens.

```typescript Signature theme={null}
async updateBalanceAllowance(
  params?: BalanceAllowanceParams
): Promise<void>
```

***

## API Key Management

***

### getApiKeys

Get all API keys associated with your account.

```typescript Signature theme={null}
async getApiKeys(): Promise<ApiKeysResponse>
```

**Response**

<ResponseField name="apiKeys" type="ApiKeyCreds[]">
  Array of API key credential objects associated with the account.
</ResponseField>

***

### deleteApiKey

Deletes (revokes) the currently authenticated API key.

```typescript Signature theme={null}
async deleteApiKey(): Promise<any>
```

***

## Notifications

***

### getNotifications

Retrieves all event notifications for the authenticated user. Records are automatically removed after 48 hours.

```typescript Signature theme={null}
async getNotifications(): Promise<Notification[]>
```

**Response**

<ResponseField name="id" type="number">
  Unique notification ID.
</ResponseField>

<ResponseField name="owner" type="string">
  The user's API key, or an empty string for global notifications.
</ResponseField>

<ResponseField name="payload" type="any">
  Type-specific payload data for the notification.
</ResponseField>

<ResponseField name="timestamp" type="number">
  Optional Unix timestamp of when the notification was created.
</ResponseField>

<ResponseField name="type" type="number">
  Notification type (see below).
</ResponseField>

| Name               | Value | Description                              |
| ------------------ | ----- | ---------------------------------------- |
| Order Cancellation | `1`   | User's order was canceled                |
| Order Fill         | `2`   | User's order was filled (maker or taker) |
| Market Resolved    | `4`   | Market was resolved                      |

***

### dropNotifications

Mark notifications as read/dismissed.

```typescript Signature theme={null}
async dropNotifications(params?: DropNotificationParams): Promise<void>
```

**Params**

<ResponseField name="ids" type="string[]">
  Array of notification IDs to dismiss.
</ResponseField>

***

## See Also

<CardGroup>
  <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>


# Public Methods
Source: https://docs.polymarket.com/trading/clients/public

These methods can be called without a signer or user credentials. Use these for reading market data, prices, and order books.

## Client Initialization

Public methods require the client to initialize with the host URL and Polygon chain ID.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { ClobClient } from "@polymarket/clob-client-v2";

    const client = new ClobClient({
      host: "https://clob.polymarket.com",
      chain: 137,
    });

    // Ready to call public methods
    const markets = await client.getMarkets();
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from py_clob_client_v2 import ClobClient

    client = ClobClient(
        host="https://clob.polymarket.com",
        chain_id=137
    )

    # Ready to call public methods
    markets = client.get_markets()
    ```
  </Tab>
</Tabs>

***

## Health Check

***

### getOk

Health check endpoint to verify the CLOB service is operational.

```typescript Signature theme={null}
async getOk(): Promise<any>
```

***

## Markets

***

### getMarket

Get details for a single market by condition ID.

```typescript Signature theme={null}
async getMarket(conditionId: string): Promise<Market>
```

<ResponseField name="accepting_order_timestamp" type="string">
  Timestamp from which the market started accepting orders, or null if not set.
</ResponseField>

<ResponseField name="accepting_orders" type="boolean">
  Whether the market is currently accepting orders.
</ResponseField>

<ResponseField name="active" type="boolean">
  Whether the market is active.
</ResponseField>

<ResponseField name="archived" type="boolean">
  Whether the market has been archived.
</ResponseField>

<ResponseField name="closed" type="boolean">
  Whether the market is closed.
</ResponseField>

<ResponseField name="condition_id" type="string">
  The unique condition ID for the market.
</ResponseField>

<ResponseField name="description" type="string">
  Human-readable description of the market.
</ResponseField>

<ResponseField name="enable_order_book" type="boolean">
  Whether the order book is enabled for this market.
</ResponseField>

<ResponseField name="end_date_iso" type="string">
  ISO 8601 end date of the market.
</ResponseField>

<ResponseField name="fpmm" type="string">
  Address of the Fixed Product Market Maker contract.
</ResponseField>

<ResponseField name="game_start_time" type="string">
  Start time of the underlying game or event.
</ResponseField>

<ResponseField name="icon" type="string">
  URL of the market icon image.
</ResponseField>

<ResponseField name="image" type="string">
  URL of the market image.
</ResponseField>

<ResponseField name="is_50_50_outcome" type="boolean">
  Whether the market has equal 50/50 outcomes.
</ResponseField>

<ResponseField name="maker_base_fee" type="number">
  Base fee charged to makers in basis points.
</ResponseField>

<ResponseField name="market_slug" type="string">
  URL-friendly slug identifier for the market.
</ResponseField>

<ResponseField name="minimum_order_size" type="number">
  Minimum order size allowed in this market.
</ResponseField>

<ResponseField name="minimum_tick_size" type="number">
  Minimum price increment allowed in this market.
</ResponseField>

<ResponseField name="neg_risk" type="boolean">
  Whether the market uses negative risk (binary complementary tokens).
</ResponseField>

<ResponseField name="neg_risk_market_id" type="string">
  Negative risk market identifier, if applicable.
</ResponseField>

<ResponseField name="neg_risk_request_id" type="string">
  Negative risk request identifier, if applicable.
</ResponseField>

<ResponseField name="notifications_enabled" type="boolean">
  Whether notifications are enabled for this market.
</ResponseField>

<ResponseField name="question" type="string">
  The market question text.
</ResponseField>

<ResponseField name="question_id" type="string">
  Unique identifier for the market question.
</ResponseField>

<ResponseField name="rewards" type="object">
  Object containing reward config: `max_spread` (number), `min_size` (number), `rates` (any)
</ResponseField>

<ResponseField name="seconds_delay" type="number">
  Delay in seconds before orders are processed.
</ResponseField>

<ResponseField name="tags" type="string[]">
  List of tags associated with the market.
</ResponseField>

<ResponseField name="taker_base_fee" type="number">
  Base fee charged to takers in basis points.
</ResponseField>

<ResponseField name="tokens" type="MarketToken[]">
  Array of market tokens, each containing `outcome` (string), `price` (number), `token_id` (string), and `winner` (boolean).
</ResponseField>

***

### getMarkets

Get details for multiple markets paginated.

```typescript Signature theme={null}
async getMarkets(): Promise<PaginationPayload>
```

<ResponseField name="limit" type="number">
  Maximum number of results per page.
</ResponseField>

<ResponseField name="count" type="number">
  Total number of markets returned.
</ResponseField>

<ResponseField name="data" type="Market[]">
  Array of Market objects. See `getMarket()` for the full Market structure.
</ResponseField>

***

### getSimplifiedMarkets

Get simplified market data paginated for faster loading.

```typescript Signature theme={null}
async getSimplifiedMarkets(): Promise<PaginationPayload>
```

<ResponseField name="limit" type="number">
  Maximum number of results per page.
</ResponseField>

<ResponseField name="count" type="number">
  Total number of markets returned.
</ResponseField>

<ResponseField name="data" type="SimplifiedMarket[]">
  Array of simplified market objects, each containing `accepting_orders` (boolean), `active` (boolean), `archived` (boolean), `closed` (boolean), `condition_id` (string), `rewards` (object with `rates`, `min_size`, `max_spread`), and `tokens` (SimplifiedToken\[]) with `outcome` (string), `price` (number), `token_id` (string).
</ResponseField>

***

### getSamplingMarkets

Get markets eligible for sampling/liquidity rewards.

```typescript Signature theme={null}
async getSamplingMarkets(): Promise<PaginationPayload>
```

***

### getSamplingSimplifiedMarkets

Get simplified market data for markets eligible for sampling/liquidity rewards.

```typescript Signature theme={null}
async getSamplingSimplifiedMarkets(): Promise<PaginationPayload>
```

***

## Order Books and Prices

***

### calculateMarketPrice

Calculate the estimated price for a market order of a given size.

```typescript Signature theme={null}
async calculateMarketPrice(
  tokenID: string,
  side: Side,
  amount: number,
  orderType: OrderType = OrderType.FOK
): Promise<number>
```

<ResponseField name="tokenID" type="string">
  The token ID to calculate the market price for.
</ResponseField>

<ResponseField name="side" type="Side">
  The side of the order. One of: `BUY`, `SELL`
</ResponseField>

<ResponseField name="amount" type="number">
  The size of the order to calculate price for.
</ResponseField>

<ResponseField name="orderType" type="OrderType">
  The order type. One of: `GTC` (Good Till Cancelled), `FOK` (Fill or Kill), `GTD` (Good Till Date), `FAK` (Fill and Kill). Defaults to `FOK`.
</ResponseField>

<ResponseField name="returns" type="number">
  The calculated estimated market price for the given order size.
</ResponseField>

***

### getOrderBook

Get the order book for a specific token ID.

```typescript Signature theme={null}
async getOrderBook(tokenID: string): Promise<OrderBookSummary>
```

<ResponseField name="market" type="string">
  The market condition ID.
</ResponseField>

<ResponseField name="asset_id" type="string">
  The token/asset ID for this order book.
</ResponseField>

<ResponseField name="timestamp" type="string">
  Timestamp of the order book snapshot.
</ResponseField>

<ResponseField name="bids" type="OrderSummary[]">
  Array of bid entries, each with `price` (string) and `size` (string).
</ResponseField>

<ResponseField name="asks" type="OrderSummary[]">
  Array of ask entries, each with `price` (string) and `size` (string).
</ResponseField>

<ResponseField name="min_order_size" type="string">
  Minimum order size for this market.
</ResponseField>

<ResponseField name="tick_size" type="string">
  Minimum price increment for this market.
</ResponseField>

<ResponseField name="neg_risk" type="boolean">
  Whether the market uses negative risk.
</ResponseField>

<ResponseField name="hash" type="string">
  Hash of the order book state.
</ResponseField>

***

### getOrderBooks

Get order books for multiple token IDs.

```typescript Signature theme={null}
async getOrderBooks(params: BookParams[]): Promise<OrderBookSummary[]>
```

<ResponseField name="token_id" type="string">
  The token ID to fetch the order book for.
</ResponseField>

<ResponseField name="side" type="Side">
  The side of the book to query. One of: `BUY`, `SELL`
</ResponseField>

<ResponseField name="returns" type="OrderBookSummary[]">
  Array of OrderBookSummary objects. See `getOrderBook()` for the full structure.
</ResponseField>

***

### getPrice

Get the current best price for buying or selling a token ID.

```typescript Signature theme={null}
async getPrice(
  tokenID: string,
  side: "BUY" | "SELL"
): Promise<any>
```

<ResponseField name="price" type="string">
  The current best price for the requested side.
</ResponseField>

***

### getPrices

Get the current best prices for multiple token IDs.

```typescript Signature theme={null}
async getPrices(params: BookParams[]): Promise<PricesResponse>
```

<ResponseField name="returns" type="PricesResponse">
  A map of token IDs to their prices. Each entry contains an optional `BUY` (string) and/or `SELL` (string) price.
</ResponseField>

***

### getMidpoint

Get the midpoint price (average of best bid and best ask) for a token ID.

```typescript Signature theme={null}
async getMidpoint(tokenID: string): Promise<any>
```

<ResponseField name="mid" type="string">
  The midpoint price, calculated as the average of best bid and best ask.
</ResponseField>

***

### getMidpoints

Get the midpoint prices for multiple token IDs.

```typescript Signature theme={null}
async getMidpoints(params: BookParams[]): Promise<any>
```

<ResponseField name="returns" type="object">
  A map of token IDs to their midpoint price strings. Each key is a token ID and its value is the midpoint price as a string.
</ResponseField>

***

### getSpread

Get the spread (difference between best ask and best bid) for a token ID.

```typescript Signature theme={null}
async getSpread(tokenID: string): Promise<SpreadResponse>
```

<ResponseField name="spread" type="string">
  The spread value, calculated as the difference between best ask and best bid.
</ResponseField>

***

### getSpreads

Get the spreads for multiple token IDs.

```typescript Signature theme={null}
async getSpreads(params: BookParams[]): Promise<SpreadsResponse>
```

<ResponseField name="returns" type="object">
  A map of token IDs to their spread strings. Each key is a token ID and its value is the spread as a string.
</ResponseField>

***

### getPricesHistory

Get historical price data for a token.

```typescript Signature theme={null}
async getPricesHistory(params: PriceHistoryFilterParams): Promise<MarketPrice[]>
```

<ResponseField name="market" type="string">
  The token ID to fetch price history for.
</ResponseField>

<ResponseField name="startTs" type="number">
  Optional start timestamp (Unix seconds) for the price history range.
</ResponseField>

<ResponseField name="endTs" type="number">
  Optional end timestamp (Unix seconds) for the price history range.
</ResponseField>

<ResponseField name="fidelity" type="number">
  Optional fidelity/resolution of the price history data.
</ResponseField>

<ResponseField name="interval" type="PriceHistoryInterval">
  Time interval for the price history. One of: `max`, `1w`, `1d`, `6h`, `1h`
</ResponseField>

<ResponseField name="t" type="number">
  Unix timestamp of the price data point.
</ResponseField>

<ResponseField name="p" type="number">
  Price value at the corresponding timestamp.
</ResponseField>

***

## Trades

***

### getLastTradePrice

Get the price of the most recent trade for a token.

```typescript Signature theme={null}
async getLastTradePrice(tokenID: string): Promise<LastTradePrice>
```

<ResponseField name="price" type="string">
  The price of the most recent trade.
</ResponseField>

<ResponseField name="side" type="string">
  The side of the most recent trade.
</ResponseField>

***

### getLastTradesPrices

Get the most recent trade prices for multiple tokens.

```typescript Signature theme={null}
async getLastTradesPrices(params: BookParams[]): Promise<LastTradePriceWithToken[]>
```

<ResponseField name="price" type="string">
  The price of the most recent trade for the token.
</ResponseField>

<ResponseField name="side" type="string">
  The side of the most recent trade.
</ResponseField>

<ResponseField name="token_id" type="string">
  The token ID this trade price corresponds to.
</ResponseField>

***

### getMarketTradesEvents

Get recent trade events for a market.

```typescript Signature theme={null}
async getMarketTradesEvents(conditionID: string): Promise<MarketTradeEvent[]>
```

<ResponseField name="event_type" type="string">
  The type of trade event.
</ResponseField>

<ResponseField name="market" type="object">
  Object containing market info: `condition_id` (string), `asset_id` (string), `question` (string), `icon` (string), `slug` (string).
</ResponseField>

<ResponseField name="user" type="object">
  Object containing user info: `address` (string), `username` (string), `profile_picture` (string), `optimized_profile_picture` (string), `pseudonym` (string).
</ResponseField>

<ResponseField name="side" type="Side">
  The side of the trade. One of: `BUY`, `SELL`
</ResponseField>

<ResponseField name="size" type="string">
  The size of the trade.
</ResponseField>

<ResponseField name="fee_rate_bps" type="string">
  The fee rate in basis points for the trade.
</ResponseField>

<ResponseField name="price" type="string">
  The price at which the trade was executed.
</ResponseField>

<ResponseField name="outcome" type="string">
  The outcome label for the traded token.
</ResponseField>

<ResponseField name="outcome_index" type="number">
  The index of the outcome in the market.
</ResponseField>

<ResponseField name="transaction_hash" type="string">
  The on-chain transaction hash for the trade.
</ResponseField>

<ResponseField name="timestamp" type="string">
  The timestamp of when the trade event occurred.
</ResponseField>

***

## Market Parameters

***

### getClobMarketInfo

Fetch all CLOB-level parameters for a market in a single call — tokens, tick size, base fees, rewards config, RFQ status, and fee details.

```typescript Signature theme={null}
async getClobMarketInfo(conditionID: string): Promise<ClobMarketDetails>
```

<ResponseField name="conditionID" type="string">
  The condition ID of the market.
</ResponseField>

**Response (`ClobMarketDetails`)**

<ResponseField name="gst" type="string | null">
  Game start time (used for sports markets), ISO 8601 timestamp or `null`.
</ResponseField>

<ResponseField name="r" type="object">
  Rewards configuration for the market.
</ResponseField>

<ResponseField name="t" type="ClobToken[]">
  Tokens for this market. Each entry has:

  * `t` (string) — token ID
  * `o` (string) — outcome label (e.g. `Yes`, `No`)
</ResponseField>

<ResponseField name="mos" type="number">
  Minimum order size.
</ResponseField>

<ResponseField name="mts" type="number">
  Minimum tick size (price increment).
</ResponseField>

<ResponseField name="mbf" type="number">
  Maker base fee in basis points.
</ResponseField>

<ResponseField name="tbf" type="number">
  Taker base fee in basis points.
</ResponseField>

<ResponseField name="rfqe" type="boolean">
  Whether RFQ (Request for Quote) is enabled for this market.
</ResponseField>

<ResponseField name="itode" type="boolean">
  Whether taker order delay is enabled.
</ResponseField>

<ResponseField name="ibce" type="boolean">
  Whether Blockaid check is enabled.
</ResponseField>

<ResponseField name="fd" type="object">
  Fee curve parameters:

  * `r` (number) — fee rate
  * `e` (number) — fee curve exponent
  * `to` (boolean) — whether fees apply to takers only
</ResponseField>

<ResponseField name="oas" type="number">
  Minimum order age in seconds.
</ResponseField>

***

### getFeeRateBps

Get the fee rate in basis points for a token.

```typescript Signature theme={null}
async getFeeRateBps(tokenID: string): Promise<number>
```

<ResponseField name="returns" type="number">
  The fee rate in basis points for the specified token.
</ResponseField>

***

### getFeeExponent

Get the fee curve exponent for a token. The exponent shapes the fee curve used by the protocol when calculating fees at match time.

```typescript Signature theme={null}
async getFeeExponent(tokenID: string): Promise<number>
```

<ResponseField name="returns" type="number">
  The fee curve exponent for the specified token's market.
</ResponseField>

***

### getTickSize

Get the tick size (minimum price increment) for a market.

```typescript Signature theme={null}
async getTickSize(tokenID: string): Promise<TickSize>
```

<ResponseField name="returns" type="string">
  The tick size for the market. One of: `0.1`, `0.01`, `0.001`, `0.0001`
</ResponseField>

***

### getNegRisk

Check if a market uses negative risk (binary complementary tokens).

```typescript Signature theme={null}
async getNegRisk(tokenID: string): Promise<boolean>
```

<ResponseField name="returns" type="boolean">
  Whether the market uses negative risk.
</ResponseField>

***

## Time and Server Info

### getServerTime

Get the current server timestamp.

```typescript Signature theme={null}
async getServerTime(): Promise<number>
```

<ResponseField name="returns" type="number">
  Unix timestamp in seconds representing the current server time.
</ResponseField>

***

## See Also

<CardGroup>
  <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>


# Merge Tokens
Source: https://docs.polymarket.com/trading/ctf/merge

Convert outcome token pairs back to pUSD

**Merging** is the inverse of splitting — it converts a full set of outcome tokens back into pUSD collateral. For every 1 Yes token and 1 No token you merge, you receive \$1 pUSD. The condition must already be prepared on the CTF contract (via `prepareCondition`).

```
100 Yes tokens + 100 No tokens → $100 pUSD
```

## Prerequisites

Before merging, you need:

1. **Equal amounts** of both Yes and No tokens
2. **Condition ID** of the market
3. **Sufficient gas** for the transaction

<Note>
  Polymarket uses thin collateral adapter contracts for pUSD-native CTF actions.
  Approve the adapter once, then route split, merge, and redeem actions through
  it. For merge flows, the adapter calls the underlying CTF contract, receives
  the released USDC.e collateral, wraps it into pUSD, and returns pUSD to your
  wallet automatically.
</Note>

## How It Works

1. You call the adapter's merge flow with the amount and market details
2. One unit of each position in a full set is burned in return for 1 collateral unit
3. The adapter converts the released collateral into pUSD and returns pUSD to your wallet

The operation is atomic — if you don't have enough of both tokens, the transaction reverts.

## Function Parameters

<ResponseField name="collateralToken" type="IERC20">
  pUSD (Polymarket USD) contract address: `0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB`
</ResponseField>

<ResponseField name="parentCollectionId" type="bytes32">
  Always `0x0000...0000` (32 zero bytes) for Polymarket markets
</ResponseField>

<ResponseField name="conditionId" type="bytes32">
  The market's condition ID, available from the Markets API
</ResponseField>

<ResponseField name="partition" type="uint[]">
  Array of index sets: `[1, 2]` for binary markets
</ResponseField>

<ResponseField name="amount" type="uint256">
  The number of full sets to merge. Also the amount of collateral to receive.
</ResponseField>

## Next Steps

<CardGroup>
  <Card title="Redeem Tokens" icon="hand-holding-dollar" href="/trading/ctf/redeem">
    Exchange winning tokens for pUSD after resolution
  </Card>

  <Card title="CTF Overview" icon="book" href="/trading/ctf/overview">
    Learn more about the Conditional Token Framework
  </Card>
</CardGroup>


# Conditional Token Framework
Source: https://docs.polymarket.com/trading/ctf/overview

Onchain token mechanics powering Polymarket positions

All outcomes on Polymarket are tokenized using the **Conditional Token Framework (CTF)**, an open standard developed by Gnosis. Understanding CTF operations enables advanced trading strategies, market making, and direct smart contract interactions.

## What is CTF

The Conditional Token Framework creates **ERC1155 tokens** representing outcomes of prediction markets. Each binary market has two tokens:

| Token   | Redeems for | Condition            |
| ------- | ----------- | -------------------- |
| **Yes** | \$1.00 pUSD | Event occurs         |
| **No**  | \$1.00 pUSD | Event does not occur |

These tokens are always **fully collateralized** — every Yes/No pair is backed by exactly \$1.00 pUSD locked in the CTF contract.

## Core Operations

CTF provides three fundamental operations:

<CardGroup>
  <Card title="Split" icon="scissors" href="/trading/ctf/split">
    Convert pUSD into Yes + No token pairs
  </Card>

  <Card title="Merge" icon="merge" href="/trading/ctf/merge">
    Convert Yes + No pairs back to pUSD
  </Card>

  <Card title="Redeem" icon="hand-holding-dollar" href="/trading/ctf/redeem">
    Exchange winning tokens for pUSD after resolution
  </Card>
</CardGroup>

## Token Flow

<Frame>
  <img alt="" />

  <img alt="" />
</Frame>

## Token Identifiers

Each outcome token has a unique **position ID** (also called token ID or asset ID), computed onchain in three steps.

### Step 1 - Condition ID

```
getConditionId(oracle, questionId, outcomeSlotCount)
```

| Parameter          | Type      | Value                                                            |
| ------------------ | --------- | ---------------------------------------------------------------- |
| `oracle`           | `address` | [UMA CTF Adapter](https://github.com/Polymarket/uma-ctf-adapter) |
| `questionId`       | `bytes32` | Hash of the UMA ancillary data                                   |
| `outcomeSlotCount` | `uint`    | `2` for all binary markets                                       |

### Step 2 - Collection IDs

```
getCollectionId(parentCollectionId, conditionId, indexSet)
```

| Parameter            | Type      | Value                                                           |
| -------------------- | --------- | --------------------------------------------------------------- |
| `parentCollectionId` | `bytes32` | `bytes32(0)` — always zero for top-level positions              |
| `conditionId`        | `bytes32` | The condition ID from step 1                                    |
| `indexSet`           | `uint`    | `1` (`0b01`) for the first outcome, `2` (`0b10`) for the second |

The `indexSet` is a bitmask denoting which outcome slots belong to a collection. It must be a nonempty proper subset of the condition's outcome slots. Binary markets always have exactly two collections — one per outcome.

### Step 3 - Position IDs

```
getPositionId(collateralToken, collectionId)
```

| Parameter         | Type      | Value                                     |
| ----------------- | --------- | ----------------------------------------- |
| `collateralToken` | `IERC20`  | pUSD contract address on Polygon          |
| `collectionId`    | `bytes32` | One of the two collection IDs from step 2 |

The two resulting position IDs are the ERC1155 token IDs for the Yes and No outcomes of the market.

<Note>
  You can look up token IDs directly via the Gamma API (`GET /markets` or `GET /events`
  — the `tokens` array on each market contains both outcome token IDs). Computing them
  manually is only necessary for direct smart contract integration.
</Note>

## Standard vs Neg Risk Markets

Polymarket has two market types with different CTF configurations:

| Feature           | Standard Markets    | Neg Risk Markets      |
| ----------------- | ------------------- | --------------------- |
| CTF Contract      | ConditionalTokens   | ConditionalTokens     |
| Exchange Contract | CTF Exchange        | Neg Risk CTF Exchange |
| Multi-outcome     | Independent markets | Linked via conversion |
| `negRisk` flag    | `false`             | `true`                |

For neg risk markets, an additional **conversion** operation allows exchanging a No token for Yes tokens in all other outcomes. See [Negative Risk Markets](/advanced/neg-risk) for details.

## Contract Addresses

See [Contracts](/resources/contracts) for all Polymarket smart contract addresses on Polygon.

## Resources

<CardGroup>
  <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>
  <Card title="Split Tokens" icon="scissors" href="/trading/ctf/split">
    Create outcome token pairs from pUSD
  </Card>

  <Card title="Merge Tokens" icon="merge" href="/trading/ctf/merge">
    Convert token pairs back to pUSD
  </Card>

  <Card title="Redeem Tokens" icon="hand-holding-dollar" href="/trading/ctf/redeem">
    Collect winnings after resolution
  </Card>
</CardGroup>


# Redeem Tokens
Source: https://docs.polymarket.com/trading/ctf/redeem

Exchange winning tokens for pUSD after market resolution

**Redeeming** converts winning outcome tokens into pUSD after a market resolves. Each winning token is worth exactly $1.00 — the losing token is worth $0.

```
Market resolves YES:
  100 Yes tokens → $100 pUSD
  100 No tokens  → $0
```

## When to Redeem

Redemption is only available **after a market resolves**. Once the oracle reports the outcome:

* **Winning tokens** can be redeemed for \$1.00 pUSD each
* **Losing tokens** are worth \$0 and produce no payout

<Note>
  You can redeem at any time after resolution — there's no deadline. Your
  winning tokens will always be redeemable.
</Note>

## How Resolution Works

1. The market's end condition is met (event occurs, date passes, etc.)
2. The UMA Adapter oracle reports the outcome via `reportPayouts()`
3. The CTF contract records the payout vector
4. Redemption becomes available for winning tokens

## Prerequisites

Before redeeming:

1. **Market must be resolved** — check the market's `resolved` status
2. **Hold winning tokens** — only the winning outcome can be redeemed
3. **Know the condition ID** — required for the redemption call

<Note>
  Polymarket uses thin collateral adapter contracts for pUSD-native CTF actions.
  Approve the adapter once, then route split, merge, and redeem actions through
  it. On redeem, the adapter burns the ERC1155 outcome tokens through the CTF
  contract, receives USDC.e collateral, wraps it into pUSD, and returns pUSD to
  your wallet automatically.
</Note>

## Function Parameters

<ResponseField name="collateralToken" type="IERC20">
  pUSD (Polymarket USD) contract address: `0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB`
</ResponseField>

<ResponseField name="parentCollectionId" type="bytes32">
  Always `0x0000...0000` (32 zero bytes) for Polymarket markets
</ResponseField>

<ResponseField name="conditionId" type="bytes32">
  The market's condition ID
</ResponseField>

<ResponseField name="indexSets" type="uint[]">
  Array of index sets to redeem: `[1, 2]` redeems both outcomes (only winning
  pays)
</ResponseField>

<Note>
  Redemption burns your entire token balance for the condition — there is no
  amount parameter.
</Note>

## Payout Mechanics

The CTF uses a **payout vector** to determine redemption values:

| Outcome  | Payout Vector | Redemption        |
| -------- | ------------- | ----------------- |
| Yes wins | `[1, 0]`      | Yes = $1, No = $0 |
| No wins  | `[0, 1]`      | Yes = $0, No = $1 |

When you redeem through the adapter:

* Your token balance is multiplied by the payout
* Winning tokens are burned
* The released collateral is wrapped into pUSD and transferred to your wallet
* Losing tokens are burned as well, but produce a \$0 payout

## Next Steps

<CardGroup>
  <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>


# Split Tokens
Source: https://docs.polymarket.com/trading/ctf/split

Convert pUSD into outcome token pairs

**Splitting** converts pUSD collateral into a full (position) set of outcome tokens. For every \$1 pUSD you split, you receive 1 Yes token and 1 No token.

```
$100 pUSD → 100 Yes tokens + 100 No tokens
```

## Prerequisites

Before splitting, ensure you have:

1. **pUSD balance** on Polygon
2. **pUSD approval** for the CTF collateral adapter to spend your tokens
3. **Condition ID** of the market — the condition must already be prepared on the CTF contract (via `prepareCondition`)

<Note>
  Polymarket uses thin collateral adapter contracts for pUSD-native CTF actions.
  Approve the adapter once, then route split, merge, and redeem actions through
  it. The adapter handles the CTF collateral plumbing so user-facing flows stay
  in pUSD.
</Note>

<Note>
  If the partition is trivial, invalid, or refers to more slots than the
  condition is prepared with, the transaction will revert.
</Note>

## How It Works

1. You approve the CTF collateral adapter to spend your pUSD
2. You call the adapter's split flow with the amount and market details
3. The adapter calls the underlying CTF contract and mints both outcome tokens

The operation is atomic — if any step fails, the entire transaction reverts.

## Function Parameters

<ResponseField name="collateralToken" type="IERC20">
  pUSD (Polymarket USD) contract address: `0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB`
</ResponseField>

<ResponseField name="parentCollectionId" type="bytes32">
  Always `0x0000...0000` (32 zero bytes) for Polymarket markets
</ResponseField>

<ResponseField name="conditionId" type="bytes32">
  The market's condition ID, available from the Markets API
</ResponseField>

<ResponseField name="partition" type="uint[]">
  Array of index sets: `[1, 2]` for binary markets (Yes = 1, No = 2)
</ResponseField>

<ResponseField name="amount" type="uint256">
  The amount of collateral or stake to split. Also the number of full sets to
  receive.
</ResponseField>

## Next Steps

<CardGroup>
  <Card title="Merge Tokens" icon="merge" href="/trading/ctf/merge">
    Convert token pairs back to pUSD
  </Card>

  <Card title="Trade on Orderbook" icon="chart-line" href="/trading/orders/create">
    Place orders using your newly split tokens
  </Card>
</CardGroup>


# Deposit Wallets
Source: https://docs.polymarket.com/trading/deposit-wallets

Create deposit wallets, execute wallet actions, and place POLY_1271 orders

Deposit wallets are the wallet path for **new API users**. Existing Safe and
Proxy users are unaffected and can continue using their current wallet setup.

For newly-created polymarket.com accounts using the deposit wallet flow, a
deposit wallet is automatically deployed for you.

<Info>
  This guide is for developers integrating directly with the APIs or SDKs. It
  does not change existing user balances, existing proxy wallets, or existing
  Safes.
</Info>

## Where Deposit Wallets Fit

| Area                 | Existing Safe/Proxy users           | New API user deposit wallet flow                 |
| -------------------- | ----------------------------------- | ------------------------------------------------ |
| Wallet type          | Existing proxy wallet or Safe       | Deposit wallet                                   |
| Wallet deployment    | Existing relayer Safe/proxy flow    | Relayer `WALLET-CREATE`                          |
| Deployment signature | Existing Safe/proxy deployment flow | No user signature in the `WALLET-CREATE` payload |
| Wallet calls         | Safe/proxy relayer transactions     | Relayer `WALLET` batches                         |
| Order signature type | `0`, `1`, or `2`                    | `3`, also called `POLY_1271`                     |
| Order maker          | EOA, proxy, or Safe                 | Deposit wallet address                           |
| Order signer field   | EOA for existing types              | Deposit wallet address                           |
| Signing key          | User EOA or session signer          | Deposit wallet owner or approved session signer  |

## Mental Model

A deposit wallet is a per-user ERC-1967 proxy deployed by a deposit wallet
factory. The wallet holds pUSD and conditional tokens on-chain.

The owner or session signer signs two different kinds of payloads:

1. A **deposit wallet Batch** for on-chain wallet calls. This is submitted to the
   relayer as a `WALLET` transaction.
2. A **CLOB order** with `signatureType = 3`. The CLOB validates this through
   ERC-1271 on the deposit wallet.

These signatures are not interchangeable. A `WALLET` batch uses a normal
65-byte EIP-712 signature over the `DepositWallet` `Batch` type. A CLOB order
uses an ERC-7739-wrapped `POLY_1271` signature and is longer than a normal ECDSA
signature.

## Integration Flow

<Steps>
  <Step title="Create or identify the owner signer">
    Use the EOA or session signer that will own the deposit wallet. This signer is
    also the key that signs deposit wallet batches and CLOB order payloads unless
    your session signer flow delegates signing elsewhere.
  </Step>

  <Step title="Deploy the deposit wallet">
    Submit a relayer `WALLET-CREATE` request. The body only needs the transaction
    type, owner address, and deposit wallet factory address.

    The deposit wallet address is deterministic. TypeScript relayer users can call
    `deriveDepositWalletAddress()`, and Python relayer users can call
    `get_expected_deposit_wallet()`. Other integrations should store the address
    returned by onboarding or derive it with the deterministic formula below.
  </Step>

  <Step title="Fund the deposit wallet">
    Transfer pUSD to the deposit wallet address. pUSD held by the EOA does not count
    as CLOB buying power for deposit wallet orders.
  </Step>

  <Step title="Approve trading contracts from the wallet">
    Approvals must be made **from the deposit wallet**, not from the owner EOA. Build
    ERC-20 or ERC-1155 approval calldata and submit it through a relayer `WALLET`
    batch.
  </Step>

  <Step title="Sync CLOB balances">
    After funding or changing allowances, call the CLOB balance allowance update
    endpoint through the SDK or API. The request must use `signature_type = 3`.
  </Step>

  <Step title="Place orders with POLY_1271">
    Initialize the CLOB client with the deposit wallet as the funder and
    `POLY_1271` as the signature type. Orders must have both `maker` and `signer`
    set to the deposit wallet address.
  </Step>
</Steps>

## SDK Users

Use a relayer client or the raw relayer API for wallet deployment and wallet
batches. Use the CLOB client for order signing, posting, cancelling, balances,
and account data.

<Tabs>
  <Tab title="TypeScript">
    Use the TypeScript clients with deposit wallet support:
    [@polymarket/builder-relayer-client](https://www.npmjs.com/package/@polymarket/builder-relayer-client)
    and
    [@polymarket/clob-client-v2](https://www.npmjs.com/package/@polymarket/clob-client-v2).

    ```bash theme={null}
    npm install @polymarket/builder-relayer-client @polymarket/clob-client-v2 @polymarket/builder-signing-sdk viem
    ```

    ### Deploy the Wallet

    ```typescript theme={null}
    import {
      BuilderApiKeyCreds,
      BuilderConfig,
    } from "@polymarket/builder-signing-sdk";
    import { RelayClient } from "@polymarket/builder-relayer-client";
    import { createWalletClient, Hex, http } from "viem";
    import { privateKeyToAccount } from "viem/accounts";
    import { polygon } from "viem/chains";

    const relayerUrl = process.env.RELAYER_URL!;
    const chainId = Number(process.env.CHAIN_ID ?? 137);
    const account = privateKeyToAccount(process.env.PRIVATE_KEY as Hex);
    const walletClient = createWalletClient({
      account,
      chain: polygon,
      transport: http(process.env.RPC_URL),
    });

    const builderCreds: BuilderApiKeyCreds = {
      key: process.env.BUILDER_API_KEY!,
      secret: process.env.BUILDER_SECRET!,
      passphrase: process.env.BUILDER_PASS_PHRASE!,
    };

    const builderConfig = new BuilderConfig({
      localBuilderCreds: builderCreds,
    });

    const relayer = new RelayClient(
      relayerUrl,
      chainId,
      walletClient,
      builderConfig,
    );

    const depositWalletAddress = await relayer.deriveDepositWalletAddress();
    const response = await relayer.deployDepositWallet();
    const confirmed = await response.wait();
    ```

    `deployDepositWallet()` submits a `WALLET-CREATE` transaction. It does not add a
    user signature to the deployment body.

    ### Execute a Wallet Batch

    ```typescript theme={null}
    import type { DepositWalletCall } from "@polymarket/builder-relayer-client";

    const calls: DepositWalletCall[] = [
      {
        target: process.env.PUSD_ADDRESS!,
        value: "0",
        data: approveCalldata,
      },
    ];

    const deadline = Math.floor(Date.now() / 1000 + 600).toString();
    const response = await relayer.executeDepositWalletBatch(
      calls,
      depositWalletAddress,
      deadline,
    );
    const confirmed = await response.wait();
    ```

    The TypeScript relayer client fetches the current `WALLET` nonce before signing
    and submitting the batch. The SDK signs the batch with this EIP-712 domain before
    submitting it to the relayer:

    ```typescript theme={null}
    {
      name: "DepositWallet",
      version: "1",
      chainId,
      verifyingContract: depositWalletAddress,
    }
    ```

    ### Trade From the Deposit Wallet

    ```typescript theme={null}
    import {
      AssetType,
      ClobClient,
      OrderType,
      Side,
      SignatureTypeV2,
    } from "@polymarket/clob-client-v2";

    const creds = {
      key: process.env.CLOB_API_KEY!,
      secret: process.env.CLOB_SECRET!,
      passphrase: process.env.CLOB_PASS_PHRASE!,
    };

    const clob = new ClobClient({
      host: process.env.CLOB_API_URL!,
      chain: chainId,
      signer: walletClient,
      creds,
      signatureType: SignatureTypeV2.POLY_1271,
      funderAddress: depositWalletAddress,
    });

    await clob.updateBalanceAllowance({ asset_type: AssetType.COLLATERAL });

    const order = await clob.createAndPostOrder(
      {
        tokenID: process.env.TOKEN_ID!,
        price: 0.5,
        size: 10,
        side: Side.BUY,
      },
      { tickSize: "0.01", negRisk: false },
      OrderType.GTC,
    );
    ```
  </Tab>

  <Tab title="Python">
    Use the Python builder relayer client with deposit wallet support:
    [py-builder-relayer-client](https://pypi.org/project/py-builder-relayer-client/).

    ```bash theme={null}
    pip install py-builder-relayer-client
    ```

    ### Deploy the Wallet

    ```python theme={null}
    import os

    from py_builder_relayer_client.client import RelayClient
    from py_builder_signing_sdk.config import BuilderApiKeyCreds, BuilderConfig

    builder_config = BuilderConfig(
        local_builder_creds=BuilderApiKeyCreds(
            key=os.environ["BUILDER_API_KEY"],
            secret=os.environ["BUILDER_SECRET"],
            passphrase=os.environ["BUILDER_PASS_PHRASE"],
        )
    )

    relayer = RelayClient(
        os.environ["RELAYER_URL"],
        int(os.environ.get("CHAIN_ID", "137")),
        os.environ["PRIVATE_KEY"],
        builder_config,
    )

    deposit_wallet = relayer.get_expected_deposit_wallet()
    response = relayer.deploy_deposit_wallet()
    confirmed = response.wait()
    ```

    `get_expected_deposit_wallet()` derives the deterministic wallet address from
    the signer and the chain's deposit wallet configuration.

    ### Execute a Wallet Batch

    ```python theme={null}
    import time

    from py_builder_relayer_client.models import DepositWalletCall, TransactionType

    nonce_payload = relayer.get_nonce(
        relayer.signer.address(),
        TransactionType.WALLET.value,
    )
    wallet_nonce = str(nonce_payload["nonce"])

    call = DepositWalletCall(
        target=os.environ["PUSD_ADDRESS"],
        value="0",
        data=approve_calldata,
    )

    response = relayer.execute_deposit_wallet_batch(
        calls=[call],
        wallet_address=deposit_wallet,
        nonce=wallet_nonce,
        deadline=str(int(time.time()) + 600),
    )
    confirmed = response.wait()
    ```

    The Python relayer client mirrors the TypeScript wire format for `WALLET-CREATE`
    and `WALLET` requests, while keeping builder API key auth in the Python client.

    ### Trade From the Deposit Wallet

    Use the Python CLOB client with deposit wallet order support:
    [py-clob-client-v2](https://pypi.org/project/py-clob-client-v2/).

    ```bash theme={null}
    pip install py-clob-client-v2
    ```

    ```python theme={null}
    import os

    from py_clob_client_v2 import (
        ApiCreds,
        AssetType,
        BalanceAllowanceParams,
        ClobClient,
        OrderArgs,
        OrderType,
        PartialCreateOrderOptions,
        Side,
        SignatureTypeV2,
    )

    creds = ApiCreds(
        api_key=os.environ["CLOB_API_KEY"],
        api_secret=os.environ["CLOB_SECRET"],
        api_passphrase=os.environ["CLOB_PASS_PHRASE"],
    )

    clob = ClobClient(
        host=os.environ["CLOB_API_URL"],
        chain_id=int(os.environ.get("CHAIN_ID", "137")),
        key=os.environ["PRIVATE_KEY"],
        creds=creds,
        signature_type=SignatureTypeV2.POLY_1271,
        funder=deposit_wallet,
    )

    clob.update_balance_allowance(
        BalanceAllowanceParams(
            asset_type=AssetType.COLLATERAL,
            signature_type=SignatureTypeV2.POLY_1271,
        )
    )

    response = clob.create_and_post_order(
        order_args=OrderArgs(
            token_id=os.environ["TOKEN_ID"],
            price=0.50,
            size=10,
            side=Side.BUY,
        ),
        options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
        order_type=OrderType.GTC,
    )
    ```
  </Tab>

  <Tab title="Rust">
    ### Deploy the Wallet and Execute Wallet Batches

    The Rust SDK supports the CLOB order path for deposit wallets. It does not
    include a builder relayer client. Use the TypeScript or Python relayer client
    above, or the raw API flow below, to submit `WALLET-CREATE` and `WALLET`
    transactions.

    Use the Rust CLOB client with deposit wallet support:
    [polymarket\_client\_sdk\_v2](https://crates.io/crates/polymarket_client_sdk_v2).

    ```bash theme={null}
    cargo add polymarket_client_sdk_v2 --features clob
    ```

    Once the deposit wallet is deployed, funded, and approved, pass the deposit
    wallet address as the Rust CLOB client funder.

    ### Trade From the Deposit Wallet

    ```rust theme={null}
    use std::str::FromStr as _;

    use polymarket_client_sdk_v2::auth::{LocalSigner, Signer as _};
    use polymarket_client_sdk_v2::clob::types::request::UpdateBalanceAllowanceRequest;
    use polymarket_client_sdk_v2::clob::types::{AssetType, OrderType, Side, SignatureType};
    use polymarket_client_sdk_v2::clob::{Client, Config};
    use polymarket_client_sdk_v2::types::{Address, Decimal, U256};
    use polymarket_client_sdk_v2::{POLYGON, PRIVATE_KEY_VAR};

    let host = std::env::var("CLOB_API_URL")?;
    let token_id = U256::from_str(&std::env::var("TOKEN_ID")?)?;
    let deposit_wallet = Address::from_str(&std::env::var("DEPOSIT_WALLET")?)?;
    let signer =
        LocalSigner::from_str(&std::env::var(PRIVATE_KEY_VAR)?)?.with_chain_id(Some(POLYGON));

    let client = Client::new(&host, Config::default())?
        .authentication_builder(&signer)
        .funder(deposit_wallet)
        .signature_type(SignatureType::Poly1271)
        .authenticate()
        .await?;

    client
        .update_balance_allowance(
            UpdateBalanceAllowanceRequest::builder()
                .asset_type(AssetType::Collateral)
                .build(),
        )
        .await?;

    let _response = client
        .limit_order()
        .token_id(token_id)
        .side(Side::Buy)
        .price(Decimal::from_str("0.50")?)
        .size(Decimal::from_str("10")?)
        .order_type(OrderType::GTC)
        .build_sign_and_post(&signer)
        .await?;
    ```

    The Rust client sets `signatureType = 3` and builds the wrapped ERC-1271 order
    signature when `SignatureType::Poly1271` and a deposit wallet funder are
    configured.
  </Tab>
</Tabs>

## API Users

Direct API integrations need to implement the same two relayer operations and
the same CLOB order signature shape used by the SDKs.

### Deploy a Deposit Wallet

Submit this body to the relayer `/submit` endpoint:

```json theme={null}
{
  "type": "WALLET-CREATE",
  "from": "0xOwnerAddress",
  "to": "0x00000000000Fb5C9ADea0298D729A0CB3823Cc07"
}
```

Field meanings:

| Field  | Description                                                         |
| ------ | ------------------------------------------------------------------- |
| `type` | Must be `WALLET-CREATE`                                             |
| `from` | Owner address for the deposit wallet                                |
| `to`   | Deposit wallet factory address for the active chain and environment |

Current factory addresses:

| Chain                 | Deposit wallet factory                       |
| --------------------- | -------------------------------------------- |
| Polygon mainnet `137` | `0x00000000000Fb5C9ADea0298D729A0CB3823Cc07` |

There is no user signature field in this payload. After submission, poll the
relayer transaction until it reaches `STATE_MINED` or `STATE_CONFIRMED`. Store
the deployed wallet address from the `WalletDeployed` event, from your
onboarding flow, or derive it deterministically using the SDK's chain config.

Deterministic address derivation follows the relayer clients:

```text theme={null}
walletId = bytes32(owner) // owner address left-padded to 32 bytes
args = abi.encode(factory, walletId)
salt = keccak256(args)
bytecodeHash = SoladyLibClone.initCodeHashERC1967(implementation, args)
depositWallet = CREATE2(factory, salt, bytecodeHash)
```

### Submit a Deposit Wallet Batch

For wallet actions such as token approvals, transfers, withdrawals, splits, or
merges, fetch the current `WALLET` nonce for the owner address, then sign a
`Batch` with the owner or session signer:

```http theme={null}
GET /nonce?address=0xOwnerAddress&type=WALLET
```

```typescript theme={null}
const types = {
  Call: [
    { name: "target", type: "address" },
    { name: "value", type: "uint256" },
    { name: "data", type: "bytes" },
  ],
  Batch: [
    { name: "wallet", type: "address" },
    { name: "nonce", type: "uint256" },
    { name: "deadline", type: "uint256" },
    { name: "calls", type: "Call[]" },
  ],
};

const domain = {
  name: "DepositWallet",
  version: "1",
  chainId,
  verifyingContract: depositWalletAddress,
};

const message = {
  wallet: depositWalletAddress,
  nonce,
  deadline,
  calls,
};
```

Submit the signed batch to the relayer:

```json theme={null}
{
  "type": "WALLET",
  "from": "0xOwnerAddress",
  "to": "0x00000000000Fb5C9ADea0298D729A0CB3823Cc07",
  "nonce": "0",
  "signature": "0x65ByteBatchSignature",
  "depositWalletParams": {
    "depositWallet": "0xDepositWallet",
    "deadline": "1760000000",
    "calls": [
      {
        "target": "0xTokenOrContract",
        "value": "0",
        "data": "0xCalldata"
      }
    ]
  }
}
```

The `signature` in a `WALLET` request is a normal 65-byte EIP-712 signature with
a `0x` prefix. This is different from the CLOB order signature described below.

### Place CLOB Orders

For deposit wallet orders, the raw order inside the `/order` request must use
`signatureType = 3`:

```json theme={null}
{
  "deferExec": false,
  "order": {
    "salt": 123456789,
    "maker": "0xDepositWallet",
    "signer": "0xDepositWallet",
    "tokenId": "TOKEN_ID",
    "makerAmount": "5000000",
    "takerAmount": "10000000",
    "side": "BUY",
    "expiration": "0",
    "signatureType": 3,
    "timestamp": "1760000000",
    "metadata": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "builder": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "signature": "0xWrapped1271Signature"
  },
  "owner": "CLOB_API_KEY",
  "orderType": "GTC"
}
```

The signature is not the raw order EIP-712 signature. It is an ERC-7739-wrapped
signature that lets the deposit wallet validate the order through ERC-1271.

The owner or session signer signs a nested `TypedDataSign` payload under the
correct CTF Exchange V2 domain. The nested wallet fields are:

| Field               | Value                                                                |
| ------------------- | -------------------------------------------------------------------- |
| `name`              | `DepositWallet`                                                      |
| `version`           | `1`                                                                  |
| `chainId`           | Current chain ID                                                     |
| `verifyingContract` | Deposit wallet address                                               |
| `salt`              | `0x0000000000000000000000000000000000000000000000000000000000000000` |

The SDKs build this wrapper for you when you configure `POLY_1271` and the
deposit wallet funder address.

<Warning>
  If you sign the CLOB order as a normal EOA order, or if `maker` and `signer`
  are not both the deposit wallet address, the order will fail ERC-1271
  validation. `POLY_1271` is supported on V2 orders only.
</Warning>

### Sync Balance and Allowance

After funding the deposit wallet or approving contracts from it, update the CLOB
balance cache using `signature_type = 3`.

```http theme={null}
GET /balance-allowance/update?asset_type=COLLATERAL&signature_type=3
```

For conditional tokens, include the token ID:

```http theme={null}
GET /balance-allowance/update?asset_type=CONDITIONAL&token_id=TOKEN_ID&signature_type=3
```

Use normal CLOB L2 authentication headers for these requests. Relayer auth and
CLOB auth are separate systems.

## Common Issues

<AccordionGroup>
  <Accordion title="Order is rejected as invalid signature">
    Check all four signature inputs: `signatureType` must be `3`, order `maker` must
    be the deposit wallet, order `signer` must be the deposit wallet, and the order
    signature must be the ERC-7739-wrapped `POLY_1271` signature. Also confirm the
    order was signed against the correct CTF Exchange V2 verifying contract for the
    market.
  </Accordion>

  <Accordion title="Wallet batch is rejected">
    Fetch the current `WALLET` nonce fresh from the relayer before signing the batch.
    Confirm the deadline is still in the future and within the relayer's accepted
    range. The `WALLET` batch signature should be a normal 65-byte EIP-712 signature
    over `DepositWallet` `Batch`.
  </Accordion>

  <Accordion title="Order says not enough balance">
    Confirm pUSD is held by the deposit wallet address. Then update the CLOB balance
    cache with `signature_type = 3`. pUSD sitting on the owner EOA does not fund
    deposit wallet orders.
  </Accordion>

  <Accordion title="Allowance is missing">
    Approvals must come from the deposit wallet. An EOA `approve()` transaction does
    not approve spending from the deposit wallet. Submit approval calldata through a
    relayer `WALLET` batch.
  </Accordion>

  <Accordion title="Direct API auth is confusing">
    Relayer auth and CLOB auth are independent. Use the auth method required by your
    relayer environment for `/submit`. Use CLOB L1/L2 authentication for order and
    balance endpoints. Do not reuse relayer cookies or headers as CLOB auth.
  </Accordion>
</AccordionGroup>


# Fees
Source: https://docs.polymarket.com/trading/fees

Understanding trading fees on Polymarket

Polymarket charges a small taker fee on certain markets. Fees are set by the protocol and applied at match time — you don't include fee information in your orders. These fees fund the [Maker Rebates Program](/market-makers/maker-rebates), which redistributes fees daily to market makers to incentivize deeper liquidity and tighter spreads.

**Geopolitical and world events markets are fee-free.** Polymarket does not charge fees or profit from trading activity on these markets. There are also no Polymarket fees to deposit or withdraw USDC (though intermediaries like Coinbase or MoonPay may charge their own fees).

<Note>
  Fees are determined per-market at match time. Markets with fees enabled have
  `feesEnabled` set to `true` on the market object. Query fee parameters for
  any market with `getClobMarketInfo(conditionID)`.
</Note>

***

## Fee Structure

Fees are calculated using the following formula:

```text theme={null}
fee = C × feeRate × p × (1 - p)
```

Where **C** = number of shares traded and **p** = price of the shares.

**Makers are never charged fees.** Only takers pay fees. The fee parameters differ by market category:

| Category        | Taker Fee Rate | Maker Fee Rate | Maker Rebate |
| --------------- | -------------- | -------------- | ------------ |
| Crypto          | 0.07           | 0              | 20%          |
| Sports          | 0.03           | 0              | 25%          |
| Finance         | 0.04           | 0              | 25%          |
| Politics        | 0.04           | 0              | 25%          |
| Economics       | 0.05           | 0              | 25%          |
| Culture         | 0.05           | 0              | 25%          |
| Weather         | 0.05           | 0              | 25%          |
| Other / General | 0.05           | 0              | 25%          |
| Mentions        | 0.04           | 0              | 25%          |
| Tech            | 0.04           | 0              | 25%          |
| Geopolitics     | 0              | 0              | —            |

Taker fees are calculated in USDC and vary based on the share price. The fee amount in USDC is symmetric around 50% probability — a trade at 30¢ incurs the same dollar fee as a trade at 70¢.

<Frame>
  <div>
    <iframe title="Fee Curves" aria-label="Line chart" />
  </div>
</Frame>

### Fee Tables (100 Shares)

<Tabs>
  <Tab title="Crypto">
    | Price  | Trade Value | Taker Fee (USDC) |
    | ------ | ----------- | ---------------- |
    | \$0.01 | \$1         | \$0.07           |
    | \$0.05 | \$5         | \$0.33           |
    | \$0.10 | \$10        | \$0.63           |
    | \$0.15 | \$15        | \$0.89           |
    | \$0.20 | \$20        | \$1.12           |
    | \$0.25 | \$25        | \$1.31           |
    | \$0.30 | \$30        | \$1.47           |
    | \$0.35 | \$35        | \$1.59           |
    | \$0.40 | \$40        | \$1.68           |
    | \$0.45 | \$45        | \$1.73           |
    | \$0.50 | \$50        | \$1.75           |
    | \$0.55 | \$55        | \$1.73           |
    | \$0.60 | \$60        | \$1.68           |
    | \$0.65 | \$65        | \$1.59           |
    | \$0.70 | \$70        | \$1.47           |
    | \$0.75 | \$75        | \$1.31           |
    | \$0.80 | \$80        | \$1.12           |
    | \$0.85 | \$85        | \$0.89           |
    | \$0.90 | \$90        | \$0.63           |
    | \$0.95 | \$95        | \$0.33           |
    | \$0.99 | \$99        | \$0.07           |

    The fee in USDC **peaks at 50%** probability (\$1.75) and decreases symmetrically toward both extremes.
  </Tab>

  <Tab title="Sports">
    | Price  | Trade Value | Taker Fee (USDC) |
    | ------ | ----------- | ---------------- |
    | \$0.01 | \$1         | \$0.03           |
    | \$0.05 | \$5         | \$0.14           |
    | \$0.10 | \$10        | \$0.27           |
    | \$0.15 | \$15        | \$0.38           |
    | \$0.20 | \$20        | \$0.48           |
    | \$0.25 | \$25        | \$0.56           |
    | \$0.30 | \$30        | \$0.63           |
    | \$0.35 | \$35        | \$0.68           |
    | \$0.40 | \$40        | \$0.72           |
    | \$0.45 | \$45        | \$0.74           |
    | \$0.50 | \$50        | \$0.75           |
    | \$0.55 | \$55        | \$0.74           |
    | \$0.60 | \$60        | \$0.72           |
    | \$0.65 | \$65        | \$0.68           |
    | \$0.70 | \$70        | \$0.63           |
    | \$0.75 | \$75        | \$0.56           |
    | \$0.80 | \$80        | \$0.48           |
    | \$0.85 | \$85        | \$0.38           |
    | \$0.90 | \$90        | \$0.27           |
    | \$0.95 | \$95        | \$0.14           |
    | \$0.99 | \$99        | \$0.03           |

    The fee in USDC **peaks at 50%** probability (\$0.75) and decreases symmetrically toward both extremes.
  </Tab>

  <Tab title="Finance / Politics / Mentions / Tech">
    | Price  | Trade Value | Taker Fee (USDC) |
    | ------ | ----------- | ---------------- |
    | \$0.01 | \$1         | \$0.04           |
    | \$0.05 | \$5         | \$0.19           |
    | \$0.10 | \$10        | \$0.36           |
    | \$0.15 | \$15        | \$0.51           |
    | \$0.20 | \$20        | \$0.64           |
    | \$0.25 | \$25        | \$0.75           |
    | \$0.30 | \$30        | \$0.84           |
    | \$0.35 | \$35        | \$0.91           |
    | \$0.40 | \$40        | \$0.96           |
    | \$0.45 | \$45        | \$0.99           |
    | \$0.50 | \$50        | \$1.00           |
    | \$0.55 | \$55        | \$0.99           |
    | \$0.60 | \$60        | \$0.96           |
    | \$0.65 | \$65        | \$0.91           |
    | \$0.70 | \$70        | \$0.84           |
    | \$0.75 | \$75        | \$0.75           |
    | \$0.80 | \$80        | \$0.64           |
    | \$0.85 | \$85        | \$0.51           |
    | \$0.90 | \$90        | \$0.36           |
    | \$0.95 | \$95        | \$0.19           |
    | \$0.99 | \$99        | \$0.04           |

    The fee in USDC **peaks at 50%** probability (\$1.00) and decreases symmetrically toward both extremes.
  </Tab>

  <Tab title="Economics / Culture / Weather / Other">
    | Price  | Trade Value | Taker Fee (USDC) |
    | ------ | ----------- | ---------------- |
    | \$0.01 | \$1         | \$0.05           |
    | \$0.05 | \$5         | \$0.24           |
    | \$0.10 | \$10        | \$0.45           |
    | \$0.15 | \$15        | \$0.64           |
    | \$0.20 | \$20        | \$0.80           |
    | \$0.25 | \$25        | \$0.94           |
    | \$0.30 | \$30        | \$1.05           |
    | \$0.35 | \$35        | \$1.14           |
    | \$0.40 | \$40        | \$1.20           |
    | \$0.45 | \$45        | \$1.24           |
    | \$0.50 | \$50        | \$1.25           |
    | \$0.55 | \$55        | \$1.24           |
    | \$0.60 | \$60        | \$1.20           |
    | \$0.65 | \$65        | \$1.14           |
    | \$0.70 | \$70        | \$1.05           |
    | \$0.75 | \$75        | \$0.94           |
    | \$0.80 | \$80        | \$0.80           |
    | \$0.85 | \$85        | \$0.64           |
    | \$0.90 | \$90        | \$0.45           |
    | \$0.95 | \$95        | \$0.24           |
    | \$0.99 | \$99        | \$0.05           |

    The fee in USDC **peaks at 50%** probability (\$1.25) and decreases symmetrically toward both extremes.
  </Tab>
</Tabs>

### Fee Precision

Fees are rounded to 5 decimal places. The smallest fee charged is **0.00001 USDC**. Anything smaller rounds to zero, so very small trades near the extremes may incur no fee at all.

***

## Fee Handling

Fees are calculated and applied at match time by the protocol — you do not need to include fee information in your orders. The SDK handles everything automatically.

To query fee parameters for a specific market, use `getClobMarketInfo(conditionID)`:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const info = await client.getClobMarketInfo(conditionID);
  // info.fd = { r: feeRate, e: exponent, to: takerOnly }
  ```

  ```python Python theme={null}
  info = client.get_clob_market_info(condition_id)
  # info["fd"] = { "r": fee_rate, "e": exponent, "to": taker_only }
  ```
</CodeGroup>

***

## Next Steps

<CardGroup>
  <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>


# Gasless Transactions
Source: https://docs.polymarket.com/trading/gasless

Execute onchain operations without paying gas fees

Polymarket's **Relayer Client** enables gasless transactions for your users. Instead of requiring users to hold POL for gas, Polymarket's infrastructure pays all transaction fees. This creates a seamless experience where users only need pUSD to trade.

## How It Works

The relayer acts as a transaction sponsor:

1. Your app creates a transaction
2. The user signs it with their private key
3. Your app sends it to Polymarket's relayer
4. The relayer submits it onchain and pays the gas fee
5. The transaction executes from the user's wallet

## What Is Covered

Polymarket pays gas for all operations routed through the relayer:

| Operation             | Description                                       |
| --------------------- | ------------------------------------------------- |
| **Wallet deployment** | Deploy deposit wallets for new API users          |
| **Token approvals**   | Approve contracts to spend pUSD or outcome tokens |
| **CTF operations**    | Split, merge, and redeem positions                |
| **Transfers**         | Move tokens between addresses                     |

## Authentication

The relayer uses **Relayer API Keys**. You can create one from [Settings > API Keys](https://polymarket.com/settings?tab=api-keys) on the Polymarket website.

<Note>
  **Already have a builder signing key?** Your existing HMAC-based builder API
  key keeps working with the Relayer — no need to rotate or reissue. Order
  attribution is now associated with the native `builderCode` field in CLOB V2.
  See [Migrating to CLOB V2](/v2-migration#builder-program) for context.
</Note>

Include these headers with your requests:

| Header                    | Description                   |
| ------------------------- | ----------------------------- |
| `RELAYER_API_KEY`         | Your Relayer API key          |
| `RELAYER_API_KEY_ADDRESS` | The address that owns the key |

<Info>
  If you want to use the Relayer API Key directly without the SDK, see the
  [Relayer API Reference](/api-reference/relayer).
</Info>

## Prerequisites

Before using the relayer, you need:

| Requirement                  | Source                                                              |
| ---------------------------- | ------------------------------------------------------------------- |
| Relayer API Key              | [Settings > API Keys](https://polymarket.com/settings?tab=api-keys) |
| User's private key or signer | Your wallet integration                                             |
| pUSD balance                 | For trading (not for gas)                                           |

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install @polymarket/builder-relayer-client
  ```

  ```bash pip theme={null}
  pip install py-builder-relayer-client
  ```
</CodeGroup>

## Client Setup

Initialize the relayer client with your Relayer API Key:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { createWalletClient, http, Hex } from "viem";
  import { privateKeyToAccount } from "viem/accounts";
  import { polygon } from "viem/chains";
  import { RelayClient } from "@polymarket/builder-relayer-client";

  const account = privateKeyToAccount(process.env.PRIVATE_KEY as Hex);
  const wallet = createWalletClient({
    account,
    chain: polygon,
    transport: http(process.env.RPC_URL),
  });

  const client = new RelayClient({
    host: "https://relayer-v2.polymarket.com/",
    chain: 137,
    signer: wallet,
    relayerApiKey: process.env.RELAYER_API_KEY!,
    relayerApiKeyAddress: process.env.RELAYER_API_KEY_ADDRESS!,
  });
  ```

  ```python Python theme={null}
  import os
  from py_builder_relayer_client.client import RelayClient

  client = RelayClient(
      host="https://relayer-v2.polymarket.com",
      chain=137,
      signer=os.getenv("PRIVATE_KEY"),
      relayer_api_key=os.environ["RELAYER_API_KEY"],
      relayer_api_key_address=os.environ["RELAYER_API_KEY_ADDRESS"],
  )
  ```
</CodeGroup>

<Warning>
  Never expose your Relayer API Key in client-side code. Use environment
  variables or a secrets manager.
</Warning>

## Wallet Types

Use deposit wallets for new API users. Existing Safe and Proxy users can keep
using their current wallet type and signature flow.

| Type               | Deployment                               | Best For                            |
| ------------------ | ---------------------------------------- | ----------------------------------- |
| **Deposit Wallet** | Call `deployDepositWallet()`             | New API users                       |
| **Safe**           | Call `deploy()` before first transaction | Existing Safe integrations          |
| **Proxy**          | Auto-deploys on first transaction        | Existing Polymarket.com proxy users |

<Info>
  For the new deposit wallet flow, including `WALLET-CREATE`, signed `WALLET`
  batches, and `POLY_1271` CLOB orders, see the [Deposit Wallet
  Guide](/trading/deposit-wallets).
</Info>

<CodeGroup>
  ```typescript Safe Wallet (TypeScript) theme={null}
  import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client";

  const client = new RelayClient({
    host: "https://relayer-v2.polymarket.com/",
    chain: 137,
    signer: wallet,
    relayerApiKey: process.env.RELAYER_API_KEY!,
    relayerApiKeyAddress: process.env.RELAYER_API_KEY_ADDRESS!,
    txType: RelayerTxType.SAFE,
  });

  // Deploy before first transaction
  const response = await client.deploy();
  const result = await response.wait();
  console.log("Safe Address:", result?.proxyAddress);
  ```

  ```python Safe Wallet (Python) theme={null}
  from py_builder_relayer_client.client import RelayClient

  # client initialized with relayer credentials (see Client Setup above)

  # Deploy before first transaction
  response = client.deploy()
  result = response.wait()
  print("Safe Address:", result.get("proxyAddress"))
  ```

  ```typescript Proxy Wallet (TypeScript) theme={null}
  import { RelayClient, RelayerTxType } from "@polymarket/builder-relayer-client";

  const client = new RelayClient({
    host: "https://relayer-v2.polymarket.com/",
    chain: 137,
    signer: wallet,
    relayerApiKey: process.env.RELAYER_API_KEY!,
    relayerApiKeyAddress: process.env.RELAYER_API_KEY_ADDRESS!,
    txType: RelayerTxType.PROXY,
  });

  // No deploy needed - auto-deploys on first transaction
  ```

  ```python Proxy Wallet (Python) theme={null}
  from py_builder_relayer_client.client import RelayClient

  # client initialized with relayer credentials (see Client Setup above)
  # No deploy needed - auto-deploys on first transaction
  ```
</CodeGroup>

## Executing Transactions

Use the `execute` method to send transactions through the relayer:

```typescript theme={null}
interface Transaction {
  to: string; // Target contract address
  data: string; // Encoded function call
  value: string; // POL to send (usually "0")
}

const response = await client.execute(transactions, "Description");
const result = await response.wait();
```

### Token Approval

Approve contracts to spend tokens:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { encodeFunctionData, maxUint256 } from "viem";

  const pUSD = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB";
  const CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045";

  const approveTx = {
    to: pUSD,
    data: encodeFunctionData({
      abi: [
        {
          name: "approve",
          type: "function",
          inputs: [
            { name: "spender", type: "address" },
            { name: "amount", type: "uint256" },
          ],
          outputs: [{ type: "bool" }],
        },
      ],
      functionName: "approve",
      args: [CTF, maxUint256],
    }),
    value: "0",
  };

  const response = await client.execute([approveTx], "Approve pUSD for CTF");
  await response.wait();
  ```

  ```python Python theme={null}
  from web3 import Web3

  pUSD = "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB"
  CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"
  MAX_UINT256 = 2**256 - 1

  approve_tx = {
      "to": pUSD,
      "data": Web3().eth.contract(
          address=pUSD,
          abi=[{
              "name": "approve",
              "type": "function",
              "inputs": [
                  {"name": "spender", "type": "address"},
                  {"name": "amount", "type": "uint256"}
              ],
              "outputs": [{"type": "bool"}]
          }]
      ).encode_abi(abi_element_identifier="approve", args=[CTF, MAX_UINT256]),
      "value": "0"
  }

  response = client.execute([approve_tx], "Approve pUSD for CTF")
  response.wait()
  ```
</CodeGroup>

### Redeem Positions

Exchange winning tokens for pUSD after market resolution:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { encodeFunctionData } from "viem";

  const redeemTx = {
    to: CTF_ADDRESS,
    data: encodeFunctionData({
      abi: [
        {
          name: "redeemPositions",
          type: "function",
          inputs: [
            { name: "collateralToken", type: "address" },
            { name: "parentCollectionId", type: "bytes32" },
            { name: "conditionId", type: "bytes32" },
            { name: "indexSets", type: "uint256[]" },
          ],
          outputs: [],
        },
      ],
      functionName: "redeemPositions",
      args: [collateralToken, parentCollectionId, conditionId, indexSets],
    }),
    value: "0",
  };

  const response = await client.execute([redeemTx], "Redeem positions");
  await response.wait();
  ```

  ```python Python theme={null}
  CTF = "0x4D97DCd97eC945f40cF65F87097ACe5EA0476045"

  redeem_tx = {
      "to": CTF,
      "data": Web3().eth.contract(
          address=CTF,
          abi=[{
              "name": "redeemPositions",
              "type": "function",
              "inputs": [
                  {"name": "collateralToken", "type": "address"},
                  {"name": "parentCollectionId", "type": "bytes32"},
                  {"name": "conditionId", "type": "bytes32"},
                  {"name": "indexSets", "type": "uint256[]"}
              ],
              "outputs": []
          }]
      ).encode_abi(
          abi_element_identifier="redeemPositions",
          args=[collateral_token, parent_collection_id, condition_id, index_sets]
      ),
      "value": "0"
  }

  response = client.execute([redeem_tx], "Redeem positions")
  response.wait()
  ```
</CodeGroup>

### Batch Transactions

Execute multiple operations atomically in a single call:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const approveTx = {
    to: pUSD,
    data: encodeFunctionData({
      abi: erc20Abi,
      functionName: "approve",
      args: [CTF, maxUint256],
    }),
    value: "0",
  };

  const transferTx = {
    to: pUSD,
    data: encodeFunctionData({
      abi: erc20Abi,
      functionName: "transfer",
      args: [recipientAddress, parseUnits("50", 6)],
    }),
    value: "0",
  };

  // Both execute atomically
  const response = await client.execute(
    [approveTx, transferTx],
    "Approve and transfer",
  );
  await response.wait();
  ```

  ```python Python theme={null}
  approve_tx = {
      "to": pUSD,
      "data": contract.encode_abi(
          abi_element_identifier="approve",
          args=[CTF, MAX_UINT256]
      ),
      "value": "0"
  }

  transfer_tx = {
      "to": pUSD,
      "data": contract.encode_abi(
          abi_element_identifier="transfer",
          args=[recipient_address, 50 * 10**6]
      ),
      "value": "0"
  }

  # Both execute atomically
  response = client.execute([approve_tx, transfer_tx], "Approve and transfer")
  response.wait()
  ```
</CodeGroup>

<Tip>
  Batching reduces latency and ensures all transactions succeed or fail
  together.
</Tip>

## Transaction States

Track transaction progress through these states:

| State             | Terminal | Description                     |
| ----------------- | -------- | ------------------------------- |
| `STATE_NEW`       | No       | Transaction received by relayer |
| `STATE_EXECUTED`  | No       | Submitted onchain               |
| `STATE_MINED`     | No       | Included in a block             |
| `STATE_CONFIRMED` | Yes      | Finalized successfully          |
| `STATE_FAILED`    | Yes      | Failed permanently              |
| `STATE_INVALID`   | Yes      | Rejected as invalid             |

## Contract Addresses

See [Contracts](/resources/contracts) for all Polymarket smart contract addresses on Polygon.

## Resources

* [Builder Relayer Client (TypeScript)](https://github.com/Polymarket/builder-relayer-client)
* [Builder Relayer Client (Python)](https://github.com/Polymarket/py-builder-relayer-client)

## Next Steps

<CardGroup>
  <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>


# Matching Engine Restarts
Source: https://docs.polymarket.com/trading/matching-engine

Restart schedule, maintenance windows, and how to handle downtime

The Polymarket matching engine undergoes periodic restarts for maintenance and upgrades. This page covers the restart schedule, how to detect and handle downtime, and where to get advance notice of changes.

***

## Restart Schedule

The matching engine restarts **weekly on Tuesdays at 7:00 AM ET**. During a restart window, the engine is temporarily unavailable — typically for about **90 seconds**.

|                      | Details                                     |
| -------------------- | ------------------------------------------- |
| **Cadence**          | Weekly                                      |
| **Day & time**       | Tuesday, 7:00 AM ET                         |
| **Typical duration** | \~90 seconds                                |
| **What happens**     | Order matching is paused, API returns `425` |

<Note>
  Unscheduled restarts may occur for critical updates or hotfixes. These are announced with as much advance notice as possible.
</Note>

***

## Announcements

Matching engine changes — planned restarts, updates, and maintenance windows — are announced **before they happen** in these channels:

<CardGroup>
  <Card title="Telegram" icon="telegram" href="https://t.me/polytradingapis">
    Join the Polymarket Trading APIs channel for real-time announcements.
  </Card>

  <Card title="Discord" icon="discord" href="https://discord.com/channels/710897173927297116/1473553279421255803">
    Join the #trading-apis channel in the Polymarket Discord.
  </Card>
</CardGroup>

Announcements typically include **what's changing**, the **scheduled time**, and the **expected downtime window**. The goal is \~2 days notice when possible.

***

## Handling HTTP 425

During a restart window, the CLOB API returns **HTTP 425 (Too Early)** on all order-related endpoints. This tells your client that the matching engine is restarting and will be back shortly.

### Recommended Retry Strategy

<Steps>
  <Step title="Detect 425">
    When you receive an HTTP `425` response, the matching engine is restarting. Do not treat this as a permanent error.
  </Step>

  <Step title="Back off and retry">
    Wait and retry with exponential backoff. Start at 1–2 seconds and increase the interval on each retry.
  </Step>

  <Step title="Resume normal operation">
    Once you receive a successful response, the engine is back online. Resume normal order flow.
  </Step>
</Steps>

### Code Examples

Check the HTTP status code on responses to the CLOB API and retry on `425`:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const CLOB_HOST = "https://clob.polymarket.com";

  async function postWithRetry(path: string, body: any, headers: Record<string, string>) {
    const MAX_RETRIES = 10;
    let delay = 1000;

    for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
      const response = await fetch(`${CLOB_HOST}${path}`, {
        method: "POST",
        headers: { "Content-Type": "application/json", ...headers },
        body: JSON.stringify(body),
      });

      if (response.status === 425) {
        console.log(`Engine restarting, retrying in ${delay / 1000}s...`);
        await new Promise((r) => setTimeout(r, delay));
        delay = Math.min(delay * 2, 30000);
        continue;
      }

      return response;
    }
    throw new Error("Engine restart exceeded maximum retry attempts");
  }
  ```

  ```python Python theme={null}
  import time
  import requests

  CLOB_HOST = "https://clob.polymarket.com"

  def post_with_retry(path, body, headers, max_retries=10):
      delay = 1

      for attempt in range(max_retries):
          response = requests.post(
              f"{CLOB_HOST}{path}",
              json=body,
              headers=headers,
          )

          if response.status_code == 425:
              print(f"Engine restarting, retrying in {delay}s...")
              time.sleep(delay)
              delay = min(delay * 2, 30)
              continue

          return response

      raise Exception("Engine restart exceeded maximum retry attempts")
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::error::{Kind, StatusCode};

  // Wrap SDK calls with retry logic for HTTP 425.
  // Re-build and re-sign the order each attempt since SignedOrder is consumed.
  let mut delay = std::time::Duration::from_secs(1);

  for _ in 0..10 {
      let order = client.limit_order()
          .token_id(token_id).price(price).size(size).side(side)
          .build().await?;
      let signed = client.sign(&signer, order).await?;

      match client.post_order(signed).await {
          Ok(response) => return Ok(response),
          Err(err) if err.kind() == Kind::Status => {
              if let Some(status) = err.downcast_ref::<polymarket_client_sdk_v2::error::Status>() {
                  if status.status_code == StatusCode::from_u16(425).unwrap() {
                      eprintln!("Engine restarting, retrying in {delay:?}...");
                      tokio::time::sleep(delay).await;
                      delay = (delay * 2).min(std::time::Duration::from_secs(30));
                      continue;
                  }
              }
              return Err(err);
          }
          Err(err) => return Err(err),
      }
  }
  ```
</CodeGroup>

***

## Best Practices

* **Subscribe to announcement channels** — get notified before restarts happen so you can prepare
* **Handle 425 gracefully** — treat it as a temporary condition, not an error; your retry logic should resume automatically
* **Avoid aggressive retries** — the engine needs time to reload orderbooks; rapid-fire retries won't speed things up and may hit rate limits once the engine is back
* **Log restart events** — track when your client encounters 425s to correlate with announced maintenance windows


# Orderbook
Source: https://docs.polymarket.com/trading/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-v2";

  const client = new ClobClient({ host: "https://clob.polymarket.com", chain: 137 });
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import ClobClient

  client = ClobClient("https://clob.polymarket.com", chain_id=137)
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::{Client, Config};

  let client = Client::new("https://clob.polymarket.com", Config::default())?;
  ```

  ```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"])
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::request::OrderBookSummaryRequest;

  let token_id = "TOKEN_ID".parse()?;
  let request = OrderBookSummaryRequest::builder().token_id(token_id).build();
  let book = client.order_book(&request).await?;

  println!("Best bid: {:?}", book.bids[0]);
  println!("Best ask: {:?}", book.asks[0]);
  println!("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"])
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::{Side, request::PriceRequest};

  let token_id = "TOKEN_ID".parse()?;

  let buy_req = PriceRequest::builder().token_id(token_id).side(Side::Buy).build();
  let buy_price = client.price(&buy_req).await?;
  println!("Best ask: {}", buy_price.price);

  let sell_req = PriceRequest::builder().token_id(token_id).side(Side::Sell).build();
  let sell_price = client.price(&sell_req).await?;
  println!("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"])
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::request::MidpointRequest;

  let token_id = "TOKEN_ID".parse()?;
  let request = MidpointRequest::builder().token_id(token_id).build();
  let midpoint = client.midpoint(&request).await?;
  println!("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"])
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::request::SpreadRequest;

  let token_id = "TOKEN_ID".parse()?;
  let request = SpreadRequest::builder().token_id(token_id).build();
  let spread = client.spread(&request).await?;
  println!("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-v2";

  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']}")
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::{Interval, TimeRange, request::PriceHistoryRequest};

  let token_id = "TOKEN_ID".parse()?;
  let request = PriceHistoryRequest::builder()
      .market(token_id) // Note: this param is named "market" but takes a token ID
      .time_range(TimeRange::Interval { interval: Interval::OneDay })
      .fidelity(60) // Data points every 60 minutes
      .build();
  let history = client.price_history(&request).await?;

  for point in &history.history {
      println!("{}: {}", 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-v2";

  // 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_v2 import OrderType

  price = client.calculate_market_price(
      token_id="TOKEN_ID",
      side="BUY",
      amount=500,
      order_type=OrderType.FOK,
  )

  print("Estimated fill price:", price)
  ```

  ```rust Rust theme={null}
  // The Rust SDK handles market price calculation automatically
  // inside the market_order() builder when no price is specified.
  // It walks the orderbook to determine the fill price for you.
  let order = client
      .market_order()
      .token_id("TOKEN_ID".parse()?)
      .amount(Amount::usdc(dec!(500))?)
      .side(Side::Buy)
      .order_type(OrderType::FOK)
      .build()
      .await?; // Price auto-calculated from orderbook depth
  ```
</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-v2";

  // 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"},
  ])
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::{Side, request::PriceRequest};

  let token_a = "TOKEN_A".parse()?;
  let token_b = "TOKEN_B".parse()?;
  let requests = vec![
      PriceRequest::builder().token_id(token_a).side(Side::Buy).build(),
      PriceRequest::builder().token_id(token_b).side(Side::Buy).build(),
  ];
  let prices = client.prices(&requests).await?;
  ```

  ```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"])
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::request::LastTradePriceRequest;

  let token_id = "TOKEN_ID".parse()?;
  let request = LastTradePriceRequest::builder().token_id(token_id).build();
  let last_trade = client.last_trade_price(&request).await?;
  println!("{} {:?}", 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 and 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>
  <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>


# Order Attribution
Source: https://docs.polymarket.com/trading/orders/attribution

Attribute orders to your builder code for volume credit and fee rewards

Order attribution credits trades to your builder account by attaching your **builder code** to every order. This enables:

* Volume tracking on the [Builder Leaderboard](https://builders.polymarket.com/)
* Fee rewards through the [Builder Program](/builders/overview)
* Performance monitoring via the Data API

***

## Builder Code

Your **builder code** is a `bytes32` identifier tied to your builder profile. Find it at [polymarket.com/settings?tab=builder](https://polymarket.com/settings?tab=builder).

That's the only credential you need for attribution — no HMAC signing, no separate API key, no special headers.

<Note>
  Builder codes are public identifiers — they appear onchain in the `builder`
  field of every order you attribute. Only you control which orders include your
  code, so keep it scoped to apps you own.
</Note>

***

## Attaching the Builder Code

Pass `builderCode` in the order struct on every order you submit. The SDK serializes it into the onchain order's `builder` field, and the protocol attributes every matched trade to your profile.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { ClobClient, Side, OrderType } from "@polymarket/clob-client-v2";

  const client = new ClobClient({
    host: "https://clob.polymarket.com",
    chain: 137,
    signer,
    creds: apiCreds,
    signatureType: 3,
    funderAddress: depositWalletAddress,
  });

  const response = await client.createAndPostOrder(
    {
      tokenID: "0x...",
      price: 0.55,
      size: 100,
      side: Side.BUY,
      builderCode: "0xabc123...", // your builder code from polymarket.com/settings?tab=builder
    },
    { tickSize: "0.01", negRisk: false },
    OrderType.GTC,
  );
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import ClobClient
  from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions
  from py_clob_client_v2.order_builder.constants import BUY

  client = ClobClient(
      host="https://clob.polymarket.com",
      chain_id=137,
      key=private_key,
      creds=api_creds,
      signature_type=3,
      funder=deposit_wallet_address,
  )

  response = client.create_and_post_order(
      OrderArgs(
          token_id="0x...",
          price=0.55,
          size=100,
          side=BUY,
          builder_code="0xabc123...",  # your builder code from polymarket.com/settings?tab=builder
      ),
      options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
      order_type=OrderType.GTC,
  )
  ```
</CodeGroup>

Every order placed with `builderCode` attached is credited to your builder profile — no additional configuration needed.

***

## Verifying Attribution

Query trades attributed to your builder code:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const trades = await client.getBuilderTrades();

  // Filtered by market
  const marketTrades = await client.getBuilderTrades({
    market: "0xbd31dc8a...",
  });
  ```

  ```python Python theme={null}
  trades = client.get_builder_trades()

  market_trades = client.get_builder_trades(
      market="0xbd31dc8a..."
  )
  ```
</CodeGroup>

Each `BuilderTrade` includes: `id`, `market`, `assetId`, `side`, `size`, `price`, `status`, `outcome`, `owner`, `maker`, `builder`, `transactionHash`, `matchTime`, `fee`, and `feeUsdc`.

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Volume not appearing on the leaderboard">
    <ul>
      <li>Confirm your `builderCode` is correctly attached to every order</li>
      <li>Check that orders are being matched, not just placed</li>
      <li>Allow up to 24 hours for volume to appear on the leaderboard</li>
    </ul>
  </Accordion>

  <Accordion title="Invalid builder code">
    Verify the code matches what's shown on [your Builder
    Profile](https://polymarket.com/settings?tab=builder). Builder codes are
    `bytes32` hex values starting with `0x`.
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup>
  <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>


# Cancel Order
Source: https://docs.polymarket.com/trading/orders/cancel

Cancel single, multiple, or all open orders

All cancel endpoints require [L2 authentication](/trading/overview#authentication). The response always includes `canceled` (list of cancelled order IDs) and `not_canceled` (map of order IDs to failure reasons).

***

## Cancel a Single Order

<CodeGroup>
  ```typescript TypeScript theme={null}
  const resp = await client.cancelOrder("0xb816482a...");
  console.log(resp);
  // { canceled: ["0xb816482a..."], not_canceled: {} }
  ```

  ```python Python theme={null}
  resp = client.cancel(order_id="0xb816482a...")
  print(resp)
  # {"canceled": ["0xb816482a..."], "not_canceled": {}}
  ```

  ```rust Rust theme={null}
  let resp = client.cancel_order("0xb816482a...").await?;
  println!("{:?}", resp);
  // CancelOrdersResponse { canceled: ["0xb816482a..."], not_canceled: {} }
  ```

  ```bash REST theme={null}
  curl -X DELETE "https://clob.polymarket.com/order" \
    -H "Content-Type: application/json" \
    -H "POLY_ADDRESS: ..." \
    -H "POLY_SIGNATURE: ..." \
    -H "POLY_TIMESTAMP: ..." \
    -H "POLY_API_KEY: ..." \
    -H "POLY_PASSPHRASE: ..." \
    -d '{"orderID": "0xb816482a..."}'
  ```
</CodeGroup>

***

## Cancel Multiple Orders

<CodeGroup>
  ```typescript TypeScript theme={null}
  const resp = await client.cancelOrders(["0xb816482a...", "0xc927593b..."]);
  ```

  ```python Python theme={null}
  resp = client.cancel_orders([
      "0xb816482a...",
      "0xc927593b...",
  ])
  ```

  ```rust Rust theme={null}
  let resp = client.cancel_orders(&["0xb816482a...", "0xc927593b..."]).await?;
  ```

  ```bash REST theme={null}
  curl -X DELETE "https://clob.polymarket.com/orders" \
    -H "Content-Type: application/json" \
    -H "POLY_ADDRESS: ..." \
    -H "POLY_SIGNATURE: ..." \
    -H "POLY_TIMESTAMP: ..." \
    -H "POLY_API_KEY: ..." \
    -H "POLY_PASSPHRASE: ..." \
    -d '["0xb816482a...", "0xc927593b..."]'
  ```
</CodeGroup>

***

## Cancel All Orders

Cancel every open order across all markets:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const resp = await client.cancelAll();
  ```

  ```python Python theme={null}
  resp = client.cancel_all()
  ```

  ```rust Rust theme={null}
  let resp = client.cancel_all_orders().await?;
  ```

  ```bash REST theme={null}
  curl -X DELETE "https://clob.polymarket.com/cancel-all" \
    -H "POLY_ADDRESS: ..." \
    -H "POLY_SIGNATURE: ..." \
    -H "POLY_TIMESTAMP: ..." \
    -H "POLY_API_KEY: ..." \
    -H "POLY_PASSPHRASE: ..."
  ```
</CodeGroup>

***

## Cancel by Market

Cancel all orders for a specific market, optionally filtered to a single token. Both `market` and `asset_id` are optional — omit both to cancel all orders.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const resp = await client.cancelMarketOrders({
    market: "0xbd31dc8a...", // optional: condition ID
    asset_id: "52114319501245...", // optional: specific token
  });
  ```

  ```python Python theme={null}
  resp = client.cancel_market_orders(
      market="0xbd31dc8a...",
      asset_id="52114319501245...",  # optional
  )
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::request::CancelMarketOrderRequest;

  let request = CancelMarketOrderRequest::builder()
      .market("0xbd31dc8a...".parse()?)
      .asset_id("52114319501245...".parse()?)
      .build();
  let resp = client.cancel_market_orders(&request).await?;
  ```

  ```bash REST theme={null}
  curl -X DELETE "https://clob.polymarket.com/cancel-market-orders" \
    -H "Content-Type: application/json" \
    -H "POLY_ADDRESS: ..." \
    -H "POLY_SIGNATURE: ..." \
    -H "POLY_TIMESTAMP: ..." \
    -H "POLY_API_KEY: ..." \
    -H "POLY_PASSPHRASE: ..." \
    -d '{"market": "0xbd31dc8a...", "asset_id": "52114319501245..."}'
  ```
</CodeGroup>

***

## Querying Orders

### Get a Single Order

<CodeGroup>
  ```typescript TypeScript theme={null}
  const order = await client.getOrder("0xb816482a...");
  console.log(order.status, order.size_matched);
  ```

  ```python Python theme={null}
  order = client.get_order("0xb816482a...")
  print(order["status"], order["size_matched"])
  ```

  ```rust Rust theme={null}
  let order = client.order("0xb816482a...").await?;
  println!("{:?} {}", order.status, order.size_matched);
  ```
</CodeGroup>

### Get Open Orders

Retrieve all open orders, optionally filtered by market or token:

<CodeGroup>
  ```typescript TypeScript theme={null}
  // All open orders
  const orders = await client.getOpenOrders();

  // Filtered by market
  const marketOrders = await client.getOpenOrders({
    market: "0xbd31dc8a...",
  });

  // Filtered by token
  const tokenOrders = await client.getOpenOrders({
    asset_id: "52114319501245...",
  });
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import OpenOrderParams

  # All open orders
  orders = client.get_orders()

  # Filtered by market
  market_orders = client.get_orders(
      OpenOrderParams(market="0xbd31dc8a...")
  )
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::request::OrdersRequest;

  // All open orders
  let orders = client.orders(&OrdersRequest::default(), None).await?;

  // Filtered by market
  let request = OrdersRequest::builder()
      .market("0xbd31dc8a...".parse()?)
      .build();
  let market_orders = client.orders(&request, None).await?;
  ```
</CodeGroup>

### OpenOrder Object

| Field              | Type      | Description                                |
| ------------------ | --------- | ------------------------------------------ |
| `id`               | string    | Order ID                                   |
| `status`           | string    | Current order status                       |
| `market`           | string    | Condition ID                               |
| `asset_id`         | string    | Token ID                                   |
| `side`             | string    | `BUY` or `SELL`                            |
| `original_size`    | string    | Size at placement                          |
| `size_matched`     | string    | Amount filled                              |
| `price`            | string    | Limit price                                |
| `outcome`          | string    | Human-readable outcome (e.g., "Yes", "No") |
| `order_type`       | string    | Order type (GTC, GTD, FOK, FAK)            |
| `maker_address`    | string    | Funder address                             |
| `owner`            | string    | API key of the order owner                 |
| `associate_trades` | string\[] | Trade IDs this order has been included in  |
| `expiration`       | string    | Unix expiration timestamp (`0` if none)    |
| `created_at`       | string    | Unix creation timestamp                    |

***

## Trade History

When an order is matched, it creates a trade. Trades progress through these statuses:

| Status      | Terminal | Description                             |
| ----------- | -------- | --------------------------------------- |
| `MATCHED`   | No       | Matched and sent for onchain submission |
| `MINED`     | No       | Mined on the chain, no finality yet     |
| `CONFIRMED` | Yes      | Achieved finality — trade successful    |
| `RETRYING`  | No       | Transaction failed — being retried      |
| `FAILED`    | Yes      | Failed permanently                      |

<CodeGroup>
  ```typescript TypeScript theme={null}
  // All trades
  const trades = await client.getTrades();

  // Filtered by market
  const marketTrades = await client.getTrades({
    market: "0xbd31dc8a...",
  });
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import TradeParams

  trades = client.get_trades()

  market_trades = client.get_trades(
      TradeParams(market="0xbd31dc8a...")
  )
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::request::TradesRequest;

  // All trades
  let trades = client.trades(&TradesRequest::default(), None).await?;

  // Filtered by market
  let request = TradesRequest::builder()
      .market("0xbd31dc8a...".parse()?)
      .build();
  let market_trades = client.trades(&request, None).await?;
  ```
</CodeGroup>

Additional filter parameters: `id`, `maker_address`, `asset_id`, `before`, `after`.

The Rust SDK uses cursor-based pagination via the `next_cursor` parameter:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const page = await client.getTradesPaginated({ market: "0xbd31dc8a..." });
  console.log(page.trades, page.count); // trades array + total count
  ```

  ```python Python theme={null}
  page = client.get_trades_paginated(TradeParams(market="0xbd31dc8a..."))
  ```

  ```rust Rust theme={null}
  // First page
  let page = client.trades(&request, None).await?;
  println!("{} trades, cursor: {}", page.data.len(), page.next_cursor);

  // Next page
  let page2 = client.trades(&request, Some(page.next_cursor)).await?;
  ```
</CodeGroup>

### Trade Object

| Field              | Type          | Description                          |
| ------------------ | ------------- | ------------------------------------ |
| `id`               | string        | Trade ID                             |
| `taker_order_id`   | string        | Taker order hash                     |
| `market`           | string        | Condition ID                         |
| `asset_id`         | string        | Token ID                             |
| `side`             | string        | `BUY` or `SELL`                      |
| `size`             | string        | Trade size                           |
| `price`            | string        | Execution price                      |
| `fee_rate_bps`     | string        | Fee rate in basis points             |
| `status`           | string        | Trade status (see table above)       |
| `match_time`       | string        | Unix timestamp when matched          |
| `last_update`      | string        | Unix timestamp of last status change |
| `outcome`          | string        | Human-readable outcome (e.g., "Yes") |
| `maker_address`    | string        | Maker's funder address               |
| `owner`            | string        | API key of the trade owner           |
| `transaction_hash` | string        | Onchain transaction hash             |
| `bucket_index`     | number        | Index for trade reconciliation       |
| `trader_side`      | string        | `TAKER` or `MAKER`                   |
| `maker_orders`     | MakerOrder\[] | Maker orders that filled this trade  |

<Note>
  A single trade can be split across multiple onchain transactions due to gas
  limits. Use `bucket_index` and `match_time` to reconcile related transactions
  back to a single logical trade.
</Note>

***

## Order Scoring

Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Single order
  const scoring = await client.isOrderScoring({ orderId: "0x..." });

  // Multiple orders
  const batch = await client.areOrdersScoring({
    orderIds: ["0x...", "0x..."],
  });
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import OrderScoringParams, OrdersScoringParams

  scoring = client.is_order_scoring(
      OrderScoringParams(orderId="0x...")
  )

  batch = client.are_orders_scoring(
      OrdersScoringParams(orderIds=["0x...", "0x..."])
  )
  ```

  ```rust Rust theme={null}
  // Single order
  let scoring = client.is_order_scoring("0x...").await?;

  // Multiple orders
  let batch = client.are_orders_scoring(&["0x...", "0x..."]).await?;
  ```
</CodeGroup>

***

## Next Steps

<CardGroup>
  <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>


# Create Order
Source: https://docs.polymarket.com/trading/orders/create

Build, sign, and submit orders

All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.

<Info>
  The SDK handles EIP-712 signing and submission for you. If you prefer the REST
  API directly, see [Authentication](/api-reference/authentication) for
  constructing the required headers and the [API
  Reference](/api-reference/introduction) for full endpoint documentation
  including the raw order object fields and request/response schemas.
</Info>

***

## Order Types

| Type    | Behavior                                                             | Use Case                        |
| ------- | -------------------------------------------------------------------- | ------------------------------- |
| **GTC** | Good-Til-Cancelled — rests on the book until filled or cancelled     | Default for limit orders        |
| **GTD** | Good-Til-Date — active until a specified expiration time             | Auto-expire before known events |
| **FOK** | Fill-Or-Kill — must fill immediately and entirely, or cancel         | All-or-nothing market orders    |
| **FAK** | Fill-And-Kill — fills what's available immediately, cancels the rest | Partial-fill market orders      |

* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
  * **BUY**: specify the dollar amount you want to spend
  * **SELL**: specify the number of shares you want to sell

***

## Limit Orders

The simplest way to place a limit order — create, sign, and submit in one call:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { ClobClient, Side, OrderType } from "@polymarket/clob-client-v2";

  const response = await client.createAndPostOrder(
    {
      tokenID: "TOKEN_ID",
      price: 0.5,
      size: 10,
      side: Side.BUY,
    },
    {
      tickSize: "0.01",
      negRisk: false,
    },
    OrderType.GTC,
  );

  console.log("Order ID:", response.orderID);
  console.log("Status:", response.status);
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions
  from py_clob_client_v2.order_builder.constants import BUY

  response = client.create_and_post_order(
      OrderArgs(
          token_id="TOKEN_ID",
          price=0.50,
          size=10,
          side=BUY,
      ),
      options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
      order_type=OrderType.GTC
  )

  print("Order ID:", response["orderID"])
  print("Status:", response["status"])
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::Side;
  use polymarket_client_sdk_v2::types::dec;

  let token_id = "TOKEN_ID".parse()?;
  let order = client
      .limit_order()
      .token_id(token_id)
      .price(dec!(0.50))
      .size(dec!(10))
      .side(Side::Buy)
      .build()
      .await?;
  let signed = client.sign(&signer, order).await?;
  let response = client.post_order(signed).await?;

  println!("Order ID: {}", response.order_id);
  println!("Status: {:?}", response.status);
  ```
</CodeGroup>

### Two-Step Sign Then Submit

For more control, you can separate signing from submission. This is useful for batch orders or custom submission logic:

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Step 1: Create and sign locally
  const signedOrder = await client.createOrder(
    {
      tokenID: "TOKEN_ID",
      price: 0.5,
      size: 10,
      side: Side.BUY,
    },
    { tickSize: "0.01", negRisk: false },
  );

  // Step 2: Submit to the CLOB
  const response = await client.postOrder(signedOrder, OrderType.GTC);
  ```

  ```python Python theme={null}
  # Step 1: Create and sign locally
  signed_order = client.create_order(
      OrderArgs(
          token_id="TOKEN_ID",
          price=0.50,
          size=10,
          side=BUY,
      ),
      options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False)
  )

  # Step 2: Submit to the CLOB
  response = client.post_order(signed_order, OrderType.GTC)
  ```

  ```rust Rust theme={null}
  // Step 1: Create order (auto-fetches tick size, neg risk, fee rate)
  let order = client
      .limit_order()
      .token_id("TOKEN_ID".parse()?)
      .price(dec!(0.50))
      .size(dec!(10))
      .side(Side::Buy)
      .build()
      .await?;

  // Step 2: Sign and submit separately
  let signed = client.sign(&signer, order).await?;
  let response = client.post_order(signed).await?;
  ```
</CodeGroup>

***

## GTD Orders

GTD orders auto-expire at a specified time. Useful for quoting around known events.

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Expire in 1 hour (+ 60s security threshold buffer)
  const expiration = Math.floor(Date.now() / 1000) + 60 + 3600;

  const response = await client.createAndPostOrder(
    {
      tokenID: "TOKEN_ID",
      price: 0.5,
      size: 10,
      side: Side.BUY,
      expiration,
    },
    { tickSize: "0.01", negRisk: false },
    OrderType.GTD,
  );
  ```

  ```python Python theme={null}
  import time

  # Expire in 1 hour (+ 60s security threshold buffer)
  expiration = int(time.time()) + 60 + 3600

  response = client.create_and_post_order(
      OrderArgs(
          token_id="TOKEN_ID",
          price=0.50,
          size=10,
          side=BUY,
          expiration=expiration,
      ),
      options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
      order_type=OrderType.GTD
  )
  ```

  ```rust Rust theme={null}
  use chrono::{TimeDelta, Utc};
  use polymarket_client_sdk_v2::clob::types::OrderType;

  let order = client
      .limit_order()
      .token_id("TOKEN_ID".parse()?)
      .price(dec!(0.50))
      .size(dec!(10))
      .side(Side::Buy)
      .order_type(OrderType::GTD)
      .expiration(Utc::now() + TimeDelta::hours(1))
      .build()
      .await?;
  let signed = client.sign(&signer, order).await?;
  let response = client.post_order(signed).await?;
  ```
</CodeGroup>

<Note>
  There is a security threshold of one minute on GTD expiration. To set an
  effective lifetime of N seconds, use `now + 60 + N`. For example, for a
  30-second effective lifetime, set the expiration to `now + 60 + 30`.
</Note>

***

## Market Orders

Market orders execute immediately against resting liquidity using FOK or FAK types:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Side, OrderType } from "@polymarket/clob-client-v2";

  // FOK BUY: spend exactly $100 or cancel entirely
  const buyOrder = await client.createMarketOrder(
    {
      tokenID: "TOKEN_ID",
      side: Side.BUY,
      amount: 100, // dollar amount
      price: 0.5, // worst-price limit (slippage protection)
    },
    { tickSize: "0.01", negRisk: false },
  );
  await client.postOrder(buyOrder, OrderType.FOK);

  // FOK SELL: sell exactly 200 shares or cancel entirely
  const sellOrder = await client.createMarketOrder(
    {
      tokenID: "TOKEN_ID",
      side: Side.SELL,
      amount: 200, // number of shares
      price: 0.45, // worst-price limit (slippage protection)
    },
    { tickSize: "0.01", negRisk: false },
  );
  await client.postOrder(sellOrder, OrderType.FOK);
  ```

  ```python Python theme={null}
  from py_clob_client_v2.order_builder.constants import BUY, SELL
  from py_clob_client_v2 import MarketOrderArgs, OrderType, PartialCreateOrderOptions

  # FOK BUY: spend exactly $100 or cancel entirely
  buy_order = client.create_market_order(
      order_args=MarketOrderArgs(
          token_id="TOKEN_ID",
          side=BUY,
          amount=100,  # dollar amount
          price=0.50,  # worst-price limit (slippage protection)
      ),
      options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
  )
  client.post_order(buy_order, OrderType.FOK)

  # FOK SELL: sell exactly 200 shares or cancel entirely
  sell_order = client.create_market_order(
      order_args=MarketOrderArgs(
          token_id="TOKEN_ID",
          side=SELL,
          amount=200,  # number of shares
          price=0.45,  # worst-price limit (slippage protection)
      ),
      options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
  )
  client.post_order(sell_order, OrderType.FOK)
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::{Amount, OrderType, Side};

  let token_id = "TOKEN_ID".parse()?;

  // FOK BUY: spend exactly $100 or cancel entirely
  let buy = client
      .market_order()
      .token_id(token_id)
      .amount(Amount::usdc(dec!(100))?)
      .price(dec!(0.50)) // worst-price limit (slippage protection)
      .side(Side::Buy)
      .order_type(OrderType::FOK)
      .build()
      .await?;
  let signed = client.sign(&signer, buy).await?;
  client.post_order(signed).await?;

  // FOK SELL: sell exactly 200 shares or cancel entirely
  let sell = client
      .market_order()
      .token_id(token_id)
      .amount(Amount::shares(dec!(200))?)
      .price(dec!(0.45)) // worst-price limit (slippage protection)
      .side(Side::Sell)
      .order_type(OrderType::FOK)
      .build()
      .await?;
  let signed = client.sign(&signer, sell).await?;
  client.post_order(signed).await?;
  ```
</CodeGroup>

* **FOK** — fill entirely or cancel the whole order
* **FAK** — fill what's available, cancel the rest

The `price` field on market orders acts as a **worst-price limit** (slippage protection), not a target execution price.

### One-Step Market Order

For convenience, `createAndPostMarketOrder` handles creation, signing, and submission in one call:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const response = await client.createAndPostMarketOrder(
    {
      tokenID: "TOKEN_ID",
      side: Side.BUY,
      amount: 100,
      price: 0.5,
    },
    { tickSize: "0.01", negRisk: false },
    OrderType.FOK,
  );
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import MarketOrderArgs, OrderType, PartialCreateOrderOptions
  from py_clob_client_v2.order_builder.constants import BUY

  response = client.create_and_post_market_order(
      order_args=MarketOrderArgs(
          token_id="TOKEN_ID",
          side=BUY,
          amount=100,
          price=0.50,
      ),
      options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False),
      order_type=OrderType.FOK,
  )
  ```

  ```rust Rust theme={null}
  let order = client
      .market_order()
      .token_id("TOKEN_ID".parse()?)
      .amount(Amount::usdc(dec!(100))?)
      .price(dec!(0.50))
      .side(Side::Buy)
      .order_type(OrderType::FOK)
      .build()
      .await?;
  let signed = client.sign(&signer, order).await?;
  let response = client.post_order(signed).await?;
  ```
</CodeGroup>

***

## Post-Only Orders

Post-only orders guarantee you're always the maker. If the order would match immediately (cross the spread), it's rejected instead of executed.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const response = await client.postOrder(signedOrder, OrderType.GTC, true);
  ```

  ```python Python theme={null}
  response = client.post_order(signed_order, OrderType.GTC, post_only=True)
  ```

  ```rust Rust theme={null}
  let order = client
      .limit_order()
      .token_id("TOKEN_ID".parse()?)
      .price(dec!(0.50))
      .size(dec!(10))
      .side(Side::Buy)
      .post_only(true)
      .build()
      .await?;
  let signed = client.sign(&signer, order).await?;
  let response = client.post_order(signed).await?;
  ```
</CodeGroup>

* Only works with **GTC** and **GTD** order types
* Rejected if combined with FOK or FAK

***

## Batch Orders

Place up to **15 orders** in a single request:

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { OrderType, Side, PostOrdersArgs } from "@polymarket/clob-client-v2";

  const orders: PostOrdersArgs[] = [
    {
      order: await client.createOrder(
        {
          tokenID: "TOKEN_ID",
          price: 0.48,
          side: Side.BUY,
          size: 500,
        },
        { tickSize: "0.01", negRisk: false },
      ),
      orderType: OrderType.GTC,
    },
    {
      order: await client.createOrder(
        {
          tokenID: "TOKEN_ID",
          price: 0.52,
          side: Side.SELL,
          size: 500,
        },
        { tickSize: "0.01", negRisk: false },
      ),
      orderType: OrderType.GTC,
    },
  ];

  const response = await client.postOrders(orders);
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import OrderArgs, OrderType, PostOrdersV2Args, PartialCreateOrderOptions
  from py_clob_client_v2.order_builder.constants import BUY, SELL

  response = client.post_orders([
      PostOrdersV2Args(
          order=client.create_order(OrderArgs(
              price=0.48,
              size=500,
              side=BUY,
              token_id="TOKEN_ID",
          ), options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False)),
          orderType=OrderType.GTC,
      ),
      PostOrdersV2Args(
          order=client.create_order(OrderArgs(
              price=0.52,
              size=500,
              side=SELL,
              token_id="TOKEN_ID",
          ), options=PartialCreateOrderOptions(tick_size="0.01", neg_risk=False)),
          orderType=OrderType.GTC,
      ),
  ])
  ```

  ```rust Rust theme={null}
  let token_id = "TOKEN_ID".parse()?;

  let bid = client
      .limit_order()
      .token_id(token_id)
      .price(dec!(0.48))
      .size(dec!(500))
      .side(Side::Buy)
      .build()
      .await?;
  let ask = client
      .limit_order()
      .token_id(token_id)
      .price(dec!(0.52))
      .size(dec!(500))
      .side(Side::Sell)
      .build()
      .await?;

  let signed_bid = client.sign(&signer, bid).await?;
  let signed_ask = client.sign(&signer, ask).await?;
  let response = client.post_orders(vec![signed_bid, signed_ask]).await?;
  ```
</CodeGroup>

***

## Order Options

Every order requires two market-specific options: `tickSize` and `negRisk`. For
details on signature types (`0` = EOA, `1` = POLY\_PROXY, `2` = GNOSIS\_SAFE,
`3` = POLY\_1271 deposit wallet), see
[Authentication](/api-reference/authentication#signature-types-and-funder).

### Tick Sizes

Your order price must conform to the market's tick size, or the order is rejected.

| Tick Size | Precision  | Example Prices         |
| --------- | ---------- | ---------------------- |
| `0.1`     | 1 decimal  | 0.1, 0.2, 0.5          |
| `0.01`    | 2 decimals | 0.01, 0.50, 0.99       |
| `0.001`   | 3 decimals | 0.001, 0.500, 0.999    |
| `0.0001`  | 4 decimals | 0.0001, 0.5000, 0.9999 |

<CodeGroup>
  ```typescript TypeScript theme={null}
  const tickSize = await client.getTickSize("TOKEN_ID");
  ```

  ```python Python theme={null}
  tick_size = client.get_tick_size("TOKEN_ID")
  ```

  ```rust Rust theme={null}
  let token_id = "TOKEN_ID".parse()?;
  let tick_size = client.tick_size(token_id).await?;
  ```
</CodeGroup>

### Negative Risk

Multi-outcome events (3+ outcomes) use the Neg Risk CTF Exchange. Pass `negRisk: true` for these markets.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const isNegRisk = await client.getNegRisk("TOKEN_ID");
  ```

  ```python Python theme={null}
  is_neg_risk = client.get_neg_risk("TOKEN_ID")
  ```

  ```rust Rust theme={null}
  let token_id = "TOKEN_ID".parse()?;
  let is_neg_risk = client.neg_risk(token_id).await?;
  ```
</CodeGroup>

<Tip>
  Both values are also available on the market object: `minimum_tick_size` and
  `neg_risk`. In Rust, the order builder auto-fetches both — you don't need to
  look them up manually.
</Tip>

***

## Prerequisites

Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:

* **BUY orders**: pUSD allowance >= spending amount
* **SELL orders**: conditional token allowance >= selling amount

Order size is limited by your available balance minus amounts reserved by existing open orders:

$$
\text{maxOrderSize} = \text{balance} - \sum(\text{openOrderSize} - \text{filledAmount})
$$

<Warning>
  Orders are continuously monitored for validity — balances and allowances are
  tracked in real time. Any maker caught intentionally abusing these checks will
  be blacklisted.
</Warning>

### Sports Markets

Sports markets have additional behaviors:

* Outstanding limit orders are **automatically cancelled** once the game begins, clearing the entire order book at the official start time
* Marketable orders have a **1-second placement delay** before matching
* Game start times can shift — monitor your orders closely, as they may not be cleared if the start time changes unexpectedly

***

## Response

A successful order placement returns:

```json theme={null}
{
  "success": true,
  "errorMsg": "",
  "orderID": "0xabc123...",
  "takingAmount": "",
  "makingAmount": "",
  "status": "live",
  "transactionsHashes": [],
  "tradeIDs": []
}
```

### Statuses

| Status      | Description                                                 |
| ----------- | ----------------------------------------------------------- |
| `live`      | Order resting on the book                                   |
| `matched`   | Order matched immediately with a resting order              |
| `delayed`   | Marketable order 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)
  ```

  ```rust Rust theme={null}
  // With the `heartbeats` feature, the Rust SDK can auto-send heartbeats
  // in a background task — no manual loop needed:
  Client::start_heartbeats(&mut client)?;
  // ... your trading logic ...
  client.stop_heartbeats().await?;

  // Or send manually:
  let resp = client.post_heartbeat(None).await?; // None for first call
  let resp = client.post_heartbeat(Some(resp.heartbeat_id)).await?;
  ```
</CodeGroup>

* Include the most recent `heartbeat_id` in each request. Use an empty string for the first request.
* If you send an expired ID, the server responds with `400` and the correct ID. Update and retry.

***

## Next Steps

<CardGroup>
  <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>


# Overview
Source: https://docs.polymarket.com/trading/orders/overview

Order types, tick sizes, and querying orders

All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.

The underlying order primitive is structured, hashed, and signed using the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) standard, then executed onchain via the Exchange contract. Preparing orders manually is involved, so we recommend using the open-source [TypeScript](https://github.com/Polymarket/clob-client-v2) or [Python](https://github.com/Polymarket/py-clob-client-v2) SDK clients, which handle signing and submission for you.

<Info>
  If you prefer to use the REST API directly, you'll need to manage order
  signing yourself. See [Authentication](/api-reference/authentication) for details on
  constructing the required headers.
</Info>

***

## Order Types

| Type                         | Behavior                                                                                           | Use Case                               |
| ---------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------- |
| **GTC** (Good-Til-Cancelled) | Rests on the book until filled or cancelled                                                        | Default for passive limit orders       |
| **GTD** (Good-Til-Date)      | Active until a specified expiration time (UTC seconds timestamp), unless filled or cancelled first | Auto-expire orders before known events |
| **FOK** (Fill-Or-Kill)       | Must be filled immediately and entirely, or the whole order is cancelled                           | All-or-nothing execution               |
| **FAK** (Fill-And-Kill)      | Fills as many shares as available immediately, then cancels any unfilled remainder                 | Partial immediate execution            |

* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
  * **BUY**: specify the dollar amount you want to spend
  * **SELL**: specify the number of shares you want to sell
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.

<Note>
  **GTD expiration**: There is a security threshold of one minute. If you need
  the order to expire in 90 seconds, the correct expiration value is `now + 1
      minute + 30 seconds`.
</Note>

### Post-Only Orders

Post-only orders are limit orders that will only rest on the book and not match immediately on entry.

* If a post-only order would cross the spread (i.e., it is marketable), it will be **rejected** rather than executed.
* Post-only **cannot** be combined with market order types (FOK or FAK). If `postOnly = true` is sent with a market order type, the order will be rejected.
* Post-only can only be used with **GTC** and **GTD** order types.

***

## Tick Sizes

Markets have different minimum price increments (tick sizes). Your order price must conform to the market's tick size, or the order will be rejected.

| Tick Size | Price Precision | Example Prices         |
| --------- | --------------- | ---------------------- |
| `0.1`     | 1 decimal       | 0.1, 0.2, 0.5          |
| `0.01`    | 2 decimals      | 0.01, 0.50, 0.99       |
| `0.001`   | 3 decimals      | 0.001, 0.500, 0.999    |
| `0.0001`  | 4 decimals      | 0.0001, 0.5000, 0.9999 |

Retrieve the tick size for a market using the SDK:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const tickSize = await client.getTickSize(tokenID);
  // Returns: "0.1" | "0.01" | "0.001" | "0.0001"
  ```

  ```python Python theme={null}
  tick_size = client.get_tick_size(token_id)
  # Returns: "0.1" | "0.01" | "0.001" | "0.0001"
  ```

  ```rust Rust theme={null}
  let resp = client.tick_size(token_id).await?;
  // resp.minimum_tick_size: TickSize::Tenth | Hundredth | Thousandth | TenThousandth
  ```
</CodeGroup>

<Tip>
  You can also check the `minimum_tick_size` field on a market object returned
  by the [Markets API](/market-data/fetching-markets).
</Tip>

***

## Negative Risk

Multi-outcome events (e.g., "Who will win the election?" with 3+ candidates) use a different exchange contract called the **Neg Risk CTF Exchange**. When placing orders on these markets, you must pass `negRisk: true` in the order options.

<CodeGroup>
  ```typescript TypeScript theme={null}
  const response = await client.createAndPostOrder(
    {
      tokenID: "TOKEN_ID",
      price: 0.5,
      size: 10,
      side: Side.BUY,
    },
    {
      tickSize: "0.01",
      negRisk: true, // Required for multi-outcome markets
    },
  );
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import OrderArgs, PartialCreateOrderOptions
  from py_clob_client_v2.order_builder.constants import BUY

  response = client.create_and_post_order(
      OrderArgs(
          token_id="TOKEN_ID",
          price=0.50,
          size=10,
          side=BUY,
      ),
      options=PartialCreateOrderOptions(
          tick_size="0.01",
          neg_risk=True,  # Required for multi-outcome markets
      )
  )
  ```

  ```rust Rust theme={null}
  // The Rust SDK auto-detects neg risk from the token ID — no flag needed.
  // The order builder fetches neg_risk and uses the correct exchange contract.
  let order = client
      .limit_order()
      .token_id("TOKEN_ID".parse()?)
      .price(dec!(0.50))
      .size(dec!(10))
      .side(Side::Buy)
      .build()
      .await?;
  let signed = client.sign(&signer, order).await?;
  let response = client.post_order(signed).await?;
  ```
</CodeGroup>

You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const isNegRisk = await client.getNegRisk(tokenID);
  ```

  ```python Python theme={null}
  is_neg_risk = client.get_neg_risk(token_id)
  ```

  ```rust Rust theme={null}
  let is_neg_risk = client.neg_risk(token_id).await?;
  ```
</CodeGroup>

***

## Allowances

Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:

* **Buying**: the funder must have set a **pUSD** allowance greater than or equal to the spending amount.
* **Selling**: the funder must have set a **conditional token** allowance greater than or equal to the selling amount.

This allows the Exchange contract to execute settlement according to your signed order instructions.

***

## Validity Checks

Orders are continually monitored to make sure they remain valid. This includes tracking:

* Underlying balances
* Allowances

<Warning>
  Any maker caught intentionally abusing these checks will be blacklisted.
</Warning>

There are also limits on order placement per market. You can only place orders that sum to less than or equal to your available balance for each market. For example, if you have 500 pUSD in your funding wallet, you can place one order to buy 1000 YES at \$0.50 — but any additional buy orders in that market will be rejected since your entire balance is reserved for the first order.

The max size you can place for an order is:

$$
\text{maxOrderSize} = \text{underlyingAssetBalance} - \sum(\text{orderSize} - \text{orderFillAmount})
$$

***

## Querying Orders

All query endpoints require [L2 authentication](/api-reference/authentication). [Builder-authenticated](/trading/clients/builder) clients can also query orders attributed to their builder account using the same methods.

### Get a Single Order

Retrieve details for a specific order by its ID:

<CodeGroup>
  ```typescript TypeScript theme={null}
  const order = await client.getOrder("0xb816482a...");
  console.log(order);
  ```

  ```python Python theme={null}
  order = client.get_order("0xb816482a...")
  print(order)
  ```

  ```rust Rust theme={null}
  let order = client.order("0xb816482a...").await?;
  println!("{order:?}");
  ```
</CodeGroup>

### Get Open Orders

Retrieve your open orders, optionally filtered by market or asset:

<CodeGroup>
  ```typescript TypeScript theme={null}
  // All open orders
  const orders = await client.getOpenOrders();

  // Filtered by market
  const marketOrders = await client.getOpenOrders({
    market: "0xbd31dc8a...",
  });

  // Filtered by asset
  const assetOrders = await client.getOpenOrders({
    asset_id: "52114319501245...",
  });
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import OpenOrderParams

  # All open orders
  orders = client.get_orders()

  # Filtered by market
  market_orders = client.get_orders(
      OpenOrderParams(
          market="0xbd31dc8a...",
      )
  )
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::request::OrdersRequest;

  // All open orders
  let orders = client.orders(&OrdersRequest::default(), None).await?;

  // Filtered by market
  let request = OrdersRequest::builder()
      .market("0xbd31dc8a...".parse()?)
      .build();
  let market_orders = client.orders(&request, None).await?;

  // Filtered by asset
  let request = OrdersRequest::builder()
      .asset_id("52114319501245...".parse()?)
      .build();
  let asset_orders = client.orders(&request, None).await?;
  ```
</CodeGroup>

### OpenOrder Object

Each order returned contains these fields:

| Field              | Type      | Description                                                  |
| ------------------ | --------- | ------------------------------------------------------------ |
| `id`               | string    | Order ID                                                     |
| `status`           | string    | Current order status                                         |
| `market`           | string    | Market ID (condition ID)                                     |
| `asset_id`         | string    | Token ID                                                     |
| `side`             | string    | `BUY` or `SELL`                                              |
| `original_size`    | string    | Original order size at placement                             |
| `size_matched`     | string    | Amount that has been filled                                  |
| `price`            | string    | Limit price                                                  |
| `outcome`          | string    | Human-readable outcome (e.g., "Yes", "No")                   |
| `order_type`       | string    | Order type (GTC, GTD, FOK, FAK)                              |
| `maker_address`    | string    | Funder address                                               |
| `owner`            | string    | API key of the order owner                                   |
| `expiration`       | string    | Unix timestamp when the order expires (`0` if no expiration) |
| `associate_trades` | string\[] | Trade IDs this order has been partially included in          |
| `created_at`       | string    | Unix timestamp when the order was created                    |

***

## Trade History

When an order is matched, it creates a trade. Trades go through the following statuses:

| Status      | Terminal? | Description                                                          |
| ----------- | --------- | -------------------------------------------------------------------- |
| `MATCHED`   | No        | Matched and sent to the executor service for onchain submission      |
| `MINED`     | No        | Observed as mined on the chain, no finality threshold yet            |
| `CONFIRMED` | Yes       | Achieved strong probabilistic finality — trade successful            |
| `RETRYING`  | No        | Transaction failed (revert or reorg) — being retried by the operator |
| `FAILED`    | Yes       | Trade failed permanently and is not being retried                    |

### Trade Object

Each trade contains these fields:

| Field              | Type   | Description                                                  |
| ------------------ | ------ | ------------------------------------------------------------ |
| `id`               | string | Trade ID                                                     |
| `taker_order_id`   | string | Taker order ID (hash)                                        |
| `market`           | string | Market ID (condition ID)                                     |
| `asset_id`         | string | Token ID                                                     |
| `side`             | string | `BUY` or `SELL`                                              |
| `size`             | string | Trade size                                                   |
| `fee_rate_bps`     | string | Fee rate in basis points                                     |
| `price`            | string | Trade price                                                  |
| `status`           | string | Trade status (see table above)                               |
| `match_time`       | string | Unix timestamp when the trade was matched                    |
| `last_update`      | string | Unix timestamp of last status update                         |
| `outcome`          | string | Human-readable outcome (e.g., "Yes", "No")                   |
| `owner`            | string | API key ID of the trade owner                                |
| `maker_address`    | string | Funder address                                               |
| `trader_side`      | string | Whether you were `TAKER` or `MAKER` in this trade            |
| `transaction_hash` | string | Onchain transaction hash (available after mining)            |
| `maker_orders`     | array  | Array of maker orders matched against this trade (see below) |

### MakerOrder Fields

Each entry in the `maker_orders` array contains:

| Field            | Type   | Description                  |
| ---------------- | ------ | ---------------------------- |
| `order_id`       | string | Maker order ID (hash)        |
| `owner`          | string | Maker's API key ID           |
| `maker_address`  | string | Maker's funder address       |
| `matched_amount` | string | Amount matched in this trade |
| `price`          | string | Maker order price            |
| `fee_rate_bps`   | string | Maker fee rate in bps        |
| `asset_id`       | string | Token ID                     |
| `outcome`        | string | Outcome name                 |
| `side`           | string | `BUY` or `SELL`              |

Retrieve your trades with the SDK:

<CodeGroup>
  ```typescript TypeScript theme={null}
  // All trades
  const trades = await client.getTrades();

  // Filtered by market
  const marketTrades = await client.getTrades({
    market: "0xbd31dc8a...",
  });

  // With pagination
  const paginatedTrades = await client.getTradesPaginated({
    market: "0xbd31dc8a...",
  });
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import TradeParams

  # All trades
  trades = client.get_trades()

  # Filtered by market
  market_trades = client.get_trades(
      TradeParams(
          market="0xbd31dc8a...",
      )
  )
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::request::TradesRequest;

  // All trades
  let trades = client.trades(&TradesRequest::default(), None).await?;

  // Filtered by market
  let request = TradesRequest::builder()
      .market("0xbd31dc8a...".parse()?)
      .build();
  let market_trades = client.trades(&request, None).await?;
  ```
</CodeGroup>

***

## Heartbeat

The heartbeat endpoint maintains session liveness for order safety. If a valid heartbeat is not received within **10 seconds** (with up to a 5-second buffer), **all of your open orders will be cancelled**.

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Send heartbeats in a loop
  let heartbeatId = "";
  setInterval(async () => {
    const resp = await client.postHeartbeat(heartbeatId);
    heartbeatId = resp.heartbeat_id;
  }, 5000);
  ```

  ```python Python theme={null}
  import time

  heartbeat_id = ""
  while True:
      resp = client.post_heartbeat(heartbeat_id)
      heartbeat_id = resp["heartbeat_id"]
      time.sleep(5)
  ```

  ```rust Rust theme={null}
  // With the `heartbeats` feature, auto-send in background:
  Client::start_heartbeats(&mut client)?;

  // Or manually:
  let resp = client.post_heartbeat(None).await?; // None for first call
  let resp = client.post_heartbeat(Some(resp.heartbeat_id)).await?;
  ```
</CodeGroup>

* On each request, include the most recent `heartbeat_id` you received. For your first request, use an empty string.
* If you send an invalid or expired `heartbeat_id`, the server responds with a `400 Bad Request` and provides the correct `heartbeat_id` in the response. Update your client and retry.

***

## Order Scoring

Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:

<CodeGroup>
  ```typescript TypeScript theme={null}
  // Single order
  const scoring = await client.isOrderScoring({ orderId: "0x..." });
  console.log(scoring); // { scoring: true }

  // Multiple orders
  const batchScoring = await client.areOrdersScoring({
    orderIds: ["0x...", "0x..."],
  });
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import OrderScoringParams, OrdersScoringParams

  # Single order
  scoring = client.is_order_scoring(
      OrderScoringParams(orderId="0x...")
  )

  # Multiple orders
  batch_scoring = client.are_orders_scoring(
      OrdersScoringParams(orderIds=["0x...", "0x..."])
  )
  ```

  ```rust Rust theme={null}
  // Single order
  let scoring = client.is_order_scoring("0x...").await?;
  println!("Scoring: {}", scoring.scoring);

  // Multiple orders
  let batch = client.are_orders_scoring(&["0x...", "0x..."]).await?;
  ```
</CodeGroup>

***

## Onchain Order Info

When a trade is settled onchain, the Exchange contract emits an `OrderFilled` event with the following fields:

| Field               | Description                                                                                   |
| ------------------- | --------------------------------------------------------------------------------------------- |
| `orderHash`         | Unique hash for the filled order                                                              |
| `maker`             | The user who generated the order and source of funds                                          |
| `taker`             | The user filling the order, or the Exchange contract if multiple limit orders are filled      |
| `makerAssetId`      | ID of the asset given out. If `0`, the order is a **BUY** (giving pUSD for outcome tokens)    |
| `takerAssetId`      | ID of the asset received. If `0`, the order is a **SELL** (receiving pUSD for outcome tokens) |
| `makerAmountFilled` | Amount of the asset given out                                                                 |
| `takerAmountFilled` | Amount of the asset received                                                                  |
| `fee`               | Fees paid by the order maker                                                                  |

***

## Error Messages

When placing an order, the response may include an `errorMsg` if the order could not be placed. If `success` is `false`, there was a server-side error:

| Error                              | Description                                            |
| ---------------------------------- | ------------------------------------------------------ |
| `INVALID_ORDER_MIN_TICK_SIZE`      | Price doesn't conform to the market's tick size        |
| `INVALID_ORDER_MIN_SIZE`           | Order size is below the minimum threshold              |
| `INVALID_ORDER_DUPLICATED`         | Identical order has already been placed                |
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Funder doesn't have sufficient balance or allowance    |
| `INVALID_ORDER_EXPIRATION`         | Expiration timestamp is in the past                    |
| `INVALID_ORDER_ERROR`              | System error while inserting order                     |
| `INVALID_POST_ONLY_ORDER_TYPE`     | Post-only flag used with a market order type (FOK/FAK) |
| `INVALID_POST_ONLY_ORDER`          | Post-only order would cross the book                   |
| `EXECUTION_ERROR`                  | System error while executing trade                     |
| `ORDER_DELAYED`                    | Order placement delayed due to market conditions       |
| `DELAYING_ORDER_ERROR`             | System error while delaying order                      |
| `FOK_ORDER_NOT_FILLED_ERROR`       | FOK order couldn't be fully filled                     |
| `MARKET_NOT_READY`                 | Market is not yet accepting orders                     |

### Insert Statuses

When an order is successfully placed, the response includes a `status` field:

| Status      | Description                                                          |
| ----------- | -------------------------------------------------------------------- |
| `matched`   | Order placed and matched with a resting order                        |
| `live`      | Order placed and resting on the book                                 |
| `delayed`   | Order is marketable but subject to a matching delay                  |
| `unmatched` | Order is marketable but failed to delay — placement still successful |

***

## Security

Polymarket's Exchange contract has been audited by Chainsecurity ([View Audit](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)).

The operator's privileges are limited to order matching and ensuring correct ordering. Operators cannot set prices or execute unauthorized trades.

***

## Next Steps

<CardGroup>
  <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>


# Overview
Source: https://docs.polymarket.com/trading/overview

Trading on the Polymarket CLOB

Polymarket's CLOB (Central Limit Order Book) is a hybrid-decentralized trading system — offchain order matching with onchain settlement via the [Exchange contract](https://github.com/Polymarket/ctf-exchange/tree/main/src) ([audited by Chainsecurity](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)). All trading is non-custodial. Orders are [EIP-712](https://eips.ethereum.org/EIPS/eip-712) signed messages, and matched trades settle atomically on Polygon. The operator cannot set prices or execute unauthorized trades.

We recommend using the open-source SDK clients, which handle order signing, authentication, and submission:

<CardGroup>
  <Card title="TypeScript Client" icon="github" href="https://github.com/Polymarket/clob-client-v2">
    <p>
      npm install @polymarket/clob-client-v2 viem
    </p>
  </Card>

  <Card title="Python Client" icon="github" href="https://github.com/Polymarket/py-clob-client-v2">
    <p>pip install py-clob-client-v2</p>
  </Card>

  <Card title="Rust Client" icon="github" href="https://github.com/Polymarket/rs-clob-client-v2">
    <p>
      cargo add polymarket\_client\_sdk\_v2 --features clob
    </p>
  </Card>
</CardGroup>

<Info>
  You can also use the REST API directly, but you'll need to manage [EIP-712
  order
  signing](https://github.com/Polymarket/clob-client-v2/blob/main/src/signing/eip712.ts)
  and [HMAC authentication
  headers](https://github.com/Polymarket/clob-client-v2/blob/main/src/signing/hmac.ts)
  yourself. See [REST API Headers](#rest-api-headers) below.
</Info>

***

## Authentication

The CLOB uses two levels of authentication:

| Level  | Method                          | Purpose                                   |
| ------ | ------------------------------- | ----------------------------------------- |
| **L1** | EIP-712 signature (private key) | Create or derive API credentials          |
| **L2** | HMAC-SHA256 (API credentials)   | Place orders, cancel orders, query trades |

You use your private key once to derive **L2 credentials** (API key, secret, passphrase), which authenticate all subsequent trading requests.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { ClobClient } from "@polymarket/clob-client-v2";
  import { createWalletClient, http } from "viem";
  import { privateKeyToAccount } from "viem/accounts";

  const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
  const signer = createWalletClient({ account, transport: http() });

  // Derive L2 API credentials
  const tempClient = new ClobClient({
    host: "https://clob.polymarket.com",
    chain: 137,
    signer,
  });
  const apiCreds = await tempClient.createOrDeriveApiKey();
  ```

  ```python Python theme={null}
  from py_clob_client_v2 import ClobClient
  import os

  private_key = os.getenv("PRIVATE_KEY")

  # Derive L2 API credentials
  temp_client = ClobClient("https://clob.polymarket.com", key=private_key, chain_id=137)
  api_creds = temp_client.create_or_derive_api_key()
  ```

  ```rust Rust theme={null}
  use std::str::FromStr;
  use polymarket_client_sdk_v2::POLYGON;
  use polymarket_client_sdk_v2::auth::{LocalSigner, Signer};
  use polymarket_client_sdk_v2::clob::{Client, Config};

  let private_key = std::env::var("POLYMARKET_PRIVATE_KEY")?;
  let signer = LocalSigner::from_str(&private_key)?
      .with_chain_id(Some(POLYGON));

  // Derive L2 API credentials and initialize client in one step
  let client = Client::new("https://clob.polymarket.com", Config::default())?
      .authentication_builder(&signer)
      .authenticate()
      .await?;
  ```
</CodeGroup>

***

## Signature Types

When initializing the trading client, you must specify your wallet's **signature type** and **funder address**:

| Wallet Type      | ID  | When to Use                                                                                                    | Funder Address              |
| ---------------- | --- | -------------------------------------------------------------------------------------------------------------- | --------------------------- |
| **EOA**          | `0` | Standalone wallet — you pay your own gas (POL for gas)                                                         | Your EOA wallet address     |
| **POLY\_PROXY**  | `1` | Existing Polymarket proxy wallet flow                                                                          | Your proxy wallet address   |
| **GNOSIS\_SAFE** | `2` | Existing Gnosis Safe wallet flow                                                                               | Your Safe wallet address    |
| **POLY\_1271**   | `3` | Deposit wallet flow for new API users. Orders are signed by the owner/session signer and validated by ERC-1271 | Your deposit wallet address |

<Note>
  New API users should use deposit wallets with signature type `3`. Existing
  Proxy and Safe users are unaffected and can keep using signature types `1` and
  `2`. Type `0` is for standalone EOA wallets only.
</Note>

### Initialize the Trading Client

<CodeGroup>
  ```typescript TypeScript theme={null}
  const depositWalletAddress = process.env.DEPOSIT_WALLET_ADDRESS!;

  const client = new ClobClient({
    host: "https://clob.polymarket.com",
    chain: 137,
    signer,
    creds: apiCreds,
    signatureType: 3, // POLY_1271
    funderAddress: depositWalletAddress,
  });
  ```

  ```python Python theme={null}
  deposit_wallet_address = os.getenv("DEPOSIT_WALLET_ADDRESS")

  client = ClobClient(
      "https://clob.polymarket.com",
      key=private_key,
      chain_id=137,
      creds=api_creds,
      signature_type=3,  # POLY_1271
      funder=deposit_wallet_address
  )
  ```

  ```rust Rust theme={null}
  use polymarket_client_sdk_v2::clob::types::SignatureType;

  let deposit_wallet = std::env::var("DEPOSIT_WALLET_ADDRESS")?.parse()?;

  let client = Client::new("https://clob.polymarket.com", Config::default())?
      .authentication_builder(&signer)
      .funder(deposit_wallet)
      .signature_type(SignatureType::Poly1271)
      .authenticate()
      .await?;
  ```
</CodeGroup>

***

## REST API Headers

If you're using the REST API directly (without the SDK), you need to attach authentication headers to each request.

**L1 Headers** — for creating or deriving API credentials:

| Header           | Description         |
| ---------------- | ------------------- |
| `POLY_ADDRESS`   | Your wallet address |
| `POLY_SIGNATURE` | EIP-712 signature   |
| `POLY_TIMESTAMP` | Unix timestamp      |
| `POLY_NONCE`     | Request nonce       |

**L2 Headers** — for all trading operations (orders, cancellations, queries):

| Header            | Description                          |
| ----------------- | ------------------------------------ |
| `POLY_ADDRESS`    | Your wallet address                  |
| `POLY_SIGNATURE`  | HMAC-SHA256 signature of the request |
| `POLY_TIMESTAMP`  | Unix timestamp                       |
| `POLY_API_KEY`    | Your API key                         |
| `POLY_PASSPHRASE` | Your API passphrase                  |

<Note>
  Even with L2 authentication, methods that create orders still require the
  user's private key for EIP-712 order payload signing. L2 credentials
  authenticate the request, but the order itself must be signed by the key.
</Note>

***

## Client Methods

<CardGroup>
  <Card title="Public Methods" icon="globe" href="/trading/clients/public">
    Market data, orderbooks, prices, and spreads — no auth required.
  </Card>

  <Card title="L1 Methods" icon="key" href="/trading/clients/l1">
    Sign orders and derive API credentials with your private key.
  </Card>

  <Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
    Place orders, cancel orders, query trades, and manage notifications.
  </Card>

  <Card title="Builder Methods" icon="hammer" href="/trading/clients/builder">
    Track orders and trades attributed to your builder code.
  </Card>
</CardGroup>

***

## What Is in This Section

<CardGroup>
  <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>


# Quickstart
Source: https://docs.polymarket.com/trading/quickstart

Place your first order on Polymarket

This guide walks you through placing an order on Polymarket end-to-end.

<Steps>
  <Step title="Install the SDK">
    <CodeGroup>
      ```bash TypeScript theme={null}
      npm install @polymarket/clob-client-v2 viem
      ```

      ```bash Python theme={null}
      pip install py-clob-client-v2
      ```

      ```bash Rust theme={null}
      cargo add polymarket_client_sdk_v2 --features clob
      ```
    </CodeGroup>
  </Step>

  <Step title="Set Up Your Client">
    Derive your API credentials and initialize the trading client. This example uses
    a deposit wallet with signature type `3` (`POLY_1271`), which is the wallet path
    for new API users:

    <CodeGroup>
      ```typescript TypeScript theme={null}
      import { ClobClient, SignatureTypeV2 } from "@polymarket/clob-client-v2";
      import { createWalletClient, http } from "viem";
      import { privateKeyToAccount } from "viem/accounts";

      const HOST = "https://clob.polymarket.com";
      const CHAIN_ID = 137; // Polygon mainnet
      const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
      const signer = createWalletClient({ account, transport: http() });
      const depositWalletAddress = process.env.DEPOSIT_WALLET_ADDRESS!;

      // Derive API credentials
      const tempClient = new ClobClient({ host: HOST, chain: CHAIN_ID, signer });
      const apiCreds = await tempClient.createOrDeriveApiKey();

      // Initialize trading client
      const client = new ClobClient({
        host: HOST,
        chain: CHAIN_ID,
        signer,
        creds: apiCreds,
        signatureType: SignatureTypeV2.POLY_1271,
        funderAddress: depositWalletAddress,
      });
      ```

      ```python Python theme={null}
      from py_clob_client_v2 import ClobClient, SignatureTypeV2
      import os

      host = "https://clob.polymarket.com"
      chain = 137  # Polygon mainnet
      private_key = os.getenv("PRIVATE_KEY")
      deposit_wallet_address = os.getenv("DEPOSIT_WALLET_ADDRESS")

      # Derive API credentials
      temp_client = ClobClient(host, key=private_key, chain_id=chain)
      api_creds = temp_client.create_or_derive_api_key()

      # Initialize trading client
      client = ClobClient(
          host,
          key=private_key,
          chain_id=chain,
          creds=api_creds,
          signature_type=SignatureTypeV2.POLY_1271,
          funder=deposit_wallet_address
      )
      ```

      ```rust Rust theme={null}
      use std::str::FromStr;
      use polymarket_client_sdk_v2::POLYGON;
      use polymarket_client_sdk_v2::auth::{LocalSigner, Signer};
      use polymarket_client_sdk_v2::clob::types::SignatureType;
      use polymarket_client_sdk_v2::clob::{Client, Config};

      let private_key = std::env::var("POLYMARKET_PRIVATE_KEY")?;
      let signer = LocalSigner::from_str(&private_key)?
          .with_chain_id(Some(POLYGON));
      let deposit_wallet = std::env::var("DEPOSIT_WALLET_ADDRESS")?.parse()?;

      // Derive API credentials and initialize client
      let client = Client::new("https://clob.polymarket.com", Config::default())?
          .authentication_builder(&signer)
          .funder(deposit_wallet)
          .signature_type(SignatureType::Poly1271)
          .authenticate()
          .await?;
      ```
    </CodeGroup>

    <Note>
      Existing EOA, Safe, and Proxy integrations can keep using their current
      signature type and funder address. See [Signature
      Types](/trading/overview#signature-types) for all wallet types.
    </Note>

    <Warning>
      Before trading from a deposit wallet, the deposit wallet needs **pUSD** and
      the required trading approvals. See the [Deposit Wallet
      Guide](/trading/deposit-wallets) for wallet creation, funding, approvals, and
      balance sync.
    </Warning>
  </Step>

  <Step title="Place an Order">
    Get a token ID from the [Markets API](/market-data/fetching-markets), then create and submit your order:

    <CodeGroup>
      ```typescript TypeScript theme={null}
      import { Side, OrderType } from "@polymarket/clob-client-v2";

      const response = await client.createAndPostOrder(
        {
          tokenID: "YOUR_TOKEN_ID",
          price: 0.5,
          size: 10,
          side: Side.BUY,
        },
        {
          tickSize: "0.01",
          negRisk: false, // Set to true for multi-outcome markets
        },
        OrderType.GTC,
      );

      console.log("Order ID:", response.orderID);
      console.log("Status:", response.status);
      ```

      ```python Python theme={null}
      from py_clob_client_v2 import OrderArgs, OrderType, PartialCreateOrderOptions
      from py_clob_client_v2.order_builder.constants import BUY

      response = client.create_and_post_order(
          OrderArgs(
              token_id="YOUR_TOKEN_ID",
              price=0.50,
              size=10,
              side=BUY,
          ),
          options=PartialCreateOrderOptions(
              tick_size="0.01",
              neg_risk=False,  # Set to True for multi-outcome markets
          ),
          order_type=OrderType.GTC
      )

      print("Order ID:", response["orderID"])
      print("Status:", response["status"])
      ```

      ```rust Rust theme={null}
      use polymarket_client_sdk_v2::clob::types::Side;
      use polymarket_client_sdk_v2::types::dec;

      let token_id = "YOUR_TOKEN_ID".parse()?;

      // Tick size and neg risk are auto-fetched by the order builder
      let order = client
          .limit_order()
          .token_id(token_id)
          .price(dec!(0.50))
          .size(dec!(10))
          .side(Side::Buy)
          .build()
          .await?;
      let signed_order = client.sign(&signer, order).await?;
      let response = client.post_order(signed_order).await?;

      println!("Order ID: {}", response.order_id);
      println!("Status: {:?}", response.status);
      ```
    </CodeGroup>

    <Tip>
      Look up a market's `tickSize` and `negRisk` values using the SDK's
      `getTickSize()` and `getNegRisk()` methods, or from the market object returned
      by the API.
    </Tip>
  </Step>

  <Step title="Check Your Orders">
    <CodeGroup>
      ```typescript TypeScript theme={null}
      // View all open orders
      const openOrders = await client.getOpenOrders();
      console.log(`You have ${openOrders.length} open orders`);

      // View your trade history
      const trades = await client.getTrades();
      console.log(`You've made ${trades.length} trades`);

      // Cancel an order
      await client.cancelOrder(response.orderID);
      ```

      ```python Python theme={null}
      # View all open orders
      open_orders = client.get_orders()
      print(f"You have {len(open_orders)} open orders")

      # View your trade history
      trades = client.get_trades()
      print(f"You've made {len(trades)} trades")

      # Cancel an order
      client.cancel(order_id=response["orderID"])
      ```

      ```rust Rust theme={null}
      use polymarket_client_sdk_v2::clob::types::request::{OrdersRequest, TradesRequest};

      // View all open orders
      let open_orders = client.orders(&OrdersRequest::default(), None).await?;
      println!("You have {} open orders", open_orders.data.len());

      // View your trade history
      let trades = client.trades(&TradesRequest::default(), None).await?;
      println!("You've made {} trades", trades.data.len());

      // Cancel an order
      client.cancel_order(&response.order_id).await?;
      ```
    </CodeGroup>
  </Step>
</Steps>

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="L2 AUTH NOT AVAILABLE - Invalid Signature">
    Wrong private key, signature type, or funder address for the derived API credentials.

    * Check that `signatureType` matches your account type (`0`, `1`, `2`, or `3`)
    * Ensure `funder` is correct for your wallet type
    * Re-derive credentials with `createOrDeriveApiKey()` if unsure
  </Accordion>

  <Accordion title="Order rejected - insufficient balance">
    Your funder address doesn't have enough tokens:

    * **BUY orders**: need pUSD in your funder address
    * **SELL orders**: need outcome tokens in your funder address
    * Ensure you have more pUSD than what's committed in open orders
  </Accordion>

  <Accordion title="Order rejected - insufficient allowance">
    You need to approve the Exchange contract to spend your tokens. Deposit wallet
    approvals must be executed from the deposit wallet through a relayer `WALLET`
    batch. Existing Safe and Proxy users should use their current relayer approval
    flow.
  </Accordion>

  <Accordion title="What is my funder address">
    Your funder address is the wallet where your funds are held:

    * **EOA (type 0)**: Your wallet address directly
    * **Deposit wallet (type 3)**: The deposit wallet deployed for the owner or session signer
    * **Proxy/Safe wallet (type 1 or 2)**: Existing Polymarket.com wallet address

    New API users should create a deposit wallet. Existing Proxy and Safe users
    can continue using their current wallet address.
  </Accordion>

  <Accordion title="Blocked by Cloudflare or Geoblock">
    You're trying to place a trade from a restricted region. See [Geographic Restrictions](/api-reference/geoblock) for details.
  </Accordion>
</AccordionGroup>

***

## Next Steps

<CardGroup>
  <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>


# Create deposit addresses
Source: https://docs.polymarket.com/api-reference/bridge/create-deposit-addresses

/api-spec/bridge-openapi.yaml post /deposit



# Create withdrawal addresses
Source: https://docs.polymarket.com/api-reference/bridge/create-withdrawal-addresses

/api-spec/bridge-openapi.yaml post /withdraw



# Get a quote
Source: https://docs.polymarket.com/api-reference/bridge/get-a-quote

/api-spec/bridge-openapi.yaml post /quote



# Get supported assets
Source: https://docs.polymarket.com/api-reference/bridge/get-supported-assets

/api-spec/bridge-openapi.yaml get /supported-assets



# Get transaction status
Source: https://docs.polymarket.com/api-reference/bridge/get-transaction-status

/api-spec/bridge-openapi.yaml get /status/{address}



# Get aggregated builder leaderboard
Source: https://docs.polymarket.com/api-reference/builders/get-aggregated-builder-leaderboard

/api-spec/data-openapi.yaml get /v1/builders/leaderboard



# Get daily builder volume time-series
Source: https://docs.polymarket.com/api-reference/builders/get-daily-builder-volume-time-series

/api-spec/data-openapi.yaml get /v1/builders/volume



# Get comments by comment id
Source: https://docs.polymarket.com/api-reference/comments/get-comments-by-comment-id

/api-spec/gamma-openapi.yaml get /comments/{id}



# Get comments by user address
Source: https://docs.polymarket.com/api-reference/comments/get-comments-by-user-address

/api-spec/gamma-openapi.yaml get /comments/user_address/{user_address}



# List comments
Source: https://docs.polymarket.com/api-reference/comments/list-comments

/api-spec/gamma-openapi.yaml get /comments



# Get closed positions for a user
Source: https://docs.polymarket.com/api-reference/core/get-closed-positions-for-a-user

/api-spec/data-openapi.yaml get /closed-positions



# Get current positions for a user
Source: https://docs.polymarket.com/api-reference/core/get-current-positions-for-a-user

/api-spec/data-openapi.yaml get /positions



# Get positions for a market
Source: https://docs.polymarket.com/api-reference/core/get-positions-for-a-market

/api-spec/data-openapi.yaml get /v1/market-positions



# Get total value of a user's positions
Source: https://docs.polymarket.com/api-reference/core/get-total-value-of-a-users-positions

/api-spec/data-openapi.yaml get /value



# Get trader leaderboard rankings
Source: https://docs.polymarket.com/api-reference/core/get-trader-leaderboard-rankings

/api-spec/data-openapi.yaml get /v1/leaderboard



# Get trades for a user or markets
Source: https://docs.polymarket.com/api-reference/core/get-trades-for-a-user-or-markets

/api-spec/data-openapi.yaml get /trades



# Get user activity
Source: https://docs.polymarket.com/api-reference/core/get-user-activity

/api-spec/data-openapi.yaml get /activity



# Get sampling markets
Source: https://docs.polymarket.com/api-reference/markets/get-sampling-markets

/api-spec/clob-openapi.yaml get /sampling-markets



# Get sampling simplified markets
Source: https://docs.polymarket.com/api-reference/markets/get-sampling-simplified-markets

/api-spec/clob-openapi.yaml get /sampling-simplified-markets



# Get simplified markets
Source: https://docs.polymarket.com/api-reference/markets/get-simplified-markets

/api-spec/clob-openapi.yaml get /simplified-markets



# Download an accounting snapshot (ZIP of CSVs)
Source: https://docs.polymarket.com/api-reference/misc/download-an-accounting-snapshot-zip-of-csvs

/api-spec/data-openapi.yaml get /v1/accounting/snapshot



# Get total markets a user has traded
Source: https://docs.polymarket.com/api-reference/misc/get-total-markets-a-user-has-traded

/api-spec/data-openapi.yaml get /traded



# Get public profile by wallet address
Source: https://docs.polymarket.com/api-reference/profiles/get-public-profile-by-wallet-address

/api-spec/gamma-openapi.yaml get /public-profile



# Get current rebated fees for a maker
Source: https://docs.polymarket.com/api-reference/rebates/get-current-rebated-fees-for-a-maker

/api-spec/clob-openapi.yaml get /rebates/current
Returns the current rebated fees for a maker address on a given date.

Each entry includes the condition ID, asset address, and the USDC amount rebated.

This endpoint does not require authentication.




# Get all relayer API keys
Source: https://docs.polymarket.com/api-reference/relayer-api-keys/get-all-relayer-api-keys

/api-spec/relayer-openapi.yaml get /relayer/api/keys
Returns all relayer API keys for the authenticated address. Auth allowed: Gamma auth or Relayer API key auth (`RELAYER_API_KEY` + `RELAYER_API_KEY_ADDRESS`).




# Check if a safe is deployed
Source: https://docs.polymarket.com/api-reference/relayer/check-if-a-safe-is-deployed

/api-spec/relayer-openapi.yaml get /deployed
Returns a payload that determines if a safe is deployed. Takes in the user's Polymarket proxy address.




# Get a transaction by ID
Source: https://docs.polymarket.com/api-reference/relayer/get-a-transaction-by-id

/api-spec/relayer-openapi.yaml get /transaction
Gets a transaction submitted to the Relayer. Takes in a required transaction ID as a query parameter.

Poll this endpoint with the `transactionID` returned from `POST /submit` to retrieve the onchain `transactionHash` once the transaction has been broadcast.




# Get current nonce for a user
Source: https://docs.polymarket.com/api-reference/relayer/get-current-nonce-for-a-user

/api-spec/relayer-openapi.yaml get /nonce
Gets the current Proxy or Safe nonce for a user. Takes in the user's signer address and the type of nonce to retrieve.




# Get recent transactions for a user
Source: https://docs.polymarket.com/api-reference/relayer/get-recent-transactions-for-a-user

/api-spec/relayer-openapi.yaml get /transactions
Gets the most recent transactions submitted to the Relayer, owned by a specific user. Authenticated using Builder API Keys or Relayer API Keys.

**Builder API Key auth headers:**
- `POLY_BUILDER_API_KEY`
- `POLY_BUILDER_TIMESTAMP`
- `POLY_BUILDER_PASSPHRASE`
- `POLY_BUILDER_SIGNATURE`

**Relayer API Key auth headers:**
- `RELAYER_API_KEY`
- `RELAYER_API_KEY_ADDRESS`




# Get relayer address and nonce
Source: https://docs.polymarket.com/api-reference/relayer/get-relayer-address-and-nonce

/api-spec/relayer-openapi.yaml get /relay-payload
Fetches the relayer address and nonce for a specific user. Takes in the user's signer address and the type of nonce to retrieve.




# Submit a transaction
Source: https://docs.polymarket.com/api-reference/relayer/submit-a-transaction

/api-spec/relayer-openapi.yaml post /submit
Submit a transaction request to the Relayer. Authenticated using Builder API Keys or Relayer API Keys.

Returns immediately with the `transactionID` and a `state` of `STATE_NEW`. The onchain transaction hash is **not** included in this response — poll `GET /transaction` with the returned `transactionID` to retrieve the `transactionHash` once the transaction has been broadcast.

**Builder API Key auth headers:**
- `POLY_BUILDER_API_KEY`
- `POLY_BUILDER_TIMESTAMP`
- `POLY_BUILDER_PASSPHRASE`
- `POLY_BUILDER_SIGNATURE`

**Relayer API Key auth headers:**
- `RELAYER_API_KEY`
- `RELAYER_API_KEY_ADDRESS`




# Get current active rewards configurations
Source: https://docs.polymarket.com/api-reference/rewards/get-current-active-rewards-configurations

/api-spec/clob-openapi.yaml get /rewards/markets/current
Returns all current active rewards configurations grouped by market.

When `sponsored=true`, returns sponsored reward configurations instead.

Results are paginated (500 items per page). Use next_cursor to fetch subsequent pages.
A next_cursor value of "LTE=" indicates the last page.




# Get earnings for user by date
Source: https://docs.polymarket.com/api-reference/rewards/get-earnings-for-user-by-date

/api-spec/clob-openapi.yaml get /rewards/user
Returns an array of user earnings per market for a provided day.

Requires CLOB L2 Auth headers.

Results are paginated (100 items per page). Use next_cursor to fetch subsequent pages.
A next_cursor value of "LTE=" indicates the last page.




# Get multiple markets with rewards
Source: https://docs.polymarket.com/api-reference/rewards/get-multiple-markets-with-rewards

/api-spec/clob-openapi.yaml get /rewards/markets/multi
Returns a list of active markets with their reward configurations.
Supports text search, tag filtering, numeric filters, and sorting.

Results are paginated (100 items per page by default). Use next_cursor to fetch subsequent pages.
A next_cursor value of "LTE=" indicates the last page.




# Get raw rewards for a specific market
Source: https://docs.polymarket.com/api-reference/rewards/get-raw-rewards-for-a-specific-market

/api-spec/clob-openapi.yaml get /rewards/markets/{condition_id}
Returns an array of present and future rewards configured on a market.

When `sponsored=true`, sponsored daily rates are folded into each config's
`rate_per_day` .

Results are paginated (100 items per page). Use next_cursor to fetch subsequent pages.
A next_cursor value of "LTE=" indicates the last page.




# Get reward percentages for user
Source: https://docs.polymarket.com/api-reference/rewards/get-reward-percentages-for-user

/api-spec/clob-openapi.yaml get /rewards/user/percentages
Returns the real-time percentages of rewards that a user is earning per market.

The response is a map of condition_id to the percentage of total rewards
the user is currently earning in that market.

Requires CLOB L2 Auth headers.




# Get total earnings for user by date
Source: https://docs.polymarket.com/api-reference/rewards/get-total-earnings-for-user-by-date

/api-spec/clob-openapi.yaml get /rewards/user/total
Returns the summed total rewards earnings for a user on a provided day,
grouped by asset address.

Requires CLOB L2 Auth headers.




# Get user earnings and markets configuration
Source: https://docs.polymarket.com/api-reference/rewards/get-user-earnings-and-markets-configuration

/api-spec/clob-openapi.yaml get /rewards/user/markets
Returns an array of current rewards including user earnings and live percentages
per market for a provided day.

Results are paginated (100 items per page by default, max 500). Use next_cursor to fetch subsequent pages.
A next_cursor value of "LTE=" indicates the last page.

Requires CLOB L2 Auth headers.

Optional features:
- Search by question/description using the `q` parameter
- Filter by tag slugs using `tag_slug` parameter (multiple values are OR'ed)
- Filter by favorite markets using `favorite_markets=true`
- Sort by various fields using `order_by` and `position` parameters




# Search markets, events, and profiles
Source: https://docs.polymarket.com/api-reference/search/search-markets-events-and-profiles

/api-spec/gamma-openapi.yaml get /public-search



# Get series by id
Source: https://docs.polymarket.com/api-reference/series/get-series-by-id

/api-spec/gamma-openapi.yaml get /series/{id}



# List series
Source: https://docs.polymarket.com/api-reference/series/list-series

/api-spec/gamma-openapi.yaml get /series



# Get sports metadata information
Source: https://docs.polymarket.com/api-reference/sports/get-sports-metadata-information

/api-spec/gamma-openapi.yaml get /sports



# Get valid sports market types
Source: https://docs.polymarket.com/api-reference/sports/get-valid-sports-market-types

/api-spec/gamma-openapi.yaml get /sports/market-types



# List teams
Source: https://docs.polymarket.com/api-reference/sports/list-teams

/api-spec/gamma-openapi.yaml get /teams



# Get related tags (relationships) by tag id
Source: https://docs.polymarket.com/api-reference/tags/get-related-tags-relationships-by-tag-id

/api-spec/gamma-openapi.yaml get /tags/{id}/related-tags



# Get related tags (relationships) by tag slug
Source: https://docs.polymarket.com/api-reference/tags/get-related-tags-relationships-by-tag-slug

/api-spec/gamma-openapi.yaml get /tags/slug/{slug}/related-tags



# Get tag by id
Source: https://docs.polymarket.com/api-reference/tags/get-tag-by-id

/api-spec/gamma-openapi.yaml get /tags/{id}



# Get tag by slug
Source: https://docs.polymarket.com/api-reference/tags/get-tag-by-slug

/api-spec/gamma-openapi.yaml get /tags/slug/{slug}



# Get tags related to a tag id
Source: https://docs.polymarket.com/api-reference/tags/get-tags-related-to-a-tag-id

/api-spec/gamma-openapi.yaml get /tags/{id}/related-tags/tags



# Get tags related to a tag slug
Source: https://docs.polymarket.com/api-reference/tags/get-tags-related-to-a-tag-slug

/api-spec/gamma-openapi.yaml get /tags/slug/{slug}/related-tags/tags



# List tags
Source: https://docs.polymarket.com/api-reference/tags/list-tags

/api-spec/gamma-openapi.yaml get /tags



# Cancel all orders
Source: https://docs.polymarket.com/api-reference/trade/cancel-all-orders

/api-spec/clob-openapi.yaml delete /cancel-all
Cancels all open orders for the authenticated user. Works even in cancel-only mode.




# Cancel multiple orders
Source: https://docs.polymarket.com/api-reference/trade/cancel-multiple-orders

/api-spec/clob-openapi.yaml delete /orders
Cancels multiple orders by their IDs. Maximum 3000 orders per request.
Duplicate order IDs in the request are automatically ignored.
Works even in cancel-only mode.




# Cancel orders for a market
Source: https://docs.polymarket.com/api-reference/trade/cancel-orders-for-a-market

/api-spec/clob-openapi.yaml delete /cancel-market-orders
Cancels all open orders for the authenticated user in a specific market (condition) and asset.
Works even in cancel-only mode.




# Get builder trades
Source: https://docs.polymarket.com/api-reference/trade/get-builder-trades

/api-spec/clob-openapi.yaml get /builder/trades
Retrieves trades attributed to a builder code.




# Get order scoring status
Source: https://docs.polymarket.com/api-reference/trade/get-order-scoring-status

/api-spec/clob-openapi.yaml get /order-scoring
Checks if a specific order is currently scoring for rewards.

An order is considered "scoring" if it meets all the criteria for earning maker rewards:
- The order is live on a rewards-eligible market
- The order meets the minimum size requirements
- The order is within the valid spread range
- The order has been live for the required duration




# Get trades
Source: https://docs.polymarket.com/api-reference/trade/get-trades

/api-spec/clob-openapi.yaml get /trades
Retrieves trades for the authenticated user. Returns paginated results.
Requires readonly or level 2 API key authentication.




# Send heartbeat
Source: https://docs.polymarket.com/api-reference/trade/send-heartbeat

/api-spec/clob-openapi.yaml post /heartbeats
Sends a heartbeat signal to maintain active session status.
If heartbeats are not sent regularly, all open orders for the user will be automatically canceled.
This is useful for automated trading systems that need to ensure orders are canceled
if the system becomes unresponsive.




# Market Channel
Source: https://docs.polymarket.com/api-reference/wss/market

Public WebSocket for real-time orderbook, price, and market lifecycle updates.



# Sports Channel
Source: https://docs.polymarket.com/api-reference/wss/sports

Public WebSocket for real-time sports match results.



# User Channel
Source: https://docs.polymarket.com/api-reference/wss/user

Authenticated WebSocket for real-time order and trade updates.



# Get supported assets
Source: https://docs.polymarket.com/api-reference/bridge/get-supported-assets

/api-spec/bridge-openapi.yaml get /supported-assets



# Get aggregated builder leaderboard
Source: https://docs.polymarket.com/api-reference/builders/get-aggregated-builder-leaderboard

/api-spec/data-openapi.yaml get /v1/builders/leaderboard



# Get daily builder volume time-series
Source: https://docs.polymarket.com/api-reference/builders/get-daily-builder-volume-time-series

/api-spec/data-openapi.yaml get /v1/builders/volume



# Get comments by comment id
Source: https://docs.polymarket.com/api-reference/comments/get-comments-by-comment-id

/api-spec/gamma-openapi.yaml get /comments/{id}



# Get comments by user address
Source: https://docs.polymarket.com/api-reference/comments/get-comments-by-user-address

/api-spec/gamma-openapi.yaml get /comments/user_address/{user_address}



# List comments
Source: https://docs.polymarket.com/api-reference/comments/list-comments

/api-spec/gamma-openapi.yaml get /comments



# Get closed positions for a user
Source: https://docs.polymarket.com/api-reference/core/get-closed-positions-for-a-user

/api-spec/data-openapi.yaml get /closed-positions



# Get current positions for a user
Source: https://docs.polymarket.com/api-reference/core/get-current-positions-for-a-user

/api-spec/data-openapi.yaml get /positions



# Get positions for a market
Source: https://docs.polymarket.com/api-reference/core/get-positions-for-a-market

/api-spec/data-openapi.yaml get /v1/market-positions



# Get top holders for markets
Source: https://docs.polymarket.com/api-reference/core/get-top-holders-for-markets

/api-spec/data-openapi.yaml get /holders



# Get total value of a user's positions
Source: https://docs.polymarket.com/api-reference/core/get-total-value-of-a-users-positions

/api-spec/data-openapi.yaml get /value



# Get trader leaderboard rankings
Source: https://docs.polymarket.com/api-reference/core/get-trader-leaderboard-rankings

/api-spec/data-openapi.yaml get /v1/leaderboard



# Get trades for a user or markets
Source: https://docs.polymarket.com/api-reference/core/get-trades-for-a-user-or-markets

/api-spec/data-openapi.yaml get /trades



# Get user activity
Source: https://docs.polymarket.com/api-reference/core/get-user-activity

/api-spec/data-openapi.yaml get /activity



# Get midpoint price
Source: https://docs.polymarket.com/api-reference/data/get-midpoint-price

/api-spec/clob-openapi.yaml get /midpoint
Retrieves the midpoint price for a specific token ID.
The midpoint is calculated as the average of the best bid and best ask prices.




# Get server time
Source: https://docs.polymarket.com/api-reference/data/get-server-time

/api-spec/clob-openapi.yaml get /time
Returns the current Unix timestamp of the server.
This can be used to synchronize client time with server time.




# Get event by id
Source: https://docs.polymarket.com/api-reference/events/get-event-by-id

/api-spec/gamma-openapi.yaml get /events/{id}



# Get event by slug
Source: https://docs.polymarket.com/api-reference/events/get-event-by-slug

/api-spec/gamma-openapi.yaml get /events/slug/{slug}



# Get event tags
Source: https://docs.polymarket.com/api-reference/events/get-event-tags

/api-spec/gamma-openapi.yaml get /events/{id}/tags



# List events
Source: https://docs.polymarket.com/api-reference/events/list-events

/api-spec/gamma-openapi.yaml get /events



# List events (keyset pagination)
Source: https://docs.polymarket.com/api-reference/events/list-events-keyset-pagination

/api-spec/gamma-openapi.yaml get /events/keyset
Returns events using cursor-based (keyset) pagination for stable, efficient paging through large result sets. Use `next_cursor` from each response as `after_cursor` in the next request. The `offset` parameter is explicitly rejected; use `after_cursor` instead.




# Get fee rate
Source: https://docs.polymarket.com/api-reference/market-data/get-fee-rate

/api-spec/clob-openapi.yaml get /fee-rate
Retrieves the base fee rate for a specific token ID.
The fee rate can be provided either as a query parameter or as a path parameter.




# Get fee rate by path parameter
Source: https://docs.polymarket.com/api-reference/market-data/get-fee-rate-by-path-parameter

/api-spec/clob-openapi.yaml get /fee-rate/{token_id}
Retrieves the base fee rate for a specific token ID using the token ID as a path parameter.




# Get last trade price
Source: https://docs.polymarket.com/api-reference/market-data/get-last-trade-price

/api-spec/clob-openapi.yaml get /last-trade-price
Retrieves the last trade price and side for a specific token ID.
Returns default values of "0.5" for price and empty string for side if no trades found.




# Get last trade prices (query parameters)
Source: https://docs.polymarket.com/api-reference/market-data/get-last-trade-prices-query-parameters

/api-spec/clob-openapi.yaml get /last-trades-prices
Retrieves last trade prices for multiple token IDs using query parameters.
Maximum 500 token IDs can be requested per call.




# Get last trade prices (request body)
Source: https://docs.polymarket.com/api-reference/market-data/get-last-trade-prices-request-body

/api-spec/clob-openapi.yaml post /last-trades-prices
Retrieves last trade prices for multiple token IDs using a request body.
Maximum 500 token IDs can be requested per call.




# Get market price
Source: https://docs.polymarket.com/api-reference/market-data/get-market-price

/api-spec/clob-openapi.yaml get /price
Retrieves the best market price for a specific token ID and side (bid or ask).
Returns the best bid price for BUY side or best ask price for SELL side.




# Get market prices (query parameters)
Source: https://docs.polymarket.com/api-reference/market-data/get-market-prices-query-parameters

/api-spec/clob-openapi.yaml get /prices
Retrieves market prices for multiple token IDs and sides using query parameters.




# Get market prices (request body)
Source: https://docs.polymarket.com/api-reference/market-data/get-market-prices-request-body

/api-spec/clob-openapi.yaml post /prices
Retrieves market prices for multiple token IDs and sides using a request body.
Each request must include both token_id and side.




# Get midpoint prices (query parameters)
Source: https://docs.polymarket.com/api-reference/market-data/get-midpoint-prices-query-parameters

/api-spec/clob-openapi.yaml get /midpoints
Retrieves midpoint prices for multiple token IDs using query parameters.
The midpoint is calculated as the average of the best bid and best ask prices.




# Get midpoint prices (request body)
Source: https://docs.polymarket.com/api-reference/market-data/get-midpoint-prices-request-body

/api-spec/clob-openapi.yaml post /midpoints
Retrieves midpoint prices for multiple token IDs using a request body.
The midpoint is calculated as the average of the best bid and best ask prices.




# Get order book
Source: https://docs.polymarket.com/api-reference/market-data/get-order-book

/api-spec/clob-openapi.yaml get /book
Retrieves the order book summary for a specific token ID.
Includes bids, asks, market details, and last trade price.




# Get order books (request body)
Source: https://docs.polymarket.com/api-reference/market-data/get-order-books-request-body

/api-spec/clob-openapi.yaml post /books
Retrieves order book summaries for multiple token IDs using a request body.




# Get spread
Source: https://docs.polymarket.com/api-reference/market-data/get-spread

/api-spec/clob-openapi.yaml get /spread
Retrieves the spread for a specific token ID.
The spread is the difference between the best ask and best bid prices.




# Get spreads
Source: https://docs.polymarket.com/api-reference/market-data/get-spreads

/api-spec/clob-openapi.yaml post /spreads
Retrieves spreads for multiple token IDs.
The spread is the difference between the best ask and best bid prices.




# Get tick size
Source: https://docs.polymarket.com/api-reference/market-data/get-tick-size

/api-spec/clob-openapi.yaml get /tick-size
Retrieves the minimum tick size (price increment) for a specific token ID.
The tick size can be provided either as a query parameter or as a path parameter.




# Get tick size by path parameter
Source: https://docs.polymarket.com/api-reference/market-data/get-tick-size-by-path-parameter

/api-spec/clob-openapi.yaml get /tick-size/{token_id}
Retrieves the minimum tick size (price increment) for a specific token ID using the token ID as a path parameter.




# Get batch prices history
Source: https://docs.polymarket.com/api-reference/markets/get-batch-prices-history

/api-spec/clob-openapi.yaml post /batch-prices-history
Retrieve historical price data for multiple markets in a single request.



# Get CLOB market info
Source: https://docs.polymarket.com/api-reference/markets/get-clob-market-info

/api-spec/clob-openapi.yaml get /clob-markets/{condition_id}
Returns all CLOB-level parameters for a market in a single call —
tokens, tick size, base fees, rewards, RFQ status, and fee details.




# Get market by id
Source: https://docs.polymarket.com/api-reference/markets/get-market-by-id

/api-spec/gamma-openapi.yaml get /markets/{id}



# Get market by slug
Source: https://docs.polymarket.com/api-reference/markets/get-market-by-slug

/api-spec/gamma-openapi.yaml get /markets/slug/{slug}



# Get market by token
Source: https://docs.polymarket.com/api-reference/markets/get-market-by-token

/api-spec/clob-openapi.yaml get /markets-by-token/{token_id}
Returns the parent market for a given token ID. Useful when you have
a token ID and need to resolve its parent market without knowing the
condition ID in advance.




# Get market tags by id
Source: https://docs.polymarket.com/api-reference/markets/get-market-tags-by-id

/api-spec/gamma-openapi.yaml get /markets/{id}/tags



# Get prices history
Source: https://docs.polymarket.com/api-reference/markets/get-prices-history

/api-spec/clob-openapi.yaml get /prices-history
Retrieve historical price data for a market.



# Get sampling markets
Source: https://docs.polymarket.com/api-reference/markets/get-sampling-markets

/api-spec/clob-openapi.yaml get /sampling-markets



# Get sampling simplified markets
Source: https://docs.polymarket.com/api-reference/markets/get-sampling-simplified-markets

/api-spec/clob-openapi.yaml get /sampling-simplified-markets



# Get simplified markets
Source: https://docs.polymarket.com/api-reference/markets/get-simplified-markets

/api-spec/clob-openapi.yaml get /simplified-markets



# List markets
Source: https://docs.polymarket.com/api-reference/markets/list-markets

/api-spec/gamma-openapi.yaml get /markets



# List markets (keyset pagination)
Source: https://docs.polymarket.com/api-reference/markets/list-markets-keyset-pagination

/api-spec/gamma-openapi.yaml get /markets/keyset
Returns markets using cursor-based (keyset) pagination for stable, efficient paging through large result sets. Use `next_cursor` from each response as `after_cursor` in the next request. The `offset` parameter is explicitly rejected; use `after_cursor` instead.




# Download an accounting snapshot (ZIP of CSVs)
Source: https://docs.polymarket.com/api-reference/misc/download-an-accounting-snapshot-zip-of-csvs

/api-spec/data-openapi.yaml get /v1/accounting/snapshot



# Get live volume for an event
Source: https://docs.polymarket.com/api-reference/misc/get-live-volume-for-an-event

/api-spec/data-openapi.yaml get /live-volume



# Get open interest
Source: https://docs.polymarket.com/api-reference/misc/get-open-interest

/api-spec/data-openapi.yaml get /oi



# Get total markets a user has traded
Source: https://docs.polymarket.com/api-reference/misc/get-total-markets-a-user-has-traded

/api-spec/data-openapi.yaml get /traded



# Get public profile by wallet address
Source: https://docs.polymarket.com/api-reference/profiles/get-public-profile-by-wallet-address

/api-spec/gamma-openapi.yaml get /public-profile



# Get current rebated fees for a maker
Source: https://docs.polymarket.com/api-reference/rebates/get-current-rebated-fees-for-a-maker

/api-spec/clob-openapi.yaml get /rebates/current
Returns the current rebated fees for a maker address on a given date.

Each entry includes the condition ID, asset address, and the USDC amount rebated.

This endpoint does not require authentication.




# Get current active rewards configurations
Source: https://docs.polymarket.com/api-reference/rewards/get-current-active-rewards-configurations

/api-spec/clob-openapi.yaml get /rewards/markets/current
Returns all current active rewards configurations grouped by market.

When `sponsored=true`, returns sponsored reward configurations instead.

Results are paginated (500 items per page). Use next_cursor to fetch subsequent pages.
A next_cursor value of "LTE=" indicates the last page.




# Get earnings for user by date
Source: https://docs.polymarket.com/api-reference/rewards/get-earnings-for-user-by-date

/api-spec/clob-openapi.yaml get /rewards/user
Returns an array of user earnings per market for a provided day.

Requires CLOB L2 Auth headers.

Results are paginated (100 items per page). Use next_cursor to fetch subsequent pages.
A next_cursor value of "LTE=" indicates the last page.




# Get multiple markets with rewards
Source: https://docs.polymarket.com/api-reference/rewards/get-multiple-markets-with-rewards

/api-spec/clob-openapi.yaml get /rewards/markets/multi
Returns a list of active markets with their reward configurations.
Supports text search, tag filtering, numeric filters, and sorting.

Results are paginated (100 items per page by default). Use next_cursor to fetch subsequent pages.
A next_cursor value of "LTE=" indicates the last page.




# Get raw rewards for a specific market
Source: https://docs.polymarket.com/api-reference/rewards/get-raw-rewards-for-a-specific-market

/api-spec/clob-openapi.yaml get /rewards/markets/{condition_id}
Returns an array of present and future rewards configured on a market.

When `sponsored=true`, sponsored daily rates are folded into each config's
`rate_per_day` .

Results are paginated (100 items per page). Use next_cursor to fetch subsequent pages.
A next_cursor value of "LTE=" indicates the last page.




# Get reward percentages for user
Source: https://docs.polymarket.com/api-reference/rewards/get-reward-percentages-for-user

/api-spec/clob-openapi.yaml get /rewards/user/percentages
Returns the real-time percentages of rewards that a user is earning per market.

The response is a map of condition_id to the percentage of total rewards
the user is currently earning in that market.

Requires CLOB L2 Auth headers.




# Get total earnings for user by date
Source: https://docs.polymarket.com/api-reference/rewards/get-total-earnings-for-user-by-date

/api-spec/clob-openapi.yaml get /rewards/user/total
Returns the summed total rewards earnings for a user on a provided day,
grouped by asset address.

Requires CLOB L2 Auth headers.




# Get user earnings and markets configuration
Source: https://docs.polymarket.com/api-reference/rewards/get-user-earnings-and-markets-configuration

/api-spec/clob-openapi.yaml get /rewards/user/markets
Returns an array of current rewards including user earnings and live percentages
per market for a provided day.

Results are paginated (100 items per page by default, max 500). Use next_cursor to fetch subsequent pages.
A next_cursor value of "LTE=" indicates the last page.

Requires CLOB L2 Auth headers.

Optional features:
- Search by question/description using the `q` parameter
- Filter by tag slugs using `tag_slug` parameter (multiple values are OR'ed)
- Filter by favorite markets using `favorite_markets=true`
- Sort by various fields using `order_by` and `position` parameters




# Search markets, events, and profiles
Source: https://docs.polymarket.com/api-reference/search/search-markets-events-and-profiles

/api-spec/gamma-openapi.yaml get /public-search



# Get series by id
Source: https://docs.polymarket.com/api-reference/series/get-series-by-id

/api-spec/gamma-openapi.yaml get /series/{id}



# List series
Source: https://docs.polymarket.com/api-reference/series/list-series

/api-spec/gamma-openapi.yaml get /series



# Get sports metadata information
Source: https://docs.polymarket.com/api-reference/sports/get-sports-metadata-information

/api-spec/gamma-openapi.yaml get /sports



# Get valid sports market types
Source: https://docs.polymarket.com/api-reference/sports/get-valid-sports-market-types

/api-spec/gamma-openapi.yaml get /sports/market-types



# List teams
Source: https://docs.polymarket.com/api-reference/sports/list-teams

/api-spec/gamma-openapi.yaml get /teams



# Get related tags (relationships) by tag id
Source: https://docs.polymarket.com/api-reference/tags/get-related-tags-relationships-by-tag-id

/api-spec/gamma-openapi.yaml get /tags/{id}/related-tags



# Get related tags (relationships) by tag slug
Source: https://docs.polymarket.com/api-reference/tags/get-related-tags-relationships-by-tag-slug

/api-spec/gamma-openapi.yaml get /tags/slug/{slug}/related-tags



# Get tag by id
Source: https://docs.polymarket.com/api-reference/tags/get-tag-by-id

/api-spec/gamma-openapi.yaml get /tags/{id}



# Get tag by slug
Source: https://docs.polymarket.com/api-reference/tags/get-tag-by-slug

/api-spec/gamma-openapi.yaml get /tags/slug/{slug}



# Get tags related to a tag id
Source: https://docs.polymarket.com/api-reference/tags/get-tags-related-to-a-tag-id

/api-spec/gamma-openapi.yaml get /tags/{id}/related-tags/tags



# Get tags related to a tag slug
Source: https://docs.polymarket.com/api-reference/tags/get-tags-related-to-a-tag-slug

/api-spec/gamma-openapi.yaml get /tags/slug/{slug}/related-tags/tags



# List tags
Source: https://docs.polymarket.com/api-reference/tags/list-tags

/api-spec/gamma-openapi.yaml get /tags



# Cancel all orders
Source: https://docs.polymarket.com/api-reference/trade/cancel-all-orders

/api-spec/clob-openapi.yaml delete /cancel-all
Cancels all open orders for the authenticated user. Works even in cancel-only mode.




# Cancel multiple orders
Source: https://docs.polymarket.com/api-reference/trade/cancel-multiple-orders

/api-spec/clob-openapi.yaml delete /orders
Cancels multiple orders by their IDs. Maximum 3000 orders per request.
Duplicate order IDs in the request are automatically ignored.
Works even in cancel-only mode.




# Cancel orders for a market
Source: https://docs.polymarket.com/api-reference/trade/cancel-orders-for-a-market

/api-spec/clob-openapi.yaml delete /cancel-market-orders
Cancels all open orders for the authenticated user in a specific market (condition) and asset.
Works even in cancel-only mode.




# Cancel single order
Source: https://docs.polymarket.com/api-reference/trade/cancel-single-order

/api-spec/clob-openapi.yaml delete /order
Cancels a single order by its ID. Works even in cancel-only mode.




# Get builder trades
Source: https://docs.polymarket.com/api-reference/trade/get-builder-trades

/api-spec/clob-openapi.yaml get /builder/trades
Retrieves trades attributed to a builder code.




# Get order scoring status
Source: https://docs.polymarket.com/api-reference/trade/get-order-scoring-status

/api-spec/clob-openapi.yaml get /order-scoring
Checks if a specific order is currently scoring for rewards.

An order is considered "scoring" if it meets all the criteria for earning maker rewards:
- The order is live on a rewards-eligible market
- The order meets the minimum size requirements
- The order is within the valid spread range
- The order has been live for the required duration




# Get single order by ID
Source: https://docs.polymarket.com/api-reference/trade/get-single-order-by-id

/api-spec/clob-openapi.yaml get /order/{orderID}
Retrieves a specific order by its ID (order hash) for the authenticated user.
Builder-authenticated clients can also use this endpoint to retrieve orders attributed to their builder account.




# Get trades
Source: https://docs.polymarket.com/api-reference/trade/get-trades

/api-spec/clob-openapi.yaml get /trades
Retrieves trades for the authenticated user. Returns paginated results.
Requires readonly or level 2 API key authentication.




# Get user orders
Source: https://docs.polymarket.com/api-reference/trade/get-user-orders

/api-spec/clob-openapi.yaml get /data/orders
Retrieves open orders for the authenticated user. Returns paginated results.
Builder-authenticated clients can also use this endpoint to retrieve orders attributed to their builder account.




# Post a new order
Source: https://docs.polymarket.com/api-reference/trade/post-a-new-order

/api-spec/clob-openapi.yaml post /order
Creates a new order in the order book




# Post multiple orders
Source: https://docs.polymarket.com/api-reference/trade/post-multiple-orders

/api-spec/clob-openapi.yaml post /orders
Creates multiple new orders in the order book. Orders are processed in parallel.
Maximum 15 orders per request.




# Send heartbeat
Source: https://docs.polymarket.com/api-reference/trade/send-heartbeat

/api-spec/clob-openapi.yaml post /heartbeats
Sends a heartbeat signal to maintain active session status.
If heartbeats are not sent regularly, all open orders for the user will be automatically canceled.
This is useful for automated trading systems that need to ensure orders are canceled
if the system becomes unresponsive.




# Create deposit addresses
Source: https://docs.polymarket.com/api-reference/bridge/create-deposit-addresses

/api-spec/bridge-openapi.yaml post /deposit



# Create withdrawal addresses
Source: https://docs.polymarket.com/api-reference/bridge/create-withdrawal-addresses

/api-spec/bridge-openapi.yaml post /withdraw



# Get a quote
Source: https://docs.polymarket.com/api-reference/bridge/get-a-quote

/api-spec/bridge-openapi.yaml post /quote



# Get transaction status
Source: https://docs.polymarket.com/api-reference/bridge/get-transaction-status

/api-spec/bridge-openapi.yaml get /status/{address}



# Get all relayer API keys
Source: https://docs.polymarket.com/api-reference/relayer-api-keys/get-all-relayer-api-keys

/api-spec/relayer-openapi.yaml get /relayer/api/keys
Returns all relayer API keys for the authenticated address. Auth allowed: Gamma auth or Relayer API key auth (`RELAYER_API_KEY` + `RELAYER_API_KEY_ADDRESS`).




# Check if a safe is deployed
Source: https://docs.polymarket.com/api-reference/relayer/check-if-a-safe-is-deployed

/api-spec/relayer-openapi.yaml get /deployed
Returns a payload that determines if a safe is deployed. Takes in the user's Polymarket proxy address.




# Get a transaction by ID
Source: https://docs.polymarket.com/api-reference/relayer/get-a-transaction-by-id

/api-spec/relayer-openapi.yaml get /transaction
Gets a transaction submitted to the Relayer. Takes in a required transaction ID as a query parameter.

Poll this endpoint with the `transactionID` returned from `POST /submit` to retrieve the onchain `transactionHash` once the transaction has been broadcast.




# Get current nonce for a user
Source: https://docs.polymarket.com/api-reference/relayer/get-current-nonce-for-a-user

/api-spec/relayer-openapi.yaml get /nonce
Gets the current Proxy or Safe nonce for a user. Takes in the user's signer address and the type of nonce to retrieve.




# Get recent transactions for a user
Source: https://docs.polymarket.com/api-reference/relayer/get-recent-transactions-for-a-user

/api-spec/relayer-openapi.yaml get /transactions
Gets the most recent transactions submitted to the Relayer, owned by a specific user. Authenticated using Builder API Keys or Relayer API Keys.

**Builder API Key auth headers:**
- `POLY_BUILDER_API_KEY`
- `POLY_BUILDER_TIMESTAMP`
- `POLY_BUILDER_PASSPHRASE`
- `POLY_BUILDER_SIGNATURE`

**Relayer API Key auth headers:**
- `RELAYER_API_KEY`
- `RELAYER_API_KEY_ADDRESS`




# Get relayer address and nonce
Source: https://docs.polymarket.com/api-reference/relayer/get-relayer-address-and-nonce

/api-spec/relayer-openapi.yaml get /relay-payload
Fetches the relayer address and nonce for a specific user. Takes in the user's signer address and the type of nonce to retrieve.




# Submit a transaction
Source: https://docs.polymarket.com/api-reference/relayer/submit-a-transaction

/api-spec/relayer-openapi.yaml post /submit
Submit a transaction request to the Relayer. Authenticated using Builder API Keys or Relayer API Keys.

Returns immediately with the `transactionID` and a `state` of `STATE_NEW`. The onchain transaction hash is **not** included in this response — poll `GET /transaction` with the returned `transactionID` to retrieve the `transactionHash` once the transaction has been broadcast.

**Builder API Key auth headers:**
- `POLY_BUILDER_API_KEY`
- `POLY_BUILDER_TIMESTAMP`
- `POLY_BUILDER_PASSPHRASE`
- `POLY_BUILDER_SIGNATURE`

**Relayer API Key auth headers:**
- `RELAYER_API_KEY`
- `RELAYER_API_KEY_ADDRESS`




