Update Polymarket documentation (2026-02-19)
- Added new documentation URLs from llms.txt index - Updated TARGET.md with 244 total documentation pages - Scraped new pages for trading, concepts, and API reference sections - Updated changelog and new index pages
This commit is contained in:
@@ -4,43 +4,60 @@
|
||||
|
||||
# Authentication
|
||||
|
||||
> Understanding authentication using Polymarket's CLOB
|
||||
> How to authenticate requests to the CLOB API
|
||||
|
||||
The CLOB uses two levels of authentication: **L1 (Private Key)** and **L2 (API Key)**.
|
||||
Either can be accomplished using the CLOB client or REST API. Authentication is not
|
||||
required to access client public methods and public endpoints.
|
||||
The CLOB API uses two levels of authentication: **L1 (Private Key)** and **L2 (API Key)**. Either can be accomplished using the CLOB client or REST API.
|
||||
|
||||
## Authentication Levels
|
||||
## Public vs Authenticated
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="L1 Authentication" icon="key" href="#l1-authentication">
|
||||
Use the private key of the user’s account to sign messages
|
||||
<CardGroup cols={1}>
|
||||
<Card title="Public (No Auth)" icon="unlock">
|
||||
The **Gamma API**, **Data API**, and CLOB read endpoints (orderbook, prices, spreads) require no authentication.
|
||||
</Card>
|
||||
|
||||
<Card title="L2 Authentication" icon="lock" href="#l2-authentication">
|
||||
Use API credentials (key, secret, passphrase) to authenticate requests to the CLOB
|
||||
<Card title="Authenticated (CLOB)" icon="lock">
|
||||
CLOB trading endpoints (placing orders, cancellations, heartbeat) require all 5 `POLY_*` L2 HTTP headers.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
***
|
||||
|
||||
## L1 Authentication
|
||||
## Two-Level Authentication Model
|
||||
|
||||
### What is L1?
|
||||
The CLOB uses two levels of authentication: L1 (Private Key) and L2 (API Key). Either can be accomplished using the CLOB client or REST API
|
||||
|
||||
L1 authentication uses the wallet's private key to sign an EIP-712 message used in the
|
||||
request header. It proves ownership and control over the private key. The private key
|
||||
stays in control of the user and all trading activity remains non-custodial.
|
||||
### L1 Authentication (Private Key)
|
||||
|
||||
### What This Enables
|
||||
L1 authentication uses the wallet's private key to sign an EIP-712 message used in the request header. It proves ownership and control over the private key. The private key stays in control of the user and all trading activity remains non-custodial.
|
||||
|
||||
Access to L1 methods that create or derive L2 authentication headers.
|
||||
**Used for:**
|
||||
|
||||
* Create user API credentials
|
||||
* Derive existing user API credentials
|
||||
* Sign/create user's orders locally
|
||||
* Creating API credentials
|
||||
* Deriving existing API credentials
|
||||
* Signing and creating user's orders locally
|
||||
|
||||
### CLOB Client
|
||||
### L2 Authentication (API Credentials)
|
||||
|
||||
L2 uses API credentials (apiKey, secret, passphrase) generated from L1 authentication. These are used solely to authenticate requests made to the CLOB API. Requests are signed using HMAC-SHA256.
|
||||
|
||||
**Used for:**
|
||||
|
||||
* Cancel or get user's open orders
|
||||
* Check user's balances and allowances
|
||||
* Post user's signed orders
|
||||
|
||||
<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 (Recommended)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
@@ -48,26 +65,21 @@ Access to L1 methods that create or derive L2 authentication headers.
|
||||
import { ClobClient } from "@polymarket/clob-client";
|
||||
import { Wallet } from "ethers"; // v5.8.0
|
||||
|
||||
const HOST = "https://clob.polymarket.com";
|
||||
const CHAIN_ID = 137; // Polygon mainnet
|
||||
const signer = new Wallet(process.env.PRIVATE_KEY);
|
||||
|
||||
const client = new ClobClient(
|
||||
HOST,
|
||||
CHAIN_ID,
|
||||
signer // Signer enables L1 methods
|
||||
"https://clob.polymarket.com",
|
||||
137, // Polygon mainnet
|
||||
new Wallet(process.env.PRIVATE_KEY)
|
||||
);
|
||||
|
||||
// Gets API key, or else creates
|
||||
const apiCreds = await client.createOrDeriveApiKey();
|
||||
// Creates new credentials or derives existing ones
|
||||
const credentials = await client.createOrDeriveApiKey();
|
||||
|
||||
/*
|
||||
apiCreds = {
|
||||
"apiKey": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"secret": "base64EncodedSecretString",
|
||||
"passphrase": "randomPassphraseString"
|
||||
}
|
||||
*/
|
||||
console.log(credentials);
|
||||
// {
|
||||
// apiKey: "550e8400-e29b-41d4-a716-446655440000",
|
||||
// secret: "base64EncodedSecretString",
|
||||
// passphrase: "randomPassphraseString"
|
||||
// }
|
||||
```
|
||||
</Tab>
|
||||
|
||||
@@ -76,20 +88,17 @@ Access to L1 methods that create or derive L2 authentication headers.
|
||||
from py_clob_client.client import ClobClient
|
||||
import os
|
||||
|
||||
host = "https://clob.polymarket.com"
|
||||
chain_id = 137 # Polygon mainnet
|
||||
private_key = os.getenv("PRIVATE_KEY")
|
||||
|
||||
client = ClobClient(
|
||||
host=host,
|
||||
chain_id=chaind_id,
|
||||
key=private_key # Signer enables L1 methods
|
||||
host="https://clob.polymarket.com",
|
||||
chain_id=137, # Polygon mainnet
|
||||
key=os.getenv("PRIVATE_KEY")
|
||||
)
|
||||
|
||||
# Gets API key, or else creates
|
||||
api_creds = await client.create_or_derive_api_key()
|
||||
# Creates new credentials or derives existing ones
|
||||
credentials = client.create_or_derive_api_creds()
|
||||
|
||||
# api_creds = {
|
||||
print(credentials)
|
||||
# {
|
||||
# "apiKey": "550e8400-e29b-41d4-a716-446655440000",
|
||||
# "secret": "base64EncodedSecretString",
|
||||
# "passphrase": "randomPassphraseString"
|
||||
@@ -103,29 +112,36 @@ Access to L1 methods that create or derive L2 authentication headers.
|
||||
variables or secure key management systems.
|
||||
</Warning>
|
||||
|
||||
***
|
||||
### Using the REST API
|
||||
|
||||
### REST API
|
||||
While we highly recommend using our provided clients to handle signing and authentication, the following is for developers who choose NOT to use our [Python](https://github.com/Polymarket/py-clob-client) or [TypeScript](https://github.com/Polymarket/clob-client) clients.
|
||||
|
||||
While we highly recommend using our provided clients to handle signing
|
||||
and authentication, the following is for developers who choose NOT to
|
||||
use our [Python](https://github.com/Polymarket/py-clob-client) or
|
||||
[TypeScript](https://github.com/Polymarket/clob-client) clients.
|
||||
**Create API Credentials**
|
||||
|
||||
When making direct REST API calls with L1 authentication, include these headers:
|
||||
```bash theme={null}
|
||||
POST https://clob.polymarket.com/auth/api-key
|
||||
```
|
||||
|
||||
| Header | Required? | Description |
|
||||
| ---------------- | --------- | ---------------------- |
|
||||
| `POLY_ADDRESS` | yes | Polygon signer address |
|
||||
| `POLY_SIGNATURE` | yes | CLOB EIP 712 signature |
|
||||
| `POLY_TIMESTAMP` | yes | Current UNIX timestamp |
|
||||
| `POLY_NONCE` | yes | Nonce. Default 0 |
|
||||
**Derive API Credentials**
|
||||
|
||||
The `POLY_SIGNATURE` is generated by signing the following EIP-712 struct.
|
||||
```bash theme={null}
|
||||
GET https://clob.polymarket.com/auth/derive-api-key
|
||||
```
|
||||
|
||||
Required L1 headers:
|
||||
|
||||
| Header | Description |
|
||||
| ---------------- | ---------------------- |
|
||||
| `POLY_ADDRESS` | Polygon signer address |
|
||||
| `POLY_SIGNATURE` | CLOB EIP-712 signature |
|
||||
| `POLY_TIMESTAMP` | Current UNIX timestamp |
|
||||
| `POLY_NONCE` | Nonce (default: 0) |
|
||||
|
||||
The `POLY_SIGNATURE` is generated by signing the following EIP-712 struct:
|
||||
|
||||
<Accordion title="EIP-712 Signing Example">
|
||||
<CodeGroup>
|
||||
```typescript Typescript theme={null}
|
||||
```typescript TypeScript theme={null}
|
||||
const domain = {
|
||||
name: "ClobAuthDomain",
|
||||
version: "1",
|
||||
@@ -174,7 +190,7 @@ The `POLY_SIGNATURE` is generated by signing the following EIP-712 struct.
|
||||
"message": "This message attests that I control the given wallet",
|
||||
}
|
||||
|
||||
sig = await signer._signTypedData(domain, types, value)
|
||||
sig = signer.sign_typed_data(domain, types, value)
|
||||
```
|
||||
</CodeGroup>
|
||||
</Accordion>
|
||||
@@ -184,25 +200,7 @@ Reference implementations:
|
||||
* [TypeScript](https://github.com/Polymarket/clob-client/blob/main/src/signing/eip712.ts)
|
||||
* [Python](https://github.com/Polymarket/py-clob-client/blob/main/py_clob_client/signing/eip712.py)
|
||||
|
||||
***
|
||||
|
||||
**Create API Credentials**
|
||||
|
||||
Create new API credentials for user.
|
||||
|
||||
```bash theme={null}
|
||||
POST {clob-endpoint}/auth/api-key
|
||||
```
|
||||
|
||||
**Derive API Credentials**
|
||||
|
||||
Derive API credentials for user.
|
||||
|
||||
```bash theme={null}
|
||||
GET {clob-endpoint}/auth/derive-api-key
|
||||
```
|
||||
|
||||
**Response**
|
||||
Response:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
@@ -216,25 +214,21 @@ GET {clob-endpoint}/auth/derive-api-key
|
||||
|
||||
***
|
||||
|
||||
## L2 Authentication
|
||||
## L2 Authentication Headers
|
||||
|
||||
### What is L2?
|
||||
All trading endpoints require these 5 headers:
|
||||
|
||||
The next level of authentication is called L2, and it consists of the
|
||||
user's API credentials (apiKey, secret, passphrase) generated from L1
|
||||
authentication. These are used solely to authenticate requests made to
|
||||
the CLOB API. Requests are signed using HMAC-SHA256.
|
||||
| Header | Description |
|
||||
| ----------------- | ----------------------------- |
|
||||
| `POLY_ADDRESS` | Polygon signer address |
|
||||
| `POLY_SIGNATURE` | HMAC signature for request |
|
||||
| `POLY_TIMESTAMP` | Current UNIX timestamp |
|
||||
| `POLY_API_KEY` | User's API `apiKey` value |
|
||||
| `POLY_PASSPHRASE` | User's API `passphrase` value |
|
||||
|
||||
### What This Enables
|
||||
The `POLY_SIGNATURE` for L2 is an HMAC-SHA256 signature created using the user's API credentials `secret` value. Reference implementations can be found in the [TypeScript](https://github.com/Polymarket/clob-client/blob/main/src/signing/hmac.ts) and [Python](https://github.com/Polymarket/py-clob-client/blob/main/py_clob_client/signing/hmac.py) clients.
|
||||
|
||||
Access to L2 methods such as posting signed/created orders, viewing open
|
||||
orders, cancelling open orders, getting trades
|
||||
|
||||
* Cancel or get user's open orders
|
||||
* Check user's balances and allowances
|
||||
* Post user's signed orders
|
||||
|
||||
### CLOB Client
|
||||
### CLOB Client (L2)
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
@@ -242,20 +236,16 @@ orders, cancelling open orders, getting trades
|
||||
import { ClobClient } from "@polymarket/clob-client";
|
||||
import { Wallet } from "ethers"; // v5.8.0
|
||||
|
||||
const HOST = "https://clob.polymarket.com";
|
||||
const CHAIN_ID = 137; // Polygon mainnet
|
||||
const signer = new Wallet(process.env.PRIVATE_KEY);
|
||||
|
||||
const client = new ClobClient(
|
||||
HOST,
|
||||
CHAIN_ID,
|
||||
signer,
|
||||
"https://clob.polymarket.com",
|
||||
137,
|
||||
new Wallet(process.env.PRIVATE_KEY),
|
||||
apiCreds, // Generated from L1 auth, API credentials enable L2 methods
|
||||
1, // signatureType explained below
|
||||
FUNDER // funder explained below
|
||||
funderAddress // funder explained below
|
||||
);
|
||||
|
||||
// Now you can trade!*
|
||||
// Now you can trade!
|
||||
const order = await client.createAndPostOrder(
|
||||
{ tokenID: "123456", price: 0.65, size: 100, side: "BUY" },
|
||||
{ tickSize: "0.01", negRisk: false }
|
||||
@@ -268,10 +258,6 @@ orders, cancelling open orders, getting trades
|
||||
from py_clob_client.client import ClobClient
|
||||
import os
|
||||
|
||||
host = "https://clob.polymarket.com"
|
||||
chain_id = 137 # Polygon mainnet
|
||||
private_key = os.getenv("PRIVATE_KEY")
|
||||
|
||||
client = ClobClient(
|
||||
host="https://clob.polymarket.com",
|
||||
chain_id=137,
|
||||
@@ -281,8 +267,8 @@ orders, cancelling open orders, getting trades
|
||||
funder=os.getenv("FUNDER_ADDRESS") # funder explained below
|
||||
)
|
||||
|
||||
# Now you can trade!*
|
||||
order = await client.create_and_post_order(
|
||||
# Now you can trade!
|
||||
order = client.create_and_post_order(
|
||||
{"token_id": "123456", "price": 0.65, "size": 100, "side": "BUY"},
|
||||
{"tick_size": "0.01", "neg_risk": False}
|
||||
)
|
||||
@@ -291,59 +277,57 @@ orders, cancelling open orders, getting trades
|
||||
</Tabs>
|
||||
|
||||
<Info>
|
||||
Even with L2 authentication headers, methods that create user orders still require the user to sign the order payload.
|
||||
Even with L2 authentication headers, methods that create user orders still
|
||||
require the user to sign the order payload.
|
||||
</Info>
|
||||
|
||||
***
|
||||
|
||||
### REST API
|
||||
|
||||
While we highly recommend using our provided clients to handle signing
|
||||
and authentication, the following is for developers who choose NOT to
|
||||
use our [Python](https://github.com/Polymarket/py-clob-client) or
|
||||
[TypeScript](https://github.com/Polymarket/clob-client) clients.
|
||||
|
||||
When making direct REST API calls with L2 authentication, include these headers:
|
||||
|
||||
| Header | Required? | Description |
|
||||
| ----------------- | --------- | ----------------------------- |
|
||||
| `POLY_ADDRESS` | yes | Polygon signer address |
|
||||
| `POLY_SIGNATURE` | yes | HMAC signature for request |
|
||||
| `POLY_TIMESTAMP` | yes | Current UNIX timestamp |
|
||||
| `POLY_API_KEY` | yes | User's API `apiKey` value |
|
||||
| `POLY_PASSPHRASE` | yes | User's API `passphrase` value |
|
||||
|
||||
The `POLY_SIGNATURE` for L2 is an HMAC-SHA256 signature created using the user's API credentials `secret` value.
|
||||
Reference implementations can be found in the [Typescript](https://github.com/Polymarket/clob-client/blob/main/src/signing/hmac.ts)
|
||||
and [Python](https://github.com/Polymarket/py-clob-client/blob/main/py_clob_client/signing/hmac.py) clients.
|
||||
|
||||
***
|
||||
|
||||
## Signature Types and Funder
|
||||
|
||||
When initializing the L2 client, you must specify your wallet **signatureType** and the **funder** address which holds the funds:
|
||||
|
||||
| Signature Type | Value | Description |
|
||||
| -------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| EOA | 0 | Standard Ethereum wallet (MetaMask). Funder is the EOA address and will need POL to pay gas on transactions. |
|
||||
| POLY\_PROXY | 1 | A custom proxy wallet only used with users who logged in via Magic Link email/Google. Using this requires the user to have exported their PK from Polymarket.com and imported into your app. |
|
||||
| GNOSIS\_SAFE | 2 | Gnosis Safe multisig proxy wallet (most common). Use this for any new or returning user who does not fit the other 2 types. |
|
||||
| EOA | `0` | Standard Ethereum wallet (MetaMask). Funder is the EOA address and will need POL to pay gas on transactions. |
|
||||
| POLY\_PROXY | `1` | A custom proxy wallet only used with users who logged in via Magic Link email/Google. Using this requires the user to have exported their PK from Polymarket.com and imported into your app. |
|
||||
| GNOSIS\_SAFE | `2` | Gnosis Safe multisig proxy wallet (most common). Use this for any new or returning user who does not fit the other 2 types. |
|
||||
|
||||
<Tip>
|
||||
The wallet addresses displayed to the user on Polymarket.com is the proxy wallet and should be used as the funder.
|
||||
These can be deterministically derived or you can deploy them on behalf of the user.
|
||||
These proxy wallets are automatically deployed for the user on their first login to Polymarket.com.
|
||||
The wallet address displayed to the user on Polymarket.com is the proxy wallet
|
||||
and should be used as the funder. These can be deterministically derived or
|
||||
you can deploy them on behalf of the user. These proxy wallets are
|
||||
automatically deployed for the user on their first login to Polymarket.com.
|
||||
</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.
|
||||
|
||||
**Solution:**
|
||||
**Solutions:**
|
||||
|
||||
* Verify your private key is a valid hex string (starts with "0x")
|
||||
* Ensure you're using the correct key for the intended address
|
||||
@@ -353,7 +337,7 @@ When initializing the L2 client, you must specify your wallet **signatureType**
|
||||
<Accordion title="Error: NONCE_ALREADY_USED">
|
||||
The nonce you provided has already been used to create an API key.
|
||||
|
||||
**Solution:**
|
||||
**Solutions:**
|
||||
|
||||
* Use `deriveApiKey()` with the same nonce to retrieve existing credentials
|
||||
* Or use a different nonce with `createApiKey()`
|
||||
@@ -367,13 +351,6 @@ When initializing the L2 client, you must specify your wallet **signatureType**
|
||||
If it does not exist or user has never logged into Polymarket.com, deploy it first before creating L2 authentication.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Lost API credentials but have nonce">
|
||||
```typescript theme={null}
|
||||
// Use deriveApiKey with the original nonce
|
||||
const recovered = await client.deriveApiKey(originalNonce);
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Lost both credentials and nonce">
|
||||
Unfortunately, there's no way to recover lost API credentials without the nonce. You'll need to create new credentials:
|
||||
|
||||
@@ -387,22 +364,14 @@ When initializing the L2 client, you must specify your wallet **signatureType**
|
||||
|
||||
***
|
||||
|
||||
## See Client Methods
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Public Methods" icon="globe" href="/developers/CLOB/clients/methods-public">
|
||||
Access market data, orderbooks, and prices.
|
||||
<Card title="Place Your First Order" icon="plus" href="/trading/quickstart">
|
||||
Learn how to create and submit orders.
|
||||
</Card>
|
||||
|
||||
<Card title="L1 Methods" icon="key" href="/developers/CLOB/clients/methods-l1">
|
||||
Private key authentication to create or derive API keys (L2 headers).
|
||||
</Card>
|
||||
|
||||
<Card title="L2 Methods" icon="lock" href="/developers/CLOB/clients/methods-l2">
|
||||
Manage and close orders. Creating orders requires signer.
|
||||
</Card>
|
||||
|
||||
<Card title="Builder Program Methods" icon="hammer" href="/developers/CLOB/clients/methods-builder">
|
||||
Builder-specific operations for those in the Builders Program.
|
||||
<Card title="Geographic Restrictions" icon="globe" href="/api-reference/geoblock">
|
||||
Check trading availability by region.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -8,9 +8,7 @@
|
||||
|
||||
## Client Initialization
|
||||
|
||||
Builder methods require the client to initialize with a separate authentication setup using
|
||||
builder configs acquired from [Polymarket.com](https://polymarket.com/settings?tab=builder)
|
||||
and the `@polymarket/builder-signing-sdk` package.
|
||||
Builder methods require the client to initialize with a separate builder config using credentials acquired from [Polymarket.com](https://polymarket.com/settings?tab=builder) and the `@polymarket/builder-signing-sdk` package.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Local Builder Credentials">
|
||||
@@ -31,7 +29,7 @@ and the `@polymarket/builder-signing-sdk` package.
|
||||
"https://clob.polymarket.com",
|
||||
137,
|
||||
signer,
|
||||
apiCreds, // The user's API credentials generated from L1 authentication
|
||||
apiCreds, // User's API credentials from L1 authentication
|
||||
signatureType,
|
||||
funderAddress,
|
||||
undefined,
|
||||
@@ -57,7 +55,7 @@ and the `@polymarket/builder-signing-sdk` package.
|
||||
host="https://clob.polymarket.com",
|
||||
chain_id=137,
|
||||
key=os.getenv("PRIVATE_KEY"),
|
||||
creds=creds, # The user's API credentials generated from L1 authentication
|
||||
creds=creds, # User's API credentials from L1 authentication
|
||||
signature_type=signature_type,
|
||||
funder=funder,
|
||||
builder_config=builder_config
|
||||
@@ -73,14 +71,14 @@ and the `@polymarket/builder-signing-sdk` package.
|
||||
import { BuilderConfig } from "@polymarket/builder-signing-sdk";
|
||||
|
||||
const builderConfig = new BuilderConfig({
|
||||
remoteBuilderConfig: {url: "http://localhost:3000/sign"}
|
||||
remoteBuilderConfig: { url: "http://localhost:3000/sign" }
|
||||
});
|
||||
|
||||
const clobClient = new ClobClient(
|
||||
"https://clob.polymarket.com",
|
||||
137,
|
||||
signer,
|
||||
apiCreds, // The user's API credentials generated from L1 authentication
|
||||
apiCreds, // User's API credentials from L1 authentication
|
||||
signatureType,
|
||||
funder,
|
||||
undefined,
|
||||
@@ -89,7 +87,7 @@ and the `@polymarket/builder-signing-sdk` package.
|
||||
);
|
||||
```
|
||||
|
||||
```typescript Python theme={null}
|
||||
```python Python theme={null}
|
||||
from py_clob_client.client import ClobClient
|
||||
from py_builder_signing_sdk.config import BuilderConfig, RemoteBuilderConfig
|
||||
import os
|
||||
@@ -104,7 +102,7 @@ and the `@polymarket/builder-signing-sdk` package.
|
||||
host="https://clob.polymarket.com",
|
||||
chain_id=137,
|
||||
key=os.getenv("PRIVATE_KEY"),
|
||||
creds=creds, # The user's API credentials generated from L1 authentication
|
||||
creds=creds, # User's API credentials from L1 authentication
|
||||
signature_type=signature_type,
|
||||
funder=funder,
|
||||
builder_config=builder_config
|
||||
@@ -115,7 +113,7 @@ and the `@polymarket/builder-signing-sdk` package.
|
||||
</Tabs>
|
||||
|
||||
<Info>
|
||||
[More information on builder signing](/developers/builders/order-attribution)
|
||||
See [Order Attribution](/trading/orders/attribution) for more information on builder signing.
|
||||
</Info>
|
||||
|
||||
***
|
||||
@@ -126,8 +124,7 @@ and the `@polymarket/builder-signing-sdk` package.
|
||||
|
||||
### getBuilderTrades()
|
||||
|
||||
Retrieves all trades attributed to your builder account.
|
||||
This method allows builders to track which trades were routed through your platform.
|
||||
Retrieves all trades attributed to your builder account. Use this to track which trades were routed through your platform.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async getBuilderTrades(
|
||||
@@ -135,81 +132,176 @@ async getBuilderTrades(
|
||||
): Promise<BuilderTradesPaginatedResponse>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface TradeParams {
|
||||
id?: string;
|
||||
maker_address?: string;
|
||||
market?: string;
|
||||
asset_id?: string;
|
||||
before?: string;
|
||||
after?: string;
|
||||
}
|
||||
```
|
||||
**Params (`TradeParams`)**
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface BuilderTradesPaginatedResponse {
|
||||
trades: BuilderTrade[];
|
||||
next_cursor: string;
|
||||
limit: number;
|
||||
count: number;
|
||||
}
|
||||
<ResponseField name="id" type="string">
|
||||
Optional. Filter trades by trade ID.
|
||||
</ResponseField>
|
||||
|
||||
interface BuilderTrade {
|
||||
id: string;
|
||||
tradeType: string;
|
||||
takerOrderHash: string;
|
||||
builder: string;
|
||||
market: string;
|
||||
assetId: string;
|
||||
side: string;
|
||||
size: string;
|
||||
sizeUsdc: string;
|
||||
price: string;
|
||||
status: string;
|
||||
outcome: string;
|
||||
outcomeIndex: number;
|
||||
owner: string;
|
||||
maker: string;
|
||||
transactionHash: string;
|
||||
matchTime: string;
|
||||
bucketIndex: number;
|
||||
fee: string;
|
||||
feeUsdc: string;
|
||||
err_msg?: string | null;
|
||||
createdAt: string | null;
|
||||
updatedAt: string | null;
|
||||
}
|
||||
```
|
||||
<ResponseField name="maker_address" type="string">
|
||||
Optional. Filter trades by maker address.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="market" type="string">
|
||||
Optional. Filter trades by market condition ID.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="asset_id" type="string">
|
||||
Optional. Filter trades by asset (token) ID.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="before" type="string">
|
||||
Optional. Return trades created before this cursor value.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="after" type="string">
|
||||
Optional. Return trades created after this cursor value.
|
||||
</ResponseField>
|
||||
|
||||
**Response (`BuilderTradesPaginatedResponse`)**
|
||||
|
||||
<ResponseField name="trades" type="BuilderTrade[]">
|
||||
Array of trades attributed to the builder account.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="next_cursor" type="string">
|
||||
Cursor string for fetching the next page of results.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="limit" type="number">
|
||||
Maximum number of trades returned per page.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="count" type="number">
|
||||
Total number of trades returned in this response.
|
||||
</ResponseField>
|
||||
|
||||
**`BuilderTrade` fields**
|
||||
|
||||
<ResponseField name="id" type="string">
|
||||
Unique identifier for the trade.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="tradeType" type="string">
|
||||
Type of the trade.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="takerOrderHash" type="string">
|
||||
Hash of the taker order associated with this trade.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="builder" type="string">
|
||||
Address of the builder who attributed this trade.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="market" type="string">
|
||||
Condition ID of the market this trade belongs to.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="assetId" type="string">
|
||||
Token ID of the asset traded.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="side" type="string">
|
||||
Side of the trade (e.g. BUY or SELL).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="size" type="string">
|
||||
Size of the trade in shares.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="sizeUsdc" type="string">
|
||||
Size of the trade denominated in USDC.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="price" type="string">
|
||||
Price at which the trade was executed.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="status" type="string">
|
||||
Current status of the trade.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="outcome" type="string">
|
||||
Outcome label associated with the traded asset.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="outcomeIndex" type="number">
|
||||
Index of the outcome within the market.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="owner" type="string">
|
||||
Address of the order owner (taker).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="maker" type="string">
|
||||
Address of the maker in the trade.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="transactionHash" type="string">
|
||||
On-chain transaction hash for the trade.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="matchTime" type="string">
|
||||
Timestamp when the trade was matched.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="bucketIndex" type="number">
|
||||
Bucket index used for trade grouping.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="fee" type="string">
|
||||
Fee charged for the trade in shares.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="feeUsdc" type="string">
|
||||
Fee charged for the trade denominated in USDC.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="err_msg" type="string | null">
|
||||
Optional. Error message if the trade encountered an issue, otherwise null.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="createdAt" type="string | null">
|
||||
Timestamp when the trade record was created, or null if unavailable.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="updatedAt" type="string | null">
|
||||
Timestamp when the trade record was last updated, or null if unavailable.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### revokeBuilderApiKey()
|
||||
|
||||
Revokes the builder API key used to authenticate the current request.
|
||||
After revocation, the key can no longer be used to make builder-authenticated requests.
|
||||
Revokes the builder API key used to authenticate the current request. After revocation, the key can no longer be used for builder-authenticated requests.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async revokeBuilderApiKey(): Promise<any>
|
||||
```
|
||||
|
||||
<ResponseField name="returns" type="any">
|
||||
Response from the revocation request.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
## See Also
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Builders Program Introduction" icon="hammer" href="/developers/builders/builder-intro">
|
||||
Learn the benefits, how to implement, and more.
|
||||
<Card title="Builders Program" icon="hammer" href="/builders/overview">
|
||||
Learn about the Builders Program and its benefits.
|
||||
</Card>
|
||||
|
||||
<Card title="Implement Builders Signing" icon="key" href="/developers/builders/order-attribution">
|
||||
Attribute orders to you, and pre-requisite to using the Relayer Client.
|
||||
<Card title="Order Attribution" icon="key" href="/trading/orders/attribution">
|
||||
Attribute orders to your builder account.
|
||||
</Card>
|
||||
|
||||
<Card title="Relayer Client" icon="globe" href="/developers/builders/relayer-client">
|
||||
The relayer executes other gasless transactions for your users, on your app.
|
||||
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
|
||||
Place and manage orders with API credentials.
|
||||
</Card>
|
||||
|
||||
<Card title="Full Example Implementations" icon="puzzle" href="/developers/builders/examples">
|
||||
Complete Next.js examples integrated with embedded wallets (Privy, Magic, Turnkey, wagmi)
|
||||
<Card title="Gasless Transactions" icon="gas-pump" href="/trading/gasless">
|
||||
Execute onchain operations without paying gas.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -43,13 +43,13 @@ L1 methods require the client to initialize with a signer.
|
||||
)
|
||||
|
||||
# Ready to create user API credentials
|
||||
api_key = await client.create_api_key()
|
||||
api_key = client.create_api_key()
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
<Warning>
|
||||
**Security:** Never commit private keys to version control. Always use environment variables or secure key management systems.
|
||||
Never commit private keys to version control. Always use environment variables or a secure key management system.
|
||||
</Warning>
|
||||
|
||||
***
|
||||
@@ -60,68 +60,75 @@ L1 methods require the client to initialize with a signer.
|
||||
|
||||
### createApiKey()
|
||||
|
||||
Creates a new API key (L2 credentials) for the wallet signer. This generates a new set of credentials that can be used for L2 authenticated requests.
|
||||
Each wallet can only have one active API key at a time. Creating a new key invalidates the previous one.
|
||||
Creates a new API key (L2 credentials) for the wallet signer. Each wallet can only have one active API key at a time — creating a new key invalidates the previous one.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async createApiKey(nonce?: number): Promise<ApiKeyCreds>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
`nonce` (optional): Custom nonce for deterministic key generation. If not provided, a default derivation is used.
|
||||
```
|
||||
<ResponseField name="nonce" type="number">
|
||||
Optional custom nonce for deterministic key generation. Optional.
|
||||
</ResponseField>
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface ApiKeyCreds {
|
||||
apiKey: string;
|
||||
secret: string;
|
||||
passphrase: string;
|
||||
}
|
||||
```
|
||||
<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 (L2 credentials) using a specific nonce. If you've already created API credentials with a particular nonce, this method will return the same credentials again.
|
||||
Derives an existing API key using a specific nonce. If you've already created credentials with a particular nonce, this returns the same credentials.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async deriveApiKey(nonce?: number): Promise<ApiKeyCreds>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
`nonce` (optional): Custom nonce for deterministic key generation. If not provided, a default derivation is used.
|
||||
```
|
||||
<ResponseField name="nonce" type="number">
|
||||
The nonce used when originally creating the key. Optional.
|
||||
</ResponseField>
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface ApiKeyCreds {
|
||||
apiKey: string;
|
||||
secret: string;
|
||||
passphrase: string;
|
||||
}
|
||||
```
|
||||
<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. This is the recommended method for initial setup if you're unsure if credentials already exist.
|
||||
Convenience method that attempts to derive an API key with the default nonce, or creates a new one if it doesn't exist. **Recommended for initial setup.**
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async createOrDeriveApiKey(nonce?: number): Promise<ApiKeyCreds>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
`nonce` (optional): Custom nonce for deterministic key generation. If not provided, a default derivation is used.
|
||||
```
|
||||
<ResponseField name="apiKey" type="string">
|
||||
The API key string, either derived or newly created.
|
||||
</ResponseField>
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface ApiKeyCreds {
|
||||
apiKey: string;
|
||||
secret: string;
|
||||
passphrase: string;
|
||||
}
|
||||
```
|
||||
<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>
|
||||
|
||||
***
|
||||
|
||||
@@ -129,9 +136,7 @@ interface ApiKeyCreds {
|
||||
|
||||
### createOrder()
|
||||
|
||||
Create and sign a limit order locally without posting it to the CLOB.
|
||||
Use this when you want to sign orders in advance or implement custom order submission logic.
|
||||
Place order via L2 methods postOrder or postOrders.
|
||||
Create and sign a limit order locally without posting it to the CLOB. Use this when you want to sign orders in advance or implement custom submission logic. Submit via [`postOrder()`](/trading/clients/l2#postorder) or [`postOrders()`](/trading/clients/l2#postorders).
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async createOrder(
|
||||
@@ -140,49 +145,103 @@ async createOrder(
|
||||
): Promise<SignedOrder>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface UserOrder {
|
||||
tokenID: string;
|
||||
price: number;
|
||||
size: number;
|
||||
side: Side;
|
||||
feeRateBps?: number;
|
||||
nonce?: number;
|
||||
expiration?: number;
|
||||
taker?: string;
|
||||
}
|
||||
<ResponseField name="tokenID" type="string">
|
||||
The token ID of the market outcome to trade.
|
||||
</ResponseField>
|
||||
|
||||
interface CreateOrderOptions {
|
||||
tickSize: TickSize;
|
||||
negRisk?: boolean;
|
||||
}
|
||||
```
|
||||
<ResponseField name="price" type="number">
|
||||
The limit price for the order.
|
||||
</ResponseField>
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface SignedOrder {
|
||||
salt: string;
|
||||
maker: string;
|
||||
signer: string;
|
||||
taker: string;
|
||||
tokenId: string;
|
||||
makerAmount: string;
|
||||
takerAmount: string;
|
||||
side: number; // 0 = BUY, 1 = SELL
|
||||
expiration: string;
|
||||
nonce: string;
|
||||
feeRateBps: string;
|
||||
signatureType: number;
|
||||
signature: string;
|
||||
}
|
||||
```
|
||||
<ResponseField name="size" type="number">
|
||||
The size (number of shares) for the order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="side" type="Side">
|
||||
The side of the order (buy or sell).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="feeRateBps" type="number">
|
||||
Optional fee rate in basis points. Optional.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="nonce" type="number">
|
||||
Optional nonce for the order. Optional.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="expiration" type="number">
|
||||
Optional expiration timestamp for the order. Optional.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="taker" type="string">
|
||||
Optional taker address for the order. Optional.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="tickSize" type="TickSize">
|
||||
The tick size used for order validation (CreateOrderOptions).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="negRisk" type="boolean">
|
||||
Optional flag for negative risk markets (CreateOrderOptions). Optional.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="salt" type="string">
|
||||
A random salt value for the signed order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="maker" type="string">
|
||||
The maker's address.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="signer" type="string">
|
||||
The signer's address.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="taker" type="string">
|
||||
The taker's address in the signed order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="tokenId" type="string">
|
||||
The token ID in the signed order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="makerAmount" type="string">
|
||||
The maker amount as a string.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="takerAmount" type="string">
|
||||
The taker amount as a string.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="side" type="number">
|
||||
The side of the order as a number (0 = BUY, 1 = SELL).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="expiration" type="string">
|
||||
The expiration timestamp as a string.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="nonce" type="string">
|
||||
The nonce as a string.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="feeRateBps" type="string">
|
||||
The fee rate in basis points as a string.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="signatureType" type="number">
|
||||
The type identifier for the signature scheme used.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="signature" type="string">
|
||||
The cryptographic signature of the order.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### createMarketOrder()
|
||||
|
||||
Create and sign a market order locally without posting it to the CLOB.
|
||||
Use this when you want to sign orders in advance or implement custom order submission logic.
|
||||
Place orders via L2 methods postOrder or postOrders.
|
||||
Create and sign a market order locally without posting it to the CLOB. Submit via [`postOrder()`](/trading/clients/l2#postorder) or [`postOrders()`](/trading/clients/l2#postorders).
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async createMarketOrder(
|
||||
@@ -191,36 +250,89 @@ async createMarketOrder(
|
||||
): Promise<SignedOrder>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface UserMarketOrder {
|
||||
tokenID: string;
|
||||
amount: number; // BUY: dollar amount, SELL: number of shares
|
||||
side: Side;
|
||||
price?: number; // Optional price limit
|
||||
feeRateBps?: number;
|
||||
nonce?: number;
|
||||
taker?: string;
|
||||
orderType?: OrderType.FOK | OrderType.FAK;
|
||||
}
|
||||
```
|
||||
<ResponseField name="tokenID" type="string">
|
||||
The token ID of the market outcome to trade.
|
||||
</ResponseField>
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface SignedOrder {
|
||||
salt: string;
|
||||
maker: string;
|
||||
signer: string;
|
||||
taker: string;
|
||||
tokenId: string;
|
||||
makerAmount: string;
|
||||
takerAmount: string;
|
||||
side: number; // 0 = BUY, 1 = SELL
|
||||
expiration: string;
|
||||
nonce: string;
|
||||
feeRateBps: string;
|
||||
signatureType: number;
|
||||
signature: string;
|
||||
}
|
||||
```
|
||||
<ResponseField name="amount" type="number">
|
||||
The order amount. For BUY orders this is a dollar amount; for SELL orders this is the number of shares.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="side" type="Side">
|
||||
The side of the order (buy or sell).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="price" type="number">
|
||||
Optional price limit for the market order. Optional.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="feeRateBps" type="number">
|
||||
Optional fee rate in basis points. Optional.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="nonce" type="number">
|
||||
Optional nonce for the order. Optional.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="taker" type="string">
|
||||
Optional taker address for the order. Optional.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="orderType" type="OrderType.FOK | OrderType.FAK">
|
||||
Optional order type, either FOK (Fill-Or-Kill) or FAK (Fill-And-Kill). Optional.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="salt" type="string">
|
||||
A random salt value for the signed order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="maker" type="string">
|
||||
The maker's address.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="signer" type="string">
|
||||
The signer's address.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="taker" type="string">
|
||||
The taker's address in the signed order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="tokenId" type="string">
|
||||
The token ID in the signed order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="makerAmount" type="string">
|
||||
The maker amount as a string.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="takerAmount" type="string">
|
||||
The taker amount as a string.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="side" type="number">
|
||||
The side of the order as a number (0 = BUY, 1 = SELL).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="expiration" type="string">
|
||||
The expiration timestamp as a string.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="nonce" type="string">
|
||||
The nonce as a string.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="feeRateBps" type="string">
|
||||
The fee rate in basis points as a string.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="signatureType" type="number">
|
||||
The type identifier for the signature scheme used.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="signature" type="string">
|
||||
The cryptographic signature of the order.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
@@ -232,7 +344,7 @@ interface SignedOrder {
|
||||
|
||||
**Solution:**
|
||||
|
||||
* Verify your private key is a valid hex string (starts with "0x")
|
||||
* Verify your private key is a valid hex string (starts with `0x`)
|
||||
* Ensure you're using the correct key for the intended address
|
||||
* Check that the key has proper permissions
|
||||
</Accordion>
|
||||
@@ -249,9 +361,7 @@ interface SignedOrder {
|
||||
<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.
|
||||
**Solution:** Check your proxy wallet address at [polymarket.com/settings](https://polymarket.com/settings). If it doesn't exist, the user has never logged in to Polymarket.com — deploy the proxy wallet first before creating L2 credentials.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Lost API credentials but have nonce">
|
||||
@@ -262,7 +372,7 @@ interface SignedOrder {
|
||||
</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:
|
||||
There's no way to recover lost credentials without the nonce. Create new ones:
|
||||
|
||||
```typescript theme={null}
|
||||
// Create fresh credentials with a new nonce
|
||||
@@ -277,19 +387,19 @@ interface SignedOrder {
|
||||
## See Also
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Understand CLOB Authentication" icon="shield" href="/developers/CLOB/authentication">
|
||||
Deep dive into L1 and L2 authentication
|
||||
<Card title="Authentication" icon="shield" href="/api-reference/authentication">
|
||||
Deep dive into L1 and L2 authentication.
|
||||
</Card>
|
||||
|
||||
<Card title="CLOB Quickstart Guide" icon="hammer" href="/developers/CLOB/quickstart">
|
||||
Initialize the CLOB quickly and place your first order.
|
||||
<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="/developers/CLOB/clients/methods-l2">
|
||||
Access market data, orderbooks, and prices.
|
||||
<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="/developers/CLOB/clients/methods-l2">
|
||||
Manage and close orders. Creating orders requires signer.
|
||||
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
|
||||
Place and manage orders with API credentials.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -4,13 +4,11 @@
|
||||
|
||||
# L2 Methods
|
||||
|
||||
> These methods require user API credentials (L2 headers). Use these for placing trades and managing user's positions.
|
||||
|
||||
***
|
||||
> These methods require user API credentials (L2 headers). Use these for placing trades and managing your positions.
|
||||
|
||||
## Client Initialization
|
||||
|
||||
L2 methods require the client to initialize with the signer, signatureType, user API credentials, and funder.
|
||||
L2 methods require the client to initialize with a signer, signature type, API credentials, and funder address.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
@@ -18,7 +16,7 @@ L2 methods require the client to initialize with the signer, signatureType, user
|
||||
import { ClobClient } from "@polymarket/clob-client";
|
||||
import { Wallet } from "ethers";
|
||||
|
||||
const signer = new Wallet(process.env.PRIVATE_KEY)
|
||||
const signer = new Wallet(process.env.PRIVATE_KEY);
|
||||
|
||||
const apiCreds = {
|
||||
apiKey: process.env.API_KEY,
|
||||
@@ -31,11 +29,11 @@ L2 methods require the client to initialize with the signer, signatureType, user
|
||||
137,
|
||||
signer,
|
||||
apiCreds,
|
||||
2, // Deployed Safe proxy wallet
|
||||
process.env.FUNDER_ADDRESS // Address of deployed Safe proxy wallet
|
||||
2, // GNOSIS_SAFE
|
||||
process.env.FUNDER_ADDRESS
|
||||
);
|
||||
|
||||
// Ready to send authenticated requests to the CLOB API!
|
||||
// Ready to send authenticated requests
|
||||
const order = await client.postOrder(signedOrder);
|
||||
```
|
||||
</Tab>
|
||||
@@ -57,12 +55,12 @@ L2 methods require the client to initialize with the signer, signatureType, user
|
||||
chain_id=137,
|
||||
key=os.getenv("PRIVATE_KEY"),
|
||||
creds=api_creds,
|
||||
signature_type=2, # Deployed Safe proxy wallet
|
||||
funder=os.getenv("FUNDER_ADDRESS") # Address of deployed Safe proxy wallet
|
||||
signature_type=2, # GNOSIS_SAFE
|
||||
funder=os.getenv("FUNDER_ADDRESS")
|
||||
)
|
||||
|
||||
# Ready to send authenticated requests to the CLOB API!
|
||||
order = await client.post_order(signed_order)
|
||||
# Ready to send authenticated requests
|
||||
order = client.post_order(signed_order)
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@@ -75,8 +73,7 @@ L2 methods require the client to initialize with the signer, signatureType, user
|
||||
|
||||
### createAndPostOrder()
|
||||
|
||||
A convenience method that creates, prompts signature, and posts an order in a single call.
|
||||
Use when you want to buy/sell at a specific price and can wait.
|
||||
Convenience method that creates, signs, and posts a limit order in a single call. Use when you want to buy or sell at a specific price.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async createAndPostOrder(
|
||||
@@ -86,44 +83,83 @@ async createAndPostOrder(
|
||||
): Promise<OrderResponse>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface UserOrder {
|
||||
tokenID: string;
|
||||
price: number;
|
||||
size: number;
|
||||
side: Side;
|
||||
feeRateBps?: number;
|
||||
nonce?: number;
|
||||
expiration?: number;
|
||||
taker?: string;
|
||||
}
|
||||
**Params**
|
||||
|
||||
type CreateOrderOptions = {
|
||||
tickSize: TickSize;
|
||||
negRisk?: boolean;
|
||||
}
|
||||
<ResponseField name="tokenID" type="string">
|
||||
The token ID of the outcome to trade.
|
||||
</ResponseField>
|
||||
|
||||
type TickSize = "0.1" | "0.01" | "0.001" | "0.0001";
|
||||
```
|
||||
<ResponseField name="price" type="number">
|
||||
The limit price for the order.
|
||||
</ResponseField>
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface OrderResponse {
|
||||
success: boolean;
|
||||
errorMsg: string;
|
||||
orderID: string;
|
||||
transactionsHashes: string[];
|
||||
status: string;
|
||||
takingAmount: string;
|
||||
makingAmount: string;
|
||||
}
|
||||
```
|
||||
<ResponseField name="size" type="number">
|
||||
The size of the order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="side" type="Side">
|
||||
The side of the order (buy or sell).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="feeRateBps" type="number">
|
||||
Optional fee rate in basis points.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="nonce" type="number">
|
||||
Optional nonce for the order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="expiration" type="number">
|
||||
Optional expiration timestamp for the order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="taker" type="string">
|
||||
Optional taker address.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="tickSize" type="TickSize">
|
||||
Tick size for the order. One of `"0.1"`, `"0.01"`, `"0.001"`, `"0.0001"`.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="negRisk" type="boolean">
|
||||
Optional. Whether the market uses negative risk.
|
||||
</ResponseField>
|
||||
|
||||
**Response**
|
||||
|
||||
<ResponseField name="success" type="boolean">
|
||||
Whether the order was successfully placed.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="errorMsg" type="string">
|
||||
Error message if the order was not successful.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="orderID" type="string">
|
||||
The ID of the placed order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="transactionsHashes" type="string[]">
|
||||
Array of transaction hashes associated with the order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="status" type="string">
|
||||
The current status of the order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="takingAmount" type="string">
|
||||
The amount being taken in the order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="makingAmount" type="string">
|
||||
The amount being made in the order.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### createAndPostMarketOrder()
|
||||
|
||||
A convenience method that creates, prompts signature, and posts an order in a single call.
|
||||
Use when you want to buy/sell right now at whatever the market price is.
|
||||
Convenience method that creates, signs, and posts a market order in a single call. Use when you want to buy or sell at the current market price.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async createAndPostMarketOrder(
|
||||
@@ -133,103 +169,109 @@ async createAndPostMarketOrder(
|
||||
): Promise<OrderResponse>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface UserMarketOrder {
|
||||
tokenID: string;
|
||||
amount: number;
|
||||
side: Side;
|
||||
price?: number;
|
||||
feeRateBps?: number;
|
||||
nonce?: number;
|
||||
taker?: string;
|
||||
orderType?: OrderType.FOK | OrderType.FAK;
|
||||
}
|
||||
**Params**
|
||||
|
||||
type CreateOrderOptions = {
|
||||
tickSize: TickSize;
|
||||
negRisk?: boolean;
|
||||
}
|
||||
<ResponseField name="tokenID" type="string">
|
||||
The token ID of the outcome to trade.
|
||||
</ResponseField>
|
||||
|
||||
type TickSize = "0.1" | "0.01" | "0.001" | "0.0001";
|
||||
```
|
||||
<ResponseField name="amount" type="number">
|
||||
The amount for the market order.
|
||||
</ResponseField>
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface OrderResponse {
|
||||
success: boolean;
|
||||
errorMsg: string;
|
||||
orderID: string;
|
||||
transactionsHashes: string[];
|
||||
status: string;
|
||||
takingAmount: string;
|
||||
makingAmount: string;
|
||||
}
|
||||
```
|
||||
<ResponseField name="side" type="Side">
|
||||
The side of the order (buy or sell).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="price" type="number">
|
||||
Optional price hint for the market order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="feeRateBps" type="number">
|
||||
Optional fee rate in basis points.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="nonce" type="number">
|
||||
Optional nonce for the order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="taker" type="string">
|
||||
Optional taker address.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="orderType" type="OrderType.FOK | OrderType.FAK">
|
||||
Optional order type override. Defaults to FOK.
|
||||
</ResponseField>
|
||||
|
||||
**Response**
|
||||
|
||||
<ResponseField name="success" type="boolean">
|
||||
Whether the order was successfully placed.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="errorMsg" type="string">
|
||||
Error message if the order was not successful.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="orderID" type="string">
|
||||
The ID of the placed order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="transactionsHashes" type="string[]">
|
||||
Array of transaction hashes associated with the order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="status" type="string">
|
||||
The current status of the order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="takingAmount" type="string">
|
||||
The amount being taken in the order.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="makingAmount" type="string">
|
||||
The amount being made in the order.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### postOrder()
|
||||
|
||||
Posts a pre-signed and created order to the CLOB.
|
||||
Posts a pre-signed order to the CLOB. Use with [`createOrder()`](/trading/clients/l1#createorder) or [`createMarketOrder()`](/trading/clients/l1#createmarketorder) from L1 methods.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async postOrder(
|
||||
order: SignedOrder,
|
||||
orderType?: OrderType, // Defaults to GTC
|
||||
postOnly?: boolean, // Defaults to false
|
||||
postOnly?: boolean, // Defaults to false
|
||||
): Promise<OrderResponse>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
order: SignedOrder // Pre-signed order from createOrder() or createMarketOrder()
|
||||
orderType?: OrderType // Optional, defaults to GTC
|
||||
postOnly?: boolean // Optional, defaults to false
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface OrderResponse {
|
||||
success: boolean;
|
||||
errorMsg: string;
|
||||
orderID: string;
|
||||
transactionsHashes: string[];
|
||||
status: string;
|
||||
takingAmount: string;
|
||||
makingAmount: string;
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### postOrders()
|
||||
|
||||
Posts up to 15 pre-signed and created orders in a single batch.
|
||||
Posts up to 15 pre-signed orders in a single batch.
|
||||
|
||||
```typescript theme={null}
|
||||
```typescript Signature theme={null}
|
||||
async postOrders(
|
||||
args: PostOrdersArgs[],
|
||||
): Promise<OrderResponse[]>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface PostOrdersArgs {
|
||||
order: SignedOrder;
|
||||
orderType: OrderType;
|
||||
postOnly?: boolean; // Defaults to false
|
||||
}
|
||||
```
|
||||
**Params**
|
||||
|
||||
```typescript Response theme={null}
|
||||
OrderResponse[] // Array of OrderResponse objects
|
||||
<ResponseField name="order" type="SignedOrder">
|
||||
The pre-signed order to post.
|
||||
</ResponseField>
|
||||
|
||||
interface OrderResponse {
|
||||
success: boolean;
|
||||
errorMsg: string;
|
||||
orderID: string;
|
||||
transactionsHashes: string[];
|
||||
status: string;
|
||||
takingAmount: string;
|
||||
makingAmount: string;
|
||||
}
|
||||
```
|
||||
<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>
|
||||
|
||||
***
|
||||
|
||||
@@ -241,12 +283,15 @@ Cancels a single open order.
|
||||
async cancelOrder(orderID: string): Promise<CancelOrdersResponse>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface CancelOrdersResponse {
|
||||
canceled: string[];
|
||||
not_canceled: Record<string, any>;
|
||||
}
|
||||
```
|
||||
**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>
|
||||
|
||||
***
|
||||
|
||||
@@ -258,17 +303,6 @@ Cancels multiple orders in a single batch.
|
||||
async cancelOrders(orderIDs: string[]): Promise<CancelOrdersResponse>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
orderIDs: string[];
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface CancelOrdersResponse {
|
||||
canceled: string[];
|
||||
not_canceled: Record<string, any>;
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### cancelAll()
|
||||
@@ -276,14 +310,7 @@ interface CancelOrdersResponse {
|
||||
Cancels all open orders.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async cancelAll(): Promise<CancelResponse>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface CancelOrdersResponse {
|
||||
canceled: string[];
|
||||
not_canceled: Record<string, any>;
|
||||
}
|
||||
async cancelAll(): Promise<CancelOrdersResponse>
|
||||
```
|
||||
|
||||
***
|
||||
@@ -298,19 +325,15 @@ async cancelMarketOrders(
|
||||
): Promise<CancelOrdersResponse>
|
||||
```
|
||||
|
||||
```typescript Parameters theme={null}
|
||||
interface OrderMarketCancelParams {
|
||||
market?: string;
|
||||
asset_id?: string;
|
||||
}
|
||||
```
|
||||
**Params**
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface CancelOrdersResponse {
|
||||
canceled: string[];
|
||||
not_canceled: Record<string, any>;
|
||||
}
|
||||
```
|
||||
<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>
|
||||
|
||||
***
|
||||
|
||||
@@ -320,31 +343,73 @@ interface CancelOrdersResponse {
|
||||
|
||||
### getOrder()
|
||||
|
||||
Get details for a specific order.
|
||||
Get details for a specific order by ID.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async getOrder(orderID: string): Promise<OpenOrder>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface OpenOrder {
|
||||
id: string;
|
||||
status: string;
|
||||
owner: string;
|
||||
maker_address: string;
|
||||
market: string;
|
||||
asset_id: string;
|
||||
side: string;
|
||||
original_size: string;
|
||||
size_matched: string;
|
||||
price: string;
|
||||
associate_trades: string[];
|
||||
outcome: string;
|
||||
created_at: number;
|
||||
expiration: string;
|
||||
order_type: string;
|
||||
}
|
||||
```
|
||||
**Response**
|
||||
|
||||
<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>
|
||||
|
||||
***
|
||||
|
||||
@@ -356,40 +421,22 @@ Get all your open orders.
|
||||
async getOpenOrders(
|
||||
params?: OpenOrderParams,
|
||||
only_first_page?: boolean,
|
||||
): Promise<OpenOrdersResponse>
|
||||
): Promise<OpenOrder[]>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface OpenOrderParams {
|
||||
id?: string; // Order ID
|
||||
market?: string; // Market condition ID
|
||||
asset_id?: string; // Token ID
|
||||
}
|
||||
**Params**
|
||||
|
||||
only_first_page?: boolean // Defaults to false
|
||||
```
|
||||
<ResponseField name="id" type="string">
|
||||
Optional. Filter by order ID.
|
||||
</ResponseField>
|
||||
|
||||
```typescript Response theme={null}
|
||||
type OpenOrdersResponse = OpenOrder[];
|
||||
<ResponseField name="market" type="string">
|
||||
Optional. Filter by market condition ID.
|
||||
</ResponseField>
|
||||
|
||||
interface OpenOrder {
|
||||
id: string;
|
||||
status: string;
|
||||
owner: string;
|
||||
maker_address: string;
|
||||
market: string;
|
||||
asset_id: string;
|
||||
side: string;
|
||||
original_size: string;
|
||||
size_matched: string;
|
||||
price: string;
|
||||
associate_trades: string[];
|
||||
outcome: string;
|
||||
created_at: number;
|
||||
expiration: string;
|
||||
order_type: string;
|
||||
}
|
||||
```
|
||||
<ResponseField name="asset_id" type="string">
|
||||
Optional. Filter by token ID.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
@@ -404,53 +451,141 @@ async getTrades(
|
||||
): Promise<Trade[]>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface TradeParams {
|
||||
id?: string;
|
||||
maker_address?: string;
|
||||
market?: string;
|
||||
asset_id?: string;
|
||||
before?: string;
|
||||
after?: string;
|
||||
}
|
||||
**Params**
|
||||
|
||||
only_first_page?: boolean // Defaults to false
|
||||
```
|
||||
<ResponseField name="id" type="string">
|
||||
Optional. Filter by trade ID.
|
||||
</ResponseField>
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface Trade {
|
||||
id: string;
|
||||
taker_order_id: string;
|
||||
market: string;
|
||||
asset_id: string;
|
||||
side: Side;
|
||||
size: string;
|
||||
fee_rate_bps: string;
|
||||
price: string;
|
||||
status: string;
|
||||
match_time: string;
|
||||
last_update: string;
|
||||
outcome: string;
|
||||
bucket_index: number;
|
||||
owner: string;
|
||||
maker_address: string;
|
||||
maker_orders: MakerOrder[];
|
||||
transaction_hash: string;
|
||||
trader_side: "TAKER" | "MAKER";
|
||||
}
|
||||
<ResponseField name="maker_address" type="string">
|
||||
Optional. Filter by maker address.
|
||||
</ResponseField>
|
||||
|
||||
interface MakerOrder {
|
||||
order_id: string;
|
||||
owner: string;
|
||||
maker_address: string;
|
||||
matched_amount: string;
|
||||
price: string;
|
||||
fee_rate_bps: string;
|
||||
asset_id: string;
|
||||
outcome: string;
|
||||
side: Side;
|
||||
}
|
||||
```
|
||||
<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=""TAKER" | "MAKER"">
|
||||
Whether the authenticated user is the taker or a maker in this trade.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
@@ -464,24 +599,19 @@ async getTradesPaginated(
|
||||
): Promise<TradesPaginatedResponse>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface TradeParams {
|
||||
id?: string;
|
||||
maker_address?: string;
|
||||
market?: string;
|
||||
asset_id?: string;
|
||||
before?: string;
|
||||
after?: string;
|
||||
}
|
||||
```
|
||||
**Response**
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface TradesPaginatedResponse {
|
||||
trades: Trade[];
|
||||
limit: number;
|
||||
count: number;
|
||||
}
|
||||
```
|
||||
<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>
|
||||
|
||||
***
|
||||
|
||||
@@ -499,24 +629,25 @@ async getBalanceAllowance(
|
||||
): Promise<BalanceAllowanceResponse>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface BalanceAllowanceParams {
|
||||
asset_type: AssetType;
|
||||
token_id?: string;
|
||||
}
|
||||
**Params**
|
||||
|
||||
enum AssetType {
|
||||
COLLATERAL = "COLLATERAL",
|
||||
CONDITIONAL = "CONDITIONAL",
|
||||
}
|
||||
```
|
||||
<ResponseField name="asset_type" type="AssetType">
|
||||
The type of asset to query. One of `"COLLATERAL"` or `"CONDITIONAL"`.
|
||||
</ResponseField>
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface BalanceAllowanceResponse {
|
||||
balance: string;
|
||||
allowance: string;
|
||||
}
|
||||
```
|
||||
<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>
|
||||
|
||||
***
|
||||
|
||||
@@ -530,21 +661,11 @@ async updateBalanceAllowance(
|
||||
): Promise<void>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface BalanceAllowanceParams {
|
||||
asset_type: AssetType;
|
||||
token_id?: string;
|
||||
}
|
||||
|
||||
enum AssetType {
|
||||
COLLATERAL = "COLLATERAL",
|
||||
CONDITIONAL = "CONDITIONAL",
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## API Key Management (L2)
|
||||
## API Key Management
|
||||
|
||||
***
|
||||
|
||||
### getApiKeys()
|
||||
|
||||
@@ -554,17 +675,11 @@ Get all API keys associated with your account.
|
||||
async getApiKeys(): Promise<ApiKeysResponse>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface ApiKeysResponse {
|
||||
apiKeys: ApiKeyCreds[];
|
||||
}
|
||||
**Response**
|
||||
|
||||
interface ApiKeyCreds {
|
||||
key: string;
|
||||
secret: string;
|
||||
passphrase: string;
|
||||
}
|
||||
```
|
||||
<ResponseField name="apiKeys" type="ApiKeyCreds[]">
|
||||
Array of API key credential objects associated with the account.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
@@ -572,9 +687,7 @@ interface ApiKeyCreds {
|
||||
|
||||
Deletes (revokes) the currently authenticated API key.
|
||||
|
||||
**TypeScript Signature:**
|
||||
|
||||
```typescript theme={null}
|
||||
```typescript Signature theme={null}
|
||||
async deleteApiKey(): Promise<any>
|
||||
```
|
||||
|
||||
@@ -586,30 +699,39 @@ async deleteApiKey(): Promise<any>
|
||||
|
||||
### getNotifications()
|
||||
|
||||
Retrieves all event notifications for the L2 authenticated user.
|
||||
Records are removed automatically after 48 hours or if manually removed via dropNotifications().
|
||||
Retrieves all event notifications for the authenticated user. Records are automatically removed after 48 hours.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
public async getNotifications(): Promise<Notification[]>
|
||||
async getNotifications(): Promise<Notification[]>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface Notification {
|
||||
id: number; // Unique notification ID
|
||||
owner: string; // User's L2 credential apiKey or empty string for global notifications
|
||||
payload: any; // Type-specific payload data
|
||||
timestamp?: number; // Unix timestamp
|
||||
type: number; // Notification type (see type mapping below)
|
||||
}
|
||||
```
|
||||
**Response**
|
||||
|
||||
**Notification Type Mapping**
|
||||
<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 |
|
||||
| Order Cancellation | `1` | User's order was canceled |
|
||||
| Order Fill | `2` | User's order was filled (maker or taker) |
|
||||
| Market Resolved | `4` | Market was resolved |
|
||||
|
||||
***
|
||||
|
||||
@@ -618,33 +740,33 @@ interface Notification {
|
||||
Mark notifications as read/dismissed.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
public async dropNotifications(params?: DropNotificationParams): Promise<void>
|
||||
async dropNotifications(params?: DropNotificationParams): Promise<void>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface DropNotificationParams {
|
||||
ids: string[]; // Array of notification IDs to mark as read
|
||||
}
|
||||
```
|
||||
**Params**
|
||||
|
||||
<ResponseField name="ids" type="string[]">
|
||||
Array of notification IDs to dismiss.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
## See Also
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Understand CLOB Authentication" icon="shield" href="/developers/CLOB/authentication">
|
||||
Deep dive into L1 and L2 authentication
|
||||
<Card title="Authentication" icon="shield" href="/api-reference/authentication">
|
||||
Deep dive into L1 and L2 authentication.
|
||||
</Card>
|
||||
|
||||
<Card title="Public Methods" icon="globe" href="/developers/CLOB/clients/methods-l2">
|
||||
Access market data, orderbooks, and prices.
|
||||
<Card title="L1 Methods" icon="key" href="/trading/clients/l1">
|
||||
Sign orders and derive API credentials with your private key.
|
||||
</Card>
|
||||
|
||||
<Card title="L1 Methods" icon="lock" href="/developers/CLOB/clients/methods-l2">
|
||||
Private key authentication to create or derive API keys (L2 headers)
|
||||
<Card title="Public Methods" icon="globe" href="/trading/clients/public">
|
||||
Read market data and orderbooks without auth.
|
||||
</Card>
|
||||
|
||||
<Card title="Web Socket API" icon="hammer" href="/developers/CLOB/websocket/wss-overview">
|
||||
Real-time market data streaming
|
||||
<Card title="WebSocket" icon="bolt" href="/market-data/websocket/overview">
|
||||
Real-time market data streaming.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -2,234 +2,96 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Methods Overview
|
||||
# Clients & SDKs
|
||||
|
||||
> CLOB client methods require different levels of authentication. This reference is organized by what credentials you need to call each method.
|
||||
> Official open-source libraries for interacting with Polymarket
|
||||
|
||||
Polymarket provides official open-source clients in TypeScript, Python, and Rust. All three support the full CLOB API including market data, order management, and authentication.
|
||||
|
||||
## Installation
|
||||
|
||||
<CodeGroup>
|
||||
```bash TypeScript theme={null}
|
||||
npm install @polymarket/clob-client ethers@5
|
||||
```
|
||||
|
||||
```bash Python theme={null}
|
||||
pip install py-clob-client
|
||||
```
|
||||
|
||||
```bash Rust theme={null}
|
||||
cargo add polymarket-client-sdk
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Quick Example
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { ClobClient } from "@polymarket/clob-client";
|
||||
|
||||
const client = new ClobClient(
|
||||
"https://clob.polymarket.com",
|
||||
137,
|
||||
signer,
|
||||
apiCreds,
|
||||
);
|
||||
|
||||
const markets = await client.getMarkets();
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.client import ClobClient
|
||||
|
||||
client = ClobClient(
|
||||
"https://clob.polymarket.com",
|
||||
key=private_key,
|
||||
chain_id=137,
|
||||
creds=api_creds,
|
||||
)
|
||||
|
||||
markets = client.get_markets()
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Source Code
|
||||
|
||||
| Language | Package | Repository |
|
||||
| ---------- | ------------------------- | ------------------------------------------------------------------------------------ |
|
||||
| TypeScript | `@polymarket/clob-client` | [github.com/Polymarket/clob-client](https://github.com/Polymarket/clob-client) |
|
||||
| Python | `py-clob-client` | [github.com/Polymarket/py-clob-client](https://github.com/Polymarket/py-clob-client) |
|
||||
| Rust | `polymarket-client-sdk` | [github.com/Polymarket/rs-clob-client](https://github.com/Polymarket/rs-clob-client) |
|
||||
|
||||
Each repository includes working examples in the `/examples` directory.
|
||||
|
||||
## Builder SDKs
|
||||
|
||||
If you're building an app through the [Builder Program](/builders/overview), additional signing SDKs are available:
|
||||
|
||||
| Language | Package | Repository |
|
||||
| ---------- | --------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| TypeScript | `@polymarket/builder-signing-sdk` | [github.com/Polymarket/builder-signing-sdk](https://github.com/Polymarket/builder-signing-sdk) |
|
||||
| Python | `py_builder_signing_sdk` | [github.com/Polymarket/py-builder-signing-sdk](https://github.com/Polymarket/py-builder-signing-sdk) |
|
||||
|
||||
See [Order Attribution](/trading/orders/attribution) for usage details.
|
||||
|
||||
## Relayer SDK
|
||||
|
||||
For [gasless transactions](/trading/gasless) using proxy wallets, the relayer client handles submitting transactions through Polymarket's relayer:
|
||||
|
||||
| Language | Package | Repository |
|
||||
| ---------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
|
||||
| TypeScript | `@polymarket/builder-relayer-client` | [github.com/Polymarket/builder-relayer-client](https://github.com/Polymarket/builder-relayer-client) |
|
||||
| Python | `py-builder-relayer-client` | [github.com/Polymarket/py-builder-relayer-client](https://github.com/Polymarket/py-builder-relayer-client) |
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Public Methods" icon="globe" href="/developers/CLOB/clients/methods-public">
|
||||
Access market data, orderbooks, and prices.
|
||||
<Card title="Quickstart" icon="rocket" href="/quickstart">
|
||||
Set up your client and place your first order.
|
||||
</Card>
|
||||
|
||||
<Card title="L1 Methods" icon="key" href="/developers/CLOB/clients/methods-l1">
|
||||
Private key authentication to create or derive API keys (L2 headers).
|
||||
</Card>
|
||||
|
||||
<Card title="L2 Methods" icon="lock" href="/developers/CLOB/clients/methods-l2">
|
||||
Manage and close orders. Creating orders requires signer.
|
||||
</Card>
|
||||
|
||||
<Card title="Builder Program Methods" icon="hammer" href="/developers/CLOB/clients/methods-builder">
|
||||
Builder-specific operations for those in the Builders Program.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
***
|
||||
|
||||
## Client Initialization by Use Case
|
||||
|
||||
<Tabs>
|
||||
<Tab title="Get Market Data">
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// No signer or credentials needed
|
||||
const client = new ClobClient(
|
||||
"https://clob.polymarket.com",
|
||||
137
|
||||
);
|
||||
|
||||
// All public methods available
|
||||
const markets = await client.getMarkets();
|
||||
const book = await client.getOrderBook(tokenId);
|
||||
const price = await client.getPrice(tokenId, "BUY");
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
# No signer or credentials needed
|
||||
client = new ClobClient(
|
||||
host="https://clob.polymarket.com",
|
||||
chain_id=137
|
||||
)
|
||||
|
||||
# All public methods available
|
||||
markets = client.get_markets()
|
||||
book = client.get_order_book()
|
||||
price = client.get_price()
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Generate User API Credentials">
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Create client with signer
|
||||
const client = new ClobClient(
|
||||
"https://clob.polymarket.com",
|
||||
137,
|
||||
signer
|
||||
);
|
||||
|
||||
// All public and L1 methods available
|
||||
const newCreds = createApiKey();
|
||||
const derivedCreds = deriveApiKey();
|
||||
const creds = createOrDeriveApiKey();
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
# Create client with signer
|
||||
client = new ClobClient(
|
||||
host="https://clob.polymarket.com",
|
||||
chain_id=137
|
||||
key="private_key"
|
||||
)
|
||||
|
||||
# All public and L1 methods available
|
||||
new_creds = client.create_api_key()
|
||||
derived_creds = client.derive_api_key()
|
||||
creds = client.create_or_derive_api_key()
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Create and Post Order">
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Create client with signer and creds
|
||||
const client = new ClobClient(
|
||||
"https://clob.polymarket.com",
|
||||
137,
|
||||
signer,
|
||||
creds,
|
||||
2, // Indicates Gnosis Safe proxy
|
||||
funder // Safe wallet address holding funds
|
||||
);
|
||||
|
||||
// All public, L1, and L2 methods available
|
||||
const order = await client.createOrder({ /* ... */ });
|
||||
const result = await client.postOrder(order);
|
||||
const trades = await client.getTrades();
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
# Create client with signer and creds
|
||||
const client = new ClobClient(
|
||||
host="https://clob.polymarket.com",
|
||||
chain_id=137,
|
||||
key="private_key",
|
||||
creds=creds,
|
||||
signature_type=2, // Indicates Gnosis Safe proxy
|
||||
funder="funder_address" // Safe wallet address holding funds
|
||||
)
|
||||
|
||||
# All public, L1, and L2 methods available
|
||||
order = client.create_order({ /* ... */ })
|
||||
result = client.post_order(order)
|
||||
trades = client.get_trades()
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Get Builders Orders">
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Create client with builder's authentication headers
|
||||
import { BuilderConfig, BuilderApiKeyCreds } from "@polymarket/builder-signing-sdk";
|
||||
|
||||
const builderCreds: BuilderApiKeyCreds = {
|
||||
key: process.env.POLY_BUILDER_API_KEY!,
|
||||
secret: process.env.POLY_BUILDER_SECRET!,
|
||||
passphrase: process.env.POLY_BUILDER_PASSPHRASE!
|
||||
};
|
||||
|
||||
const builderConfig: BuilderConfig = {
|
||||
localBuilderCreds: builderCreds
|
||||
};
|
||||
|
||||
const client = new ClobClient(
|
||||
"https://clob.polymarket.com",
|
||||
137,
|
||||
signer,
|
||||
creds, // User's API credentials
|
||||
2,
|
||||
funder,
|
||||
undefined,
|
||||
false,
|
||||
builderConfig // Builder's API credentials
|
||||
);
|
||||
|
||||
// You can call all methods including builder methods
|
||||
const builderTrades = await client.getBuilderTrades();
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
# Create client with builder's authentication headers
|
||||
from py_clob_client.client import ClobClient
|
||||
from py_clob_client.clob_types import ApiCreds
|
||||
from py_builder_signing_sdk.config import BuilderConfig, BuilderApiKeyCreds
|
||||
|
||||
builder_creds = BuilderApiKeyCreds(
|
||||
key="POLY_BUILDER_API_KEY",
|
||||
secret="POLY_BUILDER_SECRET,
|
||||
passphrase="POLY_BUILDER_PASSPHRASE"
|
||||
)
|
||||
|
||||
builder_config = BuilderConfig(
|
||||
local_builder_creds=builder_creds
|
||||
)
|
||||
|
||||
client = ClobClient(
|
||||
host="https://clob.polymarket.com",
|
||||
chain_id=137,
|
||||
key="private_key",
|
||||
creds=creds, # User's API credentials
|
||||
signature_type=2,
|
||||
funder=funder_address,
|
||||
builder_config=builder_config # Builder's API credentials
|
||||
)
|
||||
|
||||
# You can call all methods including builder methods
|
||||
builder_trades = client.get_builder_trades()
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Learn more about the Builders Program and Relay Client here
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
***
|
||||
|
||||
## Resources
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="TypeScript Client" icon="github" href="https://github.com/Polymarket/clob-client">
|
||||
Open source TypeScript client on GitHub
|
||||
</Card>
|
||||
|
||||
<Card title="Python Client" icon="github" href="https://github.com/Polymarket/py-clob-client">
|
||||
Open source Python client for GitHub
|
||||
</Card>
|
||||
|
||||
<Card title="Rust Client" icon="github" href="https://github.com/Polymarket/rs-clob-client">
|
||||
Open source Rust client on GitHub
|
||||
</Card>
|
||||
|
||||
<Card title="TypeScript Examples" icon="code" href="https://github.com/Polymarket/clob-client/tree/main/examples">
|
||||
TypeScript client method examples
|
||||
</Card>
|
||||
|
||||
<Card title="Python Examples" icon="python" href="https://github.com/Polymarket/py-clob-client/tree/main/examples">
|
||||
Python client method examples
|
||||
</Card>
|
||||
|
||||
<Card title="Rust Examples" icon="rust" href="https://github.com/Polymarket/rs-clob-client/tree/main/examples">
|
||||
Rust client method examples
|
||||
</Card>
|
||||
|
||||
<Card title="CLOB Rest API Reference" icon="hammer" href="/api-reference/orderbook/get-order-book-summary">
|
||||
Complete REST endpoint documentation
|
||||
</Card>
|
||||
|
||||
<Card title="Web Socket API" icon="hammer" href="/developers/CLOB/websocket/wss-overview">
|
||||
Real-time market data streaming
|
||||
<Card title="Authentication" icon="lock" href="/api-reference/authentication">
|
||||
Understand L1/L2 auth and API credentials.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -35,7 +35,7 @@ Public methods require the client to initialize with the host URL and Polygon ch
|
||||
)
|
||||
|
||||
# Ready to call public methods
|
||||
markets = await client.get_markets()
|
||||
markets = client.get_markets()
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@@ -68,50 +68,121 @@ Get details for a single market by condition ID.
|
||||
async getMarket(conditionId: string): Promise<Market>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface MarketToken {
|
||||
outcome: string;
|
||||
price: number;
|
||||
token_id: string;
|
||||
winner: boolean;
|
||||
}
|
||||
<ResponseField name="accepting_order_timestamp" type="string">
|
||||
Timestamp from which the market started accepting orders, or null if not set.
|
||||
</ResponseField>
|
||||
|
||||
interface Market {
|
||||
accepting_order_timestamp: string | null;
|
||||
accepting_orders: boolean;
|
||||
active: boolean;
|
||||
archived: boolean;
|
||||
closed: boolean;
|
||||
condition_id: string;
|
||||
description: string;
|
||||
enable_order_book: boolean;
|
||||
end_date_iso: string;
|
||||
fpmm: string;
|
||||
game_start_time: string;
|
||||
icon: string;
|
||||
image: string;
|
||||
is_50_50_outcome: boolean;
|
||||
maker_base_fee: number;
|
||||
market_slug: string;
|
||||
minimum_order_size: number;
|
||||
minimum_tick_size: number;
|
||||
neg_risk: boolean;
|
||||
neg_risk_market_id: string;
|
||||
neg_risk_request_id: string;
|
||||
notifications_enabled: boolean;
|
||||
question: string;
|
||||
question_id: string;
|
||||
rewards: {
|
||||
max_spread: number;
|
||||
min_size: number;
|
||||
rates: any | null;
|
||||
};
|
||||
seconds_delay: number;
|
||||
tags: string[];
|
||||
taker_base_fee: number;
|
||||
tokens: MarketToken[];
|
||||
}
|
||||
```
|
||||
<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>
|
||||
|
||||
***
|
||||
|
||||
@@ -123,56 +194,17 @@ Get details for multiple markets paginated.
|
||||
async getMarkets(): Promise<PaginationPayload>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface PaginationPayload {
|
||||
limit: number;
|
||||
count: number;
|
||||
data: Market[];
|
||||
}
|
||||
<ResponseField name="limit" type="number">
|
||||
Maximum number of results per page.
|
||||
</ResponseField>
|
||||
|
||||
interface Market {
|
||||
accepting_order_timestamp: string | null;
|
||||
accepting_orders: boolean;
|
||||
active: boolean;
|
||||
archived: boolean;
|
||||
closed: boolean;
|
||||
condition_id: string;
|
||||
description: string;
|
||||
enable_order_book: boolean;
|
||||
end_date_iso: string;
|
||||
fpmm: string;
|
||||
game_start_time: string;
|
||||
icon: string;
|
||||
image: string;
|
||||
is_50_50_outcome: boolean;
|
||||
maker_base_fee: number;
|
||||
market_slug: string;
|
||||
minimum_order_size: number;
|
||||
minimum_tick_size: number;
|
||||
neg_risk: boolean;
|
||||
neg_risk_market_id: string;
|
||||
neg_risk_request_id: string;
|
||||
notifications_enabled: boolean;
|
||||
question: string;
|
||||
question_id: string;
|
||||
rewards: {
|
||||
max_spread: number;
|
||||
min_size: number;
|
||||
rates: any | null;
|
||||
};
|
||||
seconds_delay: number;
|
||||
tags: string[];
|
||||
taker_base_fee: number;
|
||||
tokens: MarketToken[];
|
||||
}
|
||||
<ResponseField name="count" type="number">
|
||||
Total number of markets returned.
|
||||
</ResponseField>
|
||||
|
||||
interface MarketToken {
|
||||
outcome: string;
|
||||
price: number;
|
||||
token_id: string;
|
||||
winner: boolean;
|
||||
}
|
||||
```
|
||||
<ResponseField name="data" type="Market[]">
|
||||
Array of Market objects. See `getMarket()` for the full Market structure.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
@@ -184,129 +216,38 @@ Get simplified market data paginated for faster loading.
|
||||
async getSimplifiedMarkets(): Promise<PaginationPayload>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface PaginationPayload {
|
||||
limit: number;
|
||||
count: number;
|
||||
data: SimplifiedMarket[];
|
||||
}
|
||||
<ResponseField name="limit" type="number">
|
||||
Maximum number of results per page.
|
||||
</ResponseField>
|
||||
|
||||
interface SimplifiedMarket {
|
||||
accepting_orders: boolean;
|
||||
active: boolean;
|
||||
archived: boolean;
|
||||
closed: boolean;
|
||||
condition_id: string;
|
||||
rewards: {
|
||||
rates: any | null;
|
||||
min_size: number;
|
||||
max_spread: number;
|
||||
};
|
||||
tokens: SimplifiedToken[];
|
||||
}
|
||||
<ResponseField name="count" type="number">
|
||||
Total number of markets returned.
|
||||
</ResponseField>
|
||||
|
||||
interface SimplifiedToken {
|
||||
outcome: string;
|
||||
price: number;
|
||||
token_id: string;
|
||||
}
|
||||
```
|
||||
<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>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface PaginationPayload {
|
||||
limit: number;
|
||||
count: number;
|
||||
data: Market[];
|
||||
}
|
||||
|
||||
interface Market {
|
||||
accepting_order_timestamp: string | null;
|
||||
accepting_orders: boolean;
|
||||
active: boolean;
|
||||
archived: boolean;
|
||||
closed: boolean;
|
||||
condition_id: string;
|
||||
description: string;
|
||||
enable_order_book: boolean;
|
||||
end_date_iso: string;
|
||||
fpmm: string;
|
||||
game_start_time: string;
|
||||
icon: string;
|
||||
image: string;
|
||||
is_50_50_outcome: boolean;
|
||||
maker_base_fee: number;
|
||||
market_slug: string;
|
||||
minimum_order_size: number;
|
||||
minimum_tick_size: number;
|
||||
neg_risk: boolean;
|
||||
neg_risk_market_id: string;
|
||||
neg_risk_request_id: string;
|
||||
notifications_enabled: boolean;
|
||||
question: string;
|
||||
question_id: string;
|
||||
rewards: {
|
||||
max_spread: number;
|
||||
min_size: number;
|
||||
rates: any | null;
|
||||
};
|
||||
seconds_delay: number;
|
||||
tags: string[];
|
||||
taker_base_fee: number;
|
||||
tokens: MarketToken[];
|
||||
}
|
||||
|
||||
interface MarketToken {
|
||||
outcome: string;
|
||||
price: number;
|
||||
token_id: string;
|
||||
winner: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### getSamplingSimplifiedMarkets()
|
||||
|
||||
Get simplified market data for markets eligible for sampling/liquidity rewards.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async getSamplingSimplifiedMarkets(): Promise<PaginationPayload>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface PaginationPayload {
|
||||
limit: number;
|
||||
count: number;
|
||||
data: SimplifiedMarket[];
|
||||
}
|
||||
|
||||
interface SimplifiedMarket {
|
||||
accepting_orders: boolean;
|
||||
active: boolean;
|
||||
archived: boolean;
|
||||
closed: boolean;
|
||||
condition_id: string;
|
||||
rewards: {
|
||||
rates: any | null;
|
||||
min_size: number;
|
||||
max_spread: number;
|
||||
};
|
||||
tokens: SimplifiedToken[];
|
||||
}
|
||||
|
||||
interface SimplifiedToken {
|
||||
outcome: string;
|
||||
price: number;
|
||||
token_id: string;
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Order Books and Prices
|
||||
@@ -315,6 +256,8 @@ interface SimplifiedToken {
|
||||
|
||||
### calculateMarketPrice()
|
||||
|
||||
Calculate the estimated price for a market order of a given size.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async calculateMarketPrice(
|
||||
tokenID: string,
|
||||
@@ -324,23 +267,25 @@ async calculateMarketPrice(
|
||||
): Promise<number>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
enum OrderType {
|
||||
GTC = "GTC", // Good Till Cancelled
|
||||
FOK = "FOK", // Fill or Kill
|
||||
GTD = "GTD", // Good Till Date
|
||||
FAK = "FAK", // Fill and Kill
|
||||
}
|
||||
<ResponseField name="tokenID" type="string">
|
||||
The token ID to calculate the market price for.
|
||||
</ResponseField>
|
||||
|
||||
enum Side {
|
||||
BUY = "BUY",
|
||||
SELL = "SELL",
|
||||
}
|
||||
```
|
||||
<ResponseField name="side" type="Side">
|
||||
The side of the order. One of: `BUY`, `SELL`
|
||||
</ResponseField>
|
||||
|
||||
```typescript Response theme={null}
|
||||
number // calculated market price
|
||||
```
|
||||
<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>
|
||||
|
||||
***
|
||||
|
||||
@@ -352,24 +297,41 @@ Get the order book for a specific token ID.
|
||||
async getOrderBook(tokenID: string): Promise<OrderBookSummary>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface OrderBookSummary {
|
||||
market: string;
|
||||
asset_id: string;
|
||||
timestamp: string;
|
||||
bids: OrderSummary[];
|
||||
asks: OrderSummary[];
|
||||
min_order_size: string;
|
||||
tick_size: string;
|
||||
neg_risk: boolean;
|
||||
hash: string;
|
||||
}
|
||||
<ResponseField name="market" type="string">
|
||||
The market condition ID.
|
||||
</ResponseField>
|
||||
|
||||
interface OrderSummary {
|
||||
price: string;
|
||||
size: string;
|
||||
}
|
||||
```
|
||||
<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>
|
||||
|
||||
***
|
||||
|
||||
@@ -381,16 +343,17 @@ Get order books for multiple token IDs.
|
||||
async getOrderBooks(params: BookParams[]): Promise<OrderBookSummary[]>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface BookParams {
|
||||
token_id: string;
|
||||
side: Side; // Side.BUY or Side.SELL
|
||||
}
|
||||
```
|
||||
<ResponseField name="token_id" type="string">
|
||||
The token ID to fetch the order book for.
|
||||
</ResponseField>
|
||||
|
||||
```typescript Response theme={null}
|
||||
OrderBookSummary[]
|
||||
```
|
||||
<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>
|
||||
|
||||
***
|
||||
|
||||
@@ -405,11 +368,9 @@ async getPrice(
|
||||
): Promise<any>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
{
|
||||
price: string;
|
||||
}
|
||||
```
|
||||
<ResponseField name="price" type="string">
|
||||
The current best price for the requested side.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
@@ -421,23 +382,9 @@ Get the current best prices for multiple token IDs.
|
||||
async getPrices(params: BookParams[]): Promise<PricesResponse>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface BookParams {
|
||||
token_id: string;
|
||||
side: Side; // Side.BUY or Side.SELL
|
||||
}
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface TokenPrices {
|
||||
BUY?: string;
|
||||
SELL?: string;
|
||||
}
|
||||
|
||||
type PricesResponse = {
|
||||
[tokenId: string]: TokenPrices;
|
||||
}
|
||||
```
|
||||
<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>
|
||||
|
||||
***
|
||||
|
||||
@@ -449,34 +396,23 @@ Get the midpoint price (average of best bid and best ask) for a token ID.
|
||||
async getMidpoint(tokenID: string): Promise<any>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
{
|
||||
mid: string;
|
||||
}
|
||||
```
|
||||
<ResponseField name="mid" type="string">
|
||||
The midpoint price, calculated as the average of best bid and best ask.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### getMidpoints()
|
||||
|
||||
Get the midpoint prices (average of best bid and best ask) for multiple token IDs.
|
||||
Get the midpoint prices for multiple token IDs.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async getMidpoints(params: BookParams[]): Promise<any>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface BookParams {
|
||||
token_id: string;
|
||||
side: Side; // Side is ignored
|
||||
}
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
{
|
||||
[tokenId: string]: string;
|
||||
}
|
||||
```
|
||||
<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>
|
||||
|
||||
***
|
||||
|
||||
@@ -488,34 +424,23 @@ Get the spread (difference between best ask and best bid) for a token ID.
|
||||
async getSpread(tokenID: string): Promise<SpreadResponse>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface SpreadResponse {
|
||||
spread: string;
|
||||
}
|
||||
```
|
||||
<ResponseField name="spread" type="string">
|
||||
The spread value, calculated as the difference between best ask and best bid.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### getSpreads()
|
||||
|
||||
Get the spreads (difference between best ask and best bid) for multiple token IDs.
|
||||
Get the spreads for multiple token IDs.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async getSpreads(params: BookParams[]): Promise<SpreadsResponse>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface BookParams {
|
||||
token_id: string;
|
||||
side: Side;
|
||||
}
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
type SpreadsResponse = {
|
||||
[tokenId: string]: string;
|
||||
}
|
||||
```
|
||||
<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>
|
||||
|
||||
***
|
||||
|
||||
@@ -527,30 +452,33 @@ Get historical price data for a token.
|
||||
async getPricesHistory(params: PriceHistoryFilterParams): Promise<MarketPrice[]>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface PriceHistoryFilterParams {
|
||||
market: string; // tokenID
|
||||
startTs?: number;
|
||||
endTs?: number;
|
||||
fidelity?: number;
|
||||
interval: PriceHistoryInterval;
|
||||
}
|
||||
<ResponseField name="market" type="string">
|
||||
The token ID to fetch price history for.
|
||||
</ResponseField>
|
||||
|
||||
enum PriceHistoryInterval {
|
||||
MAX = "max",
|
||||
ONE_WEEK = "1w",
|
||||
ONE_DAY = "1d",
|
||||
SIX_HOURS = "6h",
|
||||
ONE_HOUR = "1h",
|
||||
}
|
||||
```
|
||||
<ResponseField name="startTs" type="number">
|
||||
Optional start timestamp (Unix seconds) for the price history range.
|
||||
</ResponseField>
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface MarketPrice {
|
||||
t: number; // timestamp
|
||||
p: number; // price
|
||||
}
|
||||
```
|
||||
<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>
|
||||
|
||||
***
|
||||
|
||||
@@ -566,73 +494,91 @@ Get the price of the most recent trade for a token.
|
||||
async getLastTradePrice(tokenID: string): Promise<LastTradePrice>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface LastTradePrice {
|
||||
price: string;
|
||||
side: string;
|
||||
}
|
||||
```
|
||||
<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 price of the most recent trade for a token.
|
||||
Get the most recent trade prices for multiple tokens.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async getLastTradesPrices(params: BookParams[]): Promise<LastTradePriceWithToken[]>
|
||||
```
|
||||
|
||||
```typescript Params theme={null}
|
||||
interface BookParams {
|
||||
token_id: string;
|
||||
side: Side;
|
||||
}
|
||||
```
|
||||
<ResponseField name="price" type="string">
|
||||
The price of the most recent trade for the token.
|
||||
</ResponseField>
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface LastTradePriceWithToken {
|
||||
price: string;
|
||||
side: string;
|
||||
token_id: string;
|
||||
}
|
||||
```
|
||||
<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
|
||||
### getMarketTradesEvents()
|
||||
|
||||
Get recent trade events for a market.
|
||||
|
||||
```typescript Signature theme={null}
|
||||
async getMarketTradesEvents(conditionID: string): Promise<MarketTradeEvent[]>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
interface MarketTradeEvent {
|
||||
event_type: string;
|
||||
market: {
|
||||
condition_id: string;
|
||||
asset_id: string;
|
||||
question: string;
|
||||
icon: string;
|
||||
slug: string;
|
||||
};
|
||||
user: {
|
||||
address: string;
|
||||
username: string;
|
||||
profile_picture: string;
|
||||
optimized_profile_picture: string;
|
||||
pseudonym: string;
|
||||
};
|
||||
side: Side;
|
||||
size: string;
|
||||
fee_rate_bps: string;
|
||||
price: string;
|
||||
outcome: string;
|
||||
outcome_index: number;
|
||||
transaction_hash: string;
|
||||
timestamp: string;
|
||||
}
|
||||
```
|
||||
<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
|
||||
|
||||
@@ -646,9 +592,9 @@ Get the fee rate in basis points for a token.
|
||||
async getFeeRateBps(tokenID: string): Promise<number>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
number
|
||||
```
|
||||
<ResponseField name="returns" type="number">
|
||||
The fee rate in basis points for the specified token.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
@@ -660,9 +606,9 @@ Get the tick size (minimum price increment) for a market.
|
||||
async getTickSize(tokenID: string): Promise<TickSize>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
type TickSize = "0.1" | "0.01" | "0.001" | "0.0001";
|
||||
```
|
||||
<ResponseField name="returns" type="string">
|
||||
The tick size for the market. One of: `0.1`, `0.01`, `0.001`, `0.0001`
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
@@ -674,9 +620,9 @@ Check if a market uses negative risk (binary complementary tokens).
|
||||
async getNegRisk(tokenID: string): Promise<boolean>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
boolean
|
||||
```
|
||||
<ResponseField name="returns" type="boolean">
|
||||
Whether the market uses negative risk.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
@@ -690,28 +636,28 @@ Get the current server timestamp.
|
||||
async getServerTime(): Promise<number>
|
||||
```
|
||||
|
||||
```typescript Response theme={null}
|
||||
number // Unix timestamp in seconds
|
||||
```
|
||||
<ResponseField name="returns" type="number">
|
||||
Unix timestamp in seconds representing the current server time.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
## See Also
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="L1 Methods" icon="key" href="/developers/CLOB/clients/methods-l1">
|
||||
Private key authentication to create or derive API keys (L2 headers).
|
||||
<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="/developers/CLOB/clients/methods-l2">
|
||||
Manage and close orders. Creating orders requires signer.
|
||||
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
|
||||
Place orders, cancel orders, and query your trades.
|
||||
</Card>
|
||||
|
||||
<Card title="CLOB Rest API Reference" icon="hammer" href="/api-reference/orderbook/get-order-book-summary">
|
||||
Complete REST endpoint documentation
|
||||
<Card title="REST API Reference" icon="code" href="/api-reference/introduction">
|
||||
Complete REST endpoint documentation.
|
||||
</Card>
|
||||
|
||||
<Card title="Web Socket API" icon="hammer" href="/developers/CLOB/websocket/wss-overview">
|
||||
Real-time market data streaming
|
||||
<Card title="WebSocket" icon="bolt" href="/market-data/websocket/overview">
|
||||
Real-time market data streaming.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -4,27 +4,18 @@
|
||||
|
||||
# Geographic Restrictions
|
||||
|
||||
> Check geographic restrictions before placing orders on Polymarket's CLOB
|
||||
> Check geographic restrictions before placing orders on the Polymarket API
|
||||
|
||||
## Overview
|
||||
|
||||
Polymarket restricts order placement from certain geographic locations due to regulatory requirements and compliance with international sanctions.
|
||||
Before placing orders, builders should verify the location.
|
||||
Polymarket restricts order placement from certain geographic locations due to regulatory requirements and compliance with international sanctions. Before placing orders, builders should verify the location.
|
||||
|
||||
<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.
|
||||
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>
|
||||
|
||||
***
|
||||
|
||||
## Server Infrastructure
|
||||
|
||||
* **Primary Servers**: eu-west-2
|
||||
* **Closest Non-Georestricted Region**: eu-west-1
|
||||
|
||||
***
|
||||
|
||||
## Geoblock Endpoint
|
||||
|
||||
Check the geographic eligibility of the requesting IP address:
|
||||
@@ -33,14 +24,16 @@ Check the geographic eligibility of the requesting IP address:
|
||||
GET https://polymarket.com/api/geoblock
|
||||
```
|
||||
|
||||
<Note>This endpoint is on `polymarket.com`, not the API servers.</Note>
|
||||
|
||||
### Response
|
||||
|
||||
```typescript theme={null}
|
||||
```json theme={null}
|
||||
{
|
||||
"blocked": boolean;
|
||||
"ip": string;
|
||||
"country": string;
|
||||
"region": string;
|
||||
"blocked": true,
|
||||
"ip": "203.0.113.42",
|
||||
"country": "US",
|
||||
"region": "NY"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -55,43 +48,43 @@ GET https://polymarket.com/api/geoblock
|
||||
|
||||
## Blocked Countries
|
||||
|
||||
The following **33 countries** are completely restricted from placing orders on Polymarket:
|
||||
The following countries are restricted from placing orders on Polymarket. Countries marked as **close-only** can close existing positions but cannot open new ones:
|
||||
|
||||
| Country Code | Country Name |
|
||||
| ------------ | ------------------------------------ |
|
||||
| AU | Australia |
|
||||
| BE | Belgium |
|
||||
| BY | Belarus |
|
||||
| BI | Burundi |
|
||||
| CF | Central African Republic |
|
||||
| CD | Congo (Kinshasa) |
|
||||
| CU | Cuba |
|
||||
| DE | Germany |
|
||||
| ET | Ethiopia |
|
||||
| FR | France |
|
||||
| GB | United Kingdom |
|
||||
| IR | Iran |
|
||||
| IQ | Iraq |
|
||||
| IT | Italy |
|
||||
| KP | North Korea |
|
||||
| LB | Lebanon |
|
||||
| LY | Libya |
|
||||
| MM | Myanmar |
|
||||
| NI | Nicaragua |
|
||||
| PL | Poland |
|
||||
| RU | Russia |
|
||||
| SG | Singapore |
|
||||
| SO | Somalia |
|
||||
| SS | South Sudan |
|
||||
| SD | Sudan |
|
||||
| SY | Syria |
|
||||
| TH | Thailand |
|
||||
| TW | Taiwan |
|
||||
| UM | United States Minor Outlying Islands |
|
||||
| US | United States |
|
||||
| VE | Venezuela |
|
||||
| YE | Yemen |
|
||||
| ZW | Zimbabwe |
|
||||
| Country Code | Country Name | Status |
|
||||
| ------------ | ------------------------------------ | ---------- |
|
||||
| AU | Australia | Blocked |
|
||||
| BE | Belgium | Blocked |
|
||||
| BY | Belarus | Blocked |
|
||||
| BI | Burundi | Blocked |
|
||||
| CF | Central African Republic | Blocked |
|
||||
| CD | Congo (Kinshasa) | Blocked |
|
||||
| CU | Cuba | Blocked |
|
||||
| DE | Germany | Blocked |
|
||||
| ET | Ethiopia | Blocked |
|
||||
| FR | France | Blocked |
|
||||
| GB | United Kingdom | Blocked |
|
||||
| IR | Iran | Blocked |
|
||||
| IQ | Iraq | Blocked |
|
||||
| IT | Italy | Blocked |
|
||||
| KP | North Korea | Blocked |
|
||||
| LB | Lebanon | Blocked |
|
||||
| LY | Libya | Blocked |
|
||||
| MM | Myanmar | Blocked |
|
||||
| NI | Nicaragua | Blocked |
|
||||
| PL | Poland | Close-only |
|
||||
| RU | Russia | Blocked |
|
||||
| SG | Singapore | Close-only |
|
||||
| SO | Somalia | Blocked |
|
||||
| SS | South Sudan | Blocked |
|
||||
| SD | Sudan | Blocked |
|
||||
| SY | Syria | Blocked |
|
||||
| TH | Thailand | Close-only |
|
||||
| TW | Taiwan | Close-only |
|
||||
| UM | United States Minor Outlying Islands | Blocked |
|
||||
| US | United States | Blocked |
|
||||
| VE | Venezuela | Blocked |
|
||||
| YE | Yemen | Blocked |
|
||||
| ZW | Zimbabwe | Blocked |
|
||||
|
||||
***
|
||||
|
||||
@@ -108,6 +101,22 @@ In addition to fully blocked countries, the following specific regions within ot
|
||||
|
||||
***
|
||||
|
||||
## Blocking Logic
|
||||
|
||||
The geoblocking system includes:
|
||||
|
||||
1. **OFAC-Sanctioned Countries**: Countries sanctioned by the U.S. Office of Foreign Assets Control (OFAC)
|
||||
2. **Additional Regulatory Restrictions**: Countries added for specific regulatory compliance reasons
|
||||
|
||||
***
|
||||
|
||||
## Server Infrastructure
|
||||
|
||||
* **Primary Servers**: eu-west-2
|
||||
* **Closest Non-Georestricted Region**: eu-west-1
|
||||
|
||||
***
|
||||
|
||||
## Usage Examples
|
||||
|
||||
<Tabs>
|
||||
@@ -154,3 +163,31 @@ In addition to fully blocked countries, the following specific regions within ot
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
***
|
||||
|
||||
## Why These Restrictions?
|
||||
|
||||
Geographic restrictions are implemented to ensure compliance with:
|
||||
|
||||
* International sanctions and embargoes
|
||||
* Local financial regulations
|
||||
* Gambling and prediction market laws
|
||||
* Anti-money laundering (AML) requirements
|
||||
* Know Your Customer (KYC) regulations
|
||||
|
||||
If you believe you are incorrectly restricted or have questions about geographic availability, please contact [Polymarket Support](https://polymarket.com/support).
|
||||
|
||||
***
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Authentication" icon="key" href="/api-reference/authentication">
|
||||
Learn how to authenticate trading requests.
|
||||
</Card>
|
||||
|
||||
<Card title="Place Orders" icon="plus" href="/trading/quickstart">
|
||||
Start placing orders (from eligible regions).
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -2,55 +2,199 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# CLOB Introduction
|
||||
# Overview
|
||||
|
||||
Welcome to the Polymarket Order Book API! This documentation provides overviews, explanations, examples, and annotations to simplify interaction with the order book. The following sections detail the Polymarket Order Book and the API usage.
|
||||
> Trading on the Polymarket CLOB
|
||||
|
||||
## System
|
||||
Polymarket's CLOB (Central Limit Order Book) is a hybrid-decentralized trading system — offchain order matching with onchain settlement via the [Exchange contract](https://github.com/Polymarket/ctf-exchange/tree/main/src) ([audited by Chainsecurity](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)). All trading is non-custodial. Orders are [EIP-712](https://eips.ethereum.org/EIPS/eip-712) signed messages, and matched trades settle atomically on Polygon. The operator cannot set prices or execute unauthorized trades — users can always cancel orders onchain independently.
|
||||
|
||||
Polymarket's Order Book, or CLOB (Central Limit Order Book), is hybrid-decentralized. It includes an operator for off-chain matching/ordering, with settlement executed on-chain, non-custodially, via signed order messages.
|
||||
We recommend using the open-source SDK clients, which handle order signing, authentication, and submission:
|
||||
|
||||
The exchange uses a custom Exchange contract facilitating atomic swaps between binary Outcome Tokens (CTF ERC1155 assets and ERC20 PToken assets) and collateral assets (ERC20), following signed limit orders. Designed for binary markets, the contract enables complementary tokens to match across a unified order book.
|
||||
<CardGroup cols={2}>
|
||||
<Card title="TypeScript Client" icon="github" href="https://github.com/Polymarket/clob-client">
|
||||
<p className="font-mono text-[0.8rem]">
|
||||
npm install @polymarket/clob-client
|
||||
</p>
|
||||
</Card>
|
||||
|
||||
Orders are EIP712-signed structured data. Matched orders have one maker and one or more takers, with price improvements benefiting the taker. The operator handles off-chain order management and submits matched trades to the blockchain for on-chain execution.
|
||||
<Card title="Python Client" icon="github" href="https://github.com/Polymarket/py-clob-client">
|
||||
<p className="font-mono text-[0.8rem]">pip install py-clob-client</p>
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## API
|
||||
<Info>
|
||||
You can also use the REST API directly, but you'll need to manage [EIP-712
|
||||
order
|
||||
signing](https://github.com/Polymarket/clob-client/blob/main/src/signing/eip712.ts)
|
||||
and [HMAC authentication
|
||||
headers](https://github.com/Polymarket/clob-client/blob/main/src/signing/hmac.ts)
|
||||
yourself. See [REST API Headers](#rest-api-headers) below.
|
||||
</Info>
|
||||
|
||||
The Polymarket Order Book API enables market makers and traders to programmatically manage market orders. Orders of any amount can be created, listed, fetched, or read from the market order books. Data includes all available markets, market prices, and order history via REST and WebSocket endpoints.
|
||||
***
|
||||
|
||||
## Security
|
||||
## Authentication
|
||||
|
||||
Polymarket's Exchange contract has been audited by Chainsecurity ([View Audit](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)).
|
||||
The CLOB uses two levels of authentication:
|
||||
|
||||
The operator's privileges are limited to order matching, non-censorship, and ensuring correct ordering. Operators can't set prices or execute unauthorized trades. Users can cancel orders on-chain independently if trust issues arise.
|
||||
| Level | Method | Purpose |
|
||||
| ------ | ------------------------------- | ----------------------------------------- |
|
||||
| **L1** | EIP-712 signature (private key) | Create or derive API credentials |
|
||||
| **L2** | HMAC-SHA256 (API credentials) | Place orders, cancel orders, query trades |
|
||||
|
||||
## Fees
|
||||
You use your private key once to derive **L2 credentials** (API key, secret, passphrase), which authenticate all subsequent trading requests.
|
||||
|
||||
### Schedule
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { ClobClient } from "@polymarket/clob-client";
|
||||
import { Wallet } from "ethers"; // v5.8.0
|
||||
|
||||
> Subject to change
|
||||
const signer = new Wallet(process.env.PRIVATE_KEY);
|
||||
|
||||
| Volume Level | Maker Fee Base Rate (bps) | Taker Fee Base Rate (bps) |
|
||||
| ------------ | ------------------------- | ------------------------- |
|
||||
| >0 USDC | 0 | 0 |
|
||||
// Derive L2 API credentials
|
||||
const tempClient = new ClobClient("https://clob.polymarket.com", 137, signer);
|
||||
const apiCreds = await tempClient.createOrDeriveApiKey();
|
||||
```
|
||||
|
||||
### Overview
|
||||
```python Python theme={null}
|
||||
from py_clob_client.client import ClobClient
|
||||
import os
|
||||
|
||||
Fees apply symmetrically in output assets (proceeds). This symmetry ensures fairness and market integrity. Fees are calculated differently depending on whether you are buying or selling:
|
||||
private_key = os.getenv("PRIVATE_KEY")
|
||||
|
||||
* **Selling outcome tokens (base) for collateral (quote):**
|
||||
# Derive L2 API credentials
|
||||
temp_client = ClobClient("https://clob.polymarket.com", key=private_key, chain_id=137)
|
||||
api_creds = temp_client.create_or_derive_api_creds()
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
$$
|
||||
feeQuote = baseRate \times \min(price, 1 - price) \times size
|
||||
$$
|
||||
***
|
||||
|
||||
* **Buying outcome tokens (base) with collateral (quote):**
|
||||
## Signature Types
|
||||
|
||||
$$
|
||||
feeBase = baseRate \times \min(price, 1 - price) \times \frac{size}{price}
|
||||
$$
|
||||
When initializing the trading client, you must specify your wallet's **signature type** and **funder address**:
|
||||
|
||||
## Additional Resources
|
||||
| Wallet Type | ID | When to Use | Funder Address |
|
||||
| ---------------- | --- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
|
||||
| **EOA** | `0` | Standalone wallet — you pay your own gas (POL for gas) | Your EOA wallet address |
|
||||
| **POLY\_PROXY** | `1` | Polymarket account via Magic Link (email/Google login). Requires [exported private key](https://polymarket.com/settings) from Polymarket.com | Your proxy wallet address |
|
||||
| **GNOSIS\_SAFE** | `2` | Polymarket account via browser wallet (MetaMask, Rabby) or embedded wallet (Privy, Turnkey). Most common type | Your proxy wallet address |
|
||||
|
||||
* [Exchange contract source code](https://github.com/Polymarket/ctf-exchange/tree/main/src)
|
||||
* [Exchange contract documentation](https://github.com/Polymarket/ctf-exchange/blob/main/docs/Overview.md)
|
||||
<Note>
|
||||
If you have a Polymarket.com account, your funds are in a proxy wallet visible
|
||||
in the profile dropdown. Use type `1` or `2`. Type `0` is for standalone EOA
|
||||
wallets only.
|
||||
</Note>
|
||||
|
||||
### Initialize the Trading Client
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const client = new ClobClient(
|
||||
"https://clob.polymarket.com",
|
||||
137,
|
||||
signer,
|
||||
apiCreds,
|
||||
2, // GNOSIS_SAFE
|
||||
"0x...", // Your proxy wallet address
|
||||
);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
client = ClobClient(
|
||||
"https://clob.polymarket.com",
|
||||
key=private_key,
|
||||
chain_id=137,
|
||||
creds=api_creds,
|
||||
signature_type=2, # GNOSIS_SAFE
|
||||
funder="0x..." # Your proxy wallet address
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## REST API Headers
|
||||
|
||||
If you're using the REST API directly (without the SDK), you need to attach authentication headers to each request.
|
||||
|
||||
**L1 Headers** — for creating or deriving API credentials:
|
||||
|
||||
| Header | Description |
|
||||
| ---------------- | ------------------- |
|
||||
| `POLY_ADDRESS` | Your wallet address |
|
||||
| `POLY_SIGNATURE` | EIP-712 signature |
|
||||
| `POLY_TIMESTAMP` | Unix timestamp |
|
||||
| `POLY_NONCE` | Request nonce |
|
||||
|
||||
**L2 Headers** — for all trading operations (orders, cancellations, queries):
|
||||
|
||||
| Header | Description |
|
||||
| ----------------- | ------------------------------------ |
|
||||
| `POLY_ADDRESS` | Your wallet address |
|
||||
| `POLY_SIGNATURE` | HMAC-SHA256 signature of the request |
|
||||
| `POLY_TIMESTAMP` | Unix timestamp |
|
||||
| `POLY_API_KEY` | Your API key |
|
||||
| `POLY_PASSPHRASE` | Your API passphrase |
|
||||
|
||||
<Note>
|
||||
Even with L2 authentication, methods that create orders still require the
|
||||
user's private key for EIP-712 order payload signing. L2 credentials
|
||||
authenticate the request, but the order itself must be signed by the key.
|
||||
</Note>
|
||||
|
||||
***
|
||||
|
||||
## Client Methods
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Public Methods" icon="globe" href="/trading/clients/public">
|
||||
Market data, orderbooks, prices, and spreads — no auth required.
|
||||
</Card>
|
||||
|
||||
<Card title="L1 Methods" icon="key" href="/trading/clients/l1">
|
||||
Sign orders and derive API credentials with your private key.
|
||||
</Card>
|
||||
|
||||
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
|
||||
Place orders, cancel orders, query trades, and manage notifications.
|
||||
</Card>
|
||||
|
||||
<Card title="Builder Methods" icon="hammer" href="/trading/clients/builder">
|
||||
Track attributed trades and manage builder credentials.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
***
|
||||
|
||||
## What's in This Section
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Quickstart" icon="bolt" href="/trading/quickstart">
|
||||
Place your first order end-to-end
|
||||
</Card>
|
||||
|
||||
<Card title="Orderbook" icon="chart-bar" href="/trading/orderbook">
|
||||
Reading the orderbook, prices, spreads, and midpoints
|
||||
</Card>
|
||||
|
||||
<Card title="Orders" icon="list-check" href="/trading/orders/create">
|
||||
Order types, tick sizes, creating, cancelling, and querying orders
|
||||
</Card>
|
||||
|
||||
<Card title="Fees" icon="receipt" href="/trading/fees">
|
||||
Fee structure, fee-enabled markets, and maker rebates
|
||||
</Card>
|
||||
|
||||
<Card title="Gasless Transactions" icon="gas-pump" href="/trading/gasless">
|
||||
Execute onchain operations without paying gas
|
||||
</Card>
|
||||
|
||||
<Card title="CTF Tokens" icon="coins" href="/trading/ctf/overview">
|
||||
Split, merge, and redeem outcome tokens
|
||||
</Card>
|
||||
|
||||
<Card title="Bridge" icon="bridge" href="/trading/bridge/deposit">
|
||||
Deposit and withdraw funds across chains
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -2,172 +2,328 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Cancel Orders(s)
|
||||
# Cancel Order
|
||||
|
||||
> Multiple endpoints to cancel a single order, multiple orders, all orders or all orders from a single market.
|
||||
> Cancel single, multiple, or all open orders
|
||||
|
||||
# Cancel an single Order
|
||||
All cancel endpoints require [L2 authentication](/trading/overview#authentication). The response always includes `canceled` (list of cancelled order IDs) and `not_canceled` (map of order IDs to failure reasons).
|
||||
|
||||
<Tip> This endpoint requires a L2 Header. </Tip>
|
||||
***
|
||||
|
||||
Cancel an order.
|
||||
|
||||
**HTTP REQUEST**
|
||||
|
||||
`DELETE /<clob-endpoint>/order`
|
||||
|
||||
### Request Payload Parameters
|
||||
|
||||
| Name | Required | Type | Description |
|
||||
| ------- | -------- | ------ | --------------------- |
|
||||
| orderID | yes | string | ID of order to cancel |
|
||||
|
||||
### Response Format
|
||||
|
||||
| Name | Type | Description |
|
||||
| ------------- | --------- | -------------------------------------------------------------------------- |
|
||||
| canceled | string\[] | list of canceled orders |
|
||||
| not\_canceled | {} | a order id -> reason map that explains why that order couldn't be canceled |
|
||||
## Cancel a Single Order
|
||||
|
||||
<CodeGroup>
|
||||
```python Python theme={null}
|
||||
resp = client.cancel(order_id="0x38a73eed1e6d177545e9ab027abddfb7e08dbe975fa777123b1752d203d6ac88")
|
||||
print(resp)
|
||||
```typescript TypeScript theme={null}
|
||||
const resp = await client.cancelOrder("0xb816482a...");
|
||||
console.log(resp);
|
||||
// { canceled: ["0xb816482a..."], not_canceled: {} }
|
||||
```
|
||||
|
||||
```javascript Typescript theme={null}
|
||||
async function main() {
|
||||
// Send it to the server
|
||||
const resp = await clobClient.cancelOrder({
|
||||
orderID:
|
||||
"0x38a73eed1e6d177545e9ab027abddfb7e08dbe975fa777123b1752d203d6ac88",
|
||||
});
|
||||
console.log(resp);
|
||||
console.log(`Done!`);
|
||||
}
|
||||
main();
|
||||
```python Python theme={null}
|
||||
resp = client.cancel(order_id="0xb816482a...")
|
||||
print(resp)
|
||||
# {"canceled": ["0xb816482a..."], "not_canceled": {}}
|
||||
```
|
||||
|
||||
```bash REST theme={null}
|
||||
curl -X DELETE "https://clob.polymarket.com/order" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "POLY_ADDRESS: ..." \
|
||||
-H "POLY_SIGNATURE: ..." \
|
||||
-H "POLY_TIMESTAMP: ..." \
|
||||
-H "POLY_API_KEY: ..." \
|
||||
-H "POLY_PASSPHRASE: ..." \
|
||||
-d '{"orderID": "0xb816482a..."}'
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
# Cancel Multiple Orders
|
||||
***
|
||||
|
||||
<Tip> This endpoint requires a L2 Header. </Tip>
|
||||
|
||||
**HTTP REQUEST**
|
||||
|
||||
`DELETE /<clob-endpoint>/orders`
|
||||
|
||||
### Request Payload Parameters
|
||||
|
||||
| Name | Required | Type | Description |
|
||||
| ---- | -------- | --------- | --------------------------- |
|
||||
| null | yes | string\[] | IDs of the orders to cancel |
|
||||
|
||||
### Response Format
|
||||
|
||||
| Name | Type | Description |
|
||||
| ------------- | --------- | -------------------------------------------------------------------------- |
|
||||
| canceled | string\[] | list of canceled orders |
|
||||
| not\_canceled | {} | a order id -> reason map that explains why that order couldn't be canceled |
|
||||
## Cancel Multiple Orders
|
||||
|
||||
<CodeGroup>
|
||||
```python Python theme={null}
|
||||
resp = client.cancel_orders(["0x38a73eed1e6d177545e9ab027abddfb7e08dbe975fa777123b1752d203d6ac88", "0xaaaa..."])
|
||||
print(resp)
|
||||
```typescript TypeScript theme={null}
|
||||
const resp = await client.cancelOrders(["0xb816482a...", "0xc927593b..."]);
|
||||
```
|
||||
|
||||
```javascript Typescript theme={null}
|
||||
async function main() {
|
||||
// Send it to the server
|
||||
const resp = await clobClient.cancelOrders([
|
||||
"0x38a73eed1e6d177545e9ab027abddfb7e08dbe975fa777123b1752d203d6ac88",
|
||||
"0xaaaa...",
|
||||
]);
|
||||
console.log(resp);
|
||||
console.log(`Done!`);
|
||||
}
|
||||
main();
|
||||
```python Python theme={null}
|
||||
resp = client.cancel_orders([
|
||||
"0xb816482a...",
|
||||
"0xc927593b...",
|
||||
])
|
||||
```
|
||||
|
||||
```bash REST theme={null}
|
||||
curl -X DELETE "https://clob.polymarket.com/orders" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "POLY_ADDRESS: ..." \
|
||||
-H "POLY_SIGNATURE: ..." \
|
||||
-H "POLY_TIMESTAMP: ..." \
|
||||
-H "POLY_API_KEY: ..." \
|
||||
-H "POLY_PASSPHRASE: ..." \
|
||||
-d '["0xb816482a...", "0xc927593b..."]'
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
# Cancel ALL Orders
|
||||
***
|
||||
|
||||
<Tip> This endpoint requires a L2 Header. </Tip>
|
||||
## Cancel All Orders
|
||||
|
||||
Cancel all open orders posted by a user.
|
||||
|
||||
**HTTP REQUEST**
|
||||
|
||||
`DELETE /<clob-endpoint>/cancel-all`
|
||||
|
||||
### Response Format
|
||||
|
||||
| Name | Type | Description |
|
||||
| ------------- | --------- | -------------------------------------------------------------------------- |
|
||||
| canceled | string\[] | list of canceled orders |
|
||||
| not\_canceled | {} | a order id -> reason map that explains why that order couldn't be canceled |
|
||||
Cancel every open order across all markets:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const resp = await client.cancelAll();
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
resp = client.cancel_all()
|
||||
print(resp)
|
||||
print("Done!")
|
||||
```
|
||||
|
||||
```javascript Typescript theme={null}
|
||||
async function main() {
|
||||
const resp = await clobClient.cancelAll();
|
||||
console.log(resp);
|
||||
console.log(`Done!`);
|
||||
}
|
||||
|
||||
main();
|
||||
```bash REST theme={null}
|
||||
curl -X DELETE "https://clob.polymarket.com/cancel-all" \
|
||||
-H "POLY_ADDRESS: ..." \
|
||||
-H "POLY_SIGNATURE: ..." \
|
||||
-H "POLY_TIMESTAMP: ..." \
|
||||
-H "POLY_API_KEY: ..." \
|
||||
-H "POLY_PASSPHRASE: ..."
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
# Cancel orders from market
|
||||
***
|
||||
|
||||
<Tip> This endpoint requires a L2 Header. </Tip>
|
||||
## Cancel by Market
|
||||
|
||||
Cancel orders from market.
|
||||
|
||||
**HTTP REQUEST**
|
||||
|
||||
`DELETE /<clob-endpoint>/cancel-market-orders`
|
||||
|
||||
### Request Payload Parameters
|
||||
|
||||
| Name | Required | Type | Description |
|
||||
| --------- | -------- | ------ | -------------------------- |
|
||||
| market | no | string | condition id of the market |
|
||||
| asset\_id | no | string | id of the asset/token |
|
||||
|
||||
### Response Format
|
||||
|
||||
| Name | Type | Description |
|
||||
| ------------- | --------- | -------------------------------------------------------------------------- |
|
||||
| canceled | string\[] | list of canceled orders |
|
||||
| not\_canceled | {} | a order id -> reason map that explains why that order couldn't be canceled |
|
||||
Cancel all orders for a specific market, optionally filtered to a single token. Both `market` and `asset_id` are optional — omit both to cancel all orders.
|
||||
|
||||
<CodeGroup>
|
||||
```python Python theme={null}
|
||||
resp = client.cancel_market_orders(market="0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af", asset_id="52114319501245915516055106046884209969926127482827954674443846427813813222426")
|
||||
print(resp)
|
||||
|
||||
```typescript TypeScript theme={null}
|
||||
const resp = await client.cancelMarketOrders({
|
||||
market: "0xbd31dc8a...", // optional: condition ID
|
||||
asset_id: "52114319501245...", // optional: specific token
|
||||
});
|
||||
```
|
||||
|
||||
```javascript Typescript theme={null}
|
||||
async function main() {
|
||||
// Send it to the server
|
||||
const resp = await clobClient.cancelMarketOrders({
|
||||
market:
|
||||
"0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
|
||||
asset_id:
|
||||
"52114319501245915516055106046884209969926127482827954674443846427813813222426",
|
||||
});
|
||||
console.log(resp);
|
||||
console.log(`Done!`);
|
||||
}
|
||||
main();
|
||||
```python Python theme={null}
|
||||
resp = client.cancel_market_orders(
|
||||
market="0xbd31dc8a...",
|
||||
asset_id="52114319501245...", # optional
|
||||
)
|
||||
```
|
||||
|
||||
```bash REST theme={null}
|
||||
curl -X DELETE "https://clob.polymarket.com/cancel-market-orders" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "POLY_ADDRESS: ..." \
|
||||
-H "POLY_SIGNATURE: ..." \
|
||||
-H "POLY_TIMESTAMP: ..." \
|
||||
-H "POLY_API_KEY: ..." \
|
||||
-H "POLY_PASSPHRASE: ..." \
|
||||
-d '{"market": "0xbd31dc8a...", "asset_id": "52114319501245..."}'
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Onchain Cancellation
|
||||
|
||||
If the API is unavailable, you can cancel orders directly on the [Exchange contract](https://github.com/Polymarket/ctf-exchange/tree/main/src) by calling `cancelOrder(Order order)` onchain. Pass the full order struct that was signed when placing the order.
|
||||
|
||||
Use the `CTFExchange` or `NegRiskCTFExchange` contract depending on the market type. See [Contract Addresses](/resources/contract-addresses) for addresses.
|
||||
|
||||
This is a fallback mechanism — API cancellation is instant while onchain cancellation requires a transaction.
|
||||
|
||||
***
|
||||
|
||||
## Querying Orders
|
||||
|
||||
### Get a Single Order
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const order = await client.getOrder("0xb816482a...");
|
||||
console.log(order.status, order.size_matched);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
order = client.get_order("0xb816482a...")
|
||||
print(order["status"], order["size_matched"])
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Get Open Orders
|
||||
|
||||
Retrieve all open orders, optionally filtered by market or token:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// All open orders
|
||||
const orders = await client.getOpenOrders();
|
||||
|
||||
// Filtered by market
|
||||
const marketOrders = await client.getOpenOrders({
|
||||
market: "0xbd31dc8a...",
|
||||
});
|
||||
|
||||
// Filtered by token
|
||||
const tokenOrders = await client.getOpenOrders({
|
||||
asset_id: "52114319501245...",
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OpenOrderParams
|
||||
|
||||
# All open orders
|
||||
orders = client.get_orders()
|
||||
|
||||
# Filtered by market
|
||||
market_orders = client.get_orders(
|
||||
OpenOrderParams(market="0xbd31dc8a...")
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### OpenOrder Object
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------ | --------- | ------------------------------------------ |
|
||||
| `id` | string | Order ID |
|
||||
| `status` | string | Current order status |
|
||||
| `market` | string | Condition ID |
|
||||
| `asset_id` | string | Token ID |
|
||||
| `side` | string | `BUY` or `SELL` |
|
||||
| `original_size` | string | Size at placement |
|
||||
| `size_matched` | string | Amount filled |
|
||||
| `price` | string | Limit price |
|
||||
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
|
||||
| `order_type` | string | Order type (GTC, GTD, FOK, FAK) |
|
||||
| `maker_address` | string | Funder address |
|
||||
| `owner` | string | API key of the order owner |
|
||||
| `associate_trades` | string\[] | Trade IDs this order has been included in |
|
||||
| `expiration` | string | Unix expiration timestamp (`0` if none) |
|
||||
| `created_at` | string | Unix creation timestamp |
|
||||
|
||||
***
|
||||
|
||||
## Trade History
|
||||
|
||||
When an order is matched, it creates a trade. Trades progress through these statuses:
|
||||
|
||||
| Status | Terminal | Description |
|
||||
| ----------- | -------- | --------------------------------------- |
|
||||
| `MATCHED` | No | Matched and sent for onchain submission |
|
||||
| `MINED` | No | Mined on the chain, no finality yet |
|
||||
| `CONFIRMED` | Yes | Achieved finality — trade successful |
|
||||
| `RETRYING` | No | Transaction failed — being retried |
|
||||
| `FAILED` | Yes | Failed permanently |
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// All trades
|
||||
const trades = await client.getTrades();
|
||||
|
||||
// Filtered by market
|
||||
const marketTrades = await client.getTrades({
|
||||
market: "0xbd31dc8a...",
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import TradeParams
|
||||
|
||||
trades = client.get_trades()
|
||||
|
||||
market_trades = client.get_trades(
|
||||
TradeParams(market="0xbd31dc8a...")
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Additional filter parameters: `id`, `maker_address`, `asset_id`, `before`, `after`.
|
||||
|
||||
For large result sets, use the paginated variant:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const page = await client.getTradesPaginated({ market: "0xbd31dc8a..." });
|
||||
console.log(page.trades, page.count); // trades array + total count
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
page = client.get_trades_paginated(TradeParams(market="0xbd31dc8a..."))
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Trade Object
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------ | ------------- | ------------------------------------ |
|
||||
| `id` | string | Trade ID |
|
||||
| `taker_order_id` | string | Taker order hash |
|
||||
| `market` | string | Condition ID |
|
||||
| `asset_id` | string | Token ID |
|
||||
| `side` | string | `BUY` or `SELL` |
|
||||
| `size` | string | Trade size |
|
||||
| `price` | string | Execution price |
|
||||
| `fee_rate_bps` | string | Fee rate in basis points |
|
||||
| `status` | string | Trade status (see table above) |
|
||||
| `match_time` | string | Unix timestamp when matched |
|
||||
| `last_update` | string | Unix timestamp of last status change |
|
||||
| `outcome` | string | Human-readable outcome (e.g., "Yes") |
|
||||
| `maker_address` | string | Maker's funder address |
|
||||
| `owner` | string | API key of the trade owner |
|
||||
| `transaction_hash` | string | Onchain transaction hash |
|
||||
| `bucket_index` | number | Index for trade reconciliation |
|
||||
| `trader_side` | string | `TAKER` or `MAKER` |
|
||||
| `maker_orders` | MakerOrder\[] | Maker orders that filled this trade |
|
||||
|
||||
<Note>
|
||||
A single trade can be split across multiple onchain transactions due to gas
|
||||
limits. Use `bucket_index` and `match_time` to reconcile related transactions
|
||||
back to a single logical trade.
|
||||
</Note>
|
||||
|
||||
***
|
||||
|
||||
## Order Scoring
|
||||
|
||||
Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Single order
|
||||
const scoring = await client.isOrderScoring({ orderId: "0x..." });
|
||||
|
||||
// Multiple orders
|
||||
const batch = await client.areOrdersScoring({
|
||||
orderIds: ["0x...", "0x..."],
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OrderScoringParams, OrdersScoringParams
|
||||
|
||||
scoring = client.is_order_scoring(
|
||||
OrderScoringParams(orderId="0x...")
|
||||
)
|
||||
|
||||
batch = client.are_orders_scoring(
|
||||
OrdersScoringParams(orderIds=["0x...", "0x..."])
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Order Attribution" icon="tag" href="/trading/orders/attribution">
|
||||
Attribute orders to your builder account for volume credit
|
||||
</Card>
|
||||
|
||||
<Card title="Fees" icon="receipt" href="/trading/fees">
|
||||
Understand fee structures and maker rebates
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -2,95 +2,462 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Check Order Reward Scoring
|
||||
# Overview
|
||||
|
||||
> Check if an order is eligble or scoring for Rewards purposes
|
||||
> Order types, tick sizes, and querying orders
|
||||
|
||||
<Tip> This endpoint requires a L2 Header. </Tip>
|
||||
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
|
||||
|
||||
Returns a boolean value where it is indicated if an order is scoring or not.
|
||||
The underlying order primitive is structured, hashed, and signed using the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) standard, then executed onchain via the Exchange contract. Preparing orders manually is involved, so we recommend using the open-source [TypeScript](https://github.com/Polymarket/clob-client) or [Python](https://github.com/Polymarket/py-clob-client) SDK clients, which handle signing and submission for you.
|
||||
|
||||
**HTTP REQUEST**
|
||||
<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>
|
||||
|
||||
`GET /<clob-endpoint>/order-scoring?order_id={...}`
|
||||
***
|
||||
|
||||
### Request Parameters
|
||||
## Order Types
|
||||
|
||||
| Name | Required | Type | Description |
|
||||
| ------- | -------- | ------ | ------------------------------------ |
|
||||
| orderId | yes | string | id of order to get information about |
|
||||
| Type | Behavior | Use Case |
|
||||
| ---------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------- |
|
||||
| **GTC** (Good-Til-Cancelled) | Rests on the book until filled or cancelled | Default for passive limit orders |
|
||||
| **GTD** (Good-Til-Date) | Active until a specified expiration time (UTC seconds timestamp), unless filled or cancelled first | Auto-expire orders before known events |
|
||||
| **FOK** (Fill-Or-Kill) | Must be filled immediately and entirely, or the whole order is cancelled | All-or-nothing execution |
|
||||
| **FAK** (Fill-And-Kill) | Fills as many shares as available immediately, then cancels any unfilled remainder | Partial immediate execution |
|
||||
|
||||
### Response Format
|
||||
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
|
||||
* **BUY**: specify the dollar amount you want to spend
|
||||
* **SELL**: specify the number of shares you want to sell
|
||||
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ------------- | ------------------ |
|
||||
| null | OrdersScoring | order scoring data |
|
||||
<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>
|
||||
|
||||
An `OrdersScoring` object is of the form:
|
||||
### Post-Only Orders
|
||||
|
||||
| Name | Type | Description |
|
||||
| ------- | ------- | ---------------------------------------- |
|
||||
| scoring | boolean | indicates if the order is scoring or not |
|
||||
Post-only orders are limit orders that will only rest on the book and not match immediately on entry.
|
||||
|
||||
# Check if some orders are scoring
|
||||
* If a post-only order would cross the spread (i.e., it is marketable), it will be **rejected** rather than executed.
|
||||
* Post-only **cannot** be combined with market order types (FOK or FAK). If `postOnly = true` is sent with a market order type, the order will be rejected.
|
||||
* Post-only can only be used with **GTC** and **GTD** order types.
|
||||
|
||||
> This endpoint requires a L2 Header.
|
||||
***
|
||||
|
||||
Returns to a dictionary with boolean value where it is indicated if an order is scoring or not.
|
||||
## Tick Sizes
|
||||
|
||||
**HTTP REQUEST**
|
||||
Markets have different minimum price increments (tick sizes). Your order price must conform to the market's tick size, or the order will be rejected.
|
||||
|
||||
`POST /<clob-endpoint>/orders-scoring`
|
||||
| Tick Size | Price Precision | Example Prices |
|
||||
| --------- | --------------- | ---------------------- |
|
||||
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
|
||||
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
|
||||
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
|
||||
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
|
||||
|
||||
### Request Parameters
|
||||
Retrieve the tick size for a market using the SDK:
|
||||
|
||||
| Name | Required | Type | Description |
|
||||
| -------- | -------- | --------- | ------------------------------------------ |
|
||||
| orderIds | yes | string\[] | ids of the orders to get information about |
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const tickSize = await client.getTickSize(tokenID);
|
||||
// Returns: "0.1" | "0.01" | "0.001" | "0.0001"
|
||||
```
|
||||
|
||||
### Response Format
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ------------- | ------------------- |
|
||||
| null | OrdersScoring | orders scoring data |
|
||||
|
||||
An `OrdersScoring` object is a dictionary that indicates the order by if it score.
|
||||
|
||||
<RequestExample>
|
||||
```python Python theme={null}
|
||||
tick_size = client.get_tick_size(token_id)
|
||||
# Returns: "0.1" | "0.01" | "0.001" | "0.0001"
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Tip>
|
||||
You can also check the `minimum_tick_size` field on a market object returned
|
||||
by the [Markets API](/market-data/fetching-markets).
|
||||
</Tip>
|
||||
|
||||
***
|
||||
|
||||
## Negative Risk
|
||||
|
||||
Multi-outcome events (e.g., "Who will win the election?" with 3+ candidates) use a different exchange contract called the **Neg Risk CTF Exchange**. When placing orders on these markets, you must pass `negRisk: true` in the order options.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const response = await client.createAndPostOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
price: 0.5,
|
||||
size: 10,
|
||||
side: Side.BUY,
|
||||
},
|
||||
{
|
||||
tickSize: "0.01",
|
||||
negRisk: true, // Required for multi-outcome markets
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
response = client.create_and_post_order(
|
||||
OrderArgs(
|
||||
token_id="TOKEN_ID",
|
||||
price=0.50,
|
||||
size=10,
|
||||
side=BUY,
|
||||
),
|
||||
options={
|
||||
"tick_size": "0.01",
|
||||
"neg_risk": True, # Required for multi-outcome markets
|
||||
}
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const isNegRisk = await client.getNegRisk(tokenID);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
is_neg_risk = client.get_neg_risk(token_id)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Allowances
|
||||
|
||||
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
|
||||
|
||||
* **Buying**: the funder must have set a **USDC.e** allowance greater than or equal to the spending amount.
|
||||
* **Selling**: the funder must have set a **conditional token** allowance greater than or equal to the selling amount.
|
||||
|
||||
This allows the Exchange contract to execute settlement according to your signed order instructions.
|
||||
|
||||
***
|
||||
|
||||
## Validity Checks
|
||||
|
||||
Orders are continually monitored to make sure they remain valid. This includes tracking:
|
||||
|
||||
* Underlying balances
|
||||
* Allowances
|
||||
* Onchain order cancellations
|
||||
|
||||
<Warning>
|
||||
Any maker caught intentionally abusing these checks will be blacklisted.
|
||||
</Warning>
|
||||
|
||||
There are also limits on order placement per market. You can only place orders that sum to less than or equal to your available balance for each market. For example, if you have 500 USDC.e in your funding wallet, you can place one order to buy 1000 YES at \$0.50 — but any additional buy orders in that market will be rejected since your entire balance is reserved for the first order.
|
||||
|
||||
The max size you can place for an order is:
|
||||
|
||||
$$
|
||||
\text{maxOrderSize} = \text{underlyingAssetBalance} - \sum(\text{orderSize} - \text{orderFillAmount})
|
||||
$$
|
||||
|
||||
***
|
||||
|
||||
## Querying Orders
|
||||
|
||||
All query endpoints require [L2 authentication](/api-reference/authentication).
|
||||
|
||||
### Get a Single Order
|
||||
|
||||
Retrieve details for a specific order by its ID:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const order = await client.getOrder("0xb816482a...");
|
||||
console.log(order);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
order = client.get_order("0xb816482a...")
|
||||
print(order)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Get Open Orders
|
||||
|
||||
Retrieve your open orders, optionally filtered by market or asset:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// All open orders
|
||||
const orders = await client.getOpenOrders();
|
||||
|
||||
// Filtered by market
|
||||
const marketOrders = await client.getOpenOrders({
|
||||
market: "0xbd31dc8a...",
|
||||
});
|
||||
|
||||
// Filtered by asset
|
||||
const assetOrders = await client.getOpenOrders({
|
||||
asset_id: "52114319501245...",
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OpenOrderParams
|
||||
|
||||
# All open orders
|
||||
orders = client.get_orders()
|
||||
|
||||
# Filtered by market
|
||||
market_orders = client.get_orders(
|
||||
OpenOrderParams(
|
||||
market="0xbd31dc8a...",
|
||||
)
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### OpenOrder Object
|
||||
|
||||
Each order returned contains these fields:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------ | --------- | ------------------------------------------------------------ |
|
||||
| `id` | string | Order ID |
|
||||
| `status` | string | Current order status |
|
||||
| `market` | string | Market ID (condition ID) |
|
||||
| `asset_id` | string | Token ID |
|
||||
| `side` | string | `BUY` or `SELL` |
|
||||
| `original_size` | string | Original order size at placement |
|
||||
| `size_matched` | string | Amount that has been filled |
|
||||
| `price` | string | Limit price |
|
||||
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
|
||||
| `order_type` | string | Order type (GTC, GTD, FOK, FAK) |
|
||||
| `maker_address` | string | Funder address |
|
||||
| `owner` | string | API key of the order owner |
|
||||
| `expiration` | string | Unix timestamp when the order expires (`0` if no expiration) |
|
||||
| `associate_trades` | string\[] | Trade IDs this order has been partially included in |
|
||||
| `created_at` | string | Unix timestamp when the order was created |
|
||||
|
||||
***
|
||||
|
||||
## Trade History
|
||||
|
||||
When an order is matched, it creates a trade. Trades go through the following statuses:
|
||||
|
||||
| Status | Terminal? | Description |
|
||||
| ----------- | --------- | -------------------------------------------------------------------- |
|
||||
| `MATCHED` | No | Matched and sent to the executor service for onchain submission |
|
||||
| `MINED` | No | Observed as mined on the chain, no finality threshold yet |
|
||||
| `CONFIRMED` | Yes | Achieved strong probabilistic finality — trade successful |
|
||||
| `RETRYING` | No | Transaction failed (revert or reorg) — being retried by the operator |
|
||||
| `FAILED` | Yes | Trade failed permanently and is not being retried |
|
||||
|
||||
### Trade Object
|
||||
|
||||
Each trade contains these fields:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------ | ------ | ------------------------------------------------------------ |
|
||||
| `id` | string | Trade ID |
|
||||
| `taker_order_id` | string | Taker order ID (hash) |
|
||||
| `market` | string | Market ID (condition ID) |
|
||||
| `asset_id` | string | Token ID |
|
||||
| `side` | string | `BUY` or `SELL` |
|
||||
| `size` | string | Trade size |
|
||||
| `fee_rate_bps` | string | Fee rate in basis points |
|
||||
| `price` | string | Trade price |
|
||||
| `status` | string | Trade status (see table above) |
|
||||
| `match_time` | string | Unix timestamp when the trade was matched |
|
||||
| `last_update` | string | Unix timestamp of last status update |
|
||||
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
|
||||
| `owner` | string | API key ID of the trade owner |
|
||||
| `maker_address` | string | Funder address |
|
||||
| `trader_side` | string | Whether you were `TAKER` or `MAKER` in this trade |
|
||||
| `transaction_hash` | string | Onchain transaction hash (available after mining) |
|
||||
| `maker_orders` | array | Array of maker orders matched against this trade (see below) |
|
||||
|
||||
### MakerOrder Fields
|
||||
|
||||
Each entry in the `maker_orders` array contains:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ---------------- | ------ | ---------------------------- |
|
||||
| `order_id` | string | Maker order ID (hash) |
|
||||
| `owner` | string | Maker's API key ID |
|
||||
| `maker_address` | string | Maker's funder address |
|
||||
| `matched_amount` | string | Amount matched in this trade |
|
||||
| `price` | string | Maker order price |
|
||||
| `fee_rate_bps` | string | Maker fee rate in bps |
|
||||
| `asset_id` | string | Token ID |
|
||||
| `outcome` | string | Outcome name |
|
||||
| `side` | string | `BUY` or `SELL` |
|
||||
|
||||
Retrieve your trades with the SDK:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// All trades
|
||||
const trades = await client.getTrades();
|
||||
|
||||
// Filtered by market
|
||||
const marketTrades = await client.getTrades({
|
||||
market: "0xbd31dc8a...",
|
||||
});
|
||||
|
||||
// With pagination
|
||||
const paginatedTrades = await client.getTradesPaginated({
|
||||
market: "0xbd31dc8a...",
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import TradeParams
|
||||
|
||||
# All trades
|
||||
trades = client.get_trades()
|
||||
|
||||
# Filtered by market
|
||||
market_trades = client.get_trades(
|
||||
TradeParams(
|
||||
market="0xbd31dc8a...",
|
||||
)
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Heartbeat
|
||||
|
||||
The heartbeat endpoint maintains session liveness for order safety. If a valid heartbeat is not received within **10 seconds** (with up to a 5-second buffer), **all of your open orders will be cancelled**.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Send heartbeats in a loop
|
||||
let heartbeatId = "";
|
||||
setInterval(async () => {
|
||||
const resp = await client.postHeartbeat(heartbeatId);
|
||||
heartbeatId = resp.heartbeat_id;
|
||||
}, 5000);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
import time
|
||||
|
||||
heartbeat_id = ""
|
||||
while True:
|
||||
resp = client.post_heartbeat(heartbeat_id)
|
||||
heartbeat_id = resp["heartbeat_id"]
|
||||
time.sleep(5)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
* On each request, include the most recent `heartbeat_id` you received. For your first request, use an empty string.
|
||||
* If you send an invalid or expired `heartbeat_id`, the server responds with a `400 Bad Request` and provides the correct `heartbeat_id` in the response. Update your client and retry.
|
||||
|
||||
***
|
||||
|
||||
## Order Scoring
|
||||
|
||||
Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Single order
|
||||
const scoring = await client.isOrderScoring({ orderId: "0x..." });
|
||||
console.log(scoring); // { scoring: true }
|
||||
|
||||
// Multiple orders
|
||||
const batchScoring = await client.areOrdersScoring({
|
||||
orderIds: ["0x...", "0x..."],
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OrderScoringParams, OrdersScoringParams
|
||||
|
||||
# Single order
|
||||
scoring = client.is_order_scoring(
|
||||
OrderScoringParams(
|
||||
orderId="0x..."
|
||||
)
|
||||
OrderScoringParams(orderId="0x...")
|
||||
)
|
||||
print(scoring)
|
||||
|
||||
scoring = client.are_orders_scoring(
|
||||
OrdersScoringParams(
|
||||
orderIds=["0x..."]
|
||||
)
|
||||
# Multiple orders
|
||||
batch_scoring = client.are_orders_scoring(
|
||||
OrdersScoringParams(orderIds=["0x...", "0x..."])
|
||||
)
|
||||
print(scoring)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
```javascript Typescript theme={null}
|
||||
async function main() {
|
||||
const scoring = await clobClient.isOrderScoring({
|
||||
orderId: "0x...",
|
||||
});
|
||||
console.log(scoring);
|
||||
}
|
||||
***
|
||||
|
||||
main();
|
||||
## Onchain Order Info
|
||||
|
||||
async function main() {
|
||||
const scoring = await clobClient.areOrdersScoring({
|
||||
orderIds: ["0x..."],
|
||||
});
|
||||
console.log(scoring);
|
||||
}
|
||||
When a trade is settled onchain, the Exchange contract emits an `OrderFilled` event with the following fields:
|
||||
|
||||
main();
|
||||
| Field | Description |
|
||||
| ------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| `orderHash` | Unique hash for the filled order |
|
||||
| `maker` | The user who generated the order and source of funds |
|
||||
| `taker` | The user filling the order, or the Exchange contract if multiple limit orders are filled |
|
||||
| `makerAssetId` | ID of the asset given out. If `0`, the order is a **BUY** (giving USDC.e for outcome tokens) |
|
||||
| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving USDC.e for outcome tokens) |
|
||||
| `makerAmountFilled` | Amount of the asset given out |
|
||||
| `takerAmountFilled` | Amount of the asset received |
|
||||
| `fee` | Fees paid by the order maker |
|
||||
|
||||
```
|
||||
</RequestExample>
|
||||
***
|
||||
|
||||
## Error Messages
|
||||
|
||||
When placing an order, the response may include an `errorMsg` if the order could not be placed. If `success` is `false`, there was a server-side error:
|
||||
|
||||
| Error | Description |
|
||||
| ---------------------------------- | ------------------------------------------------------ |
|
||||
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
|
||||
| `INVALID_ORDER_MIN_SIZE` | Order size is below the minimum threshold |
|
||||
| `INVALID_ORDER_DUPLICATED` | Identical order has already been placed |
|
||||
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Funder doesn't have sufficient balance or allowance |
|
||||
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
|
||||
| `INVALID_ORDER_ERROR` | System error while inserting order |
|
||||
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only flag used with a market order type (FOK/FAK) |
|
||||
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
|
||||
| `EXECUTION_ERROR` | System error while executing trade |
|
||||
| `ORDER_DELAYED` | Order placement delayed due to market conditions |
|
||||
| `DELAYING_ORDER_ERROR` | System error while delaying order |
|
||||
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
|
||||
| `MARKET_NOT_READY` | Market is not yet accepting orders |
|
||||
|
||||
### Insert Statuses
|
||||
|
||||
When an order is successfully placed, the response includes a `status` field:
|
||||
|
||||
| Status | Description |
|
||||
| ----------- | -------------------------------------------------------------------- |
|
||||
| `matched` | Order placed and matched with a resting order |
|
||||
| `live` | Order placed and resting on the book |
|
||||
| `delayed` | Order is marketable but subject to a matching delay |
|
||||
| `unmatched` | Order is marketable but failed to delay — placement still successful |
|
||||
|
||||
***
|
||||
|
||||
## Security
|
||||
|
||||
Polymarket's Exchange contract has been audited by Chainsecurity ([View Audit](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)).
|
||||
|
||||
The operator's privileges are limited to order matching and ensuring correct ordering. Operators cannot set prices or execute unauthorized trades. Users can cancel orders onchain independently if trust issues arise.
|
||||
|
||||
***
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Create Order" icon="plus" href="/trading/orders/create">
|
||||
Build, sign, and submit orders
|
||||
</Card>
|
||||
|
||||
<Card title="Cancel Order" icon="xmark" href="/trading/orders/cancel">
|
||||
Cancel single, multiple, or all orders
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -2,233 +2,532 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Place Multiple Orders (Batching)
|
||||
# Create Order
|
||||
|
||||
> Instructions for placing multiple orders(Batch)
|
||||
> Build, sign, and submit orders
|
||||
|
||||
<Tip> This endpoint requires a L2 Header </Tip>
|
||||
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
|
||||
|
||||
Polymarket’s CLOB supports batch orders, allowing you to place up to `15` orders in a single request. Before using this feature, make sure you're comfortable placing a single order first. You can find the documentation for that [here.](/developers/CLOB/orders/create-order)
|
||||
<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>
|
||||
|
||||
**HTTP REQUEST**
|
||||
***
|
||||
|
||||
`POST /<clob-endpoint>/orders`
|
||||
## Order Types
|
||||
|
||||
### Request Payload Parameters
|
||||
| Type | Behavior | Use Case |
|
||||
| ------- | -------------------------------------------------------------------- | ------------------------------- |
|
||||
| **GTC** | Good-Til-Cancelled — rests on the book until filled or cancelled | Default for limit orders |
|
||||
| **GTD** | Good-Til-Date — active until a specified expiration time | Auto-expire before known events |
|
||||
| **FOK** | Fill-Or-Kill — must fill immediately and entirely, or cancel | All-or-nothing market orders |
|
||||
| **FAK** | Fill-And-Kill — fills what's available immediately, cancels the rest | Partial-fill market orders |
|
||||
|
||||
| Name | Required | Type | Description |
|
||||
| --------- | -------- | ------------- | ---------------------------------------------------------------- |
|
||||
| PostOrder | yes | PostOrders\[] | list of signed order objects (Signed Order + Order Type + Owner) |
|
||||
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
|
||||
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
|
||||
* **BUY**: specify the dollar amount you want to spend
|
||||
* **SELL**: specify the number of shares you want to sell
|
||||
|
||||
A `PostOrder` object is the form:
|
||||
***
|
||||
|
||||
| Name | Required | Type | Description |
|
||||
| --------- | -------- | ------- | -------------------------------------------------------------------------------------------- |
|
||||
| order | yes | order | See below table for details on crafting this object |
|
||||
| orderType | yes | string | order type ("FOK", "GTC", "GTD", "FAK") |
|
||||
| owner | yes | string | api key of order owner |
|
||||
| postOnly | no | boolean | if `true`, the order will only rest on the book and not match immediately (default: `false`) |
|
||||
## Limit Orders
|
||||
|
||||
An `order` object is the form:
|
||||
The simplest way to place a limit order — create, sign, and submit in one call:
|
||||
|
||||
| Name | Required | Type | Description |
|
||||
| ------------- | -------- | ------- | -------------------------------------------------- |
|
||||
| salt | yes | integer | random salt used to create unique order |
|
||||
| maker | yes | string | maker address (funder) |
|
||||
| signer | yes | string | signing address |
|
||||
| taker | yes | string | taker address (operator) |
|
||||
| tokenId | yes | string | ERC1155 token ID of conditional token being traded |
|
||||
| makerAmount | yes | string | maximum amount maker is willing to spend |
|
||||
| takerAmount | yes | string | minimum amount taker will pay the maker in return |
|
||||
| expiration | yes | string | unix expiration timestamp |
|
||||
| nonce | yes | string | maker's exchange nonce of the order is associated |
|
||||
| feeRateBps | yes | string | fee rate basis points as required by the operator |
|
||||
| side | yes | string | buy or sell enum index |
|
||||
| signatureType | yes | integer | signature type enum index |
|
||||
| signature | yes | string | hex encoded signature |
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { ClobClient, Side, OrderType } from "@polymarket/clob-client";
|
||||
|
||||
### Order types
|
||||
const response = await client.createAndPostOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
price: 0.5,
|
||||
size: 10,
|
||||
side: Side.BUY,
|
||||
},
|
||||
{
|
||||
tickSize: "0.01",
|
||||
negRisk: false,
|
||||
},
|
||||
OrderType.GTC,
|
||||
);
|
||||
|
||||
* **FOK**: A Fill-Or-Kill order is an market order to buy (in dollars) or sell (in shares) shares that must be executed immediately in its entirety; otherwise, the entire order will be cancelled.
|
||||
* **FAK**: A Fill-And-Kill order is a market order to buy (in dollars) or sell (in shares) that will be executed immediately for as many shares as are available; any portion not filled at once is cancelled.
|
||||
* **GTC**: A Good-Til-Cancelled order is a limit order that is active until it is fulfilled or cancelled.
|
||||
* **GTD**: A Good-Til-Date order is a type of order that is active until its specified date (UTC seconds timestamp), unless it has already been fulfilled or cancelled. There is a security threshold of one minute. If the order needs to expire in 90 seconds the correct expiration value is: now + 1 minute + 30 seconds
|
||||
console.log("Order ID:", response.orderID);
|
||||
console.log("Status:", response.status);
|
||||
```
|
||||
|
||||
### Response Format
|
||||
|
||||
| Name | Type | Description |
|
||||
| ----------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| success | boolean | boolean indicating if server-side err (`success = false`) -> server-side error |
|
||||
| errorMsg | string | error message in case of unsuccessful placement (in case `success = false`, e.g. `client-side error`, the reason is in `errorMsg`) |
|
||||
| orderId | string | id of order |
|
||||
| orderHashes | string\[] | hash of settlement transaction order was marketable and triggered a match |
|
||||
|
||||
### Insert Error Messages
|
||||
|
||||
If the `errorMsg` field of the response object from placement is not an empty string, the order was not able to be immediately placed. This might be because of a delay or because of a failure. If the `success` is not `true`, then there was an issue placing the order. The following `errorMessages` are possible:
|
||||
|
||||
#### Error
|
||||
|
||||
| Error | Success | Message | Description |
|
||||
| ------------------------------------ | ------- | --------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
||||
| INVALID\_ORDER\_MIN\_TICK\_SIZE | yes | order is invalid. Price breaks minimum tick size rules | order price isn't accurate to correct tick sizing |
|
||||
| INVALID\_ORDER\_MIN\_SIZE | yes | order is invalid. Size lower than the minimum | order size must meet min size threshold requirement |
|
||||
| INVALID\_ORDER\_DUPLICATED | yes | order is invalid. Duplicated. Same order has already been placed, can't be placed again | |
|
||||
| INVALID\_ORDER\_NOT\_ENOUGH\_BALANCE | yes | not enough balance / allowance | funder address doesn't have sufficient balance or allowance for order |
|
||||
| INVALID\_ORDER\_EXPIRATION | yes | invalid expiration | expiration field expresses a time before now |
|
||||
| INVALID\_ORDER\_ERROR | yes | could not insert order | system error while inserting order |
|
||||
| INVALID\_POST\_ONLY\_ORDER\_TYPE | yes | invalid post-only order: only GTC and GTD order types are allowed | post only flag attached to a market order |
|
||||
| INVALID\_POST\_ONLY\_ORDER | yes | invalid post-only order: order crosses book | post only order would match |
|
||||
| EXECUTION\_ERROR | yes | could not run the execution | system error while attempting to execute trade |
|
||||
| ORDER\_DELAYED | no | order match delayed due to market conditions | order placement delayed |
|
||||
| DELAYING\_ORDER\_ERROR | yes | error delaying the order | system error while delaying order |
|
||||
| FOK\_ORDER\_NOT\_FILLED\_ERROR | yes | order couldn't be fully filled, FOK orders are fully filled/killed | FOK order not fully filled so can't be placed |
|
||||
| MARKET\_NOT\_READY | no | the market is not yet ready to process new orders | system not accepting orders for market yet |
|
||||
|
||||
### Insert Statuses
|
||||
|
||||
When placing an order, a status field is included. The status field provides additional information regarding the order's state as a result of the placement. Possible values include:
|
||||
|
||||
#### Status
|
||||
|
||||
| Status | Description |
|
||||
| --------- | ------------------------------------------------------------ |
|
||||
| matched | order placed and matched with an existing resting order |
|
||||
| live | order placed and resting on the book |
|
||||
| delayed | order marketable, but subject to matching delay |
|
||||
| unmatched | order marketable, but failure delaying, placement successful |
|
||||
|
||||
<RequestExample>
|
||||
```python Python theme={null}
|
||||
from py_clob_client.client import ClobClient
|
||||
from py_clob_client.clob_types import OrderArgs, OrderType, PostOrdersArgs
|
||||
from py_clob_client.clob_types import OrderArgs, OrderType
|
||||
from py_clob_client.order_builder.constants import BUY
|
||||
|
||||
response = client.create_and_post_order(
|
||||
OrderArgs(
|
||||
token_id="TOKEN_ID",
|
||||
price=0.50,
|
||||
size=10,
|
||||
side=BUY,
|
||||
),
|
||||
options={
|
||||
"tick_size": "0.01",
|
||||
"neg_risk": False,
|
||||
},
|
||||
order_type=OrderType.GTC
|
||||
)
|
||||
|
||||
host: str = "https://clob.polymarket.com"
|
||||
key: str = "" ##This is your Private Key. Export from https://reveal.magic.link/polymarket or from your Web3 Application
|
||||
chain_id: int = 137 #No need to adjust this
|
||||
POLYMARKET_PROXY_ADDRESS: str = '' #This is the address listed below your profile picture when using the Polymarket site.
|
||||
print("Order ID:", response["orderID"])
|
||||
print("Status:", response["status"])
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
#Select from the following 3 initialization options to matches your login method, and remove any unused lines so only one client is initialized.
|
||||
### Two-Step: Sign Then Submit
|
||||
|
||||
For more control, you can separate signing from submission. This is useful for batch orders or custom submission logic:
|
||||
|
||||
### Initialization of a client using a Polymarket Proxy associated with an Email/Magic account. If you login with your email use this example.
|
||||
client = ClobClient(host, key=key, chain_id=chain_id, signature_type=1, funder=POLYMARKET_PROXY_ADDRESS)
|
||||
<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 },
|
||||
);
|
||||
|
||||
### Initialization of a client using a Polymarket Proxy associated with a Browser Wallet(Metamask, Coinbase Wallet, etc)
|
||||
client = ClobClient(host, key=key, chain_id=chain_id, signature_type=2, funder=POLYMARKET_PROXY_ADDRESS)
|
||||
// Step 2: Submit to the CLOB
|
||||
const response = await client.postOrder(signedOrder, OrderType.GTC);
|
||||
```
|
||||
|
||||
### Initialization of a client that trades directly from an EOA.
|
||||
client = ClobClient(host, key=key, chain_id=chain_id)
|
||||
```python Python theme={null}
|
||||
# Step 1: Create and sign locally
|
||||
signed_order = client.create_order(
|
||||
OrderArgs(
|
||||
token_id="TOKEN_ID",
|
||||
price=0.50,
|
||||
size=10,
|
||||
side=BUY,
|
||||
),
|
||||
options={
|
||||
"tick_size": "0.01",
|
||||
"neg_risk": False,
|
||||
}
|
||||
)
|
||||
|
||||
## Create and sign a limit order buying 100 YES tokens for 0.50c each
|
||||
#Refer to the Markets API documentation to locate a tokenID: https://docs.polymarket.com/developers/gamma-markets-api/get-markets
|
||||
# Step 2: Submit to the CLOB
|
||||
response = client.post_order(signed_order, OrderType.GTC)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
client.set_api_creds(client.create_or_derive_api_creds())
|
||||
***
|
||||
|
||||
resp = client.post_orders([
|
||||
## GTD Orders (Expiring)
|
||||
|
||||
GTD orders auto-expire at a specified time. Useful for quoting around known events.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Expire in 1 hour (+ 60s security threshold buffer)
|
||||
const expiration = Math.floor(Date.now() / 1000) + 60 + 3600;
|
||||
|
||||
const response = await client.createAndPostOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
price: 0.5,
|
||||
size: 10,
|
||||
side: Side.BUY,
|
||||
expiration,
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
OrderType.GTD,
|
||||
);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
import time
|
||||
|
||||
# Expire in 1 hour (+ 60s security threshold buffer)
|
||||
expiration = int(time.time()) + 60 + 3600
|
||||
|
||||
response = client.create_and_post_order(
|
||||
OrderArgs(
|
||||
token_id="TOKEN_ID",
|
||||
price=0.50,
|
||||
size=10,
|
||||
side=BUY,
|
||||
expiration=expiration,
|
||||
),
|
||||
options={
|
||||
"tick_size": "0.01",
|
||||
"neg_risk": False,
|
||||
},
|
||||
order_type=OrderType.GTD
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Note>
|
||||
There is a security threshold of one minute on GTD expiration. To set an
|
||||
effective lifetime of N seconds, use `now + 60 + N`. For example, for a
|
||||
30-second effective lifetime, set the expiration to `now + 60 + 30`.
|
||||
</Note>
|
||||
|
||||
***
|
||||
|
||||
## Market Orders
|
||||
|
||||
Market orders execute immediately against resting liquidity using FOK or FAK types:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { Side, OrderType } from "@polymarket/clob-client";
|
||||
|
||||
// FOK BUY: spend exactly $100 or cancel entirely
|
||||
const buyOrder = await client.createMarketOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
side: Side.BUY,
|
||||
amount: 100, // dollar amount
|
||||
price: 0.5, // worst-price limit (slippage protection)
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
);
|
||||
await client.postOrder(buyOrder, OrderType.FOK);
|
||||
|
||||
// FOK SELL: sell exactly 200 shares or cancel entirely
|
||||
const sellOrder = await client.createMarketOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
side: Side.SELL,
|
||||
amount: 200, // number of shares
|
||||
price: 0.45, // worst-price limit (slippage protection)
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
);
|
||||
await client.postOrder(sellOrder, OrderType.FOK);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.order_builder.constants import BUY, SELL
|
||||
from py_clob_client.clob_types import OrderType
|
||||
|
||||
# FOK BUY: spend exactly $100 or cancel entirely
|
||||
buy_order = client.create_market_order(
|
||||
token_id="TOKEN_ID",
|
||||
side=BUY,
|
||||
amount=100, # dollar amount
|
||||
price=0.50, # worst-price limit (slippage protection)
|
||||
options={"tick_size": "0.01", "neg_risk": False},
|
||||
)
|
||||
client.post_order(buy_order, OrderType.FOK)
|
||||
|
||||
# FOK SELL: sell exactly 200 shares or cancel entirely
|
||||
sell_order = client.create_market_order(
|
||||
token_id="TOKEN_ID",
|
||||
side=SELL,
|
||||
amount=200, # number of shares
|
||||
price=0.45, # worst-price limit (slippage protection)
|
||||
options={"tick_size": "0.01", "neg_risk": False},
|
||||
)
|
||||
client.post_order(sell_order, OrderType.FOK)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
* **FOK** — fill entirely or cancel the whole order
|
||||
* **FAK** — fill what's available, cancel the rest
|
||||
|
||||
The `price` field on market orders acts as a **worst-price limit** (slippage protection), not a target execution price.
|
||||
|
||||
### One-Step Market Order
|
||||
|
||||
For convenience, `createAndPostMarketOrder` handles creation, signing, and submission in one call:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const response = await client.createAndPostMarketOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
side: Side.BUY,
|
||||
amount: 100,
|
||||
price: 0.5,
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
OrderType.FOK,
|
||||
);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
response = client.create_and_post_market_order(
|
||||
token_id="TOKEN_ID",
|
||||
side=BUY,
|
||||
amount=100,
|
||||
price=0.50,
|
||||
options={"tick_size": "0.01", "neg_risk": False},
|
||||
order_type=OrderType.FOK,
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Post-Only Orders
|
||||
|
||||
Post-only orders guarantee you're always the maker. If the order would match immediately (cross the spread), it's rejected instead of executed.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const response = await client.postOrder(signedOrder, OrderType.GTC, true);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
response = client.post_order(signed_order, OrderType.GTC, post_only=True)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
* Only works with **GTC** and **GTD** order types
|
||||
* Rejected if combined with FOK or FAK
|
||||
|
||||
***
|
||||
|
||||
## Batch Orders
|
||||
|
||||
Place up to **15 orders** in a single request:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { OrderType, Side, PostOrdersArgs } from "@polymarket/clob-client";
|
||||
|
||||
const orders: PostOrdersArgs[] = [
|
||||
{
|
||||
order: await client.createOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
price: 0.48,
|
||||
side: Side.BUY,
|
||||
size: 500,
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
),
|
||||
orderType: OrderType.GTC,
|
||||
},
|
||||
{
|
||||
order: await client.createOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
price: 0.52,
|
||||
side: Side.SELL,
|
||||
size: 500,
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
),
|
||||
orderType: OrderType.GTC,
|
||||
},
|
||||
];
|
||||
|
||||
const response = await client.postOrders(orders);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OrderArgs, OrderType, PostOrdersArgs
|
||||
from py_clob_client.order_builder.constants import BUY, SELL
|
||||
|
||||
response = client.post_orders([
|
||||
PostOrdersArgs(
|
||||
# Create and sign a limit order buying 100 YES tokens for 0.50 each
|
||||
order=client.create_order(OrderArgs(
|
||||
price=0.01,
|
||||
size=5,
|
||||
price=0.48,
|
||||
size=500,
|
||||
side=BUY,
|
||||
token_id="88613172803544318200496156596909968959424174365708473463931555296257475886634",
|
||||
)),
|
||||
orderType=OrderType.GTC, # Good 'Til Cancelled
|
||||
token_id="TOKEN_ID",
|
||||
), options={"tick_size": "0.01", "neg_risk": False}),
|
||||
orderType=OrderType.GTC,
|
||||
),
|
||||
PostOrdersArgs(
|
||||
# Create and sign a limit order selling 200 NO tokens for 0.25 each
|
||||
order=client.create_order(OrderArgs(
|
||||
price=0.01,
|
||||
size=5,
|
||||
side=BUY,
|
||||
token_id="93025177978745967226369398316375153283719303181694312089956059680730874301533",
|
||||
)),
|
||||
orderType=OrderType.GTC, # Good 'Til Cancelled
|
||||
)
|
||||
price=0.52,
|
||||
size=500,
|
||||
side=SELL,
|
||||
token_id="TOKEN_ID",
|
||||
), options={"tick_size": "0.01", "neg_risk": False}),
|
||||
orderType=OrderType.GTC,
|
||||
),
|
||||
])
|
||||
print(resp)
|
||||
print("Done!")
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Order Options
|
||||
|
||||
Every order requires two market-specific options: `tickSize` and `negRisk`. For details on signature types (`0` = EOA, `1` = POLY\_PROXY, `2` = GNOSIS\_SAFE), see [Authentication](/api-reference/authentication#signature-types-and-funder).
|
||||
|
||||
### Tick Sizes
|
||||
|
||||
Your order price must conform to the market's tick size, or the order is rejected.
|
||||
|
||||
| Tick Size | Precision | Example Prices |
|
||||
| --------- | ---------- | ---------------------- |
|
||||
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
|
||||
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
|
||||
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
|
||||
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const tickSize = await client.getTickSize("TOKEN_ID");
|
||||
```
|
||||
|
||||
```javascript typescript theme={null}
|
||||
import { ethers } from "ethers";
|
||||
import { config as dotenvConfig } from "dotenv";
|
||||
import { resolve } from "path";
|
||||
import { ApiKeyCreds, Chain, ClobClient, OrderType, PostOrdersArgs, Side } from "../src";
|
||||
```python Python theme={null}
|
||||
tick_size = client.get_tick_size("TOKEN_ID")
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
dotenvConfig({ path: resolve(__dirname, "../.env") });
|
||||
### Negative Risk
|
||||
|
||||
async function main() {
|
||||
const wallet = new ethers.Wallet(`${process.env.PK}`);
|
||||
const chainId = parseInt(`${process.env.CHAIN_ID || Chain.AMOY}`) as Chain;
|
||||
console.log(`Address: ${await wallet.getAddress()}, chainId: ${chainId}`);
|
||||
Multi-outcome events (3+ outcomes) use the Neg Risk CTF Exchange. Pass `negRisk: true` for these markets.
|
||||
|
||||
const host = process.env.CLOB_API_URL || "https://clob.polymarket.com";
|
||||
const creds: ApiKeyCreds = {
|
||||
key: `${process.env.CLOB_API_KEY}`,
|
||||
secret: `${process.env.CLOB_SECRET}`,
|
||||
passphrase: `${process.env.CLOB_PASS_PHRASE}`,
|
||||
};
|
||||
const clobClient = new ClobClient(host, chainId, wallet, creds);
|
||||
|
||||
await clobClient.cancelAll();
|
||||
|
||||
const YES = "71321045679252212594626385532706912750332728571942532289631379312455583992563";
|
||||
const orders: PostOrdersArgs[] = [
|
||||
{
|
||||
order: await clobClient.createOrder({
|
||||
tokenID: YES,
|
||||
price: 0.4,
|
||||
side: Side.BUY,
|
||||
size: 100,
|
||||
}),
|
||||
orderType: OrderType.GTC,
|
||||
},
|
||||
{
|
||||
order: await clobClient.createOrder({
|
||||
tokenID: YES,
|
||||
price: 0.45,
|
||||
side: Side.BUY,
|
||||
size: 100,
|
||||
}),
|
||||
orderType: OrderType.GTC,
|
||||
},
|
||||
{
|
||||
order: await clobClient.createOrder({
|
||||
tokenID: YES,
|
||||
price: 0.55,
|
||||
side: Side.SELL,
|
||||
size: 100,
|
||||
}),
|
||||
orderType: OrderType.GTC,
|
||||
},
|
||||
{
|
||||
order: await clobClient.createOrder({
|
||||
tokenID: YES,
|
||||
price: 0.6,
|
||||
side: Side.SELL,
|
||||
size: 100,
|
||||
}),
|
||||
orderType: OrderType.GTC,
|
||||
},
|
||||
];
|
||||
|
||||
// Send it to the server
|
||||
const resp = await clobClient.postOrders(orders);
|
||||
console.log(resp);
|
||||
}
|
||||
|
||||
main();
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const isNegRisk = await client.getNegRisk("TOKEN_ID");
|
||||
```
|
||||
|
||||
```REQUEST Example Payload theme={null}
|
||||
[
|
||||
{'order': {'salt': 660377097, 'maker': '0x17A9568474b5fc84B1D1C44f081A0a3aDE750B2b', 'signer': '0x17A9568474b5fc84B1D1C44f081A0a3aDE750B2b', 'taker': '0x0000000000000000000000000000000000000000', 'tokenId': '88613172803544318200496156596909968959424174365708473463931555296257475886634', 'makerAmount': '50000', 'takerAmount': '5000000', 'expiration': '0', 'nonce': '0', 'feeRateBps': '0', 'side': 'BUY', 'signatureType': 0, 'signature': '0xccb8d1298d698ebc0859e6a26044c848ac4a4b0e20a391a4574e42b9c9bf237e5fa09fc00743e3e2d2f8e909a21d60f276ce083cc35c6661410b892f5bcbe2291c'}, 'owner': 'PRIVATEKEY', 'orderType': 'GTC'},
|
||||
{'order': {'salt': 1207111323, 'maker': '0x17A9568474b5fc84B1D1C44f081A0a3aDE750B2b', 'signer': '0x17A9568474b5fc84B1D1C44f081A0a3aDE750B2b', 'taker': '0x0000000000000000000000000000000000000000', 'tokenId': '93025177978745967226369398316375153283719303181694312089956059680730874301533', 'makerAmount': '50000', 'takerAmount': '5000000', 'expiration': '0', 'nonce': '0', 'feeRateBps': '0', 'side': 'BUY', 'signatureType': 0, 'signature': '0x0feca28666283824c27d7bead0bc441dde6df20dd71ef5ff7c84d3d1d5bf8aa4296fa382769dc11a92abe05b6f731d6c32556e9b4fb29e6eb50131af23a9ac941c'}, 'owner': 'PRIVATEKEY', 'orderType': 'GTC'}
|
||||
]
|
||||
|
||||
```python Python theme={null}
|
||||
is_neg_risk = client.get_neg_risk("TOKEN_ID")
|
||||
```
|
||||
</RequestExample>
|
||||
</CodeGroup>
|
||||
|
||||
<Tip>
|
||||
Both values are also available on the market object: `minimum_tick_size` and
|
||||
`neg_risk`.
|
||||
</Tip>
|
||||
|
||||
***
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
|
||||
|
||||
* **BUY orders**: USDC.e allowance >= spending amount
|
||||
* **SELL orders**: conditional token allowance >= selling amount
|
||||
|
||||
Order size is limited by your available balance minus amounts reserved by existing open orders:
|
||||
|
||||
$$
|
||||
\text{maxOrderSize} = \text{balance} - \sum(\text{openOrderSize} - \text{filledAmount})
|
||||
$$
|
||||
|
||||
<Warning>
|
||||
Orders are continuously monitored for validity — balances, allowances, and
|
||||
onchain cancellations are tracked in real time. Any maker caught intentionally
|
||||
abusing these checks will be blacklisted.
|
||||
</Warning>
|
||||
|
||||
### Advanced Parameters
|
||||
|
||||
These optional fields can be passed in the `UserOrder` object for fine-grained control:
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| ------------ | ------ | ----------------------------------------------- |
|
||||
| `feeRateBps` | number | Fee rate in basis points (default: market rate) |
|
||||
| `nonce` | number | Custom nonce for order uniqueness |
|
||||
| `taker` | string | Restrict the order to a specific taker address |
|
||||
|
||||
### Sports Markets
|
||||
|
||||
Sports markets have additional behaviors:
|
||||
|
||||
* Outstanding limit orders are **automatically cancelled** once the game begins, clearing the entire order book at the official start time
|
||||
* Marketable orders have a **3-second placement delay** before matching
|
||||
* Game start times can shift — monitor your orders closely, as they may not be cleared if the start time changes unexpectedly
|
||||
|
||||
***
|
||||
|
||||
## Response
|
||||
|
||||
A successful order placement returns:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"success": true,
|
||||
"errorMsg": "",
|
||||
"orderID": "0xabc123...",
|
||||
"takingAmount": "",
|
||||
"makingAmount": "",
|
||||
"status": "live",
|
||||
"transactionsHashes": [],
|
||||
"tradeIDs": []
|
||||
}
|
||||
```
|
||||
|
||||
### Statuses
|
||||
|
||||
| Status | Description |
|
||||
| ----------- | ----------------------------------------------------------- |
|
||||
| `live` | Order resting on the book |
|
||||
| `matched` | Order matched immediately with a resting order |
|
||||
| `delayed` | Marketable order subject to a matching delay |
|
||||
| `unmatched` | Marketable but failed to delay — placement still successful |
|
||||
|
||||
### Error Messages
|
||||
|
||||
| Error | Description |
|
||||
| ---------------------------------- | ----------------------------------------------- |
|
||||
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
|
||||
| `INVALID_ORDER_MIN_SIZE` | Order size below the minimum threshold |
|
||||
| `INVALID_ORDER_DUPLICATED` | Identical order already placed |
|
||||
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Insufficient balance or allowance |
|
||||
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
|
||||
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only used with FOK/FAK |
|
||||
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
|
||||
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
|
||||
| `INVALID_ORDER_ERROR` | System error inserting the order |
|
||||
| `EXECUTION_ERROR` | System error executing the trade |
|
||||
| `ORDER_DELAYED` | Order match delayed due to market conditions |
|
||||
| `DELAYING_ORDER_ERROR` | System error while delaying the order |
|
||||
| `MARKET_NOT_READY` | Market not yet accepting orders |
|
||||
|
||||
***
|
||||
|
||||
## Heartbeat
|
||||
|
||||
The heartbeat endpoint maintains session liveness. If a valid heartbeat is not received within **10 seconds** (with a 5-second buffer), **all open orders are cancelled**.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
let heartbeatId = "";
|
||||
setInterval(async () => {
|
||||
const resp = await client.postHeartbeat(heartbeatId);
|
||||
heartbeatId = resp.heartbeat_id;
|
||||
}, 5000);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
import time
|
||||
|
||||
heartbeat_id = ""
|
||||
while True:
|
||||
resp = client.post_heartbeat(heartbeat_id)
|
||||
heartbeat_id = resp["heartbeat_id"]
|
||||
time.sleep(5)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
* Include the most recent `heartbeat_id` in each request. Use an empty string for the first request.
|
||||
* If you send an expired ID, the server responds with `400` and the correct ID. Update and retry.
|
||||
|
||||
***
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Cancel Orders" icon="xmark" href="/trading/orders/cancel">
|
||||
Cancel single, multiple, or all open orders
|
||||
</Card>
|
||||
|
||||
<Card title="Order Attribution" icon="tag" href="/trading/orders/attribution">
|
||||
Attribute orders to your builder account for volume credit
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -2,263 +2,532 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Place Single Order
|
||||
# Create Order
|
||||
|
||||
> Detailed instructions for creating, placing, and managing orders using Polymarket's CLOB API.
|
||||
> Build, sign, and submit orders
|
||||
|
||||
# Create and Place an Order
|
||||
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
|
||||
|
||||
<Tip> This endpoint requires a L2 Header </Tip>
|
||||
<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>
|
||||
|
||||
Create and place an order using the Polymarket CLOB API clients. All orders are represented as "limit" orders, but "market" orders are also supported. To place a market order, simply ensure your price is marketable against current resting limit orders, which are executed on input at the best price.
|
||||
***
|
||||
|
||||
**HTTP REQUEST**
|
||||
## Order Types
|
||||
|
||||
`POST /<clob-endpoint>/order`
|
||||
| Type | Behavior | Use Case |
|
||||
| ------- | -------------------------------------------------------------------- | ------------------------------- |
|
||||
| **GTC** | Good-Til-Cancelled — rests on the book until filled or cancelled | Default for limit orders |
|
||||
| **GTD** | Good-Til-Date — active until a specified expiration time | Auto-expire before known events |
|
||||
| **FOK** | Fill-Or-Kill — must fill immediately and entirely, or cancel | All-or-nothing market orders |
|
||||
| **FAK** | Fill-And-Kill — fills what's available immediately, cancels the rest | Partial-fill market orders |
|
||||
|
||||
### Request Payload Parameters
|
||||
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
|
||||
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
|
||||
* **BUY**: specify the dollar amount you want to spend
|
||||
* **SELL**: specify the number of shares you want to sell
|
||||
|
||||
| Name | Required | Type | Description |
|
||||
| --------- | -------- | ------- | -------------------------------------------------------------------------------------------- |
|
||||
| order | yes | Order | signed object |
|
||||
| owner | yes | string | api key of order owner |
|
||||
| orderType | yes | string | order type ("FOK", "GTC", "GTD") |
|
||||
| postOnly | no | boolean | if `true`, the order will only rest on the book and not match immediately (default: `false`) |
|
||||
***
|
||||
|
||||
### Post-only orders
|
||||
## Limit Orders
|
||||
|
||||
* postOnly submits a limit order that will not match resting liquidity upon entry.
|
||||
* If a postOnly order would cross the spread (i.e., it is marketable), it will be rejected rather than executed.
|
||||
* postOnly cannot be combined with market order types (e.g., FOK or FAK). If `postOnly = true` is sent with a market order type, the order will be rejected.
|
||||
The simplest way to place a limit order — create, sign, and submit in one call:
|
||||
|
||||
An `order` object is the form:
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { ClobClient, Side, OrderType } from "@polymarket/clob-client";
|
||||
|
||||
| Name | Required | Type | Description |
|
||||
| ------------- | -------- | ------- | -------------------------------------------------- |
|
||||
| salt | yes | integer | random salt used to create unique order |
|
||||
| maker | yes | string | maker address (funder) |
|
||||
| signer | yes | string | signing address |
|
||||
| taker | yes | string | taker address (operator) |
|
||||
| tokenId | yes | string | ERC1155 token ID of conditional token being traded |
|
||||
| makerAmount | yes | string | maximum amount maker is willing to spend |
|
||||
| takerAmount | yes | string | minimum amount taker will pay the maker in return |
|
||||
| expiration | yes | string | unix expiration timestamp |
|
||||
| nonce | yes | string | maker's exchange nonce of the order is associated |
|
||||
| feeRateBps | yes | string | fee rate basis points as required by the operator |
|
||||
| side | yes | string | buy or sell enum index |
|
||||
| signatureType | yes | integer | signature type enum index |
|
||||
| signature | yes | string | hex encoded signature |
|
||||
const response = await client.createAndPostOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
price: 0.5,
|
||||
size: 10,
|
||||
side: Side.BUY,
|
||||
},
|
||||
{
|
||||
tickSize: "0.01",
|
||||
negRisk: false,
|
||||
},
|
||||
OrderType.GTC,
|
||||
);
|
||||
|
||||
### Order types
|
||||
console.log("Order ID:", response.orderID);
|
||||
console.log("Status:", response.status);
|
||||
```
|
||||
|
||||
* **FOK**: A Fill-Or-Kill order is an market order to buy (in dollars) or sell (in shares) shares that must be executed immediately in its entirety; otherwise, the entire order will be cancelled.
|
||||
* **FAK**: A Fill-And-Kill order is a market order to buy (in dollars) or sell (in shares) that will be executed immediately for as many shares as are available; any portion not filled at once is cancelled.
|
||||
* **GTC**: A Good-Til-Cancelled order is a limit order that is active until it is fulfilled or cancelled.
|
||||
* **GTD**: A Good-Til-Date order is a type of order that is active until its specified date (UTC seconds timestamp), unless it has already been fulfilled or cancelled. There is a security threshold of one minute. If the order needs to expire in 90 seconds the correct expiration value is: now + 1 minute + 30 seconds
|
||||
|
||||
### Response Format
|
||||
|
||||
| Name | Type | Description |
|
||||
| ----------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| success | boolean | boolean indicating if server-side err (`success = false`) -> server-side error |
|
||||
| errorMsg | string | error message in case of unsuccessful placement (in case `success = false`, e.g. `client-side error`, the reason is in `errorMsg`) |
|
||||
| orderId | string | id of order |
|
||||
| orderHashes | string\[] | hash of settlement transaction order was marketable and triggered a match |
|
||||
|
||||
### Insert Error Messages
|
||||
|
||||
If the `errorMsg` field of the response object from placement is not an empty string, the order was not able to be immediately placed. This might be because of a delay or because of a failure. If the `success` is not `true`, then there was an issue placing the order. The following `errorMessages` are possible:
|
||||
|
||||
#### Error
|
||||
|
||||
| Error | Success | Message | Description |
|
||||
| ------------------------------------ | ------- | --------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
||||
| INVALID\_ORDER\_MIN\_TICK\_SIZE | yes | order is invalid. Price breaks minimum tick size rules | order price isn't accurate to correct tick sizing |
|
||||
| INVALID\_ORDER\_MIN\_SIZE | yes | order is invalid. Size lower than the minimum | order size must meet min size threshold requirement |
|
||||
| INVALID\_ORDER\_DUPLICATED | yes | order is invalid. Duplicated. Same order has already been placed, can't be placed again | |
|
||||
| INVALID\_ORDER\_NOT\_ENOUGH\_BALANCE | yes | not enough balance / allowance | funder address doesn't have sufficient balance or allowance for order |
|
||||
| INVALID\_ORDER\_EXPIRATION | yes | invalid expiration | expiration field expresses a time before now |
|
||||
| INVALID\_ORDER\_ERROR | yes | could not insert order | system error while inserting order |
|
||||
| INVALID\_POST\_ONLY\_ORDER\_TYPE | yes | invalid post-only order: only GTC and GTD order types are allowed | post only flag attached to a market order |
|
||||
| INVALID\_POST\_ONLY\_ORDER | yes | invalid post-only order: order crosses book | post only order would match |
|
||||
| EXECUTION\_ERROR | yes | could not run the execution | system error while attempting to execute trade |
|
||||
| ORDER\_DELAYED | no | order match delayed due to market conditions | order placement delayed |
|
||||
| DELAYING\_ORDER\_ERROR | yes | error delaying the order | system error while delaying order |
|
||||
| FOK\_ORDER\_NOT\_FILLED\_ERROR | yes | order couldn't be fully filled, FOK orders are fully filled/killed | FOK order not fully filled so can't be placed |
|
||||
| MARKET\_NOT\_READY | no | the market is not yet ready to process new orders | system not accepting orders for market yet |
|
||||
|
||||
### Insert Statuses
|
||||
|
||||
When placing an order, a status field is included. The status field provides additional information regarding the order's state as a result of the placement. Possible values include:
|
||||
|
||||
#### Status
|
||||
|
||||
| Status | Description |
|
||||
| --------- | ------------------------------------------------------------ |
|
||||
| matched | order placed and matched with an existing resting order |
|
||||
| live | order placed and resting on the book |
|
||||
| delayed | order marketable, but subject to matching delay |
|
||||
| unmatched | order marketable, but failure delaying, placement successful |
|
||||
|
||||
<RequestExample>
|
||||
```python Python theme={null}
|
||||
from py_clob_client.client import ClobClient
|
||||
from py_clob_client.clob_types import OrderArgs, OrderType
|
||||
from py_clob_client.order_builder.constants import BUY
|
||||
|
||||
host: str = "https://clob.polymarket.com"
|
||||
key: str = "" #This is your Private Key. Export from reveal.polymarket.com or from your Web3 Application
|
||||
chain_id: int = 137 #No need to adjust this
|
||||
POLYMARKET_PROXY_ADDRESS: str = '' #This is the address you deposit/send USDC to to FUND your Polymarket account.
|
||||
|
||||
#Select from the following 3 initialization options to matches your login method, and remove any unused lines so only one client is initialized.
|
||||
|
||||
|
||||
### Initialization of a client using a Polymarket Proxy associated with an Email/Magic account. If you login with your email use this example.
|
||||
client = ClobClient(host, key=key, chain_id=chain_id, signature_type=1, funder=POLYMARKET_PROXY_ADDRESS)
|
||||
|
||||
### Initialization of a client using a Polymarket Proxy associated with a Browser Wallet(Metamask, Coinbase Wallet, etc)
|
||||
client = ClobClient(host, key=key, chain_id=chain_id, signature_type=2, funder=POLYMARKET_PROXY_ADDRESS)
|
||||
|
||||
### Initialization of a client that trades directly from an EOA.
|
||||
client = ClobClient(host, key=key, chain_id=chain_id)
|
||||
|
||||
## Create and sign a limit order buying 100 YES tokens for 0.50c each
|
||||
#Refer to the Markets API documentation to locate a tokenID: https://docs.polymarket.com/developers/gamma-markets-api/get-markets
|
||||
|
||||
client.set_api_creds(client.create_or_derive_api_creds())
|
||||
|
||||
order_args = OrderArgs(
|
||||
price=0.01,
|
||||
size=5.0,
|
||||
side=BUY,
|
||||
token_id="", #Token ID you want to purchase goes here.
|
||||
response = client.create_and_post_order(
|
||||
OrderArgs(
|
||||
token_id="TOKEN_ID",
|
||||
price=0.50,
|
||||
size=10,
|
||||
side=BUY,
|
||||
),
|
||||
options={
|
||||
"tick_size": "0.01",
|
||||
"neg_risk": False,
|
||||
},
|
||||
order_type=OrderType.GTC
|
||||
)
|
||||
signed_order = client.create_order(order_args)
|
||||
|
||||
## GTC(Good-Till-Cancelled) Order
|
||||
resp = client.post_order(signed_order, OrderType.GTC)
|
||||
print(resp)
|
||||
print("Order ID:", response["orderID"])
|
||||
print("Status:", response["status"])
|
||||
```
|
||||
</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);
|
||||
```
|
||||
|
||||
```javascript typescript theme={null}
|
||||
// GTC Order example
|
||||
//
|
||||
import { Side, OrderType } from "@polymarket/clob-client";
|
||||
```python Python theme={null}
|
||||
# Step 1: Create and sign locally
|
||||
signed_order = client.create_order(
|
||||
OrderArgs(
|
||||
token_id="TOKEN_ID",
|
||||
price=0.50,
|
||||
size=10,
|
||||
side=BUY,
|
||||
),
|
||||
options={
|
||||
"tick_size": "0.01",
|
||||
"neg_risk": False,
|
||||
}
|
||||
)
|
||||
|
||||
async function main() {
|
||||
// Create a buy order for 100 YES for 0.50c
|
||||
// YES: 71321045679252212594626385532706912750332728571942532289631379312455583992563
|
||||
const order = await clobClient.createOrder({
|
||||
tokenID:
|
||||
"71321045679252212594626385532706912750332728571942532289631379312455583992563",
|
||||
# Step 2: Submit to the CLOB
|
||||
response = client.post_order(signed_order, OrderType.GTC)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## GTD Orders (Expiring)
|
||||
|
||||
GTD orders auto-expire at a specified time. Useful for quoting around known events.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Expire in 1 hour (+ 60s security threshold buffer)
|
||||
const expiration = Math.floor(Date.now() / 1000) + 60 + 3600;
|
||||
|
||||
const response = await client.createAndPostOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
price: 0.5,
|
||||
size: 10,
|
||||
side: Side.BUY,
|
||||
size: 100,
|
||||
feeRateBps: 0,
|
||||
nonce: 1,
|
||||
});
|
||||
console.log("Created Order", order);
|
||||
expiration,
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
OrderType.GTD,
|
||||
);
|
||||
```
|
||||
|
||||
// Send it to the server
|
||||
```python Python theme={null}
|
||||
import time
|
||||
|
||||
// GTC Order
|
||||
const resp = await clobClient.postOrder(order, OrderType.GTC);
|
||||
console.log(resp);
|
||||
}
|
||||
# Expire in 1 hour (+ 60s security threshold buffer)
|
||||
expiration = int(time.time()) + 60 + 3600
|
||||
|
||||
main();
|
||||
// GTD Order example
|
||||
//
|
||||
response = client.create_and_post_order(
|
||||
OrderArgs(
|
||||
token_id="TOKEN_ID",
|
||||
price=0.50,
|
||||
size=10,
|
||||
side=BUY,
|
||||
expiration=expiration,
|
||||
),
|
||||
options={
|
||||
"tick_size": "0.01",
|
||||
"neg_risk": False,
|
||||
},
|
||||
order_type=OrderType.GTD
|
||||
)
|
||||
```
|
||||
</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";
|
||||
|
||||
async function main() {
|
||||
// Create a buy order for 100 YES for 0.50c that expires in 1 minute
|
||||
// YES: 71321045679252212594626385532706912750332728571942532289631379312455583992563
|
||||
|
||||
// There is a 1 minute of security threshold for the expiration field.
|
||||
// If we need the order to expire in 30 seconds the correct expiration value is:
|
||||
// now + 1 miute + 30 seconds
|
||||
const oneMinute = 60 * 1000;
|
||||
const seconds = 30 * 1000;
|
||||
const expiration = parseInt(
|
||||
((new Date().getTime() + oneMinute + seconds) / 1000).toString()
|
||||
);
|
||||
|
||||
const order = await clobClient.createOrder({
|
||||
tokenID:
|
||||
"71321045679252212594626385532706912750332728571942532289631379312455583992563",
|
||||
price: 0.5,
|
||||
// FOK BUY: spend exactly $100 or cancel entirely
|
||||
const buyOrder = await client.createMarketOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
side: Side.BUY,
|
||||
size: 100,
|
||||
feeRateBps: 0,
|
||||
nonce: 1,
|
||||
// There is a 1 minute of security threshold for the expiration field.
|
||||
// If we need the order to expire in 30 seconds the correct expiration value is:
|
||||
// now + 1 miute + 30 seconds
|
||||
expiration: expiration,
|
||||
});
|
||||
console.log("Created Order", order);
|
||||
amount: 100, // dollar amount
|
||||
price: 0.5, // worst-price limit (slippage protection)
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
);
|
||||
await client.postOrder(buyOrder, OrderType.FOK);
|
||||
|
||||
// Send it to the server
|
||||
|
||||
// GTD Order
|
||||
const resp = await clobClient.postOrder(order, OrderType.GTD);
|
||||
console.log(resp);
|
||||
}
|
||||
|
||||
main();
|
||||
// FOK BUY Order example
|
||||
//
|
||||
import { Side, OrderType } from "@polymarket/clob-client";
|
||||
|
||||
async function main() {
|
||||
// Create a market buy order for $100
|
||||
// YES: 71321045679252212594626385532706912750332728571942532289631379312455583992563
|
||||
|
||||
const marketOrder = await clobClient.createMarketOrder({
|
||||
side: Side.BUY,
|
||||
tokenID:
|
||||
"71321045679252212594626385532706912750332728571942532289631379312455583992563",
|
||||
amount: 100, // $$$
|
||||
feeRateBps: 0,
|
||||
nonce: 0,
|
||||
price: 0.5,
|
||||
});
|
||||
console.log("Created Order", order);
|
||||
|
||||
// Send it to the server
|
||||
// FOK Order
|
||||
const resp = await clobClient.postOrder(order, OrderType.FOK);
|
||||
console.log(resp);
|
||||
}
|
||||
|
||||
main();
|
||||
// FOK SELL Order example
|
||||
//
|
||||
import { Side, OrderType } from "@polymarket/clob-client";
|
||||
|
||||
async function main() {
|
||||
// Create a market sell order for 100 shares
|
||||
// YES: 71321045679252212594626385532706912750332728571942532289631379312455583992563
|
||||
|
||||
const marketOrder = await clobClient.createMarketOrder({
|
||||
// FOK SELL: sell exactly 200 shares or cancel entirely
|
||||
const sellOrder = await client.createMarketOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
side: Side.SELL,
|
||||
tokenID:
|
||||
"71321045679252212594626385532706912750332728571942532289631379312455583992563",
|
||||
amount: 100, // shares
|
||||
feeRateBps: 0,
|
||||
nonce: 0,
|
||||
price: 0.5,
|
||||
});
|
||||
console.log("Created Order", order);
|
||||
|
||||
// Send it to the server
|
||||
// FOK Order
|
||||
const resp = await clobClient.postOrder(order, OrderType.FOK);
|
||||
console.log(resp);
|
||||
}
|
||||
|
||||
main();
|
||||
amount: 200, // number of shares
|
||||
price: 0.45, // worst-price limit (slippage protection)
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
);
|
||||
await client.postOrder(sellOrder, OrderType.FOK);
|
||||
```
|
||||
</RequestExample>
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.order_builder.constants import BUY, SELL
|
||||
from py_clob_client.clob_types import OrderType
|
||||
|
||||
# FOK BUY: spend exactly $100 or cancel entirely
|
||||
buy_order = client.create_market_order(
|
||||
token_id="TOKEN_ID",
|
||||
side=BUY,
|
||||
amount=100, # dollar amount
|
||||
price=0.50, # worst-price limit (slippage protection)
|
||||
options={"tick_size": "0.01", "neg_risk": False},
|
||||
)
|
||||
client.post_order(buy_order, OrderType.FOK)
|
||||
|
||||
# FOK SELL: sell exactly 200 shares or cancel entirely
|
||||
sell_order = client.create_market_order(
|
||||
token_id="TOKEN_ID",
|
||||
side=SELL,
|
||||
amount=200, # number of shares
|
||||
price=0.45, # worst-price limit (slippage protection)
|
||||
options={"tick_size": "0.01", "neg_risk": False},
|
||||
)
|
||||
client.post_order(sell_order, OrderType.FOK)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
* **FOK** — fill entirely or cancel the whole order
|
||||
* **FAK** — fill what's available, cancel the rest
|
||||
|
||||
The `price` field on market orders acts as a **worst-price limit** (slippage protection), not a target execution price.
|
||||
|
||||
### One-Step Market Order
|
||||
|
||||
For convenience, `createAndPostMarketOrder` handles creation, signing, and submission in one call:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const response = await client.createAndPostMarketOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
side: Side.BUY,
|
||||
amount: 100,
|
||||
price: 0.5,
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
OrderType.FOK,
|
||||
);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
response = client.create_and_post_market_order(
|
||||
token_id="TOKEN_ID",
|
||||
side=BUY,
|
||||
amount=100,
|
||||
price=0.50,
|
||||
options={"tick_size": "0.01", "neg_risk": False},
|
||||
order_type=OrderType.FOK,
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Post-Only Orders
|
||||
|
||||
Post-only orders guarantee you're always the maker. If the order would match immediately (cross the spread), it's rejected instead of executed.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const response = await client.postOrder(signedOrder, OrderType.GTC, true);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
response = client.post_order(signed_order, OrderType.GTC, post_only=True)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
* Only works with **GTC** and **GTD** order types
|
||||
* Rejected if combined with FOK or FAK
|
||||
|
||||
***
|
||||
|
||||
## Batch Orders
|
||||
|
||||
Place up to **15 orders** in a single request:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { OrderType, Side, PostOrdersArgs } from "@polymarket/clob-client";
|
||||
|
||||
const orders: PostOrdersArgs[] = [
|
||||
{
|
||||
order: await client.createOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
price: 0.48,
|
||||
side: Side.BUY,
|
||||
size: 500,
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
),
|
||||
orderType: OrderType.GTC,
|
||||
},
|
||||
{
|
||||
order: await client.createOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
price: 0.52,
|
||||
side: Side.SELL,
|
||||
size: 500,
|
||||
},
|
||||
{ tickSize: "0.01", negRisk: false },
|
||||
),
|
||||
orderType: OrderType.GTC,
|
||||
},
|
||||
];
|
||||
|
||||
const response = await client.postOrders(orders);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OrderArgs, OrderType, PostOrdersArgs
|
||||
from py_clob_client.order_builder.constants import BUY, SELL
|
||||
|
||||
response = client.post_orders([
|
||||
PostOrdersArgs(
|
||||
order=client.create_order(OrderArgs(
|
||||
price=0.48,
|
||||
size=500,
|
||||
side=BUY,
|
||||
token_id="TOKEN_ID",
|
||||
), options={"tick_size": "0.01", "neg_risk": False}),
|
||||
orderType=OrderType.GTC,
|
||||
),
|
||||
PostOrdersArgs(
|
||||
order=client.create_order(OrderArgs(
|
||||
price=0.52,
|
||||
size=500,
|
||||
side=SELL,
|
||||
token_id="TOKEN_ID",
|
||||
), options={"tick_size": "0.01", "neg_risk": False}),
|
||||
orderType=OrderType.GTC,
|
||||
),
|
||||
])
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Order Options
|
||||
|
||||
Every order requires two market-specific options: `tickSize` and `negRisk`. For details on signature types (`0` = EOA, `1` = POLY\_PROXY, `2` = GNOSIS\_SAFE), see [Authentication](/api-reference/authentication#signature-types-and-funder).
|
||||
|
||||
### Tick Sizes
|
||||
|
||||
Your order price must conform to the market's tick size, or the order is rejected.
|
||||
|
||||
| Tick Size | Precision | Example Prices |
|
||||
| --------- | ---------- | ---------------------- |
|
||||
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
|
||||
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
|
||||
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
|
||||
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const tickSize = await client.getTickSize("TOKEN_ID");
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
tick_size = client.get_tick_size("TOKEN_ID")
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Negative Risk
|
||||
|
||||
Multi-outcome events (3+ outcomes) use the Neg Risk CTF Exchange. Pass `negRisk: true` for these markets.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const isNegRisk = await client.getNegRisk("TOKEN_ID");
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
is_neg_risk = client.get_neg_risk("TOKEN_ID")
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Tip>
|
||||
Both values are also available on the market object: `minimum_tick_size` and
|
||||
`neg_risk`.
|
||||
</Tip>
|
||||
|
||||
***
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
|
||||
|
||||
* **BUY orders**: USDC.e allowance >= spending amount
|
||||
* **SELL orders**: conditional token allowance >= selling amount
|
||||
|
||||
Order size is limited by your available balance minus amounts reserved by existing open orders:
|
||||
|
||||
$$
|
||||
\text{maxOrderSize} = \text{balance} - \sum(\text{openOrderSize} - \text{filledAmount})
|
||||
$$
|
||||
|
||||
<Warning>
|
||||
Orders are continuously monitored for validity — balances, allowances, and
|
||||
onchain cancellations are tracked in real time. Any maker caught intentionally
|
||||
abusing these checks will be blacklisted.
|
||||
</Warning>
|
||||
|
||||
### Advanced Parameters
|
||||
|
||||
These optional fields can be passed in the `UserOrder` object for fine-grained control:
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| ------------ | ------ | ----------------------------------------------- |
|
||||
| `feeRateBps` | number | Fee rate in basis points (default: market rate) |
|
||||
| `nonce` | number | Custom nonce for order uniqueness |
|
||||
| `taker` | string | Restrict the order to a specific taker address |
|
||||
|
||||
### Sports Markets
|
||||
|
||||
Sports markets have additional behaviors:
|
||||
|
||||
* Outstanding limit orders are **automatically cancelled** once the game begins, clearing the entire order book at the official start time
|
||||
* Marketable orders have a **3-second placement delay** before matching
|
||||
* Game start times can shift — monitor your orders closely, as they may not be cleared if the start time changes unexpectedly
|
||||
|
||||
***
|
||||
|
||||
## Response
|
||||
|
||||
A successful order placement returns:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"success": true,
|
||||
"errorMsg": "",
|
||||
"orderID": "0xabc123...",
|
||||
"takingAmount": "",
|
||||
"makingAmount": "",
|
||||
"status": "live",
|
||||
"transactionsHashes": [],
|
||||
"tradeIDs": []
|
||||
}
|
||||
```
|
||||
|
||||
### Statuses
|
||||
|
||||
| Status | Description |
|
||||
| ----------- | ----------------------------------------------------------- |
|
||||
| `live` | Order resting on the book |
|
||||
| `matched` | Order matched immediately with a resting order |
|
||||
| `delayed` | Marketable order subject to a matching delay |
|
||||
| `unmatched` | Marketable but failed to delay — placement still successful |
|
||||
|
||||
### Error Messages
|
||||
|
||||
| Error | Description |
|
||||
| ---------------------------------- | ----------------------------------------------- |
|
||||
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
|
||||
| `INVALID_ORDER_MIN_SIZE` | Order size below the minimum threshold |
|
||||
| `INVALID_ORDER_DUPLICATED` | Identical order already placed |
|
||||
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Insufficient balance or allowance |
|
||||
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
|
||||
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only used with FOK/FAK |
|
||||
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
|
||||
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
|
||||
| `INVALID_ORDER_ERROR` | System error inserting the order |
|
||||
| `EXECUTION_ERROR` | System error executing the trade |
|
||||
| `ORDER_DELAYED` | Order match delayed due to market conditions |
|
||||
| `DELAYING_ORDER_ERROR` | System error while delaying the order |
|
||||
| `MARKET_NOT_READY` | Market not yet accepting orders |
|
||||
|
||||
***
|
||||
|
||||
## Heartbeat
|
||||
|
||||
The heartbeat endpoint maintains session liveness. If a valid heartbeat is not received within **10 seconds** (with a 5-second buffer), **all open orders are cancelled**.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
let heartbeatId = "";
|
||||
setInterval(async () => {
|
||||
const resp = await client.postHeartbeat(heartbeatId);
|
||||
heartbeatId = resp.heartbeat_id;
|
||||
}, 5000);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
import time
|
||||
|
||||
heartbeat_id = ""
|
||||
while True:
|
||||
resp = client.post_heartbeat(heartbeat_id)
|
||||
heartbeat_id = resp["heartbeat_id"]
|
||||
time.sleep(5)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
* Include the most recent `heartbeat_id` in each request. Use an empty string for the first request.
|
||||
* If you send an expired ID, the server responds with `400` and the correct ID. Update and retry.
|
||||
|
||||
***
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Cancel Orders" icon="xmark" href="/trading/orders/cancel">
|
||||
Cancel single, multiple, or all open orders
|
||||
</Card>
|
||||
|
||||
<Card title="Order Attribution" icon="tag" href="/trading/orders/attribution">
|
||||
Attribute orders to your builder account for volume credit
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -2,52 +2,462 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Get Active Orders
|
||||
# Overview
|
||||
|
||||
<Tip> This endpoint requires a L2 Header. </Tip>
|
||||
> Order types, tick sizes, and querying orders
|
||||
|
||||
Get active order(s) for a specific market.
|
||||
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
|
||||
|
||||
**HTTP REQUEST**
|
||||
The underlying order primitive is structured, hashed, and signed using the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) standard, then executed onchain via the Exchange contract. Preparing orders manually is involved, so we recommend using the open-source [TypeScript](https://github.com/Polymarket/clob-client) or [Python](https://github.com/Polymarket/py-clob-client) SDK clients, which handle signing and submission for you.
|
||||
|
||||
`GET /<clob-endpoint>/data/orders`
|
||||
<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>
|
||||
|
||||
### Request Parameters
|
||||
***
|
||||
|
||||
| Name | Required | Type | Description |
|
||||
| --------- | -------- | ------ | ------------------------------------ |
|
||||
| id | no | string | id of order to get information about |
|
||||
| market | no | string | condition id of market |
|
||||
| asset\_id | no | string | id of the asset/token |
|
||||
## Order Types
|
||||
|
||||
### Response Format
|
||||
| Type | Behavior | Use Case |
|
||||
| ---------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------- |
|
||||
| **GTC** (Good-Til-Cancelled) | Rests on the book until filled or cancelled | Default for passive limit orders |
|
||||
| **GTD** (Good-Til-Date) | Active until a specified expiration time (UTC seconds timestamp), unless filled or cancelled first | Auto-expire orders before known events |
|
||||
| **FOK** (Fill-Or-Kill) | Must be filled immediately and entirely, or the whole order is cancelled | All-or-nothing execution |
|
||||
| **FAK** (Fill-And-Kill) | Fills as many shares as available immediately, then cancels any unfilled remainder | Partial immediate execution |
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ------------ | ---------------------------------------------------- |
|
||||
| null | OpenOrder\[] | list of open orders filtered by the query parameters |
|
||||
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
|
||||
* **BUY**: specify the dollar amount you want to spend
|
||||
* **SELL**: specify the number of shares you want to sell
|
||||
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
|
||||
|
||||
<Note>
|
||||
**GTD expiration**: There is a security threshold of one minute. If you need
|
||||
the order to expire in 90 seconds, the correct expiration value is `now + 1
|
||||
minute + 30 seconds`.
|
||||
</Note>
|
||||
|
||||
### Post-Only Orders
|
||||
|
||||
Post-only orders are limit orders that will only rest on the book and not match immediately on entry.
|
||||
|
||||
* If a post-only order would cross the spread (i.e., it is marketable), it will be **rejected** rather than executed.
|
||||
* Post-only **cannot** be combined with market order types (FOK or FAK). If `postOnly = true` is sent with a market order type, the order will be rejected.
|
||||
* Post-only can only be used with **GTC** and **GTD** order types.
|
||||
|
||||
***
|
||||
|
||||
## Tick Sizes
|
||||
|
||||
Markets have different minimum price increments (tick sizes). Your order price must conform to the market's tick size, or the order will be rejected.
|
||||
|
||||
| Tick Size | Price Precision | Example Prices |
|
||||
| --------- | --------------- | ---------------------- |
|
||||
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
|
||||
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
|
||||
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
|
||||
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
|
||||
|
||||
Retrieve the tick size for a market using the SDK:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const tickSize = await client.getTickSize(tokenID);
|
||||
// Returns: "0.1" | "0.01" | "0.001" | "0.0001"
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
tick_size = client.get_tick_size(token_id)
|
||||
# Returns: "0.1" | "0.01" | "0.001" | "0.0001"
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Tip>
|
||||
You can also check the `minimum_tick_size` field on a market object returned
|
||||
by the [Markets API](/market-data/fetching-markets).
|
||||
</Tip>
|
||||
|
||||
***
|
||||
|
||||
## Negative Risk
|
||||
|
||||
Multi-outcome events (e.g., "Who will win the election?" with 3+ candidates) use a different exchange contract called the **Neg Risk CTF Exchange**. When placing orders on these markets, you must pass `negRisk: true` in the order options.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const response = await client.createAndPostOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
price: 0.5,
|
||||
size: 10,
|
||||
side: Side.BUY,
|
||||
},
|
||||
{
|
||||
tickSize: "0.01",
|
||||
negRisk: true, // Required for multi-outcome markets
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
response = client.create_and_post_order(
|
||||
OrderArgs(
|
||||
token_id="TOKEN_ID",
|
||||
price=0.50,
|
||||
size=10,
|
||||
side=BUY,
|
||||
),
|
||||
options={
|
||||
"tick_size": "0.01",
|
||||
"neg_risk": True, # Required for multi-outcome markets
|
||||
}
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const isNegRisk = await client.getNegRisk(tokenID);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
is_neg_risk = client.get_neg_risk(token_id)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Allowances
|
||||
|
||||
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
|
||||
|
||||
* **Buying**: the funder must have set a **USDC.e** allowance greater than or equal to the spending amount.
|
||||
* **Selling**: the funder must have set a **conditional token** allowance greater than or equal to the selling amount.
|
||||
|
||||
This allows the Exchange contract to execute settlement according to your signed order instructions.
|
||||
|
||||
***
|
||||
|
||||
## Validity Checks
|
||||
|
||||
Orders are continually monitored to make sure they remain valid. This includes tracking:
|
||||
|
||||
* Underlying balances
|
||||
* Allowances
|
||||
* Onchain order cancellations
|
||||
|
||||
<Warning>
|
||||
Any maker caught intentionally abusing these checks will be blacklisted.
|
||||
</Warning>
|
||||
|
||||
There are also limits on order placement per market. You can only place orders that sum to less than or equal to your available balance for each market. For example, if you have 500 USDC.e in your funding wallet, you can place one order to buy 1000 YES at \$0.50 — but any additional buy orders in that market will be rejected since your entire balance is reserved for the first order.
|
||||
|
||||
The max size you can place for an order is:
|
||||
|
||||
$$
|
||||
\text{maxOrderSize} = \text{underlyingAssetBalance} - \sum(\text{orderSize} - \text{orderFillAmount})
|
||||
$$
|
||||
|
||||
***
|
||||
|
||||
## Querying Orders
|
||||
|
||||
All query endpoints require [L2 authentication](/api-reference/authentication).
|
||||
|
||||
### Get a Single Order
|
||||
|
||||
Retrieve details for a specific order by its ID:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const order = await client.getOrder("0xb816482a...");
|
||||
console.log(order);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
order = client.get_order("0xb816482a...")
|
||||
print(order)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Get Open Orders
|
||||
|
||||
Retrieve your open orders, optionally filtered by market or asset:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// All open orders
|
||||
const orders = await client.getOpenOrders();
|
||||
|
||||
// Filtered by market
|
||||
const marketOrders = await client.getOpenOrders({
|
||||
market: "0xbd31dc8a...",
|
||||
});
|
||||
|
||||
// Filtered by asset
|
||||
const assetOrders = await client.getOpenOrders({
|
||||
asset_id: "52114319501245...",
|
||||
});
|
||||
```
|
||||
|
||||
<RequestExample>
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OpenOrderParams
|
||||
|
||||
resp = client.get_orders(
|
||||
# All open orders
|
||||
orders = client.get_orders()
|
||||
|
||||
# Filtered by market
|
||||
market_orders = client.get_orders(
|
||||
OpenOrderParams(
|
||||
market="0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
|
||||
market="0xbd31dc8a...",
|
||||
)
|
||||
)
|
||||
print(resp)
|
||||
print("Done!")
|
||||
```
|
||||
</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...",
|
||||
});
|
||||
```
|
||||
|
||||
```javascript Typescript theme={null}
|
||||
async function main() {
|
||||
const resp = await clobClient.getOpenOrders({
|
||||
market:
|
||||
"0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
|
||||
});
|
||||
console.log(resp);
|
||||
console.log(`Done!`);
|
||||
}
|
||||
main();
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import TradeParams
|
||||
|
||||
# All trades
|
||||
trades = client.get_trades()
|
||||
|
||||
# Filtered by market
|
||||
market_trades = client.get_trades(
|
||||
TradeParams(
|
||||
market="0xbd31dc8a...",
|
||||
)
|
||||
)
|
||||
```
|
||||
</RequestExample>
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Heartbeat
|
||||
|
||||
The heartbeat endpoint maintains session liveness for order safety. If a valid heartbeat is not received within **10 seconds** (with up to a 5-second buffer), **all of your open orders will be cancelled**.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Send heartbeats in a loop
|
||||
let heartbeatId = "";
|
||||
setInterval(async () => {
|
||||
const resp = await client.postHeartbeat(heartbeatId);
|
||||
heartbeatId = resp.heartbeat_id;
|
||||
}, 5000);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
import time
|
||||
|
||||
heartbeat_id = ""
|
||||
while True:
|
||||
resp = client.post_heartbeat(heartbeat_id)
|
||||
heartbeat_id = resp["heartbeat_id"]
|
||||
time.sleep(5)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
* On each request, include the most recent `heartbeat_id` you received. For your first request, use an empty string.
|
||||
* If you send an invalid or expired `heartbeat_id`, the server responds with a `400 Bad Request` and provides the correct `heartbeat_id` in the response. Update your client and retry.
|
||||
|
||||
***
|
||||
|
||||
## Order Scoring
|
||||
|
||||
Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Single order
|
||||
const scoring = await client.isOrderScoring({ orderId: "0x..." });
|
||||
console.log(scoring); // { scoring: true }
|
||||
|
||||
// Multiple orders
|
||||
const batchScoring = await client.areOrdersScoring({
|
||||
orderIds: ["0x...", "0x..."],
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OrderScoringParams, OrdersScoringParams
|
||||
|
||||
# Single order
|
||||
scoring = client.is_order_scoring(
|
||||
OrderScoringParams(orderId="0x...")
|
||||
)
|
||||
|
||||
# Multiple orders
|
||||
batch_scoring = client.are_orders_scoring(
|
||||
OrdersScoringParams(orderIds=["0x...", "0x..."])
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Onchain Order Info
|
||||
|
||||
When a trade is settled onchain, the Exchange contract emits an `OrderFilled` event with the following fields:
|
||||
|
||||
| Field | Description |
|
||||
| ------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| `orderHash` | Unique hash for the filled order |
|
||||
| `maker` | The user who generated the order and source of funds |
|
||||
| `taker` | The user filling the order, or the Exchange contract if multiple limit orders are filled |
|
||||
| `makerAssetId` | ID of the asset given out. If `0`, the order is a **BUY** (giving USDC.e for outcome tokens) |
|
||||
| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving USDC.e for outcome tokens) |
|
||||
| `makerAmountFilled` | Amount of the asset given out |
|
||||
| `takerAmountFilled` | Amount of the asset received |
|
||||
| `fee` | Fees paid by the order maker |
|
||||
|
||||
***
|
||||
|
||||
## Error Messages
|
||||
|
||||
When placing an order, the response may include an `errorMsg` if the order could not be placed. If `success` is `false`, there was a server-side error:
|
||||
|
||||
| Error | Description |
|
||||
| ---------------------------------- | ------------------------------------------------------ |
|
||||
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
|
||||
| `INVALID_ORDER_MIN_SIZE` | Order size is below the minimum threshold |
|
||||
| `INVALID_ORDER_DUPLICATED` | Identical order has already been placed |
|
||||
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Funder doesn't have sufficient balance or allowance |
|
||||
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
|
||||
| `INVALID_ORDER_ERROR` | System error while inserting order |
|
||||
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only flag used with a market order type (FOK/FAK) |
|
||||
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
|
||||
| `EXECUTION_ERROR` | System error while executing trade |
|
||||
| `ORDER_DELAYED` | Order placement delayed due to market conditions |
|
||||
| `DELAYING_ORDER_ERROR` | System error while delaying order |
|
||||
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
|
||||
| `MARKET_NOT_READY` | Market is not yet accepting orders |
|
||||
|
||||
### Insert Statuses
|
||||
|
||||
When an order is successfully placed, the response includes a `status` field:
|
||||
|
||||
| Status | Description |
|
||||
| ----------- | -------------------------------------------------------------------- |
|
||||
| `matched` | Order placed and matched with a resting order |
|
||||
| `live` | Order placed and resting on the book |
|
||||
| `delayed` | Order is marketable but subject to a matching delay |
|
||||
| `unmatched` | Order is marketable but failed to delay — placement still successful |
|
||||
|
||||
***
|
||||
|
||||
## Security
|
||||
|
||||
Polymarket's Exchange contract has been audited by Chainsecurity ([View Audit](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)).
|
||||
|
||||
The operator's privileges are limited to order matching and ensuring correct ordering. Operators cannot set prices or execute unauthorized trades. Users can cancel orders onchain independently if trust issues arise.
|
||||
|
||||
***
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Create Order" icon="plus" href="/trading/orders/create">
|
||||
Build, sign, and submit orders
|
||||
</Card>
|
||||
|
||||
<Card title="Cancel Order" icon="xmark" href="/trading/orders/cancel">
|
||||
Cancel single, multiple, or all orders
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -2,65 +2,462 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Get Order
|
||||
# Overview
|
||||
|
||||
> Get information about an existing order
|
||||
> Order types, tick sizes, and querying orders
|
||||
|
||||
<Tip>This endpoint requires a L2 Header. </Tip>
|
||||
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
|
||||
|
||||
Get single order by id.
|
||||
The underlying order primitive is structured, hashed, and signed using the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) standard, then executed onchain via the Exchange contract. Preparing orders manually is involved, so we recommend using the open-source [TypeScript](https://github.com/Polymarket/clob-client) or [Python](https://github.com/Polymarket/py-clob-client) SDK clients, which handle signing and submission for you.
|
||||
|
||||
**HTTP REQUEST**
|
||||
<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>
|
||||
|
||||
`GET /<clob-endpoint>/data/order/<order_hash>`
|
||||
***
|
||||
|
||||
### Request Parameters
|
||||
## Order Types
|
||||
|
||||
| Name | Required | Type | Description |
|
||||
| ---- | -------- | ------ | ------------------------------------ |
|
||||
| id | no | string | id of order to get information about |
|
||||
| Type | Behavior | Use Case |
|
||||
| ---------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------- |
|
||||
| **GTC** (Good-Til-Cancelled) | Rests on the book until filled or cancelled | Default for passive limit orders |
|
||||
| **GTD** (Good-Til-Date) | Active until a specified expiration time (UTC seconds timestamp), unless filled or cancelled first | Auto-expire orders before known events |
|
||||
| **FOK** (Fill-Or-Kill) | Must be filled immediately and entirely, or the whole order is cancelled | All-or-nothing execution |
|
||||
| **FAK** (Fill-And-Kill) | Fills as many shares as available immediately, then cancels any unfilled remainder | Partial immediate execution |
|
||||
|
||||
### Response Format
|
||||
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
|
||||
* **BUY**: specify the dollar amount you want to spend
|
||||
* **SELL**: specify the number of shares you want to sell
|
||||
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
|
||||
|
||||
| Name | Type | Description |
|
||||
| ----- | --------- | ------------------ |
|
||||
| order | OpenOrder | order if it exists |
|
||||
<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>
|
||||
|
||||
An `OpenOrder` object is of the form:
|
||||
### Post-Only Orders
|
||||
|
||||
| Name | Type | Description |
|
||||
| ----------------- | --------- | -------------------------------------------------------------- |
|
||||
| associate\_trades | string\[] | any Trade id the order has been partially included in |
|
||||
| id | string | order id |
|
||||
| status | string | order current status |
|
||||
| market | string | market id (condition id) |
|
||||
| original\_size | string | original order size at placement |
|
||||
| outcome | string | human readable outcome the order is for |
|
||||
| maker\_address | string | maker address (funder) |
|
||||
| owner | string | api key |
|
||||
| price | string | price |
|
||||
| side | string | buy or sell |
|
||||
| size\_matched | string | size of order that has been matched/filled |
|
||||
| asset\_id | string | token id |
|
||||
| expiration | string | unix timestamp when the order expired, 0 if it does not expire |
|
||||
| type | string | order type (GTC, FOK, GTD) |
|
||||
| created\_at | string | unix timestamp when the order was created |
|
||||
Post-only orders are limit orders that will only rest on the book and not match immediately on entry.
|
||||
|
||||
* If a post-only order would cross the spread (i.e., it is marketable), it will be **rejected** rather than executed.
|
||||
* Post-only **cannot** be combined with market order types (FOK or FAK). If `postOnly = true` is sent with a market order type, the order will be rejected.
|
||||
* Post-only can only be used with **GTC** and **GTD** order types.
|
||||
|
||||
***
|
||||
|
||||
## Tick Sizes
|
||||
|
||||
Markets have different minimum price increments (tick sizes). Your order price must conform to the market's tick size, or the order will be rejected.
|
||||
|
||||
| Tick Size | Price Precision | Example Prices |
|
||||
| --------- | --------------- | ---------------------- |
|
||||
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
|
||||
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
|
||||
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
|
||||
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
|
||||
|
||||
Retrieve the tick size for a market using the SDK:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const tickSize = await client.getTickSize(tokenID);
|
||||
// Returns: "0.1" | "0.01" | "0.001" | "0.0001"
|
||||
```
|
||||
|
||||
<RequestExample>
|
||||
```python Python theme={null}
|
||||
order = clob_client.get_order("0xb816482a5187a3d3db49cbaf6fe3ddf24f53e6c712b5a4bf5e01d0ec7b11dabc")
|
||||
tick_size = client.get_tick_size(token_id)
|
||||
# Returns: "0.1" | "0.01" | "0.001" | "0.0001"
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Tip>
|
||||
You can also check the `minimum_tick_size` field on a market object returned
|
||||
by the [Markets API](/market-data/fetching-markets).
|
||||
</Tip>
|
||||
|
||||
***
|
||||
|
||||
## Negative Risk
|
||||
|
||||
Multi-outcome events (e.g., "Who will win the election?" with 3+ candidates) use a different exchange contract called the **Neg Risk CTF Exchange**. When placing orders on these markets, you must pass `negRisk: true` in the order options.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const response = await client.createAndPostOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
price: 0.5,
|
||||
size: 10,
|
||||
side: Side.BUY,
|
||||
},
|
||||
{
|
||||
tickSize: "0.01",
|
||||
negRisk: true, // Required for multi-outcome markets
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
response = client.create_and_post_order(
|
||||
OrderArgs(
|
||||
token_id="TOKEN_ID",
|
||||
price=0.50,
|
||||
size=10,
|
||||
side=BUY,
|
||||
),
|
||||
options={
|
||||
"tick_size": "0.01",
|
||||
"neg_risk": True, # Required for multi-outcome markets
|
||||
}
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const isNegRisk = await client.getNegRisk(tokenID);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
is_neg_risk = client.get_neg_risk(token_id)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Allowances
|
||||
|
||||
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
|
||||
|
||||
* **Buying**: the funder must have set a **USDC.e** allowance greater than or equal to the spending amount.
|
||||
* **Selling**: the funder must have set a **conditional token** allowance greater than or equal to the selling amount.
|
||||
|
||||
This allows the Exchange contract to execute settlement according to your signed order instructions.
|
||||
|
||||
***
|
||||
|
||||
## Validity Checks
|
||||
|
||||
Orders are continually monitored to make sure they remain valid. This includes tracking:
|
||||
|
||||
* Underlying balances
|
||||
* Allowances
|
||||
* Onchain order cancellations
|
||||
|
||||
<Warning>
|
||||
Any maker caught intentionally abusing these checks will be blacklisted.
|
||||
</Warning>
|
||||
|
||||
There are also limits on order placement per market. You can only place orders that sum to less than or equal to your available balance for each market. For example, if you have 500 USDC.e in your funding wallet, you can place one order to buy 1000 YES at \$0.50 — but any additional buy orders in that market will be rejected since your entire balance is reserved for the first order.
|
||||
|
||||
The max size you can place for an order is:
|
||||
|
||||
$$
|
||||
\text{maxOrderSize} = \text{underlyingAssetBalance} - \sum(\text{orderSize} - \text{orderFillAmount})
|
||||
$$
|
||||
|
||||
***
|
||||
|
||||
## Querying Orders
|
||||
|
||||
All query endpoints require [L2 authentication](/api-reference/authentication).
|
||||
|
||||
### Get a Single Order
|
||||
|
||||
Retrieve details for a specific order by its ID:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const order = await client.getOrder("0xb816482a...");
|
||||
console.log(order);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
order = client.get_order("0xb816482a...")
|
||||
print(order)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
```javascript Typescript theme={null}
|
||||
async function main() {
|
||||
const order = await clobClient.getOrder(
|
||||
"0xb816482a5187a3d3db49cbaf6fe3ddf24f53e6c712b5a4bf5e01d0ec7b11dabc"
|
||||
);
|
||||
console.log(order);
|
||||
}
|
||||
### Get Open Orders
|
||||
|
||||
main();
|
||||
Retrieve your open orders, optionally filtered by market or asset:
|
||||
|
||||
<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...",
|
||||
});
|
||||
```
|
||||
</RequestExample>
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OpenOrderParams
|
||||
|
||||
# All open orders
|
||||
orders = client.get_orders()
|
||||
|
||||
# Filtered by market
|
||||
market_orders = client.get_orders(
|
||||
OpenOrderParams(
|
||||
market="0xbd31dc8a...",
|
||||
)
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### OpenOrder Object
|
||||
|
||||
Each order returned contains these fields:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------ | --------- | ------------------------------------------------------------ |
|
||||
| `id` | string | Order ID |
|
||||
| `status` | string | Current order status |
|
||||
| `market` | string | Market ID (condition ID) |
|
||||
| `asset_id` | string | Token ID |
|
||||
| `side` | string | `BUY` or `SELL` |
|
||||
| `original_size` | string | Original order size at placement |
|
||||
| `size_matched` | string | Amount that has been filled |
|
||||
| `price` | string | Limit price |
|
||||
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
|
||||
| `order_type` | string | Order type (GTC, GTD, FOK, FAK) |
|
||||
| `maker_address` | string | Funder address |
|
||||
| `owner` | string | API key of the order owner |
|
||||
| `expiration` | string | Unix timestamp when the order expires (`0` if no expiration) |
|
||||
| `associate_trades` | string\[] | Trade IDs this order has been partially included in |
|
||||
| `created_at` | string | Unix timestamp when the order was created |
|
||||
|
||||
***
|
||||
|
||||
## Trade History
|
||||
|
||||
When an order is matched, it creates a trade. Trades go through the following statuses:
|
||||
|
||||
| Status | Terminal? | Description |
|
||||
| ----------- | --------- | -------------------------------------------------------------------- |
|
||||
| `MATCHED` | No | Matched and sent to the executor service for onchain submission |
|
||||
| `MINED` | No | Observed as mined on the chain, no finality threshold yet |
|
||||
| `CONFIRMED` | Yes | Achieved strong probabilistic finality — trade successful |
|
||||
| `RETRYING` | No | Transaction failed (revert or reorg) — being retried by the operator |
|
||||
| `FAILED` | Yes | Trade failed permanently and is not being retried |
|
||||
|
||||
### Trade Object
|
||||
|
||||
Each trade contains these fields:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------ | ------ | ------------------------------------------------------------ |
|
||||
| `id` | string | Trade ID |
|
||||
| `taker_order_id` | string | Taker order ID (hash) |
|
||||
| `market` | string | Market ID (condition ID) |
|
||||
| `asset_id` | string | Token ID |
|
||||
| `side` | string | `BUY` or `SELL` |
|
||||
| `size` | string | Trade size |
|
||||
| `fee_rate_bps` | string | Fee rate in basis points |
|
||||
| `price` | string | Trade price |
|
||||
| `status` | string | Trade status (see table above) |
|
||||
| `match_time` | string | Unix timestamp when the trade was matched |
|
||||
| `last_update` | string | Unix timestamp of last status update |
|
||||
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
|
||||
| `owner` | string | API key ID of the trade owner |
|
||||
| `maker_address` | string | Funder address |
|
||||
| `trader_side` | string | Whether you were `TAKER` or `MAKER` in this trade |
|
||||
| `transaction_hash` | string | Onchain transaction hash (available after mining) |
|
||||
| `maker_orders` | array | Array of maker orders matched against this trade (see below) |
|
||||
|
||||
### MakerOrder Fields
|
||||
|
||||
Each entry in the `maker_orders` array contains:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ---------------- | ------ | ---------------------------- |
|
||||
| `order_id` | string | Maker order ID (hash) |
|
||||
| `owner` | string | Maker's API key ID |
|
||||
| `maker_address` | string | Maker's funder address |
|
||||
| `matched_amount` | string | Amount matched in this trade |
|
||||
| `price` | string | Maker order price |
|
||||
| `fee_rate_bps` | string | Maker fee rate in bps |
|
||||
| `asset_id` | string | Token ID |
|
||||
| `outcome` | string | Outcome name |
|
||||
| `side` | string | `BUY` or `SELL` |
|
||||
|
||||
Retrieve your trades with the SDK:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// All trades
|
||||
const trades = await client.getTrades();
|
||||
|
||||
// Filtered by market
|
||||
const marketTrades = await client.getTrades({
|
||||
market: "0xbd31dc8a...",
|
||||
});
|
||||
|
||||
// With pagination
|
||||
const paginatedTrades = await client.getTradesPaginated({
|
||||
market: "0xbd31dc8a...",
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import TradeParams
|
||||
|
||||
# All trades
|
||||
trades = client.get_trades()
|
||||
|
||||
# Filtered by market
|
||||
market_trades = client.get_trades(
|
||||
TradeParams(
|
||||
market="0xbd31dc8a...",
|
||||
)
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Heartbeat
|
||||
|
||||
The heartbeat endpoint maintains session liveness for order safety. If a valid heartbeat is not received within **10 seconds** (with up to a 5-second buffer), **all of your open orders will be cancelled**.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Send heartbeats in a loop
|
||||
let heartbeatId = "";
|
||||
setInterval(async () => {
|
||||
const resp = await client.postHeartbeat(heartbeatId);
|
||||
heartbeatId = resp.heartbeat_id;
|
||||
}, 5000);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
import time
|
||||
|
||||
heartbeat_id = ""
|
||||
while True:
|
||||
resp = client.post_heartbeat(heartbeat_id)
|
||||
heartbeat_id = resp["heartbeat_id"]
|
||||
time.sleep(5)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
* On each request, include the most recent `heartbeat_id` you received. For your first request, use an empty string.
|
||||
* If you send an invalid or expired `heartbeat_id`, the server responds with a `400 Bad Request` and provides the correct `heartbeat_id` in the response. Update your client and retry.
|
||||
|
||||
***
|
||||
|
||||
## Order Scoring
|
||||
|
||||
Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Single order
|
||||
const scoring = await client.isOrderScoring({ orderId: "0x..." });
|
||||
console.log(scoring); // { scoring: true }
|
||||
|
||||
// Multiple orders
|
||||
const batchScoring = await client.areOrdersScoring({
|
||||
orderIds: ["0x...", "0x..."],
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OrderScoringParams, OrdersScoringParams
|
||||
|
||||
# Single order
|
||||
scoring = client.is_order_scoring(
|
||||
OrderScoringParams(orderId="0x...")
|
||||
)
|
||||
|
||||
# Multiple orders
|
||||
batch_scoring = client.are_orders_scoring(
|
||||
OrdersScoringParams(orderIds=["0x...", "0x..."])
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Onchain Order Info
|
||||
|
||||
When a trade is settled onchain, the Exchange contract emits an `OrderFilled` event with the following fields:
|
||||
|
||||
| Field | Description |
|
||||
| ------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| `orderHash` | Unique hash for the filled order |
|
||||
| `maker` | The user who generated the order and source of funds |
|
||||
| `taker` | The user filling the order, or the Exchange contract if multiple limit orders are filled |
|
||||
| `makerAssetId` | ID of the asset given out. If `0`, the order is a **BUY** (giving USDC.e for outcome tokens) |
|
||||
| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving USDC.e for outcome tokens) |
|
||||
| `makerAmountFilled` | Amount of the asset given out |
|
||||
| `takerAmountFilled` | Amount of the asset received |
|
||||
| `fee` | Fees paid by the order maker |
|
||||
|
||||
***
|
||||
|
||||
## Error Messages
|
||||
|
||||
When placing an order, the response may include an `errorMsg` if the order could not be placed. If `success` is `false`, there was a server-side error:
|
||||
|
||||
| Error | Description |
|
||||
| ---------------------------------- | ------------------------------------------------------ |
|
||||
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
|
||||
| `INVALID_ORDER_MIN_SIZE` | Order size is below the minimum threshold |
|
||||
| `INVALID_ORDER_DUPLICATED` | Identical order has already been placed |
|
||||
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Funder doesn't have sufficient balance or allowance |
|
||||
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
|
||||
| `INVALID_ORDER_ERROR` | System error while inserting order |
|
||||
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only flag used with a market order type (FOK/FAK) |
|
||||
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
|
||||
| `EXECUTION_ERROR` | System error while executing trade |
|
||||
| `ORDER_DELAYED` | Order placement delayed due to market conditions |
|
||||
| `DELAYING_ORDER_ERROR` | System error while delaying order |
|
||||
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
|
||||
| `MARKET_NOT_READY` | Market is not yet accepting orders |
|
||||
|
||||
### Insert Statuses
|
||||
|
||||
When an order is successfully placed, the response includes a `status` field:
|
||||
|
||||
| Status | Description |
|
||||
| ----------- | -------------------------------------------------------------------- |
|
||||
| `matched` | Order placed and matched with a resting order |
|
||||
| `live` | Order placed and resting on the book |
|
||||
| `delayed` | Order is marketable but subject to a matching delay |
|
||||
| `unmatched` | Order is marketable but failed to delay — placement still successful |
|
||||
|
||||
***
|
||||
|
||||
## Security
|
||||
|
||||
Polymarket's Exchange contract has been audited by Chainsecurity ([View Audit](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)).
|
||||
|
||||
The operator's privileges are limited to order matching and ensuring correct ordering. Operators cannot set prices or execute unauthorized trades. Users can cancel orders onchain independently if trust issues arise.
|
||||
|
||||
***
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Create Order" icon="plus" href="/trading/orders/create">
|
||||
Build, sign, and submit orders
|
||||
</Card>
|
||||
|
||||
<Card title="Cancel Order" icon="xmark" href="/trading/orders/cancel">
|
||||
Cancel single, multiple, or all orders
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -2,17 +2,462 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Onchain Order Info
|
||||
# Overview
|
||||
|
||||
## How do I interpret the OrderFilled onchain event?
|
||||
> Order types, tick sizes, and querying orders
|
||||
|
||||
Given an OrderFilled event:
|
||||
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
|
||||
|
||||
* `orderHash`: a unique hash for the Order being filled
|
||||
* `maker`: the user generating the order and the source of funds for the order
|
||||
* `taker`: the user filling the order OR the Exchange contract if the order fills multiple limit orders
|
||||
* `makerAssetId`: id of the asset that is given out. If 0, indicates that the Order is a BUY, giving USDC in exchange for Outcome tokens. Else, indicates that the Order is a SELL, giving Outcome tokens in exchange for USDC.
|
||||
* `takerAssetId`: id of the asset that is received. If 0, indicates that the Order is a SELL, receiving USDC in exchange for Outcome tokens. Else, indicates that the Order is a BUY, receiving Outcome tokens in exchange for USDC.
|
||||
* `makerAmountFilled`: the amount of the asset that is given out.
|
||||
* `takerAmountFilled`: the amount of the asset that is received.
|
||||
* `fee`: the fees paid by the order maker
|
||||
The underlying order primitive is structured, hashed, and signed using the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) standard, then executed onchain via the Exchange contract. Preparing orders manually is involved, so we recommend using the open-source [TypeScript](https://github.com/Polymarket/clob-client) or [Python](https://github.com/Polymarket/py-clob-client) SDK clients, which handle signing and submission for you.
|
||||
|
||||
<Info>
|
||||
If you prefer to use the REST API directly, you'll need to manage order
|
||||
signing yourself. See [Authentication](/api-reference/authentication) for details on
|
||||
constructing the required headers.
|
||||
</Info>
|
||||
|
||||
***
|
||||
|
||||
## Order Types
|
||||
|
||||
| Type | Behavior | Use Case |
|
||||
| ---------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------- |
|
||||
| **GTC** (Good-Til-Cancelled) | Rests on the book until filled or cancelled | Default for passive limit orders |
|
||||
| **GTD** (Good-Til-Date) | Active until a specified expiration time (UTC seconds timestamp), unless filled or cancelled first | Auto-expire orders before known events |
|
||||
| **FOK** (Fill-Or-Kill) | Must be filled immediately and entirely, or the whole order is cancelled | All-or-nothing execution |
|
||||
| **FAK** (Fill-And-Kill) | Fills as many shares as available immediately, then cancels any unfilled remainder | Partial immediate execution |
|
||||
|
||||
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
|
||||
* **BUY**: specify the dollar amount you want to spend
|
||||
* **SELL**: specify the number of shares you want to sell
|
||||
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
|
||||
|
||||
<Note>
|
||||
**GTD expiration**: There is a security threshold of one minute. If you need
|
||||
the order to expire in 90 seconds, the correct expiration value is `now + 1
|
||||
minute + 30 seconds`.
|
||||
</Note>
|
||||
|
||||
### Post-Only Orders
|
||||
|
||||
Post-only orders are limit orders that will only rest on the book and not match immediately on entry.
|
||||
|
||||
* If a post-only order would cross the spread (i.e., it is marketable), it will be **rejected** rather than executed.
|
||||
* Post-only **cannot** be combined with market order types (FOK or FAK). If `postOnly = true` is sent with a market order type, the order will be rejected.
|
||||
* Post-only can only be used with **GTC** and **GTD** order types.
|
||||
|
||||
***
|
||||
|
||||
## Tick Sizes
|
||||
|
||||
Markets have different minimum price increments (tick sizes). Your order price must conform to the market's tick size, or the order will be rejected.
|
||||
|
||||
| Tick Size | Price Precision | Example Prices |
|
||||
| --------- | --------------- | ---------------------- |
|
||||
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
|
||||
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
|
||||
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
|
||||
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
|
||||
|
||||
Retrieve the tick size for a market using the SDK:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const tickSize = await client.getTickSize(tokenID);
|
||||
// Returns: "0.1" | "0.01" | "0.001" | "0.0001"
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
tick_size = client.get_tick_size(token_id)
|
||||
# Returns: "0.1" | "0.01" | "0.001" | "0.0001"
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Tip>
|
||||
You can also check the `minimum_tick_size` field on a market object returned
|
||||
by the [Markets API](/market-data/fetching-markets).
|
||||
</Tip>
|
||||
|
||||
***
|
||||
|
||||
## Negative Risk
|
||||
|
||||
Multi-outcome events (e.g., "Who will win the election?" with 3+ candidates) use a different exchange contract called the **Neg Risk CTF Exchange**. When placing orders on these markets, you must pass `negRisk: true` in the order options.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const response = await client.createAndPostOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
price: 0.5,
|
||||
size: 10,
|
||||
side: Side.BUY,
|
||||
},
|
||||
{
|
||||
tickSize: "0.01",
|
||||
negRisk: true, // Required for multi-outcome markets
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
response = client.create_and_post_order(
|
||||
OrderArgs(
|
||||
token_id="TOKEN_ID",
|
||||
price=0.50,
|
||||
size=10,
|
||||
side=BUY,
|
||||
),
|
||||
options={
|
||||
"tick_size": "0.01",
|
||||
"neg_risk": True, # Required for multi-outcome markets
|
||||
}
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const isNegRisk = await client.getNegRisk(tokenID);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
is_neg_risk = client.get_neg_risk(token_id)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Allowances
|
||||
|
||||
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
|
||||
|
||||
* **Buying**: the funder must have set a **USDC.e** allowance greater than or equal to the spending amount.
|
||||
* **Selling**: the funder must have set a **conditional token** allowance greater than or equal to the selling amount.
|
||||
|
||||
This allows the Exchange contract to execute settlement according to your signed order instructions.
|
||||
|
||||
***
|
||||
|
||||
## Validity Checks
|
||||
|
||||
Orders are continually monitored to make sure they remain valid. This includes tracking:
|
||||
|
||||
* Underlying balances
|
||||
* Allowances
|
||||
* Onchain order cancellations
|
||||
|
||||
<Warning>
|
||||
Any maker caught intentionally abusing these checks will be blacklisted.
|
||||
</Warning>
|
||||
|
||||
There are also limits on order placement per market. You can only place orders that sum to less than or equal to your available balance for each market. For example, if you have 500 USDC.e in your funding wallet, you can place one order to buy 1000 YES at \$0.50 — but any additional buy orders in that market will be rejected since your entire balance is reserved for the first order.
|
||||
|
||||
The max size you can place for an order is:
|
||||
|
||||
$$
|
||||
\text{maxOrderSize} = \text{underlyingAssetBalance} - \sum(\text{orderSize} - \text{orderFillAmount})
|
||||
$$
|
||||
|
||||
***
|
||||
|
||||
## Querying Orders
|
||||
|
||||
All query endpoints require [L2 authentication](/api-reference/authentication).
|
||||
|
||||
### Get a Single Order
|
||||
|
||||
Retrieve details for a specific order by its ID:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const order = await client.getOrder("0xb816482a...");
|
||||
console.log(order);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
order = client.get_order("0xb816482a...")
|
||||
print(order)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Get Open Orders
|
||||
|
||||
Retrieve your open orders, optionally filtered by market or asset:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// All open orders
|
||||
const orders = await client.getOpenOrders();
|
||||
|
||||
// Filtered by market
|
||||
const marketOrders = await client.getOpenOrders({
|
||||
market: "0xbd31dc8a...",
|
||||
});
|
||||
|
||||
// Filtered by asset
|
||||
const assetOrders = await client.getOpenOrders({
|
||||
asset_id: "52114319501245...",
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OpenOrderParams
|
||||
|
||||
# All open orders
|
||||
orders = client.get_orders()
|
||||
|
||||
# Filtered by market
|
||||
market_orders = client.get_orders(
|
||||
OpenOrderParams(
|
||||
market="0xbd31dc8a...",
|
||||
)
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### OpenOrder Object
|
||||
|
||||
Each order returned contains these fields:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------ | --------- | ------------------------------------------------------------ |
|
||||
| `id` | string | Order ID |
|
||||
| `status` | string | Current order status |
|
||||
| `market` | string | Market ID (condition ID) |
|
||||
| `asset_id` | string | Token ID |
|
||||
| `side` | string | `BUY` or `SELL` |
|
||||
| `original_size` | string | Original order size at placement |
|
||||
| `size_matched` | string | Amount that has been filled |
|
||||
| `price` | string | Limit price |
|
||||
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
|
||||
| `order_type` | string | Order type (GTC, GTD, FOK, FAK) |
|
||||
| `maker_address` | string | Funder address |
|
||||
| `owner` | string | API key of the order owner |
|
||||
| `expiration` | string | Unix timestamp when the order expires (`0` if no expiration) |
|
||||
| `associate_trades` | string\[] | Trade IDs this order has been partially included in |
|
||||
| `created_at` | string | Unix timestamp when the order was created |
|
||||
|
||||
***
|
||||
|
||||
## Trade History
|
||||
|
||||
When an order is matched, it creates a trade. Trades go through the following statuses:
|
||||
|
||||
| Status | Terminal? | Description |
|
||||
| ----------- | --------- | -------------------------------------------------------------------- |
|
||||
| `MATCHED` | No | Matched and sent to the executor service for onchain submission |
|
||||
| `MINED` | No | Observed as mined on the chain, no finality threshold yet |
|
||||
| `CONFIRMED` | Yes | Achieved strong probabilistic finality — trade successful |
|
||||
| `RETRYING` | No | Transaction failed (revert or reorg) — being retried by the operator |
|
||||
| `FAILED` | Yes | Trade failed permanently and is not being retried |
|
||||
|
||||
### Trade Object
|
||||
|
||||
Each trade contains these fields:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------ | ------ | ------------------------------------------------------------ |
|
||||
| `id` | string | Trade ID |
|
||||
| `taker_order_id` | string | Taker order ID (hash) |
|
||||
| `market` | string | Market ID (condition ID) |
|
||||
| `asset_id` | string | Token ID |
|
||||
| `side` | string | `BUY` or `SELL` |
|
||||
| `size` | string | Trade size |
|
||||
| `fee_rate_bps` | string | Fee rate in basis points |
|
||||
| `price` | string | Trade price |
|
||||
| `status` | string | Trade status (see table above) |
|
||||
| `match_time` | string | Unix timestamp when the trade was matched |
|
||||
| `last_update` | string | Unix timestamp of last status update |
|
||||
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
|
||||
| `owner` | string | API key ID of the trade owner |
|
||||
| `maker_address` | string | Funder address |
|
||||
| `trader_side` | string | Whether you were `TAKER` or `MAKER` in this trade |
|
||||
| `transaction_hash` | string | Onchain transaction hash (available after mining) |
|
||||
| `maker_orders` | array | Array of maker orders matched against this trade (see below) |
|
||||
|
||||
### MakerOrder Fields
|
||||
|
||||
Each entry in the `maker_orders` array contains:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ---------------- | ------ | ---------------------------- |
|
||||
| `order_id` | string | Maker order ID (hash) |
|
||||
| `owner` | string | Maker's API key ID |
|
||||
| `maker_address` | string | Maker's funder address |
|
||||
| `matched_amount` | string | Amount matched in this trade |
|
||||
| `price` | string | Maker order price |
|
||||
| `fee_rate_bps` | string | Maker fee rate in bps |
|
||||
| `asset_id` | string | Token ID |
|
||||
| `outcome` | string | Outcome name |
|
||||
| `side` | string | `BUY` or `SELL` |
|
||||
|
||||
Retrieve your trades with the SDK:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// All trades
|
||||
const trades = await client.getTrades();
|
||||
|
||||
// Filtered by market
|
||||
const marketTrades = await client.getTrades({
|
||||
market: "0xbd31dc8a...",
|
||||
});
|
||||
|
||||
// With pagination
|
||||
const paginatedTrades = await client.getTradesPaginated({
|
||||
market: "0xbd31dc8a...",
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import TradeParams
|
||||
|
||||
# All trades
|
||||
trades = client.get_trades()
|
||||
|
||||
# Filtered by market
|
||||
market_trades = client.get_trades(
|
||||
TradeParams(
|
||||
market="0xbd31dc8a...",
|
||||
)
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Heartbeat
|
||||
|
||||
The heartbeat endpoint maintains session liveness for order safety. If a valid heartbeat is not received within **10 seconds** (with up to a 5-second buffer), **all of your open orders will be cancelled**.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Send heartbeats in a loop
|
||||
let heartbeatId = "";
|
||||
setInterval(async () => {
|
||||
const resp = await client.postHeartbeat(heartbeatId);
|
||||
heartbeatId = resp.heartbeat_id;
|
||||
}, 5000);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
import time
|
||||
|
||||
heartbeat_id = ""
|
||||
while True:
|
||||
resp = client.post_heartbeat(heartbeat_id)
|
||||
heartbeat_id = resp["heartbeat_id"]
|
||||
time.sleep(5)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
* On each request, include the most recent `heartbeat_id` you received. For your first request, use an empty string.
|
||||
* If you send an invalid or expired `heartbeat_id`, the server responds with a `400 Bad Request` and provides the correct `heartbeat_id` in the response. Update your client and retry.
|
||||
|
||||
***
|
||||
|
||||
## Order Scoring
|
||||
|
||||
Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Single order
|
||||
const scoring = await client.isOrderScoring({ orderId: "0x..." });
|
||||
console.log(scoring); // { scoring: true }
|
||||
|
||||
// Multiple orders
|
||||
const batchScoring = await client.areOrdersScoring({
|
||||
orderIds: ["0x...", "0x..."],
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OrderScoringParams, OrdersScoringParams
|
||||
|
||||
# Single order
|
||||
scoring = client.is_order_scoring(
|
||||
OrderScoringParams(orderId="0x...")
|
||||
)
|
||||
|
||||
# Multiple orders
|
||||
batch_scoring = client.are_orders_scoring(
|
||||
OrdersScoringParams(orderIds=["0x...", "0x..."])
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Onchain Order Info
|
||||
|
||||
When a trade is settled onchain, the Exchange contract emits an `OrderFilled` event with the following fields:
|
||||
|
||||
| Field | Description |
|
||||
| ------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| `orderHash` | Unique hash for the filled order |
|
||||
| `maker` | The user who generated the order and source of funds |
|
||||
| `taker` | The user filling the order, or the Exchange contract if multiple limit orders are filled |
|
||||
| `makerAssetId` | ID of the asset given out. If `0`, the order is a **BUY** (giving USDC.e for outcome tokens) |
|
||||
| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving USDC.e for outcome tokens) |
|
||||
| `makerAmountFilled` | Amount of the asset given out |
|
||||
| `takerAmountFilled` | Amount of the asset received |
|
||||
| `fee` | Fees paid by the order maker |
|
||||
|
||||
***
|
||||
|
||||
## Error Messages
|
||||
|
||||
When placing an order, the response may include an `errorMsg` if the order could not be placed. If `success` is `false`, there was a server-side error:
|
||||
|
||||
| Error | Description |
|
||||
| ---------------------------------- | ------------------------------------------------------ |
|
||||
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
|
||||
| `INVALID_ORDER_MIN_SIZE` | Order size is below the minimum threshold |
|
||||
| `INVALID_ORDER_DUPLICATED` | Identical order has already been placed |
|
||||
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Funder doesn't have sufficient balance or allowance |
|
||||
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
|
||||
| `INVALID_ORDER_ERROR` | System error while inserting order |
|
||||
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only flag used with a market order type (FOK/FAK) |
|
||||
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
|
||||
| `EXECUTION_ERROR` | System error while executing trade |
|
||||
| `ORDER_DELAYED` | Order placement delayed due to market conditions |
|
||||
| `DELAYING_ORDER_ERROR` | System error while delaying order |
|
||||
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
|
||||
| `MARKET_NOT_READY` | Market is not yet accepting orders |
|
||||
|
||||
### Insert Statuses
|
||||
|
||||
When an order is successfully placed, the response includes a `status` field:
|
||||
|
||||
| Status | Description |
|
||||
| ----------- | -------------------------------------------------------------------- |
|
||||
| `matched` | Order placed and matched with a resting order |
|
||||
| `live` | Order placed and resting on the book |
|
||||
| `delayed` | Order is marketable but subject to a matching delay |
|
||||
| `unmatched` | Order is marketable but failed to delay — placement still successful |
|
||||
|
||||
***
|
||||
|
||||
## Security
|
||||
|
||||
Polymarket's Exchange contract has been audited by Chainsecurity ([View Audit](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)).
|
||||
|
||||
The operator's privileges are limited to order matching and ensuring correct ordering. Operators cannot set prices or execute unauthorized trades. Users can cancel orders onchain independently if trust issues arise.
|
||||
|
||||
***
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Create Order" icon="plus" href="/trading/orders/create">
|
||||
Build, sign, and submit orders
|
||||
</Card>
|
||||
|
||||
<Card title="Cancel Order" icon="xmark" href="/trading/orders/cancel">
|
||||
Cancel single, multiple, or all orders
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -2,32 +2,462 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Orders Overview
|
||||
# Overview
|
||||
|
||||
> Detailed instructions for creating, placing, and managing orders using Polymarket's CLOB API.
|
||||
> Order types, tick sizes, and querying orders
|
||||
|
||||
All orders are expressed as limit orders (can be marketable). The underlying order primitive must be in the form expected and executable by the on-chain binary limit order protocol contract. Preparing such an order is quite involved (structuring, hashing, signing), thus Polymarket suggests using the open source typescript, python and golang libraries.
|
||||
All orders on Polymarket are expressed as **limit orders**. Market orders are supported by submitting a limit order with a marketable price — your order executes immediately at the best available price on the book.
|
||||
|
||||
The underlying order primitive is structured, hashed, and signed using the [EIP-712](https://eips.ethereum.org/EIPS/eip-712) standard, then executed onchain via the Exchange contract. Preparing orders manually is involved, so we recommend using the open-source [TypeScript](https://github.com/Polymarket/clob-client) or [Python](https://github.com/Polymarket/py-clob-client) SDK clients, which handle signing and submission for you.
|
||||
|
||||
<Info>
|
||||
If you prefer to use the REST API directly, you'll need to manage order
|
||||
signing yourself. See [Authentication](/api-reference/authentication) for details on
|
||||
constructing the required headers.
|
||||
</Info>
|
||||
|
||||
***
|
||||
|
||||
## Order Types
|
||||
|
||||
| Type | Behavior | Use Case |
|
||||
| ---------------------------- | -------------------------------------------------------------------------------------------------- | -------------------------------------- |
|
||||
| **GTC** (Good-Til-Cancelled) | Rests on the book until filled or cancelled | Default for passive limit orders |
|
||||
| **GTD** (Good-Til-Date) | Active until a specified expiration time (UTC seconds timestamp), unless filled or cancelled first | Auto-expire orders before known events |
|
||||
| **FOK** (Fill-Or-Kill) | Must be filled immediately and entirely, or the whole order is cancelled | All-or-nothing execution |
|
||||
| **FAK** (Fill-And-Kill) | Fills as many shares as available immediately, then cancels any unfilled remainder | Partial immediate execution |
|
||||
|
||||
* **FOK** and **FAK** are market order types — they execute against resting liquidity immediately.
|
||||
* **BUY**: specify the dollar amount you want to spend
|
||||
* **SELL**: specify the number of shares you want to sell
|
||||
* **GTC** and **GTD** are limit order types — they rest on the book at your specified price.
|
||||
|
||||
<Note>
|
||||
**GTD expiration**: There is a security threshold of one minute. If you need
|
||||
the order to expire in 90 seconds, the correct expiration value is `now + 1
|
||||
minute + 30 seconds`.
|
||||
</Note>
|
||||
|
||||
### Post-Only Orders
|
||||
|
||||
Post-only orders are limit orders that will only rest on the book and not match immediately on entry.
|
||||
|
||||
* If a post-only order would cross the spread (i.e., it is marketable), it will be **rejected** rather than executed.
|
||||
* Post-only **cannot** be combined with market order types (FOK or FAK). If `postOnly = true` is sent with a market order type, the order will be rejected.
|
||||
* Post-only can only be used with **GTC** and **GTD** order types.
|
||||
|
||||
***
|
||||
|
||||
## Tick Sizes
|
||||
|
||||
Markets have different minimum price increments (tick sizes). Your order price must conform to the market's tick size, or the order will be rejected.
|
||||
|
||||
| Tick Size | Price Precision | Example Prices |
|
||||
| --------- | --------------- | ---------------------- |
|
||||
| `0.1` | 1 decimal | 0.1, 0.2, 0.5 |
|
||||
| `0.01` | 2 decimals | 0.01, 0.50, 0.99 |
|
||||
| `0.001` | 3 decimals | 0.001, 0.500, 0.999 |
|
||||
| `0.0001` | 4 decimals | 0.0001, 0.5000, 0.9999 |
|
||||
|
||||
Retrieve the tick size for a market using the SDK:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const tickSize = await client.getTickSize(tokenID);
|
||||
// Returns: "0.1" | "0.01" | "0.001" | "0.0001"
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
tick_size = client.get_tick_size(token_id)
|
||||
# Returns: "0.1" | "0.01" | "0.001" | "0.0001"
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Tip>
|
||||
You can also check the `minimum_tick_size` field on a market object returned
|
||||
by the [Markets API](/market-data/fetching-markets).
|
||||
</Tip>
|
||||
|
||||
***
|
||||
|
||||
## Negative Risk
|
||||
|
||||
Multi-outcome events (e.g., "Who will win the election?" with 3+ candidates) use a different exchange contract called the **Neg Risk CTF Exchange**. When placing orders on these markets, you must pass `negRisk: true` in the order options.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const response = await client.createAndPostOrder(
|
||||
{
|
||||
tokenID: "TOKEN_ID",
|
||||
price: 0.5,
|
||||
size: 10,
|
||||
side: Side.BUY,
|
||||
},
|
||||
{
|
||||
tickSize: "0.01",
|
||||
negRisk: true, // Required for multi-outcome markets
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
response = client.create_and_post_order(
|
||||
OrderArgs(
|
||||
token_id="TOKEN_ID",
|
||||
price=0.50,
|
||||
size=10,
|
||||
side=BUY,
|
||||
),
|
||||
options={
|
||||
"tick_size": "0.01",
|
||||
"neg_risk": True, # Required for multi-outcome markets
|
||||
}
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
You can check whether a market uses negative risk via the SDK or the market object's `neg_risk` field:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const isNegRisk = await client.getNegRisk(tokenID);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
is_neg_risk = client.get_neg_risk(token_id)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Allowances
|
||||
|
||||
To place an order, allowances must be set by the funder address for the specified `maker` asset for the Exchange contract. When buying, this means the funder must have set a USDC allowance greater than or equal to the spending amount. When selling, the funder must have set an allowance for the conditional token that is greater than or equal to the selling amount. This allows the Exchange contract to execute settlement according to the signed order instructions created by a user and matched by the operator.
|
||||
Before placing an order, your funder address must have approved the Exchange contract to spend the relevant tokens:
|
||||
|
||||
## Signature Types
|
||||
* **Buying**: the funder must have set a **USDC.e** allowance greater than or equal to the spending amount.
|
||||
* **Selling**: the funder must have set a **conditional token** allowance greater than or equal to the selling amount.
|
||||
|
||||
Polymarket’s CLOB supports 3 signature types. Orders must identify what signature type they use. The available typescript and python clients abstract the complexity of signing and preparing orders with the following signature types by allowing a funder address and signer type to be specified on initialization. The supported signature types are:
|
||||
This allows the Exchange contract to execute settlement according to your signed order instructions.
|
||||
|
||||
| Type | ID | Description |
|
||||
| ------------------ | -- | ------------------------------------------------------------------------------------------ |
|
||||
| EOA | 0 | EIP712 signature signed by an EOA |
|
||||
| POLY\_PROXY | 1 | EIP712 signatures signed by a signer associated with funding Polymarket proxy wallet |
|
||||
| POLY\_GNOSIS\_SAFE | 2 | EIP712 signatures signed by a signer associated with funding Polymarket gnosis safe wallet |
|
||||
***
|
||||
|
||||
## Validity Checks
|
||||
|
||||
Orders are continually monitored to make sure they remain valid. Specifically, this includes continually tracking underlying balances, allowances and on-chain order cancellations. Any maker that is caught intentionally abusing these checks (which are essentially real time) will be blacklisted.
|
||||
Orders are continually monitored to make sure they remain valid. This includes tracking:
|
||||
|
||||
Additionally, there are rails on order placement in a market. Specifically, you can only place orders that sum to less than or equal to your available balance for each market. For example if you have 500 USDC in your funding wallet, you can place one order to buy 1000 YES in marketA @ \$.50, then any additional buy orders to that market will be rejected since your entire balance is reserved for the first (and only) buy order. More explicitly the max size you can place for an order is:
|
||||
* Underlying balances
|
||||
* Allowances
|
||||
* Onchain order cancellations
|
||||
|
||||
<Warning>
|
||||
Any maker caught intentionally abusing these checks will be blacklisted.
|
||||
</Warning>
|
||||
|
||||
There are also limits on order placement per market. You can only place orders that sum to less than or equal to your available balance for each market. For example, if you have 500 USDC.e in your funding wallet, you can place one order to buy 1000 YES at \$0.50 — but any additional buy orders in that market will be rejected since your entire balance is reserved for the first order.
|
||||
|
||||
The max size you can place for an order is:
|
||||
|
||||
$$
|
||||
\text{maxOrderSize} = \text{underlyingAssetBalance} - \sum(\text{orderSize} - \text{orderFillAmount})
|
||||
$$
|
||||
|
||||
***
|
||||
|
||||
## Querying Orders
|
||||
|
||||
All query endpoints require [L2 authentication](/api-reference/authentication).
|
||||
|
||||
### Get a Single Order
|
||||
|
||||
Retrieve details for a specific order by its ID:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const order = await client.getOrder("0xb816482a...");
|
||||
console.log(order);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
order = client.get_order("0xb816482a...")
|
||||
print(order)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Get Open Orders
|
||||
|
||||
Retrieve your open orders, optionally filtered by market or asset:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// All open orders
|
||||
const orders = await client.getOpenOrders();
|
||||
|
||||
// Filtered by market
|
||||
const marketOrders = await client.getOpenOrders({
|
||||
market: "0xbd31dc8a...",
|
||||
});
|
||||
|
||||
// Filtered by asset
|
||||
const assetOrders = await client.getOpenOrders({
|
||||
asset_id: "52114319501245...",
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OpenOrderParams
|
||||
|
||||
# All open orders
|
||||
orders = client.get_orders()
|
||||
|
||||
# Filtered by market
|
||||
market_orders = client.get_orders(
|
||||
OpenOrderParams(
|
||||
market="0xbd31dc8a...",
|
||||
)
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### OpenOrder Object
|
||||
|
||||
Each order returned contains these fields:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------ | --------- | ------------------------------------------------------------ |
|
||||
| `id` | string | Order ID |
|
||||
| `status` | string | Current order status |
|
||||
| `market` | string | Market ID (condition ID) |
|
||||
| `asset_id` | string | Token ID |
|
||||
| `side` | string | `BUY` or `SELL` |
|
||||
| `original_size` | string | Original order size at placement |
|
||||
| `size_matched` | string | Amount that has been filled |
|
||||
| `price` | string | Limit price |
|
||||
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
|
||||
| `order_type` | string | Order type (GTC, GTD, FOK, FAK) |
|
||||
| `maker_address` | string | Funder address |
|
||||
| `owner` | string | API key of the order owner |
|
||||
| `expiration` | string | Unix timestamp when the order expires (`0` if no expiration) |
|
||||
| `associate_trades` | string\[] | Trade IDs this order has been partially included in |
|
||||
| `created_at` | string | Unix timestamp when the order was created |
|
||||
|
||||
***
|
||||
|
||||
## Trade History
|
||||
|
||||
When an order is matched, it creates a trade. Trades go through the following statuses:
|
||||
|
||||
| Status | Terminal? | Description |
|
||||
| ----------- | --------- | -------------------------------------------------------------------- |
|
||||
| `MATCHED` | No | Matched and sent to the executor service for onchain submission |
|
||||
| `MINED` | No | Observed as mined on the chain, no finality threshold yet |
|
||||
| `CONFIRMED` | Yes | Achieved strong probabilistic finality — trade successful |
|
||||
| `RETRYING` | No | Transaction failed (revert or reorg) — being retried by the operator |
|
||||
| `FAILED` | Yes | Trade failed permanently and is not being retried |
|
||||
|
||||
### Trade Object
|
||||
|
||||
Each trade contains these fields:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------ | ------ | ------------------------------------------------------------ |
|
||||
| `id` | string | Trade ID |
|
||||
| `taker_order_id` | string | Taker order ID (hash) |
|
||||
| `market` | string | Market ID (condition ID) |
|
||||
| `asset_id` | string | Token ID |
|
||||
| `side` | string | `BUY` or `SELL` |
|
||||
| `size` | string | Trade size |
|
||||
| `fee_rate_bps` | string | Fee rate in basis points |
|
||||
| `price` | string | Trade price |
|
||||
| `status` | string | Trade status (see table above) |
|
||||
| `match_time` | string | Unix timestamp when the trade was matched |
|
||||
| `last_update` | string | Unix timestamp of last status update |
|
||||
| `outcome` | string | Human-readable outcome (e.g., "Yes", "No") |
|
||||
| `owner` | string | API key ID of the trade owner |
|
||||
| `maker_address` | string | Funder address |
|
||||
| `trader_side` | string | Whether you were `TAKER` or `MAKER` in this trade |
|
||||
| `transaction_hash` | string | Onchain transaction hash (available after mining) |
|
||||
| `maker_orders` | array | Array of maker orders matched against this trade (see below) |
|
||||
|
||||
### MakerOrder Fields
|
||||
|
||||
Each entry in the `maker_orders` array contains:
|
||||
|
||||
| Field | Type | Description |
|
||||
| ---------------- | ------ | ---------------------------- |
|
||||
| `order_id` | string | Maker order ID (hash) |
|
||||
| `owner` | string | Maker's API key ID |
|
||||
| `maker_address` | string | Maker's funder address |
|
||||
| `matched_amount` | string | Amount matched in this trade |
|
||||
| `price` | string | Maker order price |
|
||||
| `fee_rate_bps` | string | Maker fee rate in bps |
|
||||
| `asset_id` | string | Token ID |
|
||||
| `outcome` | string | Outcome name |
|
||||
| `side` | string | `BUY` or `SELL` |
|
||||
|
||||
Retrieve your trades with the SDK:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// All trades
|
||||
const trades = await client.getTrades();
|
||||
|
||||
// Filtered by market
|
||||
const marketTrades = await client.getTrades({
|
||||
market: "0xbd31dc8a...",
|
||||
});
|
||||
|
||||
// With pagination
|
||||
const paginatedTrades = await client.getTradesPaginated({
|
||||
market: "0xbd31dc8a...",
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import TradeParams
|
||||
|
||||
# All trades
|
||||
trades = client.get_trades()
|
||||
|
||||
# Filtered by market
|
||||
market_trades = client.get_trades(
|
||||
TradeParams(
|
||||
market="0xbd31dc8a...",
|
||||
)
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Heartbeat
|
||||
|
||||
The heartbeat endpoint maintains session liveness for order safety. If a valid heartbeat is not received within **10 seconds** (with up to a 5-second buffer), **all of your open orders will be cancelled**.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Send heartbeats in a loop
|
||||
let heartbeatId = "";
|
||||
setInterval(async () => {
|
||||
const resp = await client.postHeartbeat(heartbeatId);
|
||||
heartbeatId = resp.heartbeat_id;
|
||||
}, 5000);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
import time
|
||||
|
||||
heartbeat_id = ""
|
||||
while True:
|
||||
resp = client.post_heartbeat(heartbeat_id)
|
||||
heartbeat_id = resp["heartbeat_id"]
|
||||
time.sleep(5)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
* On each request, include the most recent `heartbeat_id` you received. For your first request, use an empty string.
|
||||
* If you send an invalid or expired `heartbeat_id`, the server responds with a `400 Bad Request` and provides the correct `heartbeat_id` in the response. Update your client and retry.
|
||||
|
||||
***
|
||||
|
||||
## Order Scoring
|
||||
|
||||
Check if your resting orders are eligible for [maker rebates](/market-makers/maker-rebates) scoring:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// Single order
|
||||
const scoring = await client.isOrderScoring({ orderId: "0x..." });
|
||||
console.log(scoring); // { scoring: true }
|
||||
|
||||
// Multiple orders
|
||||
const batchScoring = await client.areOrdersScoring({
|
||||
orderIds: ["0x...", "0x..."],
|
||||
});
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OrderScoringParams, OrdersScoringParams
|
||||
|
||||
# Single order
|
||||
scoring = client.is_order_scoring(
|
||||
OrderScoringParams(orderId="0x...")
|
||||
)
|
||||
|
||||
# Multiple orders
|
||||
batch_scoring = client.are_orders_scoring(
|
||||
OrdersScoringParams(orderIds=["0x...", "0x..."])
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Onchain Order Info
|
||||
|
||||
When a trade is settled onchain, the Exchange contract emits an `OrderFilled` event with the following fields:
|
||||
|
||||
| Field | Description |
|
||||
| ------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| `orderHash` | Unique hash for the filled order |
|
||||
| `maker` | The user who generated the order and source of funds |
|
||||
| `taker` | The user filling the order, or the Exchange contract if multiple limit orders are filled |
|
||||
| `makerAssetId` | ID of the asset given out. If `0`, the order is a **BUY** (giving USDC.e for outcome tokens) |
|
||||
| `takerAssetId` | ID of the asset received. If `0`, the order is a **SELL** (receiving USDC.e for outcome tokens) |
|
||||
| `makerAmountFilled` | Amount of the asset given out |
|
||||
| `takerAmountFilled` | Amount of the asset received |
|
||||
| `fee` | Fees paid by the order maker |
|
||||
|
||||
***
|
||||
|
||||
## Error Messages
|
||||
|
||||
When placing an order, the response may include an `errorMsg` if the order could not be placed. If `success` is `false`, there was a server-side error:
|
||||
|
||||
| Error | Description |
|
||||
| ---------------------------------- | ------------------------------------------------------ |
|
||||
| `INVALID_ORDER_MIN_TICK_SIZE` | Price doesn't conform to the market's tick size |
|
||||
| `INVALID_ORDER_MIN_SIZE` | Order size is below the minimum threshold |
|
||||
| `INVALID_ORDER_DUPLICATED` | Identical order has already been placed |
|
||||
| `INVALID_ORDER_NOT_ENOUGH_BALANCE` | Funder doesn't have sufficient balance or allowance |
|
||||
| `INVALID_ORDER_EXPIRATION` | Expiration timestamp is in the past |
|
||||
| `INVALID_ORDER_ERROR` | System error while inserting order |
|
||||
| `INVALID_POST_ONLY_ORDER_TYPE` | Post-only flag used with a market order type (FOK/FAK) |
|
||||
| `INVALID_POST_ONLY_ORDER` | Post-only order would cross the book |
|
||||
| `EXECUTION_ERROR` | System error while executing trade |
|
||||
| `ORDER_DELAYED` | Order placement delayed due to market conditions |
|
||||
| `DELAYING_ORDER_ERROR` | System error while delaying order |
|
||||
| `FOK_ORDER_NOT_FILLED_ERROR` | FOK order couldn't be fully filled |
|
||||
| `MARKET_NOT_READY` | Market is not yet accepting orders |
|
||||
|
||||
### Insert Statuses
|
||||
|
||||
When an order is successfully placed, the response includes a `status` field:
|
||||
|
||||
| Status | Description |
|
||||
| ----------- | -------------------------------------------------------------------- |
|
||||
| `matched` | Order placed and matched with a resting order |
|
||||
| `live` | Order placed and resting on the book |
|
||||
| `delayed` | Order is marketable but subject to a matching delay |
|
||||
| `unmatched` | Order is marketable but failed to delay — placement still successful |
|
||||
|
||||
***
|
||||
|
||||
## Security
|
||||
|
||||
Polymarket's Exchange contract has been audited by Chainsecurity ([View Audit](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)).
|
||||
|
||||
The operator's privileges are limited to order matching and ensuring correct ordering. Operators cannot set prices or execute unauthorized trades. Users can cancel orders onchain independently if trust issues arise.
|
||||
|
||||
***
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Create Order" icon="plus" href="/trading/orders/create">
|
||||
Build, sign, and submit orders
|
||||
</Card>
|
||||
|
||||
<Card title="Cancel Order" icon="xmark" href="/trading/orders/cancel">
|
||||
Cancel single, multiple, or all orders
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
+165
-243
@@ -4,274 +4,211 @@
|
||||
|
||||
# Quickstart
|
||||
|
||||
> Initialize the CLOB and place your first order.
|
||||
> Place your first order on Polymarket
|
||||
|
||||
## Installation
|
||||
This guide walks you through placing an order on Polymarket end-to-end.
|
||||
|
||||
<CodeGroup>
|
||||
```bash TypeScript theme={null}
|
||||
npm install @polymarket/clob-client ethers
|
||||
```
|
||||
<Steps>
|
||||
<Step title="Install the SDK">
|
||||
<CodeGroup>
|
||||
```bash TypeScript theme={null}
|
||||
npm install @polymarket/clob-client ethers@5
|
||||
```
|
||||
|
||||
```bash Python theme={null}
|
||||
pip install py-clob-client
|
||||
```
|
||||
```bash Python theme={null}
|
||||
pip install py-clob-client
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
|
||||
```bash Rust theme={null}
|
||||
cargo add polymarket-client-sdk
|
||||
```
|
||||
</CodeGroup>
|
||||
<Step title="Set Up Your Client">
|
||||
Derive your API credentials and initialize the trading client. This example uses an EOA wallet (type `0`) — your wallet pays its own gas and acts as the funder:
|
||||
|
||||
***
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { ClobClient } from "@polymarket/clob-client";
|
||||
import { Wallet } from "ethers"; // v5.8.0
|
||||
|
||||
## Quick Start
|
||||
const HOST = "https://clob.polymarket.com";
|
||||
const CHAIN_ID = 137; // Polygon mainnet
|
||||
const signer = new Wallet(process.env.PRIVATE_KEY);
|
||||
|
||||
### 1. Setup Client
|
||||
// Derive API credentials
|
||||
const tempClient = new ClobClient(HOST, CHAIN_ID, signer);
|
||||
const apiCreds = await tempClient.createOrDeriveApiKey();
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { ClobClient } from "@polymarket/clob-client";
|
||||
import { Wallet } from "ethers"; // v5.8.0
|
||||
// Initialize trading client
|
||||
const client = new ClobClient(
|
||||
HOST,
|
||||
CHAIN_ID,
|
||||
signer,
|
||||
apiCreds,
|
||||
0, // EOA
|
||||
signer.address,
|
||||
);
|
||||
```
|
||||
|
||||
const HOST = "https://clob.polymarket.com";
|
||||
const CHAIN_ID = 137; // Polygon mainnet
|
||||
const signer = new Wallet(process.env.PRIVATE_KEY);
|
||||
```python Python theme={null}
|
||||
from py_clob_client.client import ClobClient
|
||||
import os
|
||||
|
||||
// Create or derive user API credentials
|
||||
const tempClient = new ClobClient(HOST, CHAIN_ID, signer);
|
||||
const apiCreds = await tempClient.createOrDeriveApiKey();
|
||||
|
||||
// See 'Signature Types' note below
|
||||
const signatureType = 0;
|
||||
|
||||
// Initialize trading client
|
||||
const client = new ClobClient(
|
||||
HOST,
|
||||
CHAIN_ID,
|
||||
signer,
|
||||
apiCreds,
|
||||
signatureType
|
||||
);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.client import ClobClient
|
||||
import os
|
||||
|
||||
host = "https://clob.polymarket.com"
|
||||
chain_id = 137 # Polygon mainnet
|
||||
private_key = os.getenv("PRIVATE_KEY")
|
||||
|
||||
# Create or derive user API credentials
|
||||
temp_client = ClobClient(host, key=private_key, chain_id=chain_id)
|
||||
api_creds = await temp_client.create_or_derive_api_key()
|
||||
|
||||
# See 'Signature Types' note below
|
||||
signature_type = 0
|
||||
|
||||
# Initialize trading client
|
||||
client = ClobClient(
|
||||
host,
|
||||
key=private_key,
|
||||
chain_id=chain_id,
|
||||
creds=api_creds,
|
||||
signature_type=signature_type
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Note>
|
||||
This quick start sets your EOA as the trading account. You'll need to fund this
|
||||
wallet to trade and pay for gas on transactions. Gas-less transactions are only
|
||||
available by deploying a proxy wallet and using Polymarket's Polygon relayer
|
||||
infrastructure.
|
||||
</Note>
|
||||
|
||||
<Accordion title="Signature Types">
|
||||
| Wallet Type | ID | When to Use |
|
||||
| ------------ | --- | ------------------------------------------------------ |
|
||||
| EOA | `0` | Standard Ethereum wallet (MetaMask) |
|
||||
| Custom Proxy | `1` | Specific to Magic Link users from Polymarket only |
|
||||
| Gnosis Safe | `2` | Injected providers (Metamask, Rabby, embedded wallets) |
|
||||
</Accordion>
|
||||
|
||||
***
|
||||
|
||||
### 2. Place an Order
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { Side } from "@polymarket/clob-client";
|
||||
|
||||
// Place a limit order in one step
|
||||
const response = await client.createAndPostOrder({
|
||||
tokenID: "YOUR_TOKEN_ID", // Get from Gamma API
|
||||
price: 0.65, // Price per share
|
||||
size: 10, // Number of shares
|
||||
side: Side.BUY, // or SELL
|
||||
});
|
||||
|
||||
console.log(`Order placed! ID: ${response.orderID}`);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OrderArgs
|
||||
from py_clob_client.order_builder.constants import BUY
|
||||
|
||||
# Place a limit order in one step
|
||||
response = await client.create_and_post_order(
|
||||
OrderArgs(
|
||||
token_id="YOUR_TOKEN_ID", # Get from Gamma API
|
||||
price=0.65, # Price per share
|
||||
size=10, # Number of shares
|
||||
side=BUY, # or SELL
|
||||
)
|
||||
)
|
||||
|
||||
print(f"Order placed! ID: {response['orderID']}")
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
### 3. 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`);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
# View all open orders
|
||||
open_orders = await client.get_open_orders()
|
||||
print(f"You have {len(open_orders)} open orders")
|
||||
|
||||
# View your trade history
|
||||
trades = await client.get_trades()
|
||||
print(f"You've made {len(trades)} trades")
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Complete Example
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { ClobClient, Side } from "@polymarket/clob-client";
|
||||
import { Wallet } from "ethers";
|
||||
|
||||
async function trade() {
|
||||
const HOST = "https://clob.polymarket.com";
|
||||
const CHAIN_ID = 137; // Polygon mainnet
|
||||
const signer = new Wallet(process.env.PRIVATE_KEY);
|
||||
|
||||
const tempClient = new ClobClient(HOST, CHAIN_ID, signer);
|
||||
const apiCreds = await tempClient.createOrDeriveApiKey();
|
||||
|
||||
const signatureType = 0;
|
||||
|
||||
const client = new ClobClient(
|
||||
HOST,
|
||||
CHAIN_ID,
|
||||
signer,
|
||||
apiCreds,
|
||||
signatureType
|
||||
);
|
||||
|
||||
const response = await client.createAndPostOrder({
|
||||
tokenID: "YOUR_TOKEN_ID",
|
||||
price: 0.65,
|
||||
size: 10,
|
||||
side: Side.BUY,
|
||||
});
|
||||
|
||||
console.log(`Order placed! ID: ${response.orderID}`);
|
||||
}
|
||||
|
||||
trade();
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.client import ClobClient
|
||||
from py_clob_client.clob_types import OrderArgs
|
||||
from py_clob_client.order_builder.constants import BUY
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
async def trade():
|
||||
host = "https://clob.polymarket.com"
|
||||
chain_id = 137 # Polygon mainnet
|
||||
chain_id = 137 # Polygon mainnet
|
||||
private_key = os.getenv("PRIVATE_KEY")
|
||||
|
||||
# Derive API credentials
|
||||
temp_client = ClobClient(host, key=private_key, chain_id=chain_id)
|
||||
creds = await temp_client.create_or_derive_api_key()
|
||||
|
||||
signature_type=0
|
||||
api_creds = temp_client.create_or_derive_api_creds()
|
||||
|
||||
# Initialize trading client
|
||||
client = ClobClient(
|
||||
host,
|
||||
chain_id=chain_id,
|
||||
key=private_key,
|
||||
creds=creds,
|
||||
signature_type=signature_type
|
||||
chain_id=chain_id,
|
||||
creds=api_creds,
|
||||
signature_type=0, # EOA
|
||||
funder="YOUR_WALLET_ADDRESS"
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
response = await client.create_and_post_order(
|
||||
<Note>
|
||||
If you have a Polymarket.com account, your funds are in a proxy wallet — use
|
||||
signature type `1` or `2` instead. See [Signature
|
||||
Types](/trading/overview#signature-types) for details.
|
||||
</Note>
|
||||
|
||||
<Warning>
|
||||
Before trading, your funder address needs **USDC.e** (for buying outcome
|
||||
tokens) and **POL** (for gas, if using EOA type `0`). Proxy wallet users
|
||||
(types `1` and `2`) can use Polymarket's gasless relayer instead.
|
||||
</Warning>
|
||||
</Step>
|
||||
|
||||
<Step title="Place an Order">
|
||||
Get a token ID from the [Markets API](/market-data/fetching-markets), then create and submit your order:
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { Side, OrderType } from "@polymarket/clob-client";
|
||||
|
||||
const response = await client.createAndPostOrder(
|
||||
{
|
||||
tokenID: "YOUR_TOKEN_ID",
|
||||
price: 0.5,
|
||||
size: 10,
|
||||
side: Side.BUY,
|
||||
},
|
||||
{
|
||||
tickSize: "0.01",
|
||||
negRisk: false, // Set to true for multi-outcome markets
|
||||
},
|
||||
OrderType.GTC,
|
||||
);
|
||||
|
||||
console.log("Order ID:", response.orderID);
|
||||
console.log("Status:", response.status);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import OrderArgs, OrderType
|
||||
from py_clob_client.order_builder.constants import BUY
|
||||
|
||||
response = client.create_and_post_order(
|
||||
OrderArgs(
|
||||
token_id="YOUR_TOKEN_ID",
|
||||
price=0.65,
|
||||
price=0.50,
|
||||
size=10,
|
||||
side=BUY
|
||||
)
|
||||
side=BUY,
|
||||
),
|
||||
options={
|
||||
"tick_size": "0.01",
|
||||
"neg_risk": False, # Set to True for multi-outcome markets
|
||||
},
|
||||
order_type=OrderType.GTC
|
||||
)
|
||||
|
||||
print(f"Order placed! ID: {response['orderID']}")
|
||||
print("Order ID:", response["orderID"])
|
||||
print("Status:", response["status"])
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(trade())
|
||||
```
|
||||
</CodeGroup>
|
||||
<Tip>
|
||||
Look up a market's `tickSize` and `negRisk` values using the SDK's
|
||||
`getTickSize()` and `getNegRisk()` methods, or from the market object returned
|
||||
by the API.
|
||||
</Tip>
|
||||
</Step>
|
||||
|
||||
<Step title="Check Your Orders">
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
// View all open orders
|
||||
const openOrders = await client.getOpenOrders();
|
||||
console.log(`You have ${openOrders.length} open orders`);
|
||||
|
||||
// View your trade history
|
||||
const trades = await client.getTrades();
|
||||
console.log(`You've made ${trades.length} trades`);
|
||||
|
||||
// Cancel an order
|
||||
await client.cancelOrder(response.orderID);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
# View all open orders
|
||||
open_orders = client.get_orders()
|
||||
print(f"You have {len(open_orders)} open orders")
|
||||
|
||||
# View your trade history
|
||||
trades = client.get_trades()
|
||||
print(f"You've made {len(trades)} trades")
|
||||
|
||||
# Cancel an order
|
||||
client.cancel(order_id=response["orderID"])
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
***
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Error: L2_AUTH_NOT_AVAILABLE">
|
||||
You forgot to call `createOrDeriveApiKey()`. Make sure you initialize the client with API credentials:
|
||||
<Accordion title="L2_AUTH_NOT_AVAILABLE / Invalid Signature">
|
||||
Wrong private key, signature type, or funder address for the derived API credentials.
|
||||
|
||||
```typescript theme={null}
|
||||
const creds = await clobClient.createOrDeriveApiKey();
|
||||
const client = new ClobClient(host, chainId, wallet, creds);
|
||||
```
|
||||
* Check that `signatureType` matches your account type (`0`, `1`, or `2`)
|
||||
* Ensure `funder` is correct for your wallet type
|
||||
* Re-derive credentials with `createOrDeriveApiKey()` if unsure
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Order rejected: insufficient balance">
|
||||
Ensure you have:
|
||||
Your funder address doesn't have enough tokens:
|
||||
|
||||
* **USDC** in your funder address for BUY orders
|
||||
* **Outcome tokens** in your funder address for SELL orders
|
||||
|
||||
Check your balance at [polymarket.com/portfolio](https://polymarket.com/portfolio).
|
||||
* **BUY orders**: need USDC.e in your funder address
|
||||
* **SELL orders**: need outcome tokens in your funder address
|
||||
* Ensure you have more USDC.e than what's committed in open orders
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Order rejected: insufficient allowance">
|
||||
You need to approve the Exchange contract to spend your tokens. This is typically done through the Polymarket UI on your first trade. Or use the CTF contract's `setApprovalForAll()` method.
|
||||
You need to approve the Exchange contract to spend your tokens. This is
|
||||
typically done through the Polymarket UI on your first trade, or using the CTF
|
||||
contract's `setApprovalForAll()` method.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What's my funder address?">
|
||||
Your funder address is the Polymarket proxy wallet where you deposit funds. Find it:
|
||||
Your funder address is the wallet where your funds are held:
|
||||
|
||||
1. Go to [polymarket.com/settings](https://polymarket.com/settings)
|
||||
2. Look for "Wallet Address" or "Profile Address"
|
||||
3. This is your `FUNDER_ADDRESS`
|
||||
* **EOA (type 0)**: Your wallet address directly
|
||||
* **Proxy wallet (type 1 or 2)**: Go to [polymarket.com/settings](https://polymarket.com/settings) and look for the wallet address in the profile dropdown
|
||||
|
||||
If the proxy wallet doesn't exist, log into Polymarket.com first (it's deployed on first login).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Blocked by Cloudflare / Geoblock">
|
||||
You're trying to place a trade from a restricted region. See [Geographic Restrictions](/api-reference/geoblock) for details.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
@@ -279,27 +216,12 @@
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={1}>
|
||||
<Card title="Full Example Implementations" icon="puzzle" href="/developers/builders/examples">
|
||||
Complete Next.js examples demonstrating integration of embedded wallets
|
||||
(Privy, Magic, Turnkey, wagmi) and the CLOB and Builder Relay clients
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Understand CLOB Authentication" icon="shield" href="/developers/CLOB/authentication">
|
||||
Deep dive into L1 and L2 authentication
|
||||
<Card title="Create Orders" icon="plus" href="/trading/orders/create">
|
||||
Order types, tick sizes, and error handling
|
||||
</Card>
|
||||
|
||||
<Card title="Browse Client Methods" icon="book" href="/developers/CLOB/clients/methods-overview">
|
||||
Explore the complete client reference
|
||||
</Card>
|
||||
|
||||
<Card title="Find Markets to Trade" icon="chart-line" href="/developers/gamma-markets-api/get-markets">
|
||||
Use Gamma API to discover markets
|
||||
</Card>
|
||||
|
||||
<Card title="Monitor with WebSocket" icon="signal-stream" href="/developers/CLOB/websocket/wss-overview">
|
||||
Get real-time order updates
|
||||
<Card title="Order Attribution" icon="tag" href="/trading/orders/attribution">
|
||||
Attribute orders to your builder account for volume credit
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -2,153 +2,134 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Historical Timeseries Data
|
||||
# Get prices history
|
||||
|
||||
> Fetches historical price data for a specified market token.
|
||||
> Retrieve historical price data for a market.
|
||||
|
||||
|
||||
The CLOB provides detailed price history for each traded token.
|
||||
|
||||
**HTTP REQUEST**
|
||||
|
||||
`GET /<clob-endpoint>/prices-history`
|
||||
|
||||
<Tip>We also have a Interactive Notebook to visualize the data from this endpoint available [here](https://colab.research.google.com/drive/1s4TCOR4K7fRP7EwAH1YmOactMakx24Cs?usp=sharing#scrollTo=mYCJBcfB9Zu4).</Tip>
|
||||
|
||||
|
||||
## OpenAPI
|
||||
|
||||
````yaml GET /prices-history
|
||||
openapi: 3.0.3
|
||||
````yaml api-spec/clob-openapi.yaml get /prices-history
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: CLOB (Central Limit Order Book) API
|
||||
description: >-
|
||||
API for interacting with the Central Limit Order Book system, providing
|
||||
orderbook data, prices, midpoints, and spreads
|
||||
version: 1.0.0
|
||||
contact:
|
||||
name: CLOB API Team
|
||||
title: Polymarket CLOB API
|
||||
description: Polymarket CLOB API Reference
|
||||
license:
|
||||
name: MIT
|
||||
identifier: MIT
|
||||
version: 1.0.0
|
||||
servers:
|
||||
- url: https://clob.polymarket.com/
|
||||
description: Production server
|
||||
- url: https://clob.polymarket.com
|
||||
description: Production CLOB API
|
||||
- url: https://clob-staging.polymarket.com
|
||||
description: Staging CLOB API
|
||||
security: []
|
||||
tags:
|
||||
- name: Orderbook
|
||||
description: Order book related operations
|
||||
- name: Pricing
|
||||
description: Price and midpoint operations
|
||||
- name: Spreads
|
||||
description: Spread calculation operations
|
||||
- name: Trade
|
||||
description: Trade endpoints
|
||||
- name: Markets
|
||||
description: Market data endpoints
|
||||
- name: Account
|
||||
description: Account and authentication endpoints
|
||||
- name: Notifications
|
||||
description: User notification endpoints
|
||||
- name: Rewards
|
||||
description: Rewards and earnings endpoints
|
||||
paths:
|
||||
/prices-history:
|
||||
get:
|
||||
tags:
|
||||
- Pricing
|
||||
summary: Get price history for a traded token
|
||||
description: Fetches historical price data for a specified market token
|
||||
- Markets
|
||||
summary: Get prices history
|
||||
description: Retrieve historical price data for a market.
|
||||
operationId: getPricesHistory
|
||||
parameters:
|
||||
- name: market
|
||||
in: query
|
||||
required: true
|
||||
description: The market (asset id) to query.
|
||||
schema:
|
||||
type: string
|
||||
description: The CLOB token ID for which to fetch price history
|
||||
example: '1234567890'
|
||||
- name: startTs
|
||||
in: query
|
||||
required: false
|
||||
description: Filter by items after this unix timestamp.
|
||||
schema:
|
||||
type: number
|
||||
description: The start time, a Unix timestamp in UTC
|
||||
example: 1697875200
|
||||
format: double
|
||||
- name: endTs
|
||||
in: query
|
||||
required: false
|
||||
description: Filter by items before this unix timestamp.
|
||||
schema:
|
||||
type: number
|
||||
description: The end time, a Unix timestamp in UTC
|
||||
example: 1697961600
|
||||
format: double
|
||||
- name: interval
|
||||
in: query
|
||||
required: false
|
||||
description: Time interval for data aggregation.
|
||||
schema:
|
||||
type: string
|
||||
enum:
|
||||
- max
|
||||
- all
|
||||
- 1m
|
||||
- 1w
|
||||
- 1d
|
||||
- 6h
|
||||
- 1h
|
||||
- max
|
||||
description: >-
|
||||
A string representing a duration ending at the current time.
|
||||
Mutually exclusive with startTs and endTs
|
||||
example: 1d
|
||||
- name: fidelity
|
||||
in: query
|
||||
required: false
|
||||
description: Accuracy of the data expressed in minutes. Default is 1 minute.
|
||||
schema:
|
||||
type: number
|
||||
description: The resolution of the data, in minutes
|
||||
example: 60
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: A list of timestamp/price pairs
|
||||
description: Successful response with price history
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PriceHistoryResponse'
|
||||
$ref: '#/components/schemas/PricesHistoryResponse'
|
||||
'400':
|
||||
description: Bad request
|
||||
description: Bad Request - Missing or invalid query parameters
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
'404':
|
||||
description: Market not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
'500':
|
||||
description: Internal server error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
$ref: '#/components/schemas/ErrorResponse'
|
||||
security: []
|
||||
components:
|
||||
schemas:
|
||||
PriceHistoryResponse:
|
||||
PricesHistoryResponse:
|
||||
type: object
|
||||
required:
|
||||
- history
|
||||
properties:
|
||||
history:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- t
|
||||
- p
|
||||
properties:
|
||||
t:
|
||||
type: number
|
||||
description: UTC timestamp
|
||||
example: 1697875200
|
||||
p:
|
||||
type: number
|
||||
description: Price
|
||||
example: 1800.75
|
||||
Error:
|
||||
$ref: '#/components/schemas/MarketPrice'
|
||||
ErrorResponse:
|
||||
type: object
|
||||
required:
|
||||
- error
|
||||
properties:
|
||||
error:
|
||||
type: string
|
||||
description: Error message describing what went wrong
|
||||
example: Invalid token id
|
||||
description: Error message
|
||||
MarketPrice:
|
||||
type: object
|
||||
properties:
|
||||
t:
|
||||
type: integer
|
||||
format: uint32
|
||||
p:
|
||||
type: number
|
||||
format: float
|
||||
|
||||
````
|
||||
````
|
||||
|
||||
@@ -2,18 +2,199 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Trades Overview
|
||||
# Overview
|
||||
|
||||
## Overview
|
||||
> Trading on the Polymarket CLOB
|
||||
|
||||
All historical trades can be fetched via the Polymarket CLOB REST API. A trade is initiated by a "taker" who creates a marketable limit order. This limit order can be matched against one or more resting limit orders on the associated book. A trade can be in various states as described below. Note: in some cases (due to gas limitations) the execution of a "trade" must be broken into multiple transactions which case separate trade entities will be returned. To associate trade entities, there is a bucket\_index field and a match\_time field. Trades that have been broken into multiple trade objects can be reconciled by combining trade objects with the same market\_order\_id, match\_time and incrementing bucket\_index's into a top level "trade" client side.
|
||||
Polymarket's CLOB (Central Limit Order Book) is a hybrid-decentralized trading system — offchain order matching with onchain settlement via the [Exchange contract](https://github.com/Polymarket/ctf-exchange/tree/main/src) ([audited by Chainsecurity](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)). All trading is non-custodial. Orders are [EIP-712](https://eips.ethereum.org/EIPS/eip-712) signed messages, and matched trades settle atomically on Polygon. The operator cannot set prices or execute unauthorized trades — users can always cancel orders onchain independently.
|
||||
|
||||
## Statuses
|
||||
We recommend using the open-source SDK clients, which handle order signing, authentication, and submission:
|
||||
|
||||
| Status | Terminal? | Description |
|
||||
| --------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| MATCHED | no | trade has been matched and sent to the executor service by the operator, the executor service submits the trade as a transaction to the Exchange contract |
|
||||
| MINED | no | trade is observed to be mined into the chain, no finality threshold established |
|
||||
| CONFIRMED | yes | trade has achieved strong probabilistic finality and was successful |
|
||||
| RETRYING | no | trade transaction has failed (revert or reorg) and is being retried/resubmitted by the operator |
|
||||
| FAILED | yes | trade has failed and is not being retried |
|
||||
<CardGroup cols={2}>
|
||||
<Card title="TypeScript Client" icon="github" href="https://github.com/Polymarket/clob-client">
|
||||
<p className="font-mono text-[0.8rem]">
|
||||
npm install @polymarket/clob-client
|
||||
</p>
|
||||
</Card>
|
||||
|
||||
<Card title="Python Client" icon="github" href="https://github.com/Polymarket/py-clob-client">
|
||||
<p className="font-mono text-[0.8rem]">pip install py-clob-client</p>
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
<Info>
|
||||
You can also use the REST API directly, but you'll need to manage [EIP-712
|
||||
order
|
||||
signing](https://github.com/Polymarket/clob-client/blob/main/src/signing/eip712.ts)
|
||||
and [HMAC authentication
|
||||
headers](https://github.com/Polymarket/clob-client/blob/main/src/signing/hmac.ts)
|
||||
yourself. See [REST API Headers](#rest-api-headers) below.
|
||||
</Info>
|
||||
|
||||
***
|
||||
|
||||
## Authentication
|
||||
|
||||
The CLOB uses two levels of authentication:
|
||||
|
||||
| Level | Method | Purpose |
|
||||
| ------ | ------------------------------- | ----------------------------------------- |
|
||||
| **L1** | EIP-712 signature (private key) | Create or derive API credentials |
|
||||
| **L2** | HMAC-SHA256 (API credentials) | Place orders, cancel orders, query trades |
|
||||
|
||||
You use your private key once to derive **L2 credentials** (API key, secret, passphrase), which authenticate all subsequent trading requests.
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { ClobClient } from "@polymarket/clob-client";
|
||||
import { Wallet } from "ethers"; // v5.8.0
|
||||
|
||||
const signer = new Wallet(process.env.PRIVATE_KEY);
|
||||
|
||||
// Derive L2 API credentials
|
||||
const tempClient = new ClobClient("https://clob.polymarket.com", 137, signer);
|
||||
const apiCreds = await tempClient.createOrDeriveApiKey();
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
from py_clob_client.client import ClobClient
|
||||
import os
|
||||
|
||||
private_key = os.getenv("PRIVATE_KEY")
|
||||
|
||||
# Derive L2 API credentials
|
||||
temp_client = ClobClient("https://clob.polymarket.com", key=private_key, chain_id=137)
|
||||
api_creds = temp_client.create_or_derive_api_creds()
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Signature Types
|
||||
|
||||
When initializing the trading client, you must specify your wallet's **signature type** and **funder address**:
|
||||
|
||||
| Wallet Type | ID | When to Use | Funder Address |
|
||||
| ---------------- | --- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
|
||||
| **EOA** | `0` | Standalone wallet — you pay your own gas (POL for gas) | Your EOA wallet address |
|
||||
| **POLY\_PROXY** | `1` | Polymarket account via Magic Link (email/Google login). Requires [exported private key](https://polymarket.com/settings) from Polymarket.com | Your proxy wallet address |
|
||||
| **GNOSIS\_SAFE** | `2` | Polymarket account via browser wallet (MetaMask, Rabby) or embedded wallet (Privy, Turnkey). Most common type | Your proxy wallet address |
|
||||
|
||||
<Note>
|
||||
If you have a Polymarket.com account, your funds are in a proxy wallet visible
|
||||
in the profile dropdown. Use type `1` or `2`. Type `0` is for standalone EOA
|
||||
wallets only.
|
||||
</Note>
|
||||
|
||||
### Initialize the Trading Client
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const client = new ClobClient(
|
||||
"https://clob.polymarket.com",
|
||||
137,
|
||||
signer,
|
||||
apiCreds,
|
||||
2, // GNOSIS_SAFE
|
||||
"0x...", // Your proxy wallet address
|
||||
);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
client = ClobClient(
|
||||
"https://clob.polymarket.com",
|
||||
key=private_key,
|
||||
chain_id=137,
|
||||
creds=api_creds,
|
||||
signature_type=2, # GNOSIS_SAFE
|
||||
funder="0x..." # Your proxy wallet address
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## REST API Headers
|
||||
|
||||
If you're using the REST API directly (without the SDK), you need to attach authentication headers to each request.
|
||||
|
||||
**L1 Headers** — for creating or deriving API credentials:
|
||||
|
||||
| Header | Description |
|
||||
| ---------------- | ------------------- |
|
||||
| `POLY_ADDRESS` | Your wallet address |
|
||||
| `POLY_SIGNATURE` | EIP-712 signature |
|
||||
| `POLY_TIMESTAMP` | Unix timestamp |
|
||||
| `POLY_NONCE` | Request nonce |
|
||||
|
||||
**L2 Headers** — for all trading operations (orders, cancellations, queries):
|
||||
|
||||
| Header | Description |
|
||||
| ----------------- | ------------------------------------ |
|
||||
| `POLY_ADDRESS` | Your wallet address |
|
||||
| `POLY_SIGNATURE` | HMAC-SHA256 signature of the request |
|
||||
| `POLY_TIMESTAMP` | Unix timestamp |
|
||||
| `POLY_API_KEY` | Your API key |
|
||||
| `POLY_PASSPHRASE` | Your API passphrase |
|
||||
|
||||
<Note>
|
||||
Even with L2 authentication, methods that create orders still require the
|
||||
user's private key for EIP-712 order payload signing. L2 credentials
|
||||
authenticate the request, but the order itself must be signed by the key.
|
||||
</Note>
|
||||
|
||||
***
|
||||
|
||||
## Client Methods
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Public Methods" icon="globe" href="/trading/clients/public">
|
||||
Market data, orderbooks, prices, and spreads — no auth required.
|
||||
</Card>
|
||||
|
||||
<Card title="L1 Methods" icon="key" href="/trading/clients/l1">
|
||||
Sign orders and derive API credentials with your private key.
|
||||
</Card>
|
||||
|
||||
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
|
||||
Place orders, cancel orders, query trades, and manage notifications.
|
||||
</Card>
|
||||
|
||||
<Card title="Builder Methods" icon="hammer" href="/trading/clients/builder">
|
||||
Track attributed trades and manage builder credentials.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
***
|
||||
|
||||
## What's in This Section
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Quickstart" icon="bolt" href="/trading/quickstart">
|
||||
Place your first order end-to-end
|
||||
</Card>
|
||||
|
||||
<Card title="Orderbook" icon="chart-bar" href="/trading/orderbook">
|
||||
Reading the orderbook, prices, spreads, and midpoints
|
||||
</Card>
|
||||
|
||||
<Card title="Orders" icon="list-check" href="/trading/orders/create">
|
||||
Order types, tick sizes, creating, cancelling, and querying orders
|
||||
</Card>
|
||||
|
||||
<Card title="Fees" icon="receipt" href="/trading/fees">
|
||||
Fee structure, fee-enabled markets, and maker rebates
|
||||
</Card>
|
||||
|
||||
<Card title="Gasless Transactions" icon="gas-pump" href="/trading/gasless">
|
||||
Execute onchain operations without paying gas
|
||||
</Card>
|
||||
|
||||
<Card title="CTF Tokens" icon="coins" href="/trading/ctf/overview">
|
||||
Split, merge, and redeem outcome tokens
|
||||
</Card>
|
||||
|
||||
<Card title="Bridge" icon="bridge" href="/trading/bridge/deposit">
|
||||
Deposit and withdraw funds across chains
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -2,95 +2,199 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Get Trades
|
||||
# Overview
|
||||
|
||||
<Tip> This endpoint requires a L2 Header. </Tip>
|
||||
> Trading on the Polymarket CLOB
|
||||
|
||||
Get trades for the authenticated user based on the provided filters.
|
||||
Polymarket's CLOB (Central Limit Order Book) is a hybrid-decentralized trading system — offchain order matching with onchain settlement via the [Exchange contract](https://github.com/Polymarket/ctf-exchange/tree/main/src) ([audited by Chainsecurity](https://github.com/Polymarket/ctf-exchange/blob/main/audit/ChainSecurity_Polymarket_Exchange_audit.pdf)). All trading is non-custodial. Orders are [EIP-712](https://eips.ethereum.org/EIPS/eip-712) signed messages, and matched trades settle atomically on Polygon. The operator cannot set prices or execute unauthorized trades — users can always cancel orders onchain independently.
|
||||
|
||||
**HTTP REQUEST**
|
||||
We recommend using the open-source SDK clients, which handle order signing, authentication, and submission:
|
||||
|
||||
`GET /<clob-endpoint>/data/trades`
|
||||
<CardGroup cols={2}>
|
||||
<Card title="TypeScript Client" icon="github" href="https://github.com/Polymarket/clob-client">
|
||||
<p className="font-mono text-[0.8rem]">
|
||||
npm install @polymarket/clob-client
|
||||
</p>
|
||||
</Card>
|
||||
|
||||
### Request Parameters
|
||||
<Card title="Python Client" icon="github" href="https://github.com/Polymarket/py-clob-client">
|
||||
<p className="font-mono text-[0.8rem]">pip install py-clob-client</p>
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
| Name | Required | Type | Description |
|
||||
| ------ | -------- | ------ | --------------------------------------------------------------------------------------------------- |
|
||||
| id | no | string | id of trade to fetch |
|
||||
| taker | no | string | address to get trades for where it is included as a taker |
|
||||
| maker | no | string | address to get trades for where it is included as a maker |
|
||||
| market | no | string | market for which to get the trades (condition ID) |
|
||||
| before | no | string | unix timestamp representing the cutoff up to which trades that happened before then can be included |
|
||||
| after | no | string | unix timestamp representing the cutoff for which trades that happened after can be included |
|
||||
<Info>
|
||||
You can also use the REST API directly, but you'll need to manage [EIP-712
|
||||
order
|
||||
signing](https://github.com/Polymarket/clob-client/blob/main/src/signing/eip712.ts)
|
||||
and [HMAC authentication
|
||||
headers](https://github.com/Polymarket/clob-client/blob/main/src/signing/hmac.ts)
|
||||
yourself. See [REST API Headers](#rest-api-headers) below.
|
||||
</Info>
|
||||
|
||||
### Response Format
|
||||
***
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | -------- | ------------------------------------------- |
|
||||
| null | Trade\[] | list of trades filtered by query parameters |
|
||||
## Authentication
|
||||
|
||||
A `Trade` object is of the form:
|
||||
The CLOB uses two levels of authentication:
|
||||
|
||||
| Name | Type | Description |
|
||||
| ----------------- | ------------- | ---------------------------------------------------------------------------- |
|
||||
| id | string | trade id |
|
||||
| taker\_order\_id | string | hash of taker order (market order) that catalyzed the trade |
|
||||
| market | string | market id (condition id) |
|
||||
| asset\_id | string | asset id (token id) of taker order (market order) |
|
||||
| side | string | buy or sell |
|
||||
| size | string | size |
|
||||
| fee\_rate\_bps | string | the fees paid for the taker order expressed in basic points |
|
||||
| price | string | limit price of taker order |
|
||||
| status | string | trade status (see above) |
|
||||
| match\_time | string | time at which the trade was matched |
|
||||
| last\_update | string | timestamp of last status update |
|
||||
| outcome | string | human readable outcome of the trade |
|
||||
| maker\_address | string | funder address of the taker of the trade |
|
||||
| owner | string | api key of taker of the trade |
|
||||
| transaction\_hash | string | hash of the transaction where the trade was executed |
|
||||
| bucket\_index | integer | index of bucket for trade in case trade is executed in multiple transactions |
|
||||
| maker\_orders | MakerOrder\[] | list of the maker trades the taker trade was filled against |
|
||||
| type | string | side of the trade: TAKER or MAKER |
|
||||
| Level | Method | Purpose |
|
||||
| ------ | ------------------------------- | ----------------------------------------- |
|
||||
| **L1** | EIP-712 signature (private key) | Create or derive API credentials |
|
||||
| **L2** | HMAC-SHA256 (API credentials) | Place orders, cancel orders, query trades |
|
||||
|
||||
A `MakerOrder` object is of the form:
|
||||
You use your private key once to derive **L2 credentials** (API key, secret, passphrase), which authenticate all subsequent trading requests.
|
||||
|
||||
| Name | Type | Description |
|
||||
| --------------- | ------ | ----------------------------------------------------------- |
|
||||
| order\_id | string | id of maker order |
|
||||
| maker\_address | string | maker address of the order |
|
||||
| owner | string | api key of the owner of the order |
|
||||
| matched\_amount | string | size of maker order consumed with this trade |
|
||||
| fee\_rate\_bps | string | the fees paid for the taker order expressed in basic points |
|
||||
| price | string | price of maker order |
|
||||
| asset\_id | string | token/asset id |
|
||||
| outcome | string | human readable outcome of the maker order |
|
||||
| side | string | the side of the maker order. Can be `buy` or `sell` |
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
import { ClobClient } from "@polymarket/clob-client";
|
||||
import { Wallet } from "ethers"; // v5.8.0
|
||||
|
||||
const signer = new Wallet(process.env.PRIVATE_KEY);
|
||||
|
||||
// Derive L2 API credentials
|
||||
const tempClient = new ClobClient("https://clob.polymarket.com", 137, signer);
|
||||
const apiCreds = await tempClient.createOrDeriveApiKey();
|
||||
```
|
||||
|
||||
<RequestExample>
|
||||
```python Python theme={null}
|
||||
from py_clob_client.clob_types import TradeParams
|
||||
from py_clob_client.client import ClobClient
|
||||
import os
|
||||
|
||||
resp = client.get_trades(
|
||||
TradeParams(
|
||||
maker_address=client.get_address(),
|
||||
market="0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
|
||||
),
|
||||
private_key = os.getenv("PRIVATE_KEY")
|
||||
|
||||
# Derive L2 API credentials
|
||||
temp_client = ClobClient("https://clob.polymarket.com", key=private_key, chain_id=137)
|
||||
api_creds = temp_client.create_or_derive_api_creds()
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
***
|
||||
|
||||
## Signature Types
|
||||
|
||||
When initializing the trading client, you must specify your wallet's **signature type** and **funder address**:
|
||||
|
||||
| Wallet Type | ID | When to Use | Funder Address |
|
||||
| ---------------- | --- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
|
||||
| **EOA** | `0` | Standalone wallet — you pay your own gas (POL for gas) | Your EOA wallet address |
|
||||
| **POLY\_PROXY** | `1` | Polymarket account via Magic Link (email/Google login). Requires [exported private key](https://polymarket.com/settings) from Polymarket.com | Your proxy wallet address |
|
||||
| **GNOSIS\_SAFE** | `2` | Polymarket account via browser wallet (MetaMask, Rabby) or embedded wallet (Privy, Turnkey). Most common type | Your proxy wallet address |
|
||||
|
||||
<Note>
|
||||
If you have a Polymarket.com account, your funds are in a proxy wallet visible
|
||||
in the profile dropdown. Use type `1` or `2`. Type `0` is for standalone EOA
|
||||
wallets only.
|
||||
</Note>
|
||||
|
||||
### Initialize the Trading Client
|
||||
|
||||
<CodeGroup>
|
||||
```typescript TypeScript theme={null}
|
||||
const client = new ClobClient(
|
||||
"https://clob.polymarket.com",
|
||||
137,
|
||||
signer,
|
||||
apiCreds,
|
||||
2, // GNOSIS_SAFE
|
||||
"0x...", // Your proxy wallet address
|
||||
);
|
||||
```
|
||||
|
||||
```python Python theme={null}
|
||||
client = ClobClient(
|
||||
"https://clob.polymarket.com",
|
||||
key=private_key,
|
||||
chain_id=137,
|
||||
creds=api_creds,
|
||||
signature_type=2, # GNOSIS_SAFE
|
||||
funder="0x..." # Your proxy wallet address
|
||||
)
|
||||
print(resp)
|
||||
print("Done!")
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
```typescript Typescript theme={null}
|
||||
async function main() {
|
||||
const trades = await clobClient.getTrades({
|
||||
market:
|
||||
"0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
|
||||
maker_address: await wallet.getAddress(),
|
||||
});
|
||||
console.log(`trades: `);
|
||||
console.log(trades);
|
||||
}
|
||||
***
|
||||
|
||||
main();
|
||||
```
|
||||
</RequestExample>
|
||||
## REST API Headers
|
||||
|
||||
If you're using the REST API directly (without the SDK), you need to attach authentication headers to each request.
|
||||
|
||||
**L1 Headers** — for creating or deriving API credentials:
|
||||
|
||||
| Header | Description |
|
||||
| ---------------- | ------------------- |
|
||||
| `POLY_ADDRESS` | Your wallet address |
|
||||
| `POLY_SIGNATURE` | EIP-712 signature |
|
||||
| `POLY_TIMESTAMP` | Unix timestamp |
|
||||
| `POLY_NONCE` | Request nonce |
|
||||
|
||||
**L2 Headers** — for all trading operations (orders, cancellations, queries):
|
||||
|
||||
| Header | Description |
|
||||
| ----------------- | ------------------------------------ |
|
||||
| `POLY_ADDRESS` | Your wallet address |
|
||||
| `POLY_SIGNATURE` | HMAC-SHA256 signature of the request |
|
||||
| `POLY_TIMESTAMP` | Unix timestamp |
|
||||
| `POLY_API_KEY` | Your API key |
|
||||
| `POLY_PASSPHRASE` | Your API passphrase |
|
||||
|
||||
<Note>
|
||||
Even with L2 authentication, methods that create orders still require the
|
||||
user's private key for EIP-712 order payload signing. L2 credentials
|
||||
authenticate the request, but the order itself must be signed by the key.
|
||||
</Note>
|
||||
|
||||
***
|
||||
|
||||
## Client Methods
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Public Methods" icon="globe" href="/trading/clients/public">
|
||||
Market data, orderbooks, prices, and spreads — no auth required.
|
||||
</Card>
|
||||
|
||||
<Card title="L1 Methods" icon="key" href="/trading/clients/l1">
|
||||
Sign orders and derive API credentials with your private key.
|
||||
</Card>
|
||||
|
||||
<Card title="L2 Methods" icon="lock" href="/trading/clients/l2">
|
||||
Place orders, cancel orders, query trades, and manage notifications.
|
||||
</Card>
|
||||
|
||||
<Card title="Builder Methods" icon="hammer" href="/trading/clients/builder">
|
||||
Track attributed trades and manage builder credentials.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
***
|
||||
|
||||
## What's in This Section
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Quickstart" icon="bolt" href="/trading/quickstart">
|
||||
Place your first order end-to-end
|
||||
</Card>
|
||||
|
||||
<Card title="Orderbook" icon="chart-bar" href="/trading/orderbook">
|
||||
Reading the orderbook, prices, spreads, and midpoints
|
||||
</Card>
|
||||
|
||||
<Card title="Orders" icon="list-check" href="/trading/orders/create">
|
||||
Order types, tick sizes, creating, cancelling, and querying orders
|
||||
</Card>
|
||||
|
||||
<Card title="Fees" icon="receipt" href="/trading/fees">
|
||||
Fee structure, fee-enabled markets, and maker rebates
|
||||
</Card>
|
||||
|
||||
<Card title="Gasless Transactions" icon="gas-pump" href="/trading/gasless">
|
||||
Execute onchain operations without paying gas
|
||||
</Card>
|
||||
|
||||
<Card title="CTF Tokens" icon="coins" href="/trading/ctf/overview">
|
||||
Split, merge, and redeem outcome tokens
|
||||
</Card>
|
||||
|
||||
<Card title="Bridge" icon="bridge" href="/trading/bridge/deposit">
|
||||
Deposit and withdraw funds across chains
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
@@ -4,39 +4,37 @@
|
||||
|
||||
# Market Channel
|
||||
|
||||
Public channel for updates related to market updates (level 2 price data).
|
||||
> Real-time orderbook, price, and trade data
|
||||
|
||||
**SUBSCRIBE**
|
||||
Public channel for market data updates (level 2 price data). Subscribe with asset IDs to receive orderbook snapshots, price changes, trade executions, and market events.
|
||||
|
||||
`<wss-channel> market`
|
||||
## Endpoint
|
||||
|
||||
## book Message
|
||||
```
|
||||
wss://ws-subscriptions-clob.polymarket.com/ws/market
|
||||
```
|
||||
|
||||
Emitted When:
|
||||
## Subscription
|
||||
|
||||
* First subscribed to a market
|
||||
* When there is a trade that affects the book
|
||||
```json theme={null}
|
||||
{
|
||||
"assets_ids": ["<token_id_1>", "<token_id_2>"],
|
||||
"type": "market",
|
||||
"custom_feature_enabled": true
|
||||
}
|
||||
```
|
||||
|
||||
### Structure
|
||||
Set `custom_feature_enabled: true` to receive `best_bid_ask`, `new_market`, and `market_resolved` events.
|
||||
|
||||
| Name | Type | Description |
|
||||
| ----------- | --------------- | --------------------------------------------------------------------------- |
|
||||
| event\_type | string | "book" |
|
||||
| asset\_id | string | asset ID (token ID) |
|
||||
| market | string | condition ID of market |
|
||||
| timestamp | string | unix timestamp the current book generation in milliseconds (1/1,000 second) |
|
||||
| hash | string | hash summary of the orderbook content |
|
||||
| buys | OrderSummary\[] | list of type (size, price) aggregate book levels for buys |
|
||||
| sells | OrderSummary\[] | list of type (size, price) aggregate book levels for sells |
|
||||
## Message Types
|
||||
|
||||
Where a `OrderSummary` object is of the form:
|
||||
Each message includes an `event_type` field identifying the type.
|
||||
|
||||
| Name | Type | Description |
|
||||
| ----- | ------ | ---------------------------------- |
|
||||
| price | string | price of the orderbook level |
|
||||
| size | string | size available at that price level |
|
||||
### book
|
||||
|
||||
```json Response theme={null}
|
||||
Emitted when first subscribed to a market and when there is a trade that affects the book.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"event_type": "book",
|
||||
"asset_id": "65818619657568813474341868652308942079804919287380422192892211131408793125422",
|
||||
@@ -56,137 +54,79 @@ Where a `OrderSummary` object is of the form:
|
||||
}
|
||||
```
|
||||
|
||||
## price\_change Message
|
||||
### price\_change
|
||||
|
||||
<div style={{backgroundColor: '#fff3cd', border: '1px solid #ffeaa7', borderRadius: '4px', padding: '12px', marginBottom: '16px'}}>
|
||||
<strong>⚠️ Breaking Change Notice:</strong> The price\_change message schema will be updated on September 15, 2025 at 11 PM UTC. Please see the [migration guide](/developers/CLOB/websocket/market-channel-migration-guide) for details.
|
||||
</div>
|
||||
Emitted when a new order is placed or an order is cancelled.
|
||||
|
||||
Emitted When:
|
||||
|
||||
* A new order is placed
|
||||
* An order is cancelled
|
||||
|
||||
### Structure
|
||||
|
||||
| Name | Type | Description |
|
||||
| -------------- | -------------- | ------------------------------ |
|
||||
| event\_type | string | "price\_change" |
|
||||
| market | string | condition ID of market |
|
||||
| price\_changes | PriceChange\[] | array of price change objects |
|
||||
| timestamp | string | unix timestamp in milliseconds |
|
||||
|
||||
Where a `PriceChange` object is of the form:
|
||||
|
||||
| Name | Type | Description |
|
||||
| --------- | ------ | ---------------------------------- |
|
||||
| asset\_id | string | asset ID (token ID) |
|
||||
| price | string | price level affected |
|
||||
| size | string | new aggregate size for price level |
|
||||
| side | string | "BUY" or "SELL" |
|
||||
| hash | string | hash of the order |
|
||||
| best\_bid | string | current best bid price |
|
||||
| best\_ask | string | current best ask price |
|
||||
|
||||
```json Response theme={null}
|
||||
```json theme={null}
|
||||
{
|
||||
"market": "0x5f65177b394277fd294cd75650044e32ba009a95022d88a0c1d565897d72f8f1",
|
||||
"price_changes": [
|
||||
{
|
||||
"asset_id": "71321045679252212594626385532706912750332728571942532289631379312455583992563",
|
||||
"price": "0.5",
|
||||
"size": "200",
|
||||
"side": "BUY",
|
||||
"hash": "56621a121a47ed9333273e21c83b660cff37ae50",
|
||||
"best_bid": "0.5",
|
||||
"best_ask": "1"
|
||||
},
|
||||
{
|
||||
"asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426",
|
||||
"price": "0.5",
|
||||
"size": "200",
|
||||
"side": "SELL",
|
||||
"hash": "1895759e4df7a796bf4f1c5a5950b748306923e2",
|
||||
"best_bid": "0",
|
||||
"best_ask": "0.5"
|
||||
}
|
||||
],
|
||||
"timestamp": "1757908892351",
|
||||
"event_type": "price_change"
|
||||
"market": "0x5f65177b394277fd294cd75650044e32ba009a95022d88a0c1d565897d72f8f1",
|
||||
"price_changes": [
|
||||
{
|
||||
"asset_id": "71321045679252212594626385532706912750332728571942532289631379312455583992563",
|
||||
"price": "0.5",
|
||||
"size": "200",
|
||||
"side": "BUY",
|
||||
"hash": "56621a121a47ed9333273e21c83b660cff37ae50",
|
||||
"best_bid": "0.5",
|
||||
"best_ask": "1"
|
||||
},
|
||||
{
|
||||
"asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426",
|
||||
"price": "0.5",
|
||||
"size": "200",
|
||||
"side": "SELL",
|
||||
"hash": "1895759e4df7a796bf4f1c5a5950b748306923e2",
|
||||
"best_bid": "0",
|
||||
"best_ask": "0.5"
|
||||
}
|
||||
],
|
||||
"timestamp": "1757908892351",
|
||||
"event_type": "price_change"
|
||||
}
|
||||
```
|
||||
|
||||
## tick\_size\_change Message
|
||||
A `size` of `"0"` means the price level has been removed from the book.
|
||||
|
||||
Emitted When:
|
||||
### tick\_size\_change
|
||||
|
||||
* The minimum tick size of the market changes. This happens when the book's price reaches the limits: price > 0.96 or price \< 0.04
|
||||
Emitted when the minimum tick size of a market changes. This happens when the book's price reaches the limits: price > 0.96 or price \< 0.04.
|
||||
|
||||
### Structure
|
||||
|
||||
| Name | Type | Description |
|
||||
| --------------- | ------ | -------------------------- |
|
||||
| event\_type | string | "price\_change" |
|
||||
| asset\_id | string | asset ID (token ID) |
|
||||
| market | string | condition ID of market |
|
||||
| old\_tick\_size | string | previous minimum tick size |
|
||||
| new\_tick\_size | string | current minimum tick size |
|
||||
| side | string | buy/sell |
|
||||
| timestamp | string | time of event |
|
||||
|
||||
```json Response theme={null}
|
||||
```json theme={null}
|
||||
{
|
||||
"event_type": "tick_size_change",
|
||||
"asset_id": "65818619657568813474341868652308942079804919287380422192892211131408793125422",\
|
||||
"market": "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
|
||||
"old_tick_size": "0.01",
|
||||
"new_tick_size": "0.001",
|
||||
"timestamp": "100000000"
|
||||
"event_type": "tick_size_change",
|
||||
"asset_id": "65818619657568813474341868652308942079804919287380422192892211131408793125422",
|
||||
"market": "0xbd31dc8a20211944f6b70f31557f1001557b59905b7738480ca09bd4532f84af",
|
||||
"old_tick_size": "0.01",
|
||||
"new_tick_size": "0.001",
|
||||
"timestamp": "100000000"
|
||||
}
|
||||
```
|
||||
|
||||
## last\_trade\_price Message
|
||||
### last\_trade\_price
|
||||
|
||||
Emitted When:
|
||||
Emitted when a maker and taker order is matched, creating a trade event.
|
||||
|
||||
* When a maker and taker order is matched creating a trade event.
|
||||
|
||||
```json Response theme={null}
|
||||
```json theme={null}
|
||||
{
|
||||
"asset_id":"114122071509644379678018727908709560226618148003371446110114509806601493071694",
|
||||
"event_type":"last_trade_price",
|
||||
"fee_rate_bps":"0",
|
||||
"market":"0x6a67b9d828d53862160e470329ffea5246f338ecfffdf2cab45211ec578b0347",
|
||||
"price":"0.456",
|
||||
"side":"BUY",
|
||||
"size":"219.217767",
|
||||
"timestamp":"1750428146322"
|
||||
"asset_id": "114122071509644379678018727908709560226618148003371446110114509806601493071694",
|
||||
"event_type": "last_trade_price",
|
||||
"fee_rate_bps": "0",
|
||||
"market": "0x6a67b9d828d53862160e470329ffea5246f338ecfffdf2cab45211ec578b0347",
|
||||
"price": "0.456",
|
||||
"side": "BUY",
|
||||
"size": "219.217767",
|
||||
"timestamp": "1750428146322"
|
||||
}
|
||||
```
|
||||
|
||||
## best\_bid\_ask Message
|
||||
### best\_bid\_ask
|
||||
|
||||
Emitted When:
|
||||
<Note>Requires `custom_feature_enabled: true`.</Note>
|
||||
|
||||
* The best bid and ask prices for a market change.
|
||||
Emitted when the best bid or ask prices for a market change.
|
||||
|
||||
(This message is behind the `custom_feature_enabled` flag)
|
||||
|
||||
### Structure
|
||||
|
||||
| Name | Type | Description |
|
||||
| ----------- | ------ | ------------------------------- |
|
||||
| event\_type | string | "best\_bid\_ask" |
|
||||
| market | string | condition ID of market |
|
||||
| asset\_id | string | asset ID (token ID) |
|
||||
| best\_bid | string | current best bid price |
|
||||
| best\_ask | string | current best ask price |
|
||||
| spread | string | spread between best bid and ask |
|
||||
| timestamp | string | unix timestamp in milliseconds |
|
||||
|
||||
### Example
|
||||
|
||||
```json Response theme={null}
|
||||
```json theme={null}
|
||||
{
|
||||
"event_type": "best_bid_ask",
|
||||
"market": "0x0005c0d312de0be897668695bae9f32b624b4a1ae8b140c49f08447fcc74f442",
|
||||
@@ -198,126 +138,64 @@ Emitted When:
|
||||
}
|
||||
```
|
||||
|
||||
## new\_market Message
|
||||
### new\_market
|
||||
|
||||
Emitted When:
|
||||
<Note>Requires `custom_feature_enabled: true`.</Note>
|
||||
|
||||
* A new market is created.
|
||||
Emitted when a new market is created.
|
||||
|
||||
(This message is behind the `custom_feature_enabled` flag)
|
||||
|
||||
### Structure
|
||||
|
||||
| Name | Type | Description |
|
||||
| -------------- | --------- | ------------------------------ |
|
||||
| id | string | market ID |
|
||||
| question | string | market question |
|
||||
| market | string | condition ID of market |
|
||||
| slug | string | market slug |
|
||||
| description | string | market description |
|
||||
| assets\_ids | string\[] | list of asset IDs |
|
||||
| outcomes | string\[] | list of outcomes |
|
||||
| event\_message | object | event message object |
|
||||
| timestamp | string | unix timestamp in milliseconds |
|
||||
| event\_type | string | "new\_market" |
|
||||
|
||||
Where a `EventMessage` object is of the form:
|
||||
|
||||
| Name | Type | Description |
|
||||
| ----------- | ------ | ------------------------- |
|
||||
| id | string | event message ID |
|
||||
| ticker | string | event message ticker |
|
||||
| slug | string | event message slug |
|
||||
| title | string | event message title |
|
||||
| description | string | event message description |
|
||||
|
||||
### Example
|
||||
|
||||
```json Response theme={null}
|
||||
```json theme={null}
|
||||
{
|
||||
"id": "1031769",
|
||||
"question": "Will NVIDIA (NVDA) close above $240 end of January?",
|
||||
"market": "0x311d0c4b6671ab54af4970c06fcf58662516f5168997bdda209ec3db5aa6b0c1",
|
||||
"slug": "nvda-above-240-on-january-30-2026",
|
||||
"description": "This market will resolve to \"Yes\" if the official closing price for NVIDIA (NVDA) on the final trading day of January 2026 is higher than the listed price. Otherwise, this market will resolve to \"No\".\n\nIf the final trading day of the month is shortened (for example, due to a market-holiday schedule), the official closing price published for that shortened session will still be used for resolution.\n\nIf no official closing price is published for that session (for example, due to a trading halt into the close, system issue, or other disruption), the market will use the last valid on-exchange trade price of the regular session as the effective closing price.\n\nThe resolution source for this market is Yahoo Finance — specifically, the NVIDIA (NVDA) \"Close\" prices available at https://finance.yahoo.com/quote/NVDA/history, published under \"Historical Prices.\"\n\nIn the event of a stock split, reverse stock split, or similar corporate action affecting the listed company during the listed time frame, this market will resolve based on split-adjusted prices as displayed on Yahoo Finance.",
|
||||
"assets_ids": [
|
||||
"76043073756653678226373981964075571318267289248134717369284518995922789326425",
|
||||
"31690934263385727664202099278545688007799199447969475608906331829650099442770"
|
||||
],
|
||||
"outcomes": [
|
||||
"Yes",
|
||||
"No"
|
||||
],
|
||||
"event_message": {
|
||||
"id": "125819",
|
||||
"ticker": "nvda-above-in-january-2026",
|
||||
"slug": "nvda-above-in-january-2026",
|
||||
"title": "Will NVIDIA (NVDA) close above ___ end of January?",
|
||||
"description": "This market will resolve to \"Yes\" if the official closing price for NVIDIA (NVDA) on the final trading day of January 2026 is higher than the listed price. Otherwise, this market will resolve to \"No\".\n\nIf the final trading day of the month is shortened (for example, due to a market-holiday schedule), the official closing price published for that shortened session will still be used for resolution.\n\nIf no official closing price is published for that session (for example, due to a trading halt into the close, system issue, or other disruption), the market will use the last valid on-exchange trade price of the regular session as the effective closing price.\n\nThe resolution source for this market is Yahoo Finance — specifically, the NVIDIA (NVDA) \"Close\" prices available at https://finance.yahoo.com/quote/NVDA/history, published under \"Historical Prices.\"\n\nIn the event of a stock split, reverse stock split, or similar corporate action affecting the listed company during the listed time frame, this market will resolve based on split-adjusted prices as displayed on Yahoo Finance."
|
||||
},
|
||||
"timestamp": "1766790415550",
|
||||
"event_type": "new_market"
|
||||
"id": "1031769",
|
||||
"question": "Will NVIDIA (NVDA) close above $240 end of January?",
|
||||
"market": "0x311d0c4b6671ab54af4970c06fcf58662516f5168997bdda209ec3db5aa6b0c1",
|
||||
"slug": "nvda-above-240-on-january-30-2026",
|
||||
"description": "This market will resolve to \"Yes\" if the official closing price...",
|
||||
"assets_ids": [
|
||||
"76043073756653678226373981964075571318267289248134717369284518995922789326425",
|
||||
"31690934263385727664202099278545688007799199447969475608906331829650099442770"
|
||||
],
|
||||
"outcomes": ["Yes", "No"],
|
||||
"event_message": {
|
||||
"id": "125819",
|
||||
"ticker": "nvda-above-in-january-2026",
|
||||
"slug": "nvda-above-in-january-2026",
|
||||
"title": "Will NVIDIA (NVDA) close above ___ end of January?",
|
||||
"description": "This market will resolve to \"Yes\" if the official closing price..."
|
||||
},
|
||||
"timestamp": "1766790415550",
|
||||
"event_type": "new_market"
|
||||
}
|
||||
```
|
||||
|
||||
## market\_resolved Message
|
||||
### market\_resolved
|
||||
|
||||
Emitted When:
|
||||
<Note>Requires `custom_feature_enabled: true`.</Note>
|
||||
|
||||
* A market is resolved.
|
||||
Emitted when a market is resolved.
|
||||
|
||||
(This message is behind the `custom_feature_enabled` flag)
|
||||
|
||||
### Structure
|
||||
|
||||
| Name | Type | Description |
|
||||
| ------------------ | --------- | ------------------------------ |
|
||||
| id | string | market ID |
|
||||
| question | string | market question |
|
||||
| market | string | condition ID of market |
|
||||
| slug | string | market slug |
|
||||
| description | string | market description |
|
||||
| assets\_ids | string\[] | list of asset IDs |
|
||||
| outcomes | string\[] | list of outcomes |
|
||||
| winning\_asset\_id | string | winning asset ID |
|
||||
| winning\_outcome | string | winning outcome |
|
||||
| event\_message | object | event message object |
|
||||
| timestamp | string | unix timestamp in milliseconds |
|
||||
| event\_type | string | "market\_resolved" |
|
||||
|
||||
Where a `EventMessage` object is of the form:
|
||||
|
||||
| Name | Type | Description |
|
||||
| ----------- | ------ | ------------------------- |
|
||||
| id | string | event message ID |
|
||||
| ticker | string | event message ticker |
|
||||
| slug | string | event message slug |
|
||||
| title | string | event message title |
|
||||
| description | string | event message description |
|
||||
|
||||
### Example
|
||||
|
||||
```json Response theme={null}
|
||||
```json theme={null}
|
||||
{
|
||||
"id": "1031769",
|
||||
"question": "Will NVIDIA (NVDA) close above $240 end of January?",
|
||||
"market": "0x311d0c4b6671ab54af4970c06fcf58662516f5168997bdda209ec3db5aa6b0c1",
|
||||
"slug": "nvda-above-240-on-january-30-2026",
|
||||
"description": "This market will resolve to \"Yes\" if the official closing price for NVIDIA (NVDA) on the final trading day of January 2026 is higher than the listed price. Otherwise, this market will resolve to \"No\".\n\nIf the final trading day of the month is shortened (for example, due to a market-holiday schedule), the official closing price published for that shortened session will still be used for resolution.\n\nIf no official closing price is published for that session (for example, due to a trading halt into the close, system issue, or other disruption), the market will use the last valid on-exchange trade price of the regular session as the effective closing price.\n\nThe resolution source for this market is Yahoo Finance — specifically, the NVIDIA (NVDA) \"Close\" prices available at https://finance.yahoo.com/quote/NVDA/history, published under \"Historical Prices.\"\n\nIn the event of a stock split, reverse stock split, or similar corporate action affecting the listed company during the listed time frame, this market will resolve based on split-adjusted prices as displayed on Yahoo Finance.",
|
||||
"assets_ids": [
|
||||
"76043073756653678226373981964075571318267289248134717369284518995922789326425",
|
||||
"31690934263385727664202099278545688007799199447969475608906331829650099442770"
|
||||
],
|
||||
"winning_asset_id": "76043073756653678226373981964075571318267289248134717369284518995922789326425",
|
||||
"winning_outcome": "Yes",
|
||||
"event_message": {
|
||||
"id": "125819",
|
||||
"ticker": "nvda-above-in-january-2026",
|
||||
"slug": "nvda-above-in-january-2026",
|
||||
"title": "Will NVIDIA (NVDA) close above ___ end of January?",
|
||||
"description": "This market will resolve to \"Yes\" if the official closing price for NVIDIA (NVDA) on the final trading day of January 2026 is higher than the listed price. Otherwise, this market will resolve to \"No\".\n\nIf the final trading day of the month is shortened (for example, due to a market-holiday schedule), the official closing price published for that shortened session will still be used for resolution.\n\nIf no official closing price is published for that session (for example, due to a trading halt into the close, system issue, or other disruption), the market will use the last valid on-exchange trade price of the regular session as the effective closing price.\n\nThe resolution source for this market is Yahoo Finance — specifically, the NVIDIA (NVDA) \"Close\" prices available at https://finance.yahoo.com/quote/NVDA/history, published under \"Historical Prices.\"\n\nIn the event of a stock split, reverse stock split, or similar corporate action affecting the listed company during the listed time frame, this market will resolve based on split-adjusted prices as displayed on Yahoo Finance."
|
||||
},
|
||||
"timestamp": "1766790415550",
|
||||
"event_type": "new_market"
|
||||
"id": "1031769",
|
||||
"question": "Will NVIDIA (NVDA) close above $240 end of January?",
|
||||
"market": "0x311d0c4b6671ab54af4970c06fcf58662516f5168997bdda209ec3db5aa6b0c1",
|
||||
"slug": "nvda-above-240-on-january-30-2026",
|
||||
"description": "This market will resolve to \"Yes\" if the official closing price...",
|
||||
"assets_ids": [
|
||||
"76043073756653678226373981964075571318267289248134717369284518995922789326425",
|
||||
"31690934263385727664202099278545688007799199447969475608906331829650099442770"
|
||||
],
|
||||
"outcomes": ["Yes", "No"],
|
||||
"winning_asset_id": "76043073756653678226373981964075571318267289248134717369284518995922789326425",
|
||||
"winning_outcome": "Yes",
|
||||
"event_message": {
|
||||
"id": "125819",
|
||||
"ticker": "nvda-above-in-january-2026",
|
||||
"slug": "nvda-above-in-january-2026",
|
||||
"title": "Will NVIDIA (NVDA) close above ___ end of January?",
|
||||
"description": "This market will resolve to \"Yes\" if the official closing price..."
|
||||
},
|
||||
"timestamp": "1766790415550",
|
||||
"event_type": "market_resolved"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -4,54 +4,50 @@
|
||||
|
||||
# User Channel
|
||||
|
||||
Authenticated channel for updates related to user activities (orders, trades), filtered for authenticated user by apikey.
|
||||
> Authenticated order and trade updates
|
||||
|
||||
**SUBSCRIBE**
|
||||
Authenticated channel for updates related to your orders and trades, filtered by API key.
|
||||
|
||||
`<wss-channel> user`
|
||||
## Endpoint
|
||||
|
||||
## Trade Message
|
||||
```
|
||||
wss://ws-subscriptions-clob.polymarket.com/ws/user
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
Include API credentials in your subscription message:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"auth": {
|
||||
"apiKey": "your-api-key",
|
||||
"secret": "your-api-secret",
|
||||
"passphrase": "your-passphrase"
|
||||
},
|
||||
"markets": ["0x1234...condition_id"],
|
||||
"type": "user"
|
||||
}
|
||||
```
|
||||
|
||||
<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:
|
||||
|
||||
* when a market order is matched ("MATCHED")
|
||||
* when a limit order for the user is included in a trade ("MATCHED")
|
||||
* subsequent status changes for trade ("MINED", "CONFIRMED", "RETRYING", "FAILED")
|
||||
* A market order is matched (`MATCHED`)
|
||||
* A limit order for the user is included in a trade (`MATCHED`)
|
||||
* Subsequent status changes for the trade (`MINED`, `CONFIRMED`, `RETRYING`, `FAILED`)
|
||||
|
||||
### Structure
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---------------- | ------------- | ------------------------------------------- |
|
||||
| asset\_id | string | asset id (token ID) of order (market order) |
|
||||
| event\_type | string | "trade" |
|
||||
| id | string | trade id |
|
||||
| last\_update | string | time of last update to trade |
|
||||
| maker\_orders | MakerOrder\[] | array of maker order details |
|
||||
| market | string | market identifier (condition ID) |
|
||||
| matchtime | string | time trade was matched |
|
||||
| outcome | string | outcome |
|
||||
| owner | string | api key of event owner |
|
||||
| price | string | price |
|
||||
| side | string | BUY/SELL |
|
||||
| size | string | size |
|
||||
| status | string | trade status |
|
||||
| taker\_order\_id | string | id of taker order |
|
||||
| timestamp | string | time of event |
|
||||
| trade\_owner | string | api key of trade owner |
|
||||
| type | string | "TRADE" |
|
||||
|
||||
Where a `MakerOrder` object is of the form:
|
||||
|
||||
| Name | Type | Description |
|
||||
| --------------- | ------ | -------------------------------------- |
|
||||
| asset\_id | string | asset of the maker order |
|
||||
| matched\_amount | string | amount of maker order matched in trade |
|
||||
| order\_id | string | maker order ID |
|
||||
| outcome | string | outcome |
|
||||
| owner | string | owner of maker order |
|
||||
| price | string | price of maker order |
|
||||
|
||||
```json Response theme={null}
|
||||
```json theme={null}
|
||||
{
|
||||
"asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426",
|
||||
"event_type": "trade",
|
||||
@@ -82,34 +78,33 @@ Where a `MakerOrder` object is of the form:
|
||||
}
|
||||
```
|
||||
|
||||
## Order Message
|
||||
#### Trade Statuses
|
||||
|
||||
```
|
||||
MATCHED → MINED → CONFIRMED
|
||||
↓ ↑
|
||||
RETRYING ───┘
|
||||
↓
|
||||
FAILED
|
||||
```
|
||||
|
||||
| Status | Terminal | Description |
|
||||
| ----------- | -------- | ----------------------------------------------------------------------------------------------- |
|
||||
| `MATCHED` | No | Trade has been matched and sent to the executor service by the operator |
|
||||
| `MINED` | No | Trade observed to be mined into the chain, no finality threshold established |
|
||||
| `CONFIRMED` | Yes | Trade has achieved strong probabilistic finality and was successful |
|
||||
| `RETRYING` | No | Trade transaction has failed (revert or reorg) and is being retried/resubmitted by the operator |
|
||||
| `FAILED` | Yes | Trade has failed and is not being retried |
|
||||
|
||||
### order
|
||||
|
||||
Emitted when:
|
||||
|
||||
* When an order is placed (PLACEMENT)
|
||||
* When an order is updated (some of it is matched) (UPDATE)
|
||||
* When an order is canceled (CANCELLATION)
|
||||
* An order is placed (`PLACEMENT`)
|
||||
* An order is updated — some of it is matched (`UPDATE`)
|
||||
* An order is cancelled (`CANCELLATION`)
|
||||
|
||||
### Structure
|
||||
|
||||
| Name | Type | Description |
|
||||
| ----------------- | --------- | ------------------------------------------------------------------- |
|
||||
| asset\_id | string | asset ID (token ID) of order |
|
||||
| associate\_trades | string\[] | array of ids referencing trades that the order has been included in |
|
||||
| event\_type | string | "order" |
|
||||
| id | string | order id |
|
||||
| market | string | condition ID of market |
|
||||
| order\_owner | string | owner of order |
|
||||
| original\_size | string | original order size |
|
||||
| outcome | string | outcome |
|
||||
| owner | string | owner of orders |
|
||||
| price | string | price of order |
|
||||
| side | string | BUY/SELL |
|
||||
| size\_matched | string | size of order that has been matched |
|
||||
| timestamp | string | time of event |
|
||||
| type | string | PLACEMENT/UPDATE/CANCELLATION |
|
||||
|
||||
```json Response theme={null}
|
||||
```json theme={null}
|
||||
{
|
||||
"asset_id": "52114319501245915516055106046884209969926127482827954674443846427813813222426",
|
||||
"associate_trades": null,
|
||||
|
||||
@@ -2,12 +2,180 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# WSS Authentication
|
||||
# Overview
|
||||
|
||||
<Tip> Only connections to `user` channel require authentication. </Tip>
|
||||
> Real-time market data and trading updates via WebSocket
|
||||
|
||||
| Field | Optional | Description |
|
||||
| ---------- | -------- | ------------------------------------- |
|
||||
| apikey | yes | Polygon account's CLOB api key |
|
||||
| secret | yes | Polygon account's CLOB api secret |
|
||||
| passphrase | yes | Polygon account's CLOB api passphrase |
|
||||
Polymarket provides WebSocket channels for near real-time streaming of orderbook data, trades, and personal order activity. There are four available channels: `market`, `user`, `sports`, and `RTDS` (Real-Time Data Socket).
|
||||
|
||||
## Channels
|
||||
|
||||
| Channel | Endpoint | Auth |
|
||||
| ----------------------------------- | ------------------------------------------------------ | -------- |
|
||||
| Market | `wss://ws-subscriptions-clob.polymarket.com/ws/market` | No |
|
||||
| User | `wss://ws-subscriptions-clob.polymarket.com/ws/user` | Yes |
|
||||
| Sports | `wss://sports-api.polymarket.com/ws` | No |
|
||||
| [RTDS](/market-data/websocket/rtds) | `wss://ws-live-data.polymarket.com` | Optional |
|
||||
|
||||
### Market Channel
|
||||
|
||||
| Type | Description | Custom Feature |
|
||||
| ------------------ | ----------------------- | -------------- |
|
||||
| `book` | Full orderbook snapshot | No |
|
||||
| `price_change` | Price level updates | No |
|
||||
| `tick_size_change` | Tick size changes | No |
|
||||
| `last_trade_price` | Trade executions | No |
|
||||
| `best_bid_ask` | Best prices update | Yes |
|
||||
| `new_market` | New market created | Yes |
|
||||
| `market_resolved` | Market resolution | Yes |
|
||||
|
||||
Types marked "Custom Feature" require `custom_feature_enabled: true` in your subscription.
|
||||
|
||||
### User Channel
|
||||
|
||||
| Type | Description |
|
||||
| ------- | --------------------------------------------- |
|
||||
| `trade` | Trade lifecycle updates (MATCHED → CONFIRMED) |
|
||||
| `order` | Order placements, updates, and cancellations |
|
||||
|
||||
### Sports
|
||||
|
||||
| Type | Description |
|
||||
| -------------- | ------------------------------------- |
|
||||
| `sport_result` | Live game scores, periods, and status |
|
||||
|
||||
## Subscribing
|
||||
|
||||
Send a subscription message after connecting to specify which data you want to receive.
|
||||
|
||||
### Market Channel
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"assets_ids": [
|
||||
"21742633143463906290569050155826241533067272736897614950488156847949938836455",
|
||||
"48331043336612883890938759509493159234755048973500640148014422747788308965732"
|
||||
],
|
||||
"type": "market",
|
||||
"custom_feature_enabled": true
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------------ | --------- | ----------------------------------------------------------------- |
|
||||
| `assets_ids` | string\[] | Token IDs to subscribe to |
|
||||
| `type` | string | Channel identifier |
|
||||
| `custom_feature_enabled` | boolean | Enable `best_bid_ask`, `new_market`, and `market_resolved` events |
|
||||
|
||||
### User Channel
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"auth": {
|
||||
"apiKey": "your-api-key",
|
||||
"secret": "your-api-secret",
|
||||
"passphrase": "your-passphrase"
|
||||
},
|
||||
"markets": ["0x1234...condition_id"],
|
||||
"type": "user"
|
||||
}
|
||||
```
|
||||
|
||||
<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 & 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 ~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>
|
||||
|
||||
@@ -2,35 +2,180 @@
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# WSS Overview
|
||||
# Overview
|
||||
|
||||
> Overview and general information about the Polymarket Websocket
|
||||
> Real-time market data and trading updates via WebSocket
|
||||
|
||||
## Overview
|
||||
Polymarket provides WebSocket channels for near real-time streaming of orderbook data, trades, and personal order activity. There are four available channels: `market`, `user`, `sports`, and `RTDS` (Real-Time Data Socket).
|
||||
|
||||
The Polymarket CLOB API provides websocket (wss) channels through which clients can get pushed updates. These endpoints allow clients to maintain almost real-time views of their orders, their trades and markets in general. There are two available channels `user` and `market`.
|
||||
## Channels
|
||||
|
||||
## Subscription
|
||||
| Channel | Endpoint | Auth |
|
||||
| ----------------------------------- | ------------------------------------------------------ | -------- |
|
||||
| Market | `wss://ws-subscriptions-clob.polymarket.com/ws/market` | No |
|
||||
| User | `wss://ws-subscriptions-clob.polymarket.com/ws/user` | Yes |
|
||||
| Sports | `wss://sports-api.polymarket.com/ws` | No |
|
||||
| [RTDS](/market-data/websocket/rtds) | `wss://ws-live-data.polymarket.com` | Optional |
|
||||
|
||||
To subscribe send a message including the following authentication and intent information upon opening the connection.
|
||||
### Market Channel
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------------ | --------- | --------------------------------------------------------------------------- |
|
||||
| auth | Auth | see next page for auth information |
|
||||
| markets | string\[] | array of markets (condition IDs) to receive events for (for `user` channel) |
|
||||
| assets\_ids | string\[] | array of asset ids (token IDs) to receive events for (for `market` channel) |
|
||||
| type | string | id of channel to subscribe to (USER or MARKET) |
|
||||
| custom\_feature\_enabled | bool | enabling / disabling custom features |
|
||||
| Type | Description | Custom Feature |
|
||||
| ------------------ | ----------------------- | -------------- |
|
||||
| `book` | Full orderbook snapshot | No |
|
||||
| `price_change` | Price level updates | No |
|
||||
| `tick_size_change` | Tick size changes | No |
|
||||
| `last_trade_price` | Trade executions | No |
|
||||
| `best_bid_ask` | Best prices update | Yes |
|
||||
| `new_market` | New market created | Yes |
|
||||
| `market_resolved` | Market resolution | Yes |
|
||||
|
||||
Where the `auth` field is of type `Auth` which has the form described in the WSS Authentication section below.
|
||||
Types marked "Custom Feature" require `custom_feature_enabled: true` in your subscription.
|
||||
|
||||
### User Channel
|
||||
|
||||
| Type | Description |
|
||||
| ------- | --------------------------------------------- |
|
||||
| `trade` | Trade lifecycle updates (MATCHED → CONFIRMED) |
|
||||
| `order` | Order placements, updates, and cancellations |
|
||||
|
||||
### Sports
|
||||
|
||||
| Type | Description |
|
||||
| -------------- | ------------------------------------- |
|
||||
| `sport_result` | Live game scores, periods, and status |
|
||||
|
||||
## Subscribing
|
||||
|
||||
Send a subscription message after connecting to specify which data you want to receive.
|
||||
|
||||
### Market Channel
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"assets_ids": [
|
||||
"21742633143463906290569050155826241533067272736897614950488156847949938836455",
|
||||
"48331043336612883890938759509493159234755048973500640148014422747788308965732"
|
||||
],
|
||||
"type": "market",
|
||||
"custom_feature_enabled": true
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------------ | --------- | ----------------------------------------------------------------- |
|
||||
| `assets_ids` | string\[] | Token IDs to subscribe to |
|
||||
| `type` | string | Channel identifier |
|
||||
| `custom_feature_enabled` | boolean | Enable `best_bid_ask`, `new_market`, and `market_resolved` events |
|
||||
|
||||
### User Channel
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"auth": {
|
||||
"apiKey": "your-api-key",
|
||||
"secret": "your-api-secret",
|
||||
"passphrase": "your-passphrase"
|
||||
},
|
||||
"markets": ["0x1234...condition_id"],
|
||||
"type": "user"
|
||||
}
|
||||
```
|
||||
|
||||
<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
|
||||
|
||||
Once connected, the client can subscribe and unsubscribe to `asset_ids` by sending the following message:
|
||||
```json theme={null}
|
||||
{
|
||||
"assets_ids": ["new_asset_id_1", "new_asset_id_2"],
|
||||
"operation": "subscribe",
|
||||
"custom_feature_enabled": true
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
| ------------------------ | --------- | ------------------------------------------------------------------------------ |
|
||||
| assets\_ids | string\[] | array of asset ids (token IDs) to receive events for (for `market` channel) |
|
||||
| markets | string\[] | array of market ids (condition IDs) to receive events for (for `user` channel) |
|
||||
| operation | string | "subscribe" or "unsubscribe" |
|
||||
| custom\_feature\_enabled | bool | enabling / disabling custom features |
|
||||
### Unsubscribe from assets
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"assets_ids": ["asset_id_to_remove"],
|
||||
"operation": "unsubscribe"
|
||||
}
|
||||
```
|
||||
|
||||
For the user channel, use `markets` instead of `assets_ids`:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"markets": ["0x1234...condition_id"],
|
||||
"operation": "subscribe"
|
||||
}
|
||||
```
|
||||
|
||||
## Heartbeats
|
||||
|
||||
### Market & User Channels
|
||||
|
||||
Send `PING` every 10 seconds. The server responds with `PONG`.
|
||||
|
||||
```
|
||||
PING
|
||||
```
|
||||
|
||||
### Sports Channel
|
||||
|
||||
The server sends `ping` every 5 seconds. Respond with `pong` within 10 seconds.
|
||||
|
||||
```
|
||||
pong
|
||||
```
|
||||
|
||||
<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 ~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>
|
||||
|
||||
Reference in New Issue
Block a user