docs: sync Polymarket docs updates 2026-07-13 - add 90 new pages incl. Perps section
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,653 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Authenticated Sessions
|
||||
|
||||
> Set up authenticated access for Perps trading and account data
|
||||
|
||||
An authenticated session is a two-way authenticated communication channel with
|
||||
the Perps system that allows your app to place orders, read private Perps account
|
||||
data, and receive private real-time updates.
|
||||
|
||||
## Set Up Perps Access
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
<Steps>
|
||||
<Step title="Create a Secure Client">
|
||||
Create a `SecureClient` for the Polymarket wallet that owns the Perps account,
|
||||
using the signer that controls it.
|
||||
|
||||
```ts theme={null}
|
||||
import { createSecureClient } from "@polymarket/client";
|
||||
import { privateKey } from "@polymarket/client/viem";
|
||||
|
||||
const client = await createSecureClient({
|
||||
wallet: process.env.POLYMARKET_WALLET_ADDRESS!,
|
||||
signer: privateKey(process.env.PRIVATE_KEY!),
|
||||
});
|
||||
```
|
||||
|
||||
<Note>
|
||||
This example uses Viem for wallet signing. See the [TypeScript tooling
|
||||
guide](/dev-tooling/typescript#wallet-integrations) for other wallet library
|
||||
integrations.
|
||||
</Note>
|
||||
</Step>
|
||||
|
||||
<Step title="Open a Perps Session">
|
||||
Open a Perps session. By default, delegated Perps credentials expire after one
|
||||
week.
|
||||
|
||||
```ts theme={null}
|
||||
const session = await client.openPerpsSession();
|
||||
```
|
||||
|
||||
You can also set the session lifetime and label explicitly. `expiresIn` is
|
||||
measured in milliseconds.
|
||||
|
||||
```ts theme={null}
|
||||
const session = await client.openPerpsSession({
|
||||
expiresIn: 7 * 24 * 60 * 60 * 1000,
|
||||
label: "trading-app",
|
||||
});
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
<Steps>
|
||||
<Step title="Create a Secure Client">
|
||||
Create an `AsyncSecureClient` for the Polymarket wallet that owns the Perps
|
||||
account, using the signer that controls it.
|
||||
|
||||
```python theme={null}
|
||||
import os
|
||||
|
||||
from polymarket import AsyncSecureClient
|
||||
|
||||
client = await AsyncSecureClient.create(
|
||||
private_key=os.environ["PRIVATE_KEY"],
|
||||
wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Open a Perps Session">
|
||||
Open a Perps session. By default, delegated Perps credentials expire after one
|
||||
week.
|
||||
|
||||
```python theme={null}
|
||||
session = await client.open_perps_session()
|
||||
```
|
||||
|
||||
You can also set the session lifetime and label explicitly. `expires_in` is a
|
||||
`timedelta`.
|
||||
|
||||
```python theme={null}
|
||||
from datetime import timedelta
|
||||
|
||||
session = await client.open_perps_session(
|
||||
expires_in=timedelta(days=7),
|
||||
label="trading-app",
|
||||
)
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Start by registering new proxy credentials for an existing Polymarket account.
|
||||
If you do not have one yet, create an account at
|
||||
[polymarket.com](https://polymarket.com) first.
|
||||
|
||||
<Steps>
|
||||
<Step title="Generate a Proxy Signer">
|
||||
Generate a fresh keypair for the proxy signer. Perps uses this key to authorize
|
||||
trading operations on behalf of the Polymarket account signer, without requiring
|
||||
the account signer to sign every order.
|
||||
|
||||
Use any secure EVM key-generation flow.
|
||||
|
||||
<CodeGroup>
|
||||
```bash Foundry theme={null}
|
||||
$ cast wallet new
|
||||
Successfully created new keypair.
|
||||
Address: <proxy_address>
|
||||
Private key: <proxy_private_key>
|
||||
```
|
||||
|
||||
```ts Viem theme={null}
|
||||
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
|
||||
|
||||
const privateKey = generatePrivateKey();
|
||||
const { address } = privateKeyToAccount(privateKey);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Store the private key securely. It will be used to sign Perps trading operations
|
||||
for the Polymarket account signer.
|
||||
</Step>
|
||||
|
||||
<Step title="Create Proxy Typed Data">
|
||||
Create an EIP-712 `CreateProxy` payload.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"domain": {
|
||||
"name": "Polymarket",
|
||||
"version": "1",
|
||||
"chainId": 137
|
||||
},
|
||||
"primaryType": "CreateProxy",
|
||||
"types": {
|
||||
"CreateProxy": [
|
||||
{ "name": "addr", "type": "address" },
|
||||
{ "name": "exp", "type": "uint64" },
|
||||
{ "name": "salt", "type": "uint64" },
|
||||
{ "name": "ts", "type": "uint64" }
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"addr": "<proxy_address>",
|
||||
"exp": 1767225600000,
|
||||
"salt": 123456789,
|
||||
"ts": 1767000000000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use these values consistently in the typed data and request body.
|
||||
|
||||
| Field | Value |
|
||||
| ------ | ----------------------------------------------------------------------- |
|
||||
| `addr` | `<proxy_address>` from the previous step. |
|
||||
| `exp` | Unix timestamp in milliseconds when the proxy signer stops being valid. |
|
||||
| `ts` | Current Unix timestamp in milliseconds. |
|
||||
| `salt` | Random integer generated for this signed request. |
|
||||
</Step>
|
||||
|
||||
<Step title="Sign Proxy Typed Data">
|
||||
Sign the `CreateProxy` typed data with the signer for the Polymarket account.
|
||||
|
||||
```ts Viem theme={null}
|
||||
import { privateKeyToAccount } from "viem/accounts";
|
||||
|
||||
const account = privateKeyToAccount("<polymarket_account_signer_private_key>");
|
||||
|
||||
const signature = await account.signTypedData({
|
||||
domain: {
|
||||
name: "Polymarket",
|
||||
version: "1",
|
||||
chainId: 137,
|
||||
},
|
||||
primaryType: "CreateProxy",
|
||||
types: {
|
||||
CreateProxy: [
|
||||
{ name: "addr", type: "address" },
|
||||
{ name: "exp", type: "uint64" },
|
||||
{ name: "salt", type: "uint64" },
|
||||
{ name: "ts", type: "uint64" },
|
||||
],
|
||||
},
|
||||
message: {
|
||||
addr: "<proxy_address>",
|
||||
exp: 1767225600000,
|
||||
salt: 123456789,
|
||||
ts: 1767000000000,
|
||||
},
|
||||
});
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Authorize the Proxy Signer">
|
||||
Authorize the generated proxy signer for your Perps account.
|
||||
|
||||
```bash theme={null}
|
||||
curl -X POST "https://api.perpetuals.polymarket.com/v1/account/proxy" \
|
||||
-H "content-type: application/json" \
|
||||
-d '{
|
||||
"op": {
|
||||
"type": "createProxy",
|
||||
"args": {
|
||||
"owner": "<polymarket_account_signer_address>",
|
||||
"proxy": "<proxy_address>",
|
||||
"expiry": 1767225600000
|
||||
}
|
||||
},
|
||||
"sig": "<signature>",
|
||||
"salt": 123456789,
|
||||
"ts": 1767000000000,
|
||||
"label": "trading-app"
|
||||
}'
|
||||
```
|
||||
|
||||
Map the request fields to the values from the previous steps.
|
||||
|
||||
* `owner` is the signer address for the Polymarket account.
|
||||
* `proxy` is `<proxy_address>` from the first step.
|
||||
* `sig` is `<signature>` from the previous step.
|
||||
* `salt` and `ts` are the same values used in the typed data from step 2.
|
||||
* `label` is an identifier for this proxy credential instance.
|
||||
|
||||
The response contains the proxy secret.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"secret": "<proxy_secret>"
|
||||
}
|
||||
```
|
||||
|
||||
Store the proxy private key, proxy address, proxy secret, and expiry securely.
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Session Lifecycle
|
||||
|
||||
Open an authenticated session to start trading, read private Perps account data,
|
||||
and receive private real-time updates.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
<Steps>
|
||||
<Step title="Listen for Session Events">
|
||||
After opening a Perps session, iterate over it to receive private real-time
|
||||
updates.
|
||||
|
||||
```ts theme={null}
|
||||
const session = await client.openPerpsSession();
|
||||
|
||||
for await (const event of session) {
|
||||
switch (event.type) {
|
||||
case "order":
|
||||
// Update local order state.
|
||||
break;
|
||||
|
||||
case "fill":
|
||||
// Update position, PnL, or execution history.
|
||||
break;
|
||||
|
||||
case "portfolio":
|
||||
// Refresh margin, equity, and position views.
|
||||
break;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This example handles a few common session events. `order` and `fill` are the
|
||||
core trading updates, while `portfolio` provides periodic account-level snapshots
|
||||
for margin, equity, positions, and withdrawable balance.
|
||||
|
||||
See [Reconcile Trade State](/perps/trading#reconcile-trade-state) for how to use
|
||||
these events to keep local trading state in sync.
|
||||
</Step>
|
||||
|
||||
<Step title="Close the Session">
|
||||
You can close the session at any time by calling `session.close()`. Closing a
|
||||
session releases local resources; stored credentials can still be resumed until
|
||||
they expire.
|
||||
|
||||
```ts theme={null}
|
||||
for await (const event of session) {
|
||||
if (shouldCloseSession) {
|
||||
await session.close();
|
||||
break;
|
||||
}
|
||||
|
||||
// …
|
||||
}
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
<Steps>
|
||||
<Step title="Listen for Session Events">
|
||||
After opening a Perps session, iterate over it to receive private real-time
|
||||
updates.
|
||||
|
||||
```python theme={null}
|
||||
session = await client.open_perps_session()
|
||||
|
||||
async for event in session:
|
||||
if event.type == "order":
|
||||
# Update local order state.
|
||||
pass
|
||||
elif event.type == "fill":
|
||||
# Update position, PnL, or execution history.
|
||||
pass
|
||||
elif event.type == "portfolio":
|
||||
# Refresh margin, equity, and position views.
|
||||
pass
|
||||
```
|
||||
|
||||
This example handles a few common session events. `order` and `fill` are the
|
||||
core trading updates, while `portfolio` provides periodic account-level snapshots
|
||||
for margin, equity, positions, and withdrawable balance.
|
||||
|
||||
See [Reconcile Trade State](/perps/trading#reconcile-trade-state) for how to use
|
||||
these events to keep local trading state in sync.
|
||||
</Step>
|
||||
|
||||
<Step title="Close the Session">
|
||||
You can close the session at any time by calling `session.close()`. Closing a
|
||||
session releases local resources; stored credentials can still be resumed until
|
||||
they expire.
|
||||
|
||||
```python theme={null}
|
||||
async for event in session:
|
||||
if should_close_session:
|
||||
await session.close()
|
||||
break
|
||||
|
||||
# …
|
||||
```
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
<Steps>
|
||||
<Step title="Authenticate a WebSocket Connection">
|
||||
Connect to the Perps WebSocket production URL.
|
||||
|
||||
```text theme={null}
|
||||
wss://ws.perpetuals.polymarket.com/v1/ws
|
||||
```
|
||||
|
||||
After the connection opens, send an authentication frame with the proxy address
|
||||
and proxy secret.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"id": 1,
|
||||
"req": "post",
|
||||
"op": {
|
||||
"type": "auth",
|
||||
"args": {
|
||||
"proxy": "<proxy_address>",
|
||||
"secret": "<proxy_secret>"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Check the authentication response before subscribing to private channels.
|
||||
|
||||
<CodeGroup>
|
||||
```json Success theme={null}
|
||||
{
|
||||
"id": 1,
|
||||
"data": {
|
||||
"status": "ok"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json Failure theme={null}
|
||||
{
|
||||
"id": 1,
|
||||
"data": {
|
||||
"status": "err",
|
||||
"error": "<error_message>"
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
|
||||
<Step title="Handle Session Events">
|
||||
Authenticated WebSocket connections receive private session update frames. These
|
||||
examples show a few common events: `orders` and `fills` for trading activity,
|
||||
and `portfolio` for periodic account-level snapshots.
|
||||
|
||||
<CodeGroup>
|
||||
```json Order theme={null}
|
||||
{
|
||||
"ch": "orders",
|
||||
"ts": 1767225600000,
|
||||
"sq": 1234567890,
|
||||
"data": {
|
||||
"oid": 1234567890,
|
||||
"iid": 1,
|
||||
"buy": true,
|
||||
"p": "65000.00",
|
||||
"qty": "0.01",
|
||||
"tif": "gtc",
|
||||
"po": false,
|
||||
"status": "open",
|
||||
"rest": "0.01",
|
||||
"fill": "0",
|
||||
"cts": 1767225600000,
|
||||
"uts": 1767225600000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json Fill theme={null}
|
||||
{
|
||||
"ch": "fills",
|
||||
"ts": 1767225600000,
|
||||
"sq": 1234567891,
|
||||
"data": {
|
||||
"tid": 987654321,
|
||||
"oid": 1234567890,
|
||||
"iid": 1,
|
||||
"side": "long",
|
||||
"p": "65000.00",
|
||||
"qty": "0.01",
|
||||
"taker": true,
|
||||
"fee": "0.26",
|
||||
"fea": "pUSD",
|
||||
"psz": "0",
|
||||
"pep": "0",
|
||||
"pnl": "0",
|
||||
"liq": false,
|
||||
"ts": 1767225600000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json Portfolio theme={null}
|
||||
{
|
||||
"ch": "portfolio",
|
||||
"ts": 1767225600000,
|
||||
"sq": 1234567892,
|
||||
"data": {
|
||||
"positions": [],
|
||||
"margin": {
|
||||
"total_account_value": "10.00",
|
||||
"total_initial_margin": "0",
|
||||
"total_maintenance_margin": "0",
|
||||
"total_position_value": "0"
|
||||
},
|
||||
"withdrawable": "10.00",
|
||||
"in_liquidation": false,
|
||||
"timestamp": 1767225600000
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
These are examples of common session events, not the full event list.
|
||||
</Step>
|
||||
|
||||
<Step title="Keep the Connection Alive">
|
||||
Send an application-level ping from the client about every 25 seconds.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"id": 0,
|
||||
"req": "post",
|
||||
"op": {
|
||||
"type": "ping"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The server responds with a pong payload.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"id": 0,
|
||||
"data": {
|
||||
"status": "ok",
|
||||
"ts": 1767225600000,
|
||||
"sq": 1234567890
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Treat the connection as stale if no messages arrive for about 65 seconds.
|
||||
</Step>
|
||||
|
||||
<Step title="Close the Connection">
|
||||
Close the WebSocket connection when the current workflow is finished. Closing the
|
||||
connection does not revoke the proxy credential.
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Resume a Session
|
||||
|
||||
Resume a session when stored credentials are still valid and a Perps workflow
|
||||
needs to continue in a new runtime context.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
Read `session.credentials` after opening a session and store the object in secure
|
||||
credential storage.
|
||||
|
||||
```ts theme={null}
|
||||
const credentials = session.credentials;
|
||||
// credentials: PerpsCredentials
|
||||
```
|
||||
|
||||
where `PerpsCredentials` is:
|
||||
|
||||
<CodeGroup>
|
||||
```ts Type theme={null}
|
||||
type PerpsCredentials = {
|
||||
proxy: EvmAddress;
|
||||
privateKey: PrivateKey;
|
||||
secret: string;
|
||||
expiresAt: number;
|
||||
};
|
||||
```
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"proxy": "0x1111111111111111111111111111111111111111",
|
||||
"privateKey": "0x2222222222222222222222222222222222222222222222222222222222222222",
|
||||
"secret": "<proxy_secret>",
|
||||
"expiresAt": 1766725200000
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Pass stored credentials back to `openPerpsSession()` while they are still valid.
|
||||
The SDK validates them and resumes the session.
|
||||
|
||||
```ts theme={null}
|
||||
const session = await client.openPerpsSession({
|
||||
credentials,
|
||||
});
|
||||
// session: PerpsSession
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
Read `session.credentials` after opening a session and store the object in secure
|
||||
credential storage.
|
||||
|
||||
```python theme={null}
|
||||
credentials = session.credentials
|
||||
# credentials: PerpsCredentials
|
||||
```
|
||||
|
||||
where `PerpsCredentials` is:
|
||||
|
||||
<CodeGroup>
|
||||
```python Type theme={null}
|
||||
from polymarket import PerpsCredentials
|
||||
|
||||
# credentials: PerpsCredentials
|
||||
```
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"proxy": "0x1111111111111111111111111111111111111111",
|
||||
"private_key": "0x2222222222222222222222222222222222222222222222222222222222222222",
|
||||
"secret": "<proxy_secret>",
|
||||
"expires_at": "2026-01-25T18:20:00Z"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
For JSON-backed storage, serialize the model and keep the result encrypted.
|
||||
|
||||
```python theme={null}
|
||||
stored_credentials = credentials.model_dump(mode="json")
|
||||
```
|
||||
|
||||
Pass stored credentials back to `open_perps_session()` while they are still
|
||||
valid. The SDK validates them and resumes the session.
|
||||
|
||||
```python theme={null}
|
||||
from polymarket import PerpsCredentials
|
||||
|
||||
credentials = PerpsCredentials.model_validate(stored_credentials)
|
||||
|
||||
session = await client.open_perps_session(credentials=credentials)
|
||||
# session: PerpsSession
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Resume an API session by reusing stored proxy credentials while they are still
|
||||
valid.
|
||||
|
||||
Store the credential material from the setup flow in secure credential storage.
|
||||
|
||||
| Field | Use it to |
|
||||
| --------------------- | ----------------------------------------------- |
|
||||
| `<proxy_address>` | Identify the proxy credential. |
|
||||
| `<proxy_private_key>` | Sign Perps trading operations. |
|
||||
| `<proxy_secret>` | Authenticate private REST and real-time access. |
|
||||
| `expiry` | Know when to register a new proxy credential. |
|
||||
|
||||
For private REST reads, pass the proxy address and proxy secret as headers.
|
||||
|
||||
```bash theme={null}
|
||||
curl "https://api.perpetuals.polymarket.com/v1/account/portfolio" \
|
||||
-H "polymarket-proxy: <proxy_address>" \
|
||||
-H "polymarket-secret: <proxy_secret>"
|
||||
```
|
||||
|
||||
For a new WebSocket connection, send the same authentication frame used when the
|
||||
session was opened.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"id": 1,
|
||||
"req": "post",
|
||||
"op": {
|
||||
"type": "auth",
|
||||
"args": {
|
||||
"proxy": "<proxy_address>",
|
||||
"secret": "<proxy_secret>"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If the credential has expired, register a new proxy credential before resuming
|
||||
private workflows.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@@ -0,0 +1,53 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Changelog
|
||||
|
||||
> Recent changes to the Polymarket Perps API and platform
|
||||
|
||||
Notable changes to the Polymarket Perps API.
|
||||
|
||||
<Update label="Jun 11, 2026" description="Cancel responses include order IDs">
|
||||
Cancel responses now include `oid` and `coid` fields.
|
||||
</Update>
|
||||
|
||||
<Update label="Jun 10, 2026" description="Taker delay added for immediately matching orders">
|
||||
Added a 20ms taker delay for orders that immediately match on entry.
|
||||
</Update>
|
||||
|
||||
<Update label="Jun 9, 2026" description="Reduce-only orders added">
|
||||
Added the reduce-only field to order submission and order updates.
|
||||
</Update>
|
||||
|
||||
<Update label="Jun 8, 2026" description="Auto-cancel and rate-limit updates">
|
||||
<ul>
|
||||
<li>
|
||||
Added <code>PATCH /v1/trade/auto-cancel</code> to arm or clear a dead
|
||||
man's switch that cancels all open orders at a specified time.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Added <code>GET /v1/account/auto-cancel</code> to check the current
|
||||
auto-cancel status, trigger count, and daily reset time.
|
||||
</li>
|
||||
|
||||
<li>Auto-cancel is limited to 10 triggers per UTC day per account.</li>
|
||||
|
||||
<li>
|
||||
Added <code>updateLeverage</code> and <code>autoCancel</code> WebSocket
|
||||
post messages.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<code>portfolio</code> and <code>balances</code> WebSocket channels no
|
||||
longer push updates on every order or fill, only periodically.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Rate limit error messages now distinguish between{" "}
|
||||
<code>ip\_rate\_limited</code>, <code>action\_rate\_limited</code>, and{" "}
|
||||
<code>message\_rate\_limited</code>.
|
||||
</li>
|
||||
</ul>
|
||||
</Update>
|
||||
@@ -0,0 +1,186 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Concepts
|
||||
|
||||
> Core concepts for Polymarket perpetual markets
|
||||
|
||||
Perps trading depends on how order fills create or change positions, how prices
|
||||
affect account equity, and how collateral supports trading risk. The concepts
|
||||
below describe the moving parts that determine what an account can trade and when
|
||||
a position is at risk.
|
||||
|
||||
## Instruments
|
||||
|
||||
An instrument identifies a Perps market: a tradable perpetual contract that
|
||||
tracks an underlying asset such as the S\&P 500 Index, gold, or bitcoin. Each
|
||||
instrument carries the information needed to identify the market and the rules
|
||||
for trading it.
|
||||
|
||||
| Attribute | Meaning |
|
||||
| ------------------- | ---------------------------------------------------------------------------------------------- |
|
||||
| ID | The instrument identifier used in market data and orders |
|
||||
| Symbol | A short market label, such as `SP500-USD`, `GOLD-USD`, or `BTC-USD` |
|
||||
| Underlying asset | The asset or index the market tracks, such as the S\&P 500 Index, gold, or bitcoin |
|
||||
| Collateral asset | The asset used to fund Perps accounts and support open positions. Polymarket Perps use pUSD. |
|
||||
| Trading constraints | Market-specific rules such as price precision, quantity precision, order limits, and leverage. |
|
||||
|
||||
## Perps Accounts
|
||||
|
||||
A Perps account is tied to a signer account. The signer account controls private
|
||||
actions such as trading and withdrawals.
|
||||
|
||||
The Perps account holds the state created by those actions: collateral, open
|
||||
positions, orders, fills, and history. Later sections explain how those pieces
|
||||
change as orders execute, prices move, and funding payments settle.
|
||||
|
||||
Perps accounts are funded through onchain collateral deposits.
|
||||
|
||||
<Note>
|
||||
If you're building on Perps, delegated credentials let your app act for the
|
||||
Perps account without using the owner key for every private action. See
|
||||
[Authenticated Sessions](/perps/authenticated-sessions).
|
||||
</Note>
|
||||
|
||||
## Prices
|
||||
|
||||
A Perps market has two broad categories of prices: execution prices and
|
||||
calculated prices. Execution prices come from trades in the order book.
|
||||
Calculated prices are produced by Polymarket and used for reference, margin, and
|
||||
liquidation checks.
|
||||
|
||||
This separation matters because one small or isolated trade should not be able to
|
||||
change an account's risk state or trigger liquidation by itself.
|
||||
|
||||
| Price | Category | Meaning | Used for |
|
||||
| ------------ | ---------------- | ---------------------------------------------------------- | --------------------------------------------------- |
|
||||
| Traded price | Execution price | The price of an executed order book fill | Trade history and execution records |
|
||||
| Index price | Calculated price | Polymarket's estimate of the underlying asset's fair value | Reference price and price anchoring |
|
||||
| Mark price | Calculated price | The price used to value positions | Unrealized PnL, margin checks, and liquidation risk |
|
||||
|
||||
Calculated prices are computed from external price feeds. The feed set can
|
||||
change with market sessions, such as regular hours, overnight trading, and
|
||||
weekends, while funding, margin, and liquidation rules stay the same around the
|
||||
clock. See [Market Sessions](/perps/learn-about-trading/market-sessions).
|
||||
|
||||
## Orders And Fills
|
||||
|
||||
Orders are requests to trade in a Perps market. They can execute immediately or
|
||||
rest in the order book until another order matches them.
|
||||
|
||||
The order book is the list of resting buy and sell orders for a market. A fill is
|
||||
an executed match between orders in that book.
|
||||
|
||||
<Note>
|
||||
Fills update Perps account state; they are not separate onchain transactions.
|
||||
</Note>
|
||||
|
||||
```mermaid theme={null}
|
||||
flowchart LR
|
||||
A[Submit order] --> B{Matches now?}
|
||||
B -->|Yes| C[Fill updates account]
|
||||
B -->|No| D[Order rests in book]
|
||||
D --> E[Later fill or cancel]
|
||||
E --> C
|
||||
```
|
||||
|
||||
Limit orders are useful when the trade needs an explicit price. If the order does
|
||||
not fill immediately, it can rest in the book where it can be inspected,
|
||||
modified, or cancelled.
|
||||
|
||||
## Trading Positions
|
||||
|
||||
Once an order fills, it changes the account's position in that market. A position
|
||||
is what the account currently holds: long exposure, short exposure, or no open
|
||||
exposure.
|
||||
|
||||
| Position | Benefits when | Loses when |
|
||||
| -------- | ----------------------- | ----------------------- |
|
||||
| Long | The tracked asset rises | The tracked asset falls |
|
||||
| Short | The tracked asset falls | The tracked asset rises |
|
||||
|
||||
A fill that adds to the account's current side increases exposure. A fill against
|
||||
the current side reduces exposure. When the position size reaches zero, the
|
||||
position is closed. If losses exceed what the account can support, the position
|
||||
can also be liquidated.
|
||||
|
||||
## Margin And Liquidation
|
||||
|
||||
Perps accounts use collateral to support open positions. Margin checks compare
|
||||
the account's current value against the collateral required to open, increase, or
|
||||
maintain those positions.
|
||||
|
||||
Margin checks use these terms:
|
||||
|
||||
| Term | Meaning |
|
||||
| ------------------ | --------------------------------------------------------------------------------------------- |
|
||||
| Collateral | Funds available to support positions and withdrawals |
|
||||
| Account equity | The current value of the account after open-position gains, losses, fees, and funding effects |
|
||||
| Initial margin | Collateral required to open or increase a position |
|
||||
| Maintenance margin | Minimum collateral required to keep a position open |
|
||||
| Liquidation | Forced position closing when account equity falls below maintenance margin |
|
||||
|
||||
Account equity moves as the mark price changes and as account debits or credits
|
||||
settle. It can move up or down even before a position is closed.
|
||||
|
||||
<Tip>
|
||||
If you're building on Perps, monitor account equity to decide when to reduce
|
||||
exposure, add collateral, or stop placing new orders.
|
||||
</Tip>
|
||||
|
||||
At a high level, account equity is the account's collateral plus open-position
|
||||
gains or losses, minus amounts owed.
|
||||
|
||||
```text theme={null}
|
||||
Account equity = collateral + unrealized PnL - amounts owed
|
||||
```
|
||||
|
||||
If account equity falls below maintenance margin, the account is at risk of
|
||||
liquidation. Liquidation closes exposure to prevent losses from exceeding the
|
||||
account's collateral.
|
||||
|
||||
## Funding Payments
|
||||
|
||||
**Funding payments** help keep a Perps market close to its index price. They are
|
||||
not order-book trades; they are account debits or credits applied to open
|
||||
positions over time.
|
||||
|
||||
<Note>
|
||||
Funding payments are different from collateral deposits. Deposits add
|
||||
collateral to a Perps account; funding payments are debits or credits between
|
||||
long and short positions.
|
||||
</Note>
|
||||
|
||||
| Market state | Typical payment direction |
|
||||
| ------------------------------- | ------------------------- |
|
||||
| Market trades above index price | Longs pay shorts |
|
||||
| Market trades below index price | Shorts pay longs |
|
||||
|
||||
A funding payment credited to the account increases account equity. A funding
|
||||
payment owed by the account reduces account equity.
|
||||
|
||||
The **funding rate** is the rate used to calculate these payments. Public market
|
||||
data shows funding rates over time, while private account history shows the
|
||||
funding payments applied to an account.
|
||||
|
||||
## Realtime Account State
|
||||
|
||||
If you're building on Perps, realtime account state helps your integration keep a
|
||||
local view in sync.
|
||||
|
||||
Integrations often keep a local view of account state so they can react quickly
|
||||
to fills, risk changes, and collateral movements. Realtime updates help keep that
|
||||
local view in sync.
|
||||
|
||||
| State change | Why it matters |
|
||||
| --------------------- | -------------------------------------------------------------- |
|
||||
| Order update | A resting order opened, changed, filled, or cancelled |
|
||||
| Fill | A trade executed and changed the account's position or balance |
|
||||
| Portfolio update | Account equity, margin, or position state changed |
|
||||
| Funding payment | A funding debit or credit changed account state |
|
||||
| Deposit or withdrawal | Collateral moved into or out of the account |
|
||||
|
||||
Realtime streams can reconnect or detect gaps. When that happens, the integration
|
||||
should resync by refetching the account state it depends on before trusting the
|
||||
local view again.
|
||||
@@ -0,0 +1,261 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# FAQ
|
||||
|
||||
> Common questions about Polymarket Perps trading, pricing, margin, liquidation, fees, and integration
|
||||
|
||||
Common questions about Polymarket Perps.
|
||||
|
||||
## General
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What is Polymarket Perps?">
|
||||
Polymarket Perps is a perpetual futures exchange offering continuous exposure to equities, indices, commodities, and other underlyings. Positions have no expiry. A funding rate keeps the contract price tethered to the underlying's spot price over time.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Which instruments can I trade?">
|
||||
Fetch the current product list, symbols, underlyings, reference feeds, and
|
||||
leverage settings from [`GET
|
||||
/v1/info/instruments`](/perps/market-data#fetch-instruments).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Is the exchange on-chain or off-chain?">
|
||||
Hybrid. Order matching, margin, and funding run off-chain for low latency.
|
||||
Deposits and withdrawals settle on Polygon, and the exchange periodically
|
||||
posts state-root commitments on-chain so off-chain activity stays verifiable.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Does the perp trade 24/7, even when the underlying market is closed?">
|
||||
Yes. The order book, matching, funding, margin checks, and liquidations all
|
||||
run continuously. What changes outside of regular hours is the set of external
|
||||
feeds used to compute Index and Mark.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Do Polymarket Perps expire?">
|
||||
No. Perpetual futures have no expiration date. A Perps position stays open
|
||||
until you close it or it is force-closed by liquidation.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Are perps and perpetual futures the same thing?">
|
||||
Yes. "Perps" is trader shorthand for "perpetual futures." Both refer to the
|
||||
same derivative contract: a futures-style instrument with no expiry, anchored
|
||||
to the underlying's spot price through periodic funding.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How are Perps different from Polymarket prediction markets?">
|
||||
Polymarket's prediction markets settle Yes or No shares at $1 or $0 based on a discrete event outcome. Perps are continuous: there is no event resolution and no $0/$1 settlement. Instead you take a long or short position whose value moves with the underlying asset's price, subject to funding payments and margin requirements like any perpetual futures contract.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Trading and Orders
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What order types are supported?">
|
||||
Limit and market-style orders are supported with `gtc`, `ioc`, and `fok` time-in-force values. GTC orders can be tagged post-only, which rejects the order if it would take liquidity. Closing orders can be tagged reduce-only, which prevents the order from increasing exposure. See [Configure Order Behavior](/perps/trading#configure-order-behavior) and [Close a Position](/perps/trading#close-a-position).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Why was my order rejected when my balance looks fine?">
|
||||
Pre-trade margin uses the worst-case position size from your existing exposure plus all resting orders on each side, not just the current position.
|
||||
|
||||
```text theme={null}
|
||||
WorstCaseSize = max(|Position + OpenBuys|, |Position - OpenSells|)
|
||||
```
|
||||
|
||||
If `Equity < IM_required` for that worst case, the order is rejected even though current equity is comfortable.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What is self-trade prevention?">
|
||||
Self-trade prevention is on by default for every order and runs in CancelMaker mode: when a taker would match against a resting order on the same account, the conflicting resting maker is canceled and the taker continues matching against other makers. It is not an API setting. There is no way to turn it off or change its mode.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Pricing, Mark, Index, and Funding
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What's the difference between Mark Price, Index Price, and last trade price?">
|
||||
* Index Price is the protocol's estimate of the underlying's fair value, aggregated from external oracle feeds.
|
||||
* Mark Price is the price the system uses for margin, PnL, liquidation, and funding.
|
||||
* Last trade price is the price of the most recent fill on the local book. It is not used for margining.
|
||||
|
||||
See [Prices](/perps/concepts#prices).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What happens to Mark when external feeds go down?">
|
||||
Each Mark candidate degrades gracefully to the Index. If the order book mid is
|
||||
missing, the candidate falls back to Index. If there are no recent trades or
|
||||
quotes, the candidate falls back to Index. If external mark feeds are
|
||||
unavailable, the candidate falls back to Index. In the worst case, all
|
||||
candidates converge to Index and Mark tracks Index directly.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How is funding calculated and when does it settle?">
|
||||
A premium index is sampled every 5 seconds by walking the book for 1,000
|
||||
quote-asset notional on each side. Samples are averaged over a 1-hour charge
|
||||
window, run through an 8-hour formula with a fixed interest leg and clamp,
|
||||
divided by 8, and capped at +/-4% per hour. Settlement happens once per
|
||||
window. Longs pay shorts when the rate is positive, and shorts pay longs when
|
||||
negative. The protocol takes no cut.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Can I see funding pressure between settlements?">
|
||||
Yes. A rolling 5-second premium sample and its implied 8-hour rate are published continuously through public market data. You can also read funding history with [`GET /v1/info/funding`](/perps/market-data#list-funding-history).
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Margin and Leverage
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What's the difference between cross and isolated margin?">
|
||||
* Isolated margin funds each position with a dedicated margin allocation. Liquidation only closes the affected position.
|
||||
* Cross margin shares account collateral across all cross positions. Unrealized PnL on one position can offset margin on another, but a liquidation evaluates and can unwind the whole cross account.
|
||||
|
||||
The web app opens new positions in isolated mode by default. Cross is opt-in through the API using leverage configuration. See [Update Leverage](/perps/trading#update-leverage).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What are leverage tiers and why does my margin go up as my position grows?">
|
||||
Margin requirements scale with position notional through tiers. Larger
|
||||
positions need proportionally more margin to limit system-wide risk and reduce
|
||||
liquidation cascades. Margin is calculated incrementally across tiers,
|
||||
equivalent to summing bracket by bracket. Fetch live tier values from [`GET
|
||||
/v1/info/instruments`](/perps/market-data#fetch-instruments).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Why is maintenance margin always half of initial margin?">
|
||||
By design, maintenance margin rate is half of the maximum leverage requirement
|
||||
for the tier. A position is liquidated only after losing roughly half of the
|
||||
margin posted to open it, which gives traders a buffer between entering a
|
||||
position and being force-closed.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What happens between margin call and liquidation?">
|
||||
Three states are evaluated continuously.
|
||||
|
||||
| State | Condition | Behavior |
|
||||
| ----------- | ------------------- | ------------------------------------------------- |
|
||||
| Healthy | `Equity >= IM` | Normal trading |
|
||||
| Margin call | `MM <= Equity < IM` | Reduce-only: close exposure or deposit collateral |
|
||||
| Liquidation | `Equity < MM` | System closes the position |
|
||||
|
||||
A deposit during margin call instantly increases equity and can restore healthy status.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Can I withdraw collateral while I have an open position?">
|
||||
Yes, as long as `Equity_after >= IM_required` after the withdrawal. You cannot withdraw yourself into a margin call.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Liquidation
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="When am I liquidated?">
|
||||
Liquidation occurs when account equity falls below maintenance margin. Cross and isolated positions are checked independently: each isolated position has its own equity and maintenance margin, while cross uses the account's combined equity and combined maintenance margin. See [Margin and Liquidation](/perps/concepts#margin-and-liquidation).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Why does my liquidation price move when I haven't changed anything?">
|
||||
For cross positions, the liquidation price depends on available balance:
|
||||
everything in the cross account that is not this position's own equity. Mark
|
||||
moves on other cross positions, size changes, or collateral changes can all
|
||||
shift the liquidation price for every cross position simultaneously.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What happens during liquidation?">
|
||||
The affected scope is flagged and new orders on it are blocked. Cross blocks
|
||||
the whole account. Isolated blocks just that instrument. The system closes
|
||||
positions with reduce-only IOC orders, rate-limited per account, re-evaluating
|
||||
margin between fills. Cross liquidation closes one position at a time across
|
||||
cycles. If equity recovers above the recovery initial margin, the flag clears.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What is the insurance fund and when does it step in?">
|
||||
When equity falls below two-thirds of maintenance margin, order-book
|
||||
liquidation is unlikely to recover value, so the system absorbs the position
|
||||
directly into the insurance-fund account along with its margin. For cross
|
||||
backstop, the system absorbs all cross positions plus quote balance.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Are there extra fees on liquidation fills?">
|
||||
Yes. While flagged, every fill pays an additional liquidation fee rate on top of the maker or taker rate.
|
||||
|
||||
```text theme={null}
|
||||
FillFee = Notional * (MakerOrTakerRate + LiquidationFeeRate)
|
||||
```
|
||||
|
||||
Fetch the live rate per instrument from [`GET /v1/info/instruments`](/perps/market-data#fetch-instruments).
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Fees
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What are the current maker and taker fees?">
|
||||
Fees are tiered by trailing 30-day trading volume. New accounts start at the \$0 tier and move up as their volume crosses each threshold.
|
||||
|
||||
| 30-Day Volume ≥ | Taker | Maker |
|
||||
| --------------- | ------- | -------- |
|
||||
| \$0 | 0.0400% | 0.0125% |
|
||||
| \$1M | 0.0370% | 0.0100% |
|
||||
| \$5M | 0.0350% | 0.0080% |
|
||||
| \$25M | 0.0300% | 0.0050% |
|
||||
| \$100M | 0.0270% | 0.0020% |
|
||||
| \$500M | 0.0250% | 0.0000% |
|
||||
| \$1B | 0.0200% | -0.0050% |
|
||||
|
||||
Fees are calculated per fill as `abs(Price * Quantity) * Rate`, denominated in the instrument's quote asset (pUSD). Only the top tier earns a maker rebate; lower tiers pay a positive maker fee. See [Fees](/perps/learn-about-trading/fees) and [Trading Fees](/perps/trading#trading-fees).
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## API and Integration
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What's the difference between my main wallet and the proxy?">
|
||||
Your main wallet signs the one-time create-proxy request and never trades directly. The returned proxy address and secret are what you use day to day: the proxy private key signs trade requests, and the `(proxy, secret)` pair authenticates private REST and WebSocket reads. This isolates the trading key from the wallet that holds funds. See [Set Up Authentication](/perps/authenticated-sessions#set-up-authentication).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What address identifies my Perps account?">
|
||||
Your account is keyed by your EOA base address, the externally-owned account
|
||||
that signs `createProxy`, not a Safe smart-contract wallet address. Even if
|
||||
you use a Safe wallet elsewhere on Polymarket, your Perps balances, positions,
|
||||
and history are all tracked against the underlying EOA. Use that EOA when
|
||||
looking up your account or referencing it in support requests.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Which requests need a signature vs. just headers?">
|
||||
* Signed requests with `sig`, `salt`, and `ts`: `POST /account/key`, all `/trade/*` actions, and `PATCH /trade/leverage`. The signer is the main address for `createProxy` and the proxy address for everything else.
|
||||
* Header credentials with `POLYMARKET-PROXY` and `POLYMARKET-SECRET`: private `/account/*` reads.
|
||||
* WebSocket authentication: send a single `auth` message after connecting, then subscribe to private channels.
|
||||
|
||||
See [Authenticated Sessions](/perps/authenticated-sessions).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How do I avoid clock-skew rejections?">
|
||||
Each signed request must include a fresh `ts` request timestamp in
|
||||
milliseconds and `salt`. Reused or stale values are rejected. Sync against
|
||||
`GET /v1/info/time` and do not sign requests far in the past or future. The
|
||||
optional `expa` field caps the validity window.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How do deposits and withdrawals work?">
|
||||
Deposits and withdrawals are the only operations that move assets in or out of the exchange. Both settle on Polygon. Deposits credit equity as soon as the engine sees them. Withdrawals are signed off-chain and require `Equity_after >= IM_required`. See [Fund Your Account](/perps/fund-your-account).
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Are there geographic restrictions on order placement?">
|
||||
Yes. Order placement is not permitted from the United States, Canada, Cuba, Iran, North Korea, Syria, Crimea, Donetsk, or Luhansk. Builders are responsible for verifying user location before submitting orders.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Sessions
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What do market sessions actually change?">
|
||||
Sessions affect which set of external feeds is used to compute Index Price and Mark Price. They do not change funding, margin, leverage tiers, order matching, or liquidation triggers. Those run identically around the clock.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What's the difference between Disrupted and Halted?">
|
||||
* Disrupted means external feeds are unavailable or failing sanity checks. The system falls back to whatever feed set is still healthy.
|
||||
* Halted means the underlying itself has a trading halt or corporate-action freeze.
|
||||
|
||||
Both are categorizations of feed-source health and only affect Index and Mark sourcing. The perp continues to match orders.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
@@ -0,0 +1,740 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Fund Your Account
|
||||
|
||||
> Deposit and withdraw pUSD collateral for Perps trading
|
||||
|
||||
Fund the Perps account with pUSD before placing orders. Deposits move pUSD from
|
||||
the user's Polymarket wallet into the Perps account. Withdrawals move available
|
||||
pUSD back to the authenticated wallet.
|
||||
|
||||
## Deposit Collateral
|
||||
|
||||
Deposit pUSD when the account needs collateral for opening or maintaining Perps
|
||||
positions.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
<Steps>
|
||||
<Step title="Create a Secure Client">
|
||||
Create a `SecureClient` for the wallet that will fund the Perps account. If you
|
||||
already have a Polymarket wallet, pass it as `wallet` and include a Relayer API
|
||||
key so the SDK can submit gasless transactions. If you are creating a wallet
|
||||
programmatically, use a Builder API key so the SDK can create the Deposit Wallet
|
||||
for that signer.
|
||||
|
||||
<CodeGroup>
|
||||
```ts Existing Account theme={null}
|
||||
import { createSecureClient, relayerApiKey } from "@polymarket/client";
|
||||
import { privateKey } from "@polymarket/client/viem";
|
||||
|
||||
const client = await createSecureClient({
|
||||
wallet: process.env.POLYMARKET_WALLET_ADDRESS!,
|
||||
signer: privateKey(process.env.PRIVATE_KEY!),
|
||||
apiKey: relayerApiKey({
|
||||
key: process.env.RELAYER_API_KEY!,
|
||||
address: process.env.RELAYER_API_KEY_ADDRESS!,
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
```ts New Programmatic Wallet theme={null}
|
||||
import { createSecureClient } from "@polymarket/client";
|
||||
import { builderApiKey } from "@polymarket/client/node";
|
||||
import { privateKey } from "@polymarket/client/viem";
|
||||
|
||||
const client = await createSecureClient({
|
||||
signer: privateKey(process.env.PRIVATE_KEY!),
|
||||
apiKey: builderApiKey({
|
||||
key: process.env.BUILDER_API_KEY!,
|
||||
secret: process.env.BUILDER_SECRET!,
|
||||
passphrase: process.env.BUILDER_PASSPHRASE!,
|
||||
}),
|
||||
});
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
|
||||
<Step title="Set Up Deposit Approvals">
|
||||
Set up the approvals required for Perps collateral deposits. The SDK skips work
|
||||
that is already complete.
|
||||
|
||||
```ts theme={null}
|
||||
await client.setupTradingApprovals();
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Deposit Collateral">
|
||||
Deposit pUSD from the user's Polymarket wallet into the Perps account. Make sure
|
||||
the wallet has pUSD before depositing. The minimum Perps deposit is 10 pUSD.
|
||||
Amounts use raw pUSD base units, so 10 pUSD is `10_000_000n`.
|
||||
|
||||
```ts theme={null}
|
||||
const deposit = await client.depositToPerps({
|
||||
amount: 10_000_000n,
|
||||
});
|
||||
|
||||
const receipt = await deposit.wait();
|
||||
// receipt.transactionHash: TxHash
|
||||
```
|
||||
|
||||
`deposit.wait()` confirms that the chain transaction settled. Perps may take a
|
||||
moment to credit the account after that.
|
||||
</Step>
|
||||
|
||||
<Step title="Verify the Deposit">
|
||||
Open a Perps session and read account state after the deposit settles.
|
||||
|
||||
```ts theme={null}
|
||||
const session = await client.openPerpsSession();
|
||||
|
||||
try {
|
||||
const portfolio = await session.fetchPortfolio();
|
||||
const deposits = await session.listDeposits().firstPage();
|
||||
} finally {
|
||||
await session.close();
|
||||
}
|
||||
```
|
||||
|
||||
Use `portfolio.withdrawable` to check available collateral and `deposits.items`
|
||||
to reconcile deposit history.
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
<Steps>
|
||||
<Step title="Create a Secure Client">
|
||||
Create an `AsyncSecureClient` for the wallet that will fund the Perps account.
|
||||
If you already have a Polymarket wallet, pass it as `wallet` and include a
|
||||
Relayer API key so the SDK can submit gasless transactions. If you are creating a
|
||||
wallet programmatically, use a Builder API key so the SDK can create the Deposit
|
||||
Wallet for that signer.
|
||||
|
||||
<CodeGroup>
|
||||
```python Existing Account theme={null}
|
||||
import os
|
||||
|
||||
from polymarket import AsyncSecureClient, RelayerApiKey
|
||||
|
||||
client = await AsyncSecureClient.create(
|
||||
private_key=os.environ["PRIVATE_KEY"],
|
||||
wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
|
||||
api_key=RelayerApiKey(
|
||||
key=os.environ["RELAYER_API_KEY"],
|
||||
address=os.environ["RELAYER_API_KEY_ADDRESS"],
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
```python New Programmatic Wallet theme={null}
|
||||
import os
|
||||
|
||||
from polymarket import AsyncSecureClient, BuilderApiKey
|
||||
|
||||
client = await AsyncSecureClient.create(
|
||||
private_key=os.environ["PRIVATE_KEY"],
|
||||
api_key=BuilderApiKey(
|
||||
key=os.environ["BUILDER_API_KEY"],
|
||||
secret=os.environ["BUILDER_SECRET"],
|
||||
passphrase=os.environ["BUILDER_PASSPHRASE"],
|
||||
),
|
||||
)
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
|
||||
<Step title="Set Up Deposit Approvals">
|
||||
Set up the approvals required for Perps collateral deposits. The SDK skips work
|
||||
that is already complete.
|
||||
|
||||
```python theme={null}
|
||||
await client.setup_trading_approvals()
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Deposit Collateral">
|
||||
Deposit pUSD from the user's Polymarket wallet into the Perps account. Make sure
|
||||
the wallet has pUSD before depositing. The minimum Perps deposit is 10 pUSD.
|
||||
Amounts use raw pUSD base units, so 10 pUSD is `10_000_000`.
|
||||
|
||||
```python theme={null}
|
||||
deposit = await client.deposit_to_perps(amount=10_000_000)
|
||||
|
||||
receipt = await deposit.wait()
|
||||
# receipt.transaction_hash: TransactionHash
|
||||
```
|
||||
|
||||
`deposit.wait()` confirms that the chain transaction settled. Perps may take a
|
||||
moment to credit the account after that.
|
||||
</Step>
|
||||
|
||||
<Step title="Verify the Deposit">
|
||||
Open a Perps session and read account state after the deposit settles.
|
||||
|
||||
```python theme={null}
|
||||
session = await client.open_perps_session()
|
||||
|
||||
try:
|
||||
portfolio = await session.fetch_portfolio()
|
||||
deposits = await session.list_deposits().first_page()
|
||||
finally:
|
||||
await session.close()
|
||||
```
|
||||
|
||||
Use `portfolio.withdrawable` to check available collateral and `deposits.items`
|
||||
to reconcile deposit history.
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
<Steps>
|
||||
<Step title="Check Deposit Approval">
|
||||
Before depositing, the Polymarket wallet must approve the Perps deposit contract
|
||||
to spend pUSD. If the approval is already in place, skip the approval call.
|
||||
|
||||
```solidity Approval Call theme={null}
|
||||
pUSD.approve(PerpsDepositContract, maxUint256)
|
||||
```
|
||||
|
||||
Use these contract addresses when building the approval call.
|
||||
|
||||
| Contract | Address |
|
||||
| ---------------------- | -------------------------------------------- |
|
||||
| pUSD collateral token | `0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB` |
|
||||
| Perps deposit contract | `0xDCa4af75705dbB50f62437045afF9921947917d2` |
|
||||
|
||||
<Note>
|
||||
The following steps show the Deposit Wallet batch path. If you are trading
|
||||
with a Safe or Poly Proxy wallet, use an SDK that handles the wallet-specific
|
||||
transaction flow for you.
|
||||
</Note>
|
||||
</Step>
|
||||
|
||||
<Step title="Build the Deposit Call">
|
||||
Create the Perps deposit call. Deposit amounts use pUSD base units, so 10 pUSD
|
||||
is `10000000`.
|
||||
|
||||
```solidity theme={null}
|
||||
function deposit(address token, uint256 amount, address to);
|
||||
```
|
||||
|
||||
Encode the deposit calldata with these arguments.
|
||||
|
||||
| Argument | Value |
|
||||
| -------- | -------------------------------------------- |
|
||||
| `token` | `0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB` |
|
||||
| `amount` | `10000000` |
|
||||
| `to` | Signer address for the Polymarket account. |
|
||||
|
||||
Build the final ordered call list. Include the approval call first only when
|
||||
approval is needed.
|
||||
|
||||
<CodeGroup>
|
||||
```json Without Approval theme={null}
|
||||
[
|
||||
{
|
||||
"target": "0xDCa4af75705dbB50f62437045afF9921947917d2",
|
||||
"value": "0",
|
||||
"data": "<deposit_calldata>"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
```json With Approval theme={null}
|
||||
[
|
||||
{
|
||||
"target": "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB",
|
||||
"value": "0",
|
||||
"data": "<approve_calldata>"
|
||||
},
|
||||
{
|
||||
"target": "0xDCa4af75705dbB50f62437045afF9921947917d2",
|
||||
"value": "0",
|
||||
"data": "<deposit_calldata>"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
|
||||
<Step title="Fetch a Relayer Nonce">
|
||||
Fetch a fresh `WALLET` nonce before submitting the Deposit Wallet batch.
|
||||
|
||||
```bash theme={null}
|
||||
curl -G "https://relayer-v2.polymarket.com/v1/account/transactions/params" \
|
||||
-H "RELAYER_API_KEY: $RELAYER_API_KEY" \
|
||||
-H "RELAYER_API_KEY_ADDRESS: $RELAYER_API_KEY_ADDRESS" \
|
||||
--data-urlencode "address=<polymarket_account_signer_address>" \
|
||||
--data-urlencode "type=WALLET"
|
||||
```
|
||||
|
||||
The response includes the nonce to sign with the batch.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"address": "<polymarket_account_signer_address>",
|
||||
"nonce": "<wallet_nonce>"
|
||||
}
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Build the Deposit Wallet Batch">
|
||||
Build the EIP-712 `Batch` typed data for the Deposit Wallet. Use the final
|
||||
ordered call list from the previous step, and omit the approval call when
|
||||
allowance is already sufficient. Set `deadline` to a Unix timestamp in seconds
|
||||
after which the relayer should reject the batch.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"domain": {
|
||||
"name": "DepositWallet",
|
||||
"version": "1",
|
||||
"chainId": 137,
|
||||
"verifyingContract": "<polymarket_wallet_address>"
|
||||
},
|
||||
"primaryType": "Batch",
|
||||
"types": {
|
||||
"Call": [
|
||||
{ "name": "target", "type": "address" },
|
||||
{ "name": "value", "type": "uint256" },
|
||||
{ "name": "data", "type": "bytes" }
|
||||
],
|
||||
"Batch": [
|
||||
{ "name": "wallet", "type": "address" },
|
||||
{ "name": "nonce", "type": "uint256" },
|
||||
{ "name": "deadline", "type": "uint256" },
|
||||
{ "name": "calls", "type": "Call[]" }
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"wallet": "<polymarket_wallet_address>",
|
||||
"nonce": "<wallet_nonce>",
|
||||
"deadline": "<unix_seconds>",
|
||||
"calls": [
|
||||
{
|
||||
"target": "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB",
|
||||
"value": "0",
|
||||
"data": "<approve_calldata>"
|
||||
},
|
||||
{
|
||||
"target": "0xDCa4af75705dbB50f62437045afF9921947917d2",
|
||||
"value": "0",
|
||||
"data": "<deposit_calldata>"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Sign this typed data with the signer for the Polymarket account.
|
||||
</Step>
|
||||
|
||||
<Step title="Submit the Deposit Transaction">
|
||||
Submit the signed batch to the Relayer API. Use the same ordered call list you
|
||||
signed in the previous step.
|
||||
|
||||
```bash theme={null}
|
||||
curl -X POST "https://relayer-v2.polymarket.com/submit" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "RELAYER_API_KEY: $RELAYER_API_KEY" \
|
||||
-H "RELAYER_API_KEY_ADDRESS: $RELAYER_API_KEY_ADDRESS" \
|
||||
-d '{
|
||||
"type": "WALLET",
|
||||
"from": "<polymarket_account_signer_address>",
|
||||
"to": "0x00000000000Fb5C9ADea0298D729A0CB3823Cc07",
|
||||
"nonce": "<wallet_nonce>",
|
||||
"signature": "<wallet_batch_signature>",
|
||||
"metadata": "Deposit pUSD to Perps",
|
||||
"depositWalletParams": {
|
||||
"depositWallet": "<polymarket_wallet_address>",
|
||||
"deadline": "<unix_seconds>",
|
||||
"calls": [
|
||||
{
|
||||
"target": "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB",
|
||||
"value": "0",
|
||||
"data": "<approve_calldata>"
|
||||
},
|
||||
{
|
||||
"target": "0xDCa4af75705dbB50f62437045afF9921947917d2",
|
||||
"value": "0",
|
||||
"data": "<deposit_calldata>"
|
||||
}
|
||||
]
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
The response includes the relayer transaction ID.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"transactionID": "<transaction_id>",
|
||||
"state": "STATE_NEW"
|
||||
}
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Poll the Deposit Transaction">
|
||||
Poll the relayer transaction until it reaches `STATE_CONFIRMED` before relying
|
||||
on the deposited collateral.
|
||||
|
||||
```bash theme={null}
|
||||
curl "https://relayer-v2.polymarket.com/v1/account/transactions/<transaction_id>" \
|
||||
-H "RELAYER_API_KEY: $RELAYER_API_KEY" \
|
||||
-H "RELAYER_API_KEY_ADDRESS: $RELAYER_API_KEY_ADDRESS"
|
||||
```
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"transaction_id": "<transaction_id>",
|
||||
"transaction_hash": "<transaction_hash>",
|
||||
"state": "STATE_CONFIRMED",
|
||||
"error_msg": null
|
||||
}
|
||||
```
|
||||
|
||||
Perps may take a moment to credit the account after the onchain transaction
|
||||
settles. Treat `STATE_FAILED` and `STATE_INVALID` as terminal failures.
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Withdraw Collateral
|
||||
|
||||
Withdraw pUSD when the account has available collateral that should return to the
|
||||
authenticated wallet.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
Request a withdrawal to the authenticated wallet.
|
||||
Amounts use raw pUSD base units, so 10 pUSD is `10_000_000n`.
|
||||
|
||||
```ts theme={null}
|
||||
const withdrawalId = await client.withdrawFromPerps({
|
||||
amount: 10_000_000n,
|
||||
});
|
||||
```
|
||||
|
||||
The SDK signs the withdrawal request with the Polymarket account signer and
|
||||
returns the Perps withdrawal ID.
|
||||
|
||||
To track the withdrawal, open a Perps session and list withdrawals.
|
||||
|
||||
```ts theme={null}
|
||||
const session = await client.openPerpsSession();
|
||||
|
||||
try {
|
||||
const withdrawals = await session.listWithdrawals().firstPage();
|
||||
} finally {
|
||||
await session.close();
|
||||
}
|
||||
```
|
||||
|
||||
For more details on authenticated sessions, see [Authenticated
|
||||
Sessions](/perps/authenticated-sessions).
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
Request a withdrawal to the authenticated wallet. Amounts use raw pUSD base
|
||||
units, so 10 pUSD is `10_000_000`.
|
||||
|
||||
```python theme={null}
|
||||
withdrawal_id = await client.withdraw_from_perps(amount=10_000_000)
|
||||
```
|
||||
|
||||
The SDK signs the withdrawal request with the Polymarket account signer and
|
||||
returns the Perps withdrawal ID.
|
||||
|
||||
To track the withdrawal, open a Perps session and list withdrawals.
|
||||
|
||||
```python theme={null}
|
||||
session = await client.open_perps_session()
|
||||
|
||||
try:
|
||||
withdrawals = await session.list_withdrawals().first_page()
|
||||
finally:
|
||||
await session.close()
|
||||
```
|
||||
|
||||
For more details on authenticated sessions, see [Authenticated
|
||||
Sessions](/perps/authenticated-sessions).
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
<Steps>
|
||||
<Step title="Build the Withdrawal Operation">
|
||||
Create a `withdraw` operation with the account signer, pUSD token, raw token
|
||||
amount, and destination wallet. For withdrawals, `amount` is the raw pUSD token
|
||||
amount, so 10 pUSD is `10000000`.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "withdraw",
|
||||
"args": {
|
||||
"account": "<polymarket_account_signer_address>",
|
||||
"token": "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB",
|
||||
"amount": "10000000",
|
||||
"to": "<polymarket_wallet_address>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Value |
|
||||
| --------- | ------------------------------------------ |
|
||||
| `account` | Signer address for the Polymarket account. |
|
||||
| `token` | pUSD collateral token address. |
|
||||
| `amount` | Raw pUSD token amount. |
|
||||
| `to` | Wallet that receives the withdrawal. |
|
||||
</Step>
|
||||
|
||||
<Step title="Create Withdrawal Typed Data">
|
||||
The withdrawal signature uses EIP-712 typed data with `Withdraw` as the primary
|
||||
type. Use the same `account`, `token`, `amount`, and `to` values from the
|
||||
withdrawal operation.
|
||||
|
||||
For withdrawals, `ts` is a Unix timestamp in seconds because the onchain contract
|
||||
validates it against `block.timestamp`. It must match the `ts` value in the
|
||||
request body.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"domain": {
|
||||
"name": "Polymarket",
|
||||
"version": "1",
|
||||
"chainId": 137,
|
||||
"verifyingContract": "0xDCa4af75705dbB50f62437045afF9921947917d2"
|
||||
},
|
||||
"primaryType": "Withdraw",
|
||||
"types": {
|
||||
"Withdraw": [
|
||||
{ "name": "account", "type": "address" },
|
||||
{ "name": "token", "type": "address" },
|
||||
{ "name": "amount", "type": "uint256" },
|
||||
{ "name": "fee", "type": "uint256" },
|
||||
{ "name": "to", "type": "address" },
|
||||
{ "name": "salt", "type": "uint64" },
|
||||
{ "name": "ts", "type": "uint64" }
|
||||
]
|
||||
},
|
||||
"message": {
|
||||
"account": "<polymarket_account_signer_address>",
|
||||
"token": "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB",
|
||||
"amount": "10000000",
|
||||
"fee": "0",
|
||||
"to": "<polymarket_wallet_address>",
|
||||
"salt": 555555555,
|
||||
"ts": 1767000014
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Value |
|
||||
| ------ | ---------------------------------------------------- |
|
||||
| `salt` | Random integer generated for this signed request. |
|
||||
| `ts` | Current Unix timestamp in seconds, not milliseconds. |
|
||||
</Step>
|
||||
|
||||
<Step title="Sign Withdrawal Typed Data">
|
||||
Sign the typed data with the Polymarket account signer. The example below uses
|
||||
Viem.
|
||||
|
||||
```ts Viem theme={null}
|
||||
import { privateKeyToAccount } from "viem/accounts";
|
||||
|
||||
const account = privateKeyToAccount("<polymarket_account_signer_private_key>");
|
||||
|
||||
const signature = await account.signTypedData({
|
||||
domain: {
|
||||
name: "Polymarket",
|
||||
version: "1",
|
||||
chainId: 137,
|
||||
verifyingContract: "0xDCa4af75705dbB50f62437045afF9921947917d2",
|
||||
},
|
||||
primaryType: "Withdraw",
|
||||
types: {
|
||||
Withdraw: [
|
||||
{ name: "account", type: "address" },
|
||||
{ name: "token", type: "address" },
|
||||
{ name: "amount", type: "uint256" },
|
||||
{ name: "fee", type: "uint256" },
|
||||
{ name: "to", type: "address" },
|
||||
{ name: "salt", type: "uint64" },
|
||||
{ name: "ts", type: "uint64" },
|
||||
],
|
||||
},
|
||||
message: {
|
||||
account: "<polymarket_account_signer_address>",
|
||||
token: "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB",
|
||||
amount: 10000000n,
|
||||
fee: 0n,
|
||||
to: "<polymarket_wallet_address>",
|
||||
salt: 555555555n,
|
||||
ts: 1767000014n,
|
||||
},
|
||||
});
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Submit the Withdrawal">
|
||||
Submit the signed withdrawal request to `POST /v1/account/withdraw`. Use the
|
||||
same operation values, `salt`, and `ts` from the typed data.
|
||||
|
||||
```bash theme={null}
|
||||
curl -X POST "https://api.perpetuals.polymarket.com/v1/account/withdraw" \
|
||||
-H "content-type: application/json" \
|
||||
-d '{
|
||||
"op": {
|
||||
"type": "withdraw",
|
||||
"args": {
|
||||
"account": "<polymarket_account_signer_address>",
|
||||
"token": "0xC011a7E12a19f7B1f670d46F03B03f3342E82DFB",
|
||||
"amount": "10000000",
|
||||
"to": "<polymarket_wallet_address>"
|
||||
}
|
||||
},
|
||||
"sig": "<signature>",
|
||||
"salt": 555555555,
|
||||
"ts": 1767000014
|
||||
}'
|
||||
```
|
||||
|
||||
The response indicates whether the withdrawal was accepted.
|
||||
|
||||
<CodeGroup>
|
||||
```json Success theme={null}
|
||||
{
|
||||
"status": "ok",
|
||||
"withdraw_id": 1234567890
|
||||
}
|
||||
```
|
||||
|
||||
```json Failure theme={null}
|
||||
{
|
||||
"status": "err",
|
||||
"withdraw_id": 1234567890,
|
||||
"error": "insufficient_balance"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
|
||||
<Step title="Track the Withdrawal">
|
||||
Use the returned `withdraw_id` to match the withdrawal against history results.
|
||||
|
||||
```bash theme={null}
|
||||
curl -G "https://api.perpetuals.polymarket.com/v1/account/withdrawals" \
|
||||
-H "polymarket-proxy: <proxy_address>" \
|
||||
-H "polymarket-secret: <proxy_secret>" \
|
||||
--data-urlencode "withdrawal_status=pending"
|
||||
```
|
||||
|
||||
For more details on proxy credentials and private account-read headers, see
|
||||
[Authenticated Sessions](/perps/authenticated-sessions).
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Review Funding History
|
||||
|
||||
Use deposit and withdrawal history to reconcile collateral movements after your
|
||||
integration submits funding requests.
|
||||
|
||||
See [Authenticated Sessions](/perps/authenticated-sessions) for how to create an
|
||||
authenticated session for private account history reads.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
List deposit or withdrawal history from an authenticated Perps session.
|
||||
|
||||
<CodeGroup>
|
||||
```ts Deposits theme={null}
|
||||
import type { PerpsDeposit } from "@polymarket/client";
|
||||
|
||||
const session = await client.openPerpsSession();
|
||||
|
||||
try {
|
||||
const deposits: PerpsDeposit[] = [];
|
||||
|
||||
for await (const page of session.listDeposits()) {
|
||||
deposits.push(...page.items);
|
||||
}
|
||||
} finally {
|
||||
await session.close();
|
||||
}
|
||||
```
|
||||
|
||||
```ts Withdrawals theme={null}
|
||||
import type { PerpsWithdrawal } from "@polymarket/client";
|
||||
|
||||
const session = await client.openPerpsSession();
|
||||
|
||||
try {
|
||||
const withdrawals: PerpsWithdrawal[] = [];
|
||||
|
||||
for await (const page of session.listWithdrawals()) {
|
||||
withdrawals.push(...page.items);
|
||||
}
|
||||
} finally {
|
||||
await session.close();
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
List deposit or withdrawal history from an authenticated Perps session.
|
||||
|
||||
<CodeGroup>
|
||||
```python Deposits theme={null}
|
||||
session = await client.open_perps_session()
|
||||
|
||||
try:
|
||||
deposits = []
|
||||
|
||||
async for page in session.list_deposits():
|
||||
deposits.extend(page.items)
|
||||
finally:
|
||||
await session.close()
|
||||
```
|
||||
|
||||
```python Withdrawals theme={null}
|
||||
session = await client.open_perps_session()
|
||||
|
||||
try:
|
||||
withdrawals = []
|
||||
|
||||
async for page in session.list_withdrawals():
|
||||
withdrawals.extend(page.items)
|
||||
finally:
|
||||
await session.close()
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
List deposit history.
|
||||
|
||||
```bash theme={null}
|
||||
curl -G "https://api.perpetuals.polymarket.com/v1/account/deposits" \
|
||||
-H "polymarket-proxy: <proxy_address>" \
|
||||
-H "polymarket-secret: <proxy_secret>"
|
||||
```
|
||||
|
||||
List withdrawal history.
|
||||
|
||||
```bash theme={null}
|
||||
curl -G "https://api.perpetuals.polymarket.com/v1/account/withdrawals" \
|
||||
-H "polymarket-proxy: <proxy_address>" \
|
||||
-H "polymarket-secret: <proxy_secret>"
|
||||
```
|
||||
|
||||
Use the optional `deposit_status`, `withdrawal_status`, `start_timestamp`, and
|
||||
`end_timestamp` query parameters when reconciling a specific window.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@@ -0,0 +1,49 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Architecture
|
||||
|
||||
> High-level architecture of the Polymarket Perps exchange
|
||||
|
||||
Polymarket Perps is a hybrid exchange: matching happens offchain for speed, while
|
||||
custody and settlement live on Polygon. Exchange state is periodically committed
|
||||
onchain so offchain activity remains verifiable.
|
||||
|
||||
## Offchain Matching
|
||||
|
||||
When a trader places an order, the matching engine maintains the order book,
|
||||
applies risk checks, matches orders, and updates balances, positions, margin, and
|
||||
funding offchain. This gives the exchange its latency profile because matching
|
||||
does not wait on block times.
|
||||
|
||||
Orders are authorized by the trader, so the system can only act on trades the
|
||||
trader approved.
|
||||
|
||||
## Onchain Components
|
||||
|
||||
The following operations are onchain and settle on Polygon:
|
||||
|
||||
* Deposits move funds from a user's Polymarket wallet into the exchange and
|
||||
credit their Perps account.
|
||||
* Withdrawals move funds out of the exchange back to a user's Polymarket wallet.
|
||||
|
||||
Deposits and withdrawals are the only way assets enter or leave the exchange.
|
||||
Trading itself does not produce per-trade onchain transactions.
|
||||
|
||||
## State Root Commitments
|
||||
|
||||
The exchange periodically commits its trading state onchain in the form of state
|
||||
root commitments. A state root summarizes the offchain ledger at a point in time,
|
||||
including account balances, and lets observers verify that reported exchange
|
||||
state matches what Polymarket has committed to Polygon.
|
||||
|
||||
## Data Flow
|
||||
|
||||
1. A trader deposits collateral from their Polymarket wallet into the exchange,
|
||||
crediting their Perps account.
|
||||
2. The engine credits the deposit and opens the account for trading.
|
||||
3. The trader authorizes and places orders.
|
||||
4. The engine matches orders and updates state offchain.
|
||||
5. The engine publishes state root commitments onchain on a recurring cadence.
|
||||
6. The trader authorizes a withdrawal, and funds move back to their Polymarket wallet on Polygon.
|
||||
@@ -0,0 +1,78 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Fees
|
||||
|
||||
> Tiered maker and taker trading fees for Polymarket Perps
|
||||
|
||||
Perps trading fees are tiered by an account's trailing 30-day trading volume.
|
||||
Higher-volume accounts pay lower taker fees, and the top tier earns a maker
|
||||
rebate instead of paying a maker fee.
|
||||
|
||||
## Fee Calculation
|
||||
|
||||
For each fill, the fee is calculated on the notional value of the trade:
|
||||
|
||||
```text theme={null}
|
||||
Fee = abs(Price * Quantity) * Rate
|
||||
```
|
||||
|
||||
Fees are denominated in the instrument's quote asset (pUSD). The rate applied
|
||||
to a fill is set by the account's current volume tier.
|
||||
|
||||
| 30-Day Volume ≥ | Taker | Maker |
|
||||
| --------------- | ------- | -------- |
|
||||
| \$0 | 0.0400% | 0.0125% |
|
||||
| \$1M | 0.0370% | 0.0100% |
|
||||
| \$5M | 0.0350% | 0.0080% |
|
||||
| \$25M | 0.0300% | 0.0050% |
|
||||
| \$100M | 0.0270% | 0.0020% |
|
||||
| \$500M | 0.0250% | 0.0000% |
|
||||
| \$1B | 0.0200% | -0.0050% |
|
||||
|
||||
New accounts start at the \$0 tier and move up as trailing 30-day volume crosses
|
||||
each threshold.
|
||||
|
||||
A negative maker fee is a rebate: the maker receives the rebate amount, and the
|
||||
fee recipient's internal ledger is debited by the same amount.
|
||||
|
||||
<Note>
|
||||
A subset of accounts created during the Perps beta are temporarily on the
|
||||
top-tier fee schedule regardless of trailing 30-day volume. Standard
|
||||
volume-based tiering applies to these accounts once the transition period
|
||||
ends.
|
||||
</Note>
|
||||
|
||||
If you're integrating Perps, read the current fee schedule from
|
||||
[Trading Fees](/perps/trading#trading-fees).
|
||||
|
||||
## Fee Metrics
|
||||
|
||||
Trailing 7-day activity metrics are available for visibility. They are a
|
||||
rolling view of recent activity and do not, on their own, determine the volume
|
||||
tier used to set fees.
|
||||
|
||||
| Metric | Meaning |
|
||||
| ------------------- | ------------------------------------------------------------------------------ |
|
||||
| Total volume | Total Perps trading volume |
|
||||
| Taker volume | Perps volume that removed liquidity |
|
||||
| Maker volume | Perps volume that added liquidity |
|
||||
| Account maker share | Account maker volume divided by total exchange volume |
|
||||
| Entity maker share | Entity maker volume divided by total exchange volume, when the account has one |
|
||||
|
||||
These metrics are cached by UTC day and may be stale by up to 24 hours.
|
||||
|
||||
If you're integrating Perps, read account metrics from
|
||||
[Account Stats](/perps/account-management#account-stats).
|
||||
|
||||
## Fee Accounting
|
||||
|
||||
Every fill's fee flows through a single fee-recipient account on the internal
|
||||
ledger:
|
||||
|
||||
* Taker fees credit the recipient.
|
||||
* Maker fees credit the recipient at every tier where the maker rate is
|
||||
non-negative.
|
||||
* At the top tier the maker rate is a rebate, so it debits the recipient and
|
||||
credits the maker.
|
||||
@@ -0,0 +1,99 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Funding
|
||||
|
||||
> Funding rate calculation and settlement
|
||||
|
||||
Unlike futures contracts, perpetuals have no expiry date. Funding is the
|
||||
mechanism that keeps the perpetual price anchored to the underlying's fair value.
|
||||
When the perpetual trades above Index, longs pay shorts. When it trades below
|
||||
Index, shorts pay longs.
|
||||
|
||||
Funding runs continuously across all sessions, regardless of whether the
|
||||
underlying reference market is open. This keeps the convergence incentive active
|
||||
and prevents positions from being left unanchored from fair value.
|
||||
|
||||
## How Funding Works
|
||||
|
||||
Funding is computed in three stages:
|
||||
|
||||
1. A premium index is sampled from the order book every 5 seconds.
|
||||
2. Samples are averaged over the 1-hour charge window to produce an hourly rate.
|
||||
3. The rate is settled against every open position at the end of the window.
|
||||
|
||||
### Premium Index
|
||||
|
||||
Every 5 seconds, the protocol takes one snapshot per market of how far the book
|
||||
has drifted from Index. It walks the book for a fixed quote notional on each side.
|
||||
|
||||
```text theme={null}
|
||||
bid_impact = VWAP of top bids filling 1,000 quote notional
|
||||
ask_impact = VWAP of top asks filling 1,000 quote notional
|
||||
```
|
||||
|
||||
If one side of the book cannot fill the notional because it is too thin or empty,
|
||||
that side falls back to Index, which zeros its contribution.
|
||||
|
||||
The impact price difference and premium index are:
|
||||
|
||||
```text theme={null}
|
||||
IPD = max(bid_impact - Index, 0) - max(Index - ask_impact, 0)
|
||||
PremiumIndex = IPD / Index
|
||||
```
|
||||
|
||||
A positive premium means the perpetual is trading rich versus Index. A negative
|
||||
premium means it is trading cheap.
|
||||
|
||||
### Funding Rate
|
||||
|
||||
At the end of each charge window, premium samples are averaged, passed through the
|
||||
8-hour funding formula, divided by 8 to get an hourly rate, and capped.
|
||||
|
||||
```text theme={null}
|
||||
mean_P = average of PremiumIndex samples over the window
|
||||
scale = 1.0 for crypto markets; 0.5 otherwise
|
||||
F_8h = scale * (mean_P + clamp(0.0001 - mean_P, +/-0.0005))
|
||||
FR_hour = clamp(F_8h / 8, +/-0.04)
|
||||
```
|
||||
|
||||
* The 0.01% term is a fixed interest leg per 8 hours.
|
||||
* The +/-0.05% clamp bounds the interest-versus-premium adjustment.
|
||||
* Crypto markets use a 1.0 scale.
|
||||
* Non-crypto markets use a 0.5 scale.
|
||||
* The 4% per hour cap prevents extreme funding during sustained dislocation.
|
||||
|
||||
### Payment
|
||||
|
||||
At the end of each charge window, every open position in the market settles a
|
||||
funding payment proportional to position size and the hourly rate.
|
||||
|
||||
| Condition | Longs | Shorts |
|
||||
| ------------------------------------- | ------- | ------- |
|
||||
| Hourly rate > 0, perp rich vs Index | Pay | Receive |
|
||||
| Hourly rate \< 0, perp cheap vs Index | Receive | Pay |
|
||||
|
||||
Funding is a direct transfer between longs and shorts. The protocol takes no cut.
|
||||
Settlement credits or debits the quote balance, and realized funding is tracked
|
||||
separately from trading PnL.
|
||||
|
||||
### Interval
|
||||
|
||||
The charge window is 1 hour. Samples are averaged over the hour, and the hourly
|
||||
rate is applied once at the end.
|
||||
|
||||
Between settlements, rolling premium samples and implied rates are published so
|
||||
traders can see funding pressure build in real time.
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Default | Description |
|
||||
| ---------------- | ------------------------- | ----------------------------------------- |
|
||||
| Sample interval | 5 seconds | Cadence of premium index samples |
|
||||
| Impact notional | 1,000 quote notional | Quote notional used for impact VWAP |
|
||||
| Interest leg | 0.01% per 8 hours | Fixed component in the 8-hour formula |
|
||||
| Interest clamp | +/-0.05% | Symmetric clamp on interest minus premium |
|
||||
| Funding scale | 1.0 crypto; 0.5 otherwise | Multiplier applied to the 8-hour formula |
|
||||
| Charge window | 1 hour | Interval between funding settlements |
|
||||
| Funding rate cap | 4% per hour | Maximum absolute hourly funding rate |
|
||||
@@ -0,0 +1,43 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Geographic Restrictions
|
||||
|
||||
> Jurisdictions where Polymarket Perps order placement is not permitted
|
||||
|
||||
Polymarket restricts order placement from certain geographic locations to comply
|
||||
with regulatory requirements and international sanctions. Users in restricted
|
||||
jurisdictions cannot place Perps orders.
|
||||
|
||||
## Restricted Jurisdictions
|
||||
|
||||
Order placement is not permitted from:
|
||||
|
||||
* United States
|
||||
* Canada
|
||||
* Cuba
|
||||
* Iran
|
||||
* North Korea
|
||||
* Syria
|
||||
* Crimea
|
||||
* Donetsk
|
||||
* Luhansk
|
||||
|
||||
<Warning>
|
||||
This list can change. Additional restrictions may apply under Polymarket
|
||||
notices or applicable law.
|
||||
</Warning>
|
||||
|
||||
## For Builders
|
||||
|
||||
If you're integrating Perps, enforce these restrictions before submitting orders
|
||||
for a user:
|
||||
|
||||
* Verify the end user's location before [placing orders](/perps/trading#place-orders).
|
||||
* Block order submission entirely for users in any of the listed jurisdictions.
|
||||
Do not only display a warning.
|
||||
* Apply the same check to any flow that results in a new position, including
|
||||
programmatic strategies that act on behalf of a user.
|
||||
|
||||
Read-only market data is not subject to these restrictions.
|
||||
@@ -0,0 +1,33 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Index Price
|
||||
|
||||
> How the Index Price is computed for Perps
|
||||
|
||||
Index Price is Polymarket's estimate of the underlying asset's fair value. It is
|
||||
computed from external price feeds, aggregated to resist stale or anomalous
|
||||
inputs, and published every 200 milliseconds per market.
|
||||
|
||||
## Feed Sources
|
||||
|
||||
Index Price can use feeds from external sources such as:
|
||||
|
||||
* Pyth
|
||||
* Chainlink Data Streams
|
||||
* Hyperliquid
|
||||
|
||||
## Feed Selection
|
||||
|
||||
The system selects different feeds based on the current market session so it can
|
||||
use the most accurate feed set for each market. See [Market Sessions](/perps/learn-about-trading/market-sessions).
|
||||
|
||||
## Aggregation
|
||||
|
||||
Index Price is computed as a weighted average across the selected feeds after
|
||||
dropping stale prices and filtering outliers. This prevents any single stale or
|
||||
anomalous feed from moving the Index.
|
||||
|
||||
The same aggregation approach is used to build the [C3 candidate in Mark Price](/perps/learn-about-trading/mark-price),
|
||||
using a separate mark feed set.
|
||||
@@ -0,0 +1,94 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Liquidation Mechanics
|
||||
|
||||
> Detection, execution, and insurance-fund backstop
|
||||
|
||||
When a trader's equity drops below maintenance margin, the system closes the
|
||||
position before it becomes insolvent. Normal liquidations route through the order
|
||||
book as reduce-only immediate-or-cancel orders. If the breach is severe, the
|
||||
position is absorbed directly by the insurance fund instead.
|
||||
|
||||
## Trigger
|
||||
|
||||
An account or isolated position is at risk when:
|
||||
|
||||
```text theme={null}
|
||||
MarginRatio = Equity / MaintenanceMargin
|
||||
```
|
||||
|
||||
Liquidation starts when `MarginRatio < 1.0`, which means `Equity < MM`.
|
||||
|
||||
Cross and isolated positions are checked independently:
|
||||
|
||||
* Cross uses the account's cross equity and combined cross maintenance margin.
|
||||
* Isolated evaluates each isolated position using its own equity and maintenance margin.
|
||||
|
||||
Margin health is re-evaluated continuously, so the system reacts as soon as a new
|
||||
Mark Price, fill, or deposit moves the account across the threshold.
|
||||
|
||||
## While Liquidating
|
||||
|
||||
When liquidation starts, the affected scope is flagged:
|
||||
|
||||
* Cross liquidation blocks new orders on every market for the account.
|
||||
* Isolated liquidation blocks new orders only on the affected market.
|
||||
|
||||
Order submissions from the account are rejected while the flag is set. Existing
|
||||
resting orders remain on the book.
|
||||
|
||||
## Execution
|
||||
|
||||
The system closes flagged positions with reduce-only immediate-or-cancel orders.
|
||||
These orders execute immediately against available liquidity and cancel any
|
||||
unfilled quantity. Margin health is re-evaluated between orders, so partial fills
|
||||
that restore the account naturally stop the process.
|
||||
|
||||
### Target Selection
|
||||
|
||||
Cross liquidation closes one position at a time. After each fill settles, the
|
||||
system re-evaluates and picks again from the remaining cross positions, so a
|
||||
trader with multiple cross positions is unwound across several cycles rather than
|
||||
all at once.
|
||||
|
||||
Isolated liquidation closes the flagged position in full.
|
||||
|
||||
### Order Shape
|
||||
|
||||
Liquidation orders are IOC, reduce-only, and market-priced. They sweep whatever
|
||||
liquidity is resting on the book at the moment they land. There is no protective
|
||||
spread off Mark.
|
||||
|
||||
## Recovery
|
||||
|
||||
When a liquidating account's equity recovers to or above its recovery initial
|
||||
margin, the flag clears and normal order submission resumes.
|
||||
|
||||
If a position is fully closed during liquidation, the flag is also cleared because
|
||||
the market no longer has a position to liquidate.
|
||||
|
||||
## Insurance-Fund Backstop
|
||||
|
||||
If equity falls far enough below maintenance margin that order-book liquidation is
|
||||
unlikely to recover value, the system skips the order book and absorbs the
|
||||
position into the insurance fund.
|
||||
|
||||
* Cross backstop absorbs all of the trader's cross positions plus their quote-asset balance into the insurance-fund account.
|
||||
* Isolated backstop absorbs the specific isolated position and its allocated isolated margin.
|
||||
|
||||
Once absorbed, the insurance fund holds the position and manages it like any other
|
||||
account.
|
||||
|
||||
## Fees
|
||||
|
||||
The liquidating account pays an extra liquidation fee on every fill while flagged,
|
||||
on top of its normal maker or taker rate.
|
||||
|
||||
```text theme={null}
|
||||
FillFee = Notional * (MakerOrTakerRate + LiquidationFeeRate)
|
||||
```
|
||||
|
||||
Liquidation fee rates vary by market. If you're integrating Perps, read current
|
||||
values from [Market Data](/perps/market-data#fetch-instruments).
|
||||
@@ -0,0 +1,86 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Margin
|
||||
|
||||
> Initial margin, maintenance margin, and equity calculations
|
||||
|
||||
Margin is the collateral required to open and maintain leveraged positions. It
|
||||
ensures traders have enough collateral to cover potential losses and gives the
|
||||
system a buffer to close positions before they become insolvent.
|
||||
|
||||
There are two thresholds. **Initial margin (IM)** is the collateral required to
|
||||
open or increase a position. **Maintenance margin (MM)** is the minimum
|
||||
collateral required to keep a position open. When equity drops below maintenance
|
||||
margin, the position is [liquidated](/perps/learn-about-trading/liquidation-mechanics).
|
||||
|
||||
## Equity
|
||||
|
||||
Equity is the real-time value of an account, incorporating all open positions at
|
||||
current Mark Price.
|
||||
|
||||
```text theme={null}
|
||||
Equity = Collateral + UnrealizedPnL(Mark) - FeesDue - FundingDue
|
||||
```
|
||||
|
||||
### Unrealized PnL
|
||||
|
||||
```text theme={null}
|
||||
Long PnL = PositionSize * (Mark - EntryPrice)
|
||||
Short PnL = PositionSize * (EntryPrice - Mark)
|
||||
```
|
||||
|
||||
Because equity depends on Mark Price, equity follows live mark updates. See
|
||||
[Mark Price](/perps/learn-about-trading/mark-price).
|
||||
|
||||
## Margin Requirements
|
||||
|
||||
```text theme={null}
|
||||
IM = Notional / L_max
|
||||
MM = Notional / L_maint
|
||||
```
|
||||
|
||||
Margin requirements scale with position size through leverage tiers. Larger
|
||||
positions require proportionally more margin. Margin is calculated incrementally
|
||||
across tiers, so a position spanning two tiers uses the lower tier's rate on
|
||||
notional up to its upper bound and the next tier's rate on the remainder.
|
||||
|
||||
Margin requirements are static across sessions.
|
||||
|
||||
## Margin States
|
||||
|
||||
An account is always in one of three states.
|
||||
|
||||
| State | Condition | What Happens |
|
||||
| ----------- | ------------------- | ---------------------------------------------- |
|
||||
| Healthy | `Equity >= IM` | Normal trading |
|
||||
| Margin call | `MM <= Equity < IM` | Can only reduce exposure or deposit collateral |
|
||||
| Liquidation | `Equity < MM` | The system begins closing the position |
|
||||
|
||||
## Margin Checks
|
||||
|
||||
### Pre-Trade
|
||||
|
||||
Before any order executes, the system verifies the account can afford it:
|
||||
|
||||
1. Compute the new position after the order fills.
|
||||
2. Calculate required initial margin using the market's leverage tiers.
|
||||
3. Reject the order if equity is below required initial margin.
|
||||
|
||||
This prevents accounts from entering a margin-call state through new trades.
|
||||
|
||||
### Continuous Monitoring
|
||||
|
||||
The system continuously evaluates accounts:
|
||||
|
||||
* If equity falls below maintenance margin, liquidation begins.
|
||||
* If equity is between maintenance margin and initial margin, the account may enter reduce-only mode.
|
||||
|
||||
## Deposits and Withdrawals
|
||||
|
||||
Deposits increase equity. A deposit during margin call can restore the account to
|
||||
healthy status immediately.
|
||||
|
||||
Withdrawals require the account to remain above required initial margin after the
|
||||
withdrawal. You cannot withdraw yourself into a margin call.
|
||||
@@ -0,0 +1,92 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Mark Price
|
||||
|
||||
> How the Mark Price is computed for Perps
|
||||
|
||||
Mark Price is the price used across the system for margin, unrealized PnL,
|
||||
liquidation triggers, funding premium computation, and risk checks. It is updated
|
||||
every 200 milliseconds.
|
||||
|
||||
Mark Price is computed as the median of three candidates, each capturing a
|
||||
different view of fair value.
|
||||
|
||||
```text theme={null}
|
||||
Mark = median(C1, C2, C3)
|
||||
```
|
||||
|
||||
## C1: Smoothed Order Book Mid
|
||||
|
||||
C1 anchors to Index and adjusts gradually based on where the local order book mid
|
||||
is trading relative to it.
|
||||
|
||||
```text theme={null}
|
||||
C1 = Index + EMA(Mid - Index)
|
||||
```
|
||||
|
||||
* `Mid = (BestBid + BestAsk) / 2` when both sides of the book exist.
|
||||
* The EMA uses a 150-second window, so C1 moves slowly and resists short-term manipulation.
|
||||
* If the order book mid is unavailable, C1 falls back to Index.
|
||||
|
||||
## C2: Local Market Activity
|
||||
|
||||
C2 reflects what is actually trading on the local book.
|
||||
|
||||
```text theme={null}
|
||||
C2 = median(BestBid, BestAsk, LastTrade)
|
||||
```
|
||||
|
||||
* Last trade is only included if it is recent.
|
||||
* Stale trades are excluded so one old print cannot anchor the price.
|
||||
* If no usable values exist, C2 falls back to Index.
|
||||
|
||||
## C3: Aggregated External Mark
|
||||
|
||||
C3 is built from external mark feeds, separate from Index feeds, that provide an
|
||||
independent view of fair value outside the local order book.
|
||||
|
||||
For each market, the system:
|
||||
|
||||
1. Selects active mark feeds from eligible external sources.
|
||||
2. Drops stale samples.
|
||||
3. Computes the candidate median and filters outliers beyond the allowed tolerance.
|
||||
4. Returns the weighted average of the remaining samples.
|
||||
|
||||
If no valid external mark data is available, C3 falls back to Index.
|
||||
|
||||
## Why Three Candidates?
|
||||
|
||||
Using the median of three independent price signals provides resilience:
|
||||
|
||||
* C1 is slow-moving and resistant to sudden order book manipulation, but can lag during fast moves.
|
||||
* C2 is responsive to real local trading activity, but can be influenced by thin liquidity.
|
||||
* C3 is independent of the local book, but depends on external feed availability.
|
||||
|
||||
The median ensures that no single signal can unilaterally move Mark Price. At
|
||||
least two of the three candidates must agree for the mark to shift.
|
||||
|
||||
## Finalization
|
||||
|
||||
After computing `median(C1, C2, C3)`, the raw mark is normalized before being
|
||||
published:
|
||||
|
||||
* Snapped to the nearest tick size
|
||||
* Rounded to the market's price precision
|
||||
|
||||
## Fallback Summary
|
||||
|
||||
Every input degrades gracefully to [Index Price](/perps/learn-about-trading/index-price).
|
||||
|
||||
| Condition | Behavior |
|
||||
| ------------------------------- | ----------------------------------------------------------- |
|
||||
| Index input stale | Falls back to last known market index |
|
||||
| Order book mid unavailable | C1 falls back to Index |
|
||||
| No recent trades or quotes | C2 falls back to Index |
|
||||
| External mark feeds unavailable | C3 falls back to Index |
|
||||
| All inputs missing | Mark tracks Index because all candidates fall back to Index |
|
||||
|
||||
In the worst case, when there is no local book, no recent trades, and no external
|
||||
mark feeds, all three candidates converge to Index and Mark Price tracks Index
|
||||
directly.
|
||||
@@ -0,0 +1,46 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Market Sessions
|
||||
|
||||
> How session state affects pricing feed selection
|
||||
|
||||
Perps trade 24/7, but the underlying markets do not. Liquidity and external price
|
||||
feed availability vary by time of day and day of week. Sessions are the system's
|
||||
categorization of these conditions.
|
||||
|
||||
## What Sessions Affect
|
||||
|
||||
Sessions affect one thing: which set of external feeds is used to compute [Index Price](/perps/learn-about-trading/index-price) and the [C3 candidate in Mark Price](/perps/learn-about-trading/mark-price).
|
||||
|
||||
Each category can use its own feed set. For example, primary venue feeds may be
|
||||
used during regular hours and after-hours venue feeds may be used overnight. If
|
||||
the current category has no dedicated feed set, the system falls back to the
|
||||
overnight feed set.
|
||||
|
||||
## What Sessions Do Not Affect
|
||||
|
||||
Sessions do not change:
|
||||
|
||||
* Funding
|
||||
* Margin and leverage tiers
|
||||
* Order matching
|
||||
* Liquidation triggers
|
||||
|
||||
Those systems run identically around the clock.
|
||||
|
||||
## Categories
|
||||
|
||||
* Regular: the underlying is open and primary feeds are available.
|
||||
* Overnight: the underlying is closed but some external feeds may still exist.
|
||||
* Weekend: a calendar-based closed period with thin or absent external data.
|
||||
* Disrupted: external feeds are unavailable or failing sanity checks.
|
||||
* Halted: a trading halt or corporate-action freeze on the underlying.
|
||||
|
||||
## How the Category Is Determined
|
||||
|
||||
Each market has a schedule that defines its time windows and exceptions. The
|
||||
system evaluates the schedule on time boundaries to produce the current category.
|
||||
When the category changes, subsequent Index and Mark updates use the feed set
|
||||
assigned to the new category.
|
||||
@@ -0,0 +1,48 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Markets
|
||||
|
||||
> Listed perpetual markets and trading parameters
|
||||
|
||||
Polymarket Perps markets track underlying assets across indices, commodities,
|
||||
crypto assets, and equities. Each market has its own trading parameters.
|
||||
|
||||
## Instruments
|
||||
|
||||
Perps markets are represented by instruments, which are the listed perpetual
|
||||
contracts available to trade.
|
||||
|
||||
| ID | Symbol | Category | Base Asset | Max Leverage |
|
||||
| -- | ------------ | ----------- | ---------- | ------------ |
|
||||
| 1 | `SP500-USD` | `index` | `SP500` | 20x |
|
||||
| 2 | `GOLD-USD` | `commodity` | `GOLD` | 20x |
|
||||
| 3 | `WTIOIL-USD` | `commodity` | `WTIOIL` | 20x |
|
||||
| 4 | `NAS100-USD` | `index` | `NAS100` | 20x |
|
||||
| 5 | `SILVER-USD` | `commodity` | `SILVER` | 20x |
|
||||
| 6 | `BTC-USD` | `crypto` | `BTC` | 20x |
|
||||
| 7 | `ETH-USD` | `crypto` | `ETH` | 20x |
|
||||
| 8 | `SOL-USD` | `crypto` | `SOL` | 20x |
|
||||
| 9 | `SPCX-USD` | `equity` | `SPCX` | 10x |
|
||||
|
||||
Each instrument also includes details that shape how it trades:
|
||||
|
||||
* Underlying asset
|
||||
* Collateral and quote asset
|
||||
* Price and quantity precision
|
||||
* Tick size
|
||||
* Minimum order size
|
||||
* Risk tiers and leverage caps
|
||||
* Mark, index, and funding configuration
|
||||
|
||||
<Note>
|
||||
Market parameters can change as markets evolve. Builders should read live
|
||||
instrument details from [Market Data](/perps/market-data#fetch-instruments)
|
||||
before submitting orders.
|
||||
</Note>
|
||||
|
||||
## Price Feeds
|
||||
|
||||
Each market tracks an underlying market through external price feeds. Those
|
||||
feeds drive the [Index Price](/perps/learn-about-trading/index-price), and the Index Price helps anchor the [Mark Price](/perps/learn-about-trading/mark-price).
|
||||
@@ -0,0 +1,53 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Overview
|
||||
|
||||
> The market mechanics behind Perps trading
|
||||
|
||||
Perps markets follow a small set of system rules. This section explains how
|
||||
those rules work so you can anticipate how positions are valued, when they are
|
||||
at risk, and why account balances change.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Architecture" icon="sitemap" href="/perps/learn-about-trading/architecture">
|
||||
How offchain matching and onchain settlement fit together.
|
||||
</Card>
|
||||
|
||||
<Card title="Markets" icon="list" href="/perps/learn-about-trading/markets">
|
||||
Available Perps markets and the parameters that shape trading.
|
||||
</Card>
|
||||
|
||||
<Card title="Fees" icon="percent" href="/perps/learn-about-trading/fees">
|
||||
What each fill costs and how the volume-based fee tiers work.
|
||||
</Card>
|
||||
|
||||
<Card title="Margin" icon="scale-balanced" href="/perps/learn-about-trading/margin">
|
||||
Equity, initial margin, maintenance margin, and margin states.
|
||||
</Card>
|
||||
|
||||
<Card title="Liquidation Mechanics" icon="triangle-exclamation" href="/perps/learn-about-trading/liquidation-mechanics">
|
||||
How liquidation is detected, executed, and backstopped.
|
||||
</Card>
|
||||
|
||||
<Card title="Funding" icon="repeat" href="/perps/learn-about-trading/funding">
|
||||
How funding rates are computed and settled against open positions.
|
||||
</Card>
|
||||
|
||||
<Card title="Mark Price" icon="chart-line" href="/perps/learn-about-trading/mark-price">
|
||||
How the price used for margin, PnL, and liquidation is computed.
|
||||
</Card>
|
||||
|
||||
<Card title="Index Price" icon="crosshairs" href="/perps/learn-about-trading/index-price">
|
||||
How the underlying's fair value is sourced and aggregated.
|
||||
</Card>
|
||||
|
||||
<Card title="Market Sessions" icon="clock" href="/perps/learn-about-trading/market-sessions">
|
||||
How session state affects pricing feed selection.
|
||||
</Card>
|
||||
|
||||
<Card title="Geographic Restrictions" icon="globe" href="/perps/learn-about-trading/geographic-restrictions">
|
||||
Where order placement is restricted.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,846 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Market Data
|
||||
|
||||
> Discover Perps markets and monitor public market activity
|
||||
|
||||
Use market data to understand what can be traded, where the market is trading
|
||||
now, and how activity has changed over time.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
The TypeScript examples on this page use a `PublicClient`. The same market-data
|
||||
methods are also available on `SecureClient` instances.
|
||||
|
||||
```ts theme={null}
|
||||
import { createPublicClient } from "@polymarket/client";
|
||||
|
||||
const client = createPublicClient();
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
The Python examples on this page use an `AsyncPublicClient`. The same market-data
|
||||
methods are also available on `AsyncSecureClient` instances.
|
||||
|
||||
```python theme={null}
|
||||
from polymarket import AsyncPublicClient
|
||||
|
||||
client = AsyncPublicClient()
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Use the Perps REST API production URL.
|
||||
|
||||
```text theme={null}
|
||||
https://api.perpetuals.polymarket.com
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Fetch Instruments
|
||||
|
||||
Fetch instruments before your integration lets users choose or submit orders for
|
||||
a Perps market. Instrument data gives you the constraints needed to validate that
|
||||
workflow.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
Fetch the available instruments.
|
||||
|
||||
```ts theme={null}
|
||||
const instruments = await client.fetchPerpsInstruments();
|
||||
// instruments: PerpsInstrument[]
|
||||
```
|
||||
|
||||
where `PerpsInstrument` is:
|
||||
|
||||
<CodeGroup>
|
||||
```ts Type theme={null}
|
||||
type PerpsInstrument = {
|
||||
id: PerpsInstrumentId;
|
||||
category: PerpsInstrumentCategory;
|
||||
symbol: string;
|
||||
baseAsset: string;
|
||||
quoteAsset: string;
|
||||
fundingInterval: PerpsFundingInterval;
|
||||
quantityDecimals: number;
|
||||
priceDecimals: number;
|
||||
priceBounds: DecimalString;
|
||||
liquidationFee: DecimalString;
|
||||
maxOrderCount: number;
|
||||
minNotional: DecimalString;
|
||||
maxMarketNotional: DecimalString;
|
||||
maxLimitNotional: DecimalString;
|
||||
maxLeverage: number;
|
||||
riskTiers: PerpsRiskTier[];
|
||||
};
|
||||
|
||||
type PerpsRiskTier = {
|
||||
lowerBound: DecimalString;
|
||||
maxLeverage: number;
|
||||
};
|
||||
```
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"id": 1,
|
||||
"category": "crypto",
|
||||
"symbol": "BTC-PERP",
|
||||
"baseAsset": "BTC",
|
||||
"quoteAsset": "USD",
|
||||
"fundingInterval": "1h",
|
||||
"quantityDecimals": 4,
|
||||
"priceDecimals": 2,
|
||||
"priceBounds": "0.1",
|
||||
"liquidationFee": "0.01",
|
||||
"maxOrderCount": 200,
|
||||
"minNotional": "1",
|
||||
"maxMarketNotional": "100000",
|
||||
"maxLimitNotional": "1000000",
|
||||
"maxLeverage": 10,
|
||||
"riskTiers": [{ "lowerBound": "0", "maxLeverage": 10 }]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
`PerpsInstrument` includes the market metadata and trading constraints your app
|
||||
needs before submitting orders.
|
||||
|
||||
| Field | Description |
|
||||
| ------------------- | ------------------------------------------------------------- |
|
||||
| `id` | Instrument identifier. |
|
||||
| `category` | Market category, such as crypto, index, equity, or commodity. |
|
||||
| `symbol` | Human-readable market symbol. |
|
||||
| `baseAsset` | Base asset for the instrument. |
|
||||
| `quoteAsset` | Quote asset used for prices. |
|
||||
| `fundingInterval` | Funding interval for the instrument, such as `1h`. |
|
||||
| `quantityDecimals` | Decimal precision for quantities. |
|
||||
| `priceDecimals` | Decimal precision for prices. |
|
||||
| `priceBounds` | Price-bound value for the instrument. |
|
||||
| `liquidationFee` | Liquidation fee value for the instrument. |
|
||||
| `maxOrderCount` | Maximum order count for the instrument. |
|
||||
| `minNotional` | Minimum notional value for orders. |
|
||||
| `maxMarketNotional` | Maximum notional value for market orders. |
|
||||
| `maxLimitNotional` | Maximum notional value for limit orders. |
|
||||
| `maxLeverage` | Maximum leverage allowed for the instrument. |
|
||||
| `riskTiers` | Risk tiers for larger position sizes. |
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
Fetch the available instruments.
|
||||
|
||||
```python theme={null}
|
||||
instruments = await client.fetch_perps_instruments()
|
||||
# instruments: tuple[PerpsInstrument, ...]
|
||||
```
|
||||
|
||||
Filter by instrument ID when you already know the market you need.
|
||||
|
||||
```python theme={null}
|
||||
instruments = await client.fetch_perps_instruments(instrument_id=1)
|
||||
```
|
||||
|
||||
`PerpsInstrument` includes the market metadata and trading constraints your app
|
||||
needs before submitting orders.
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"id": 1,
|
||||
"category": "crypto",
|
||||
"symbol": "BTC-PERP",
|
||||
"base_asset": "BTC",
|
||||
"quote_asset": "USD",
|
||||
"funding_interval": "1h",
|
||||
"quantity_decimals": 4,
|
||||
"price_decimals": 2,
|
||||
"price_bounds": "0.1",
|
||||
"liquidation_fee": "0.01",
|
||||
"max_order_count": 200,
|
||||
"min_notional": "1",
|
||||
"max_market_notional": "100000",
|
||||
"max_limit_notional": "1000000",
|
||||
"max_leverage": 10,
|
||||
"risk_tiers": [{ "lower_bound": "0", "max_leverage": 10 }]
|
||||
}
|
||||
```
|
||||
|
||||
`PerpsInstrument` exposes these attributes:
|
||||
|
||||
| Attribute | Description |
|
||||
| --------------------------- | ------------------------------------------------------------- |
|
||||
| `id` | Instrument identifier. |
|
||||
| `category` | Market category, such as crypto, index, equity, or commodity. |
|
||||
| `symbol` | Human-readable market symbol. |
|
||||
| `base_asset` | Base asset for the instrument. |
|
||||
| `quote_asset` | Quote asset used for prices. |
|
||||
| `funding_interval` | Funding interval for the instrument, such as `1h`. |
|
||||
| `quantity_decimals` | Decimal precision for quantities. |
|
||||
| `price_decimals` | Decimal precision for prices. |
|
||||
| `price_bounds` | Price-bound value for the instrument. |
|
||||
| `liquidation_fee` | Liquidation fee value for the instrument. |
|
||||
| `max_order_count` | Maximum order count for the instrument. |
|
||||
| `min_notional` | Minimum notional value for orders. |
|
||||
| `max_market_notional` | Maximum notional value for market orders. |
|
||||
| `max_limit_notional` | Maximum notional value for limit orders. |
|
||||
| `max_leverage` | Maximum leverage allowed for the instrument. |
|
||||
| `risk_tiers` | Risk tiers for larger position sizes. |
|
||||
| `risk_tiers[].lower_bound` | Lower notional bound for the risk tier. |
|
||||
| `risk_tiers[].max_leverage` | Maximum leverage allowed for the risk tier. |
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Fetch the available instruments.
|
||||
|
||||
```bash theme={null}
|
||||
curl "https://api.perpetuals.polymarket.com/v1/info/instruments"
|
||||
```
|
||||
|
||||
Filter by instrument ID when you already know the market you need.
|
||||
|
||||
```bash theme={null}
|
||||
curl -G "https://api.perpetuals.polymarket.com/v1/info/instruments" \
|
||||
--data-urlencode "instrument_id=1"
|
||||
```
|
||||
|
||||
The response is an array of instruments.
|
||||
|
||||
```json theme={null}
|
||||
[
|
||||
{
|
||||
"instrument_id": 1,
|
||||
"instrument_type": "perpetual",
|
||||
"category": "crypto",
|
||||
"symbol": "BTC-PERP",
|
||||
"base_asset": "BTC",
|
||||
"quote_asset": "USD",
|
||||
"funding_interval": "1h",
|
||||
"quantity_decimals": 4,
|
||||
"price_decimals": 2,
|
||||
"price_bounds": "0.1",
|
||||
"liquidation_fee": "0.01",
|
||||
"max_order_count": 200,
|
||||
"min_notional": "1",
|
||||
"max_market_notional": "100000",
|
||||
"max_limit_notional": "1000000",
|
||||
"max_leverage": 10,
|
||||
"risk_tiers": [{ "lower_bound": "0", "max_leverage": 10 }]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Each instrument object includes the market metadata and trading constraints your
|
||||
app needs before submitting orders.
|
||||
|
||||
| Field | Description |
|
||||
| --------------------------- | --------------------------------------------------------------------- |
|
||||
| `instrument_id` | Instrument identifier. |
|
||||
| `instrument_type` | Instrument type. Perps instruments use `perpetual`. |
|
||||
| `category` | Market category, such as `crypto`, `index`, `equity`, or `commodity`. |
|
||||
| `symbol` | Human-readable market symbol. |
|
||||
| `base_asset` | Base asset for the instrument. |
|
||||
| `quote_asset` | Quote asset used for prices. |
|
||||
| `funding_interval` | Funding interval for the instrument, such as `1h`. |
|
||||
| `quantity_decimals` | Decimal precision for quantities. |
|
||||
| `price_decimals` | Decimal precision for prices. |
|
||||
| `price_bounds` | Price-bound value for the instrument. |
|
||||
| `liquidation_fee` | Liquidation fee value for the instrument. |
|
||||
| `max_order_count` | Maximum order count for the instrument. |
|
||||
| `min_notional` | Minimum notional value for orders. |
|
||||
| `max_market_notional` | Maximum notional value for market orders. |
|
||||
| `max_limit_notional` | Maximum notional value for limit orders. |
|
||||
| `max_leverage` | Maximum leverage allowed for the instrument. |
|
||||
| `risk_tiers` | Risk tiers for larger position sizes. |
|
||||
| `risk_tiers[].lower_bound` | Lower notional bound for the risk tier. |
|
||||
| `risk_tiers[].max_leverage` | Maximum leverage allowed for the risk tier. |
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Fetch Tickers
|
||||
|
||||
Use tickers when you need a lightweight view of where one or more markets are
|
||||
trading now.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
Fetch one ticker when you already know which instrument your integration is
|
||||
tracking.
|
||||
|
||||
```ts theme={null}
|
||||
const ticker = await client.fetchPerpsTicker({
|
||||
instrumentId: instrument.id,
|
||||
});
|
||||
// ticker: PerpsTicker
|
||||
```
|
||||
|
||||
Fetch all tickers to build a market list or refresh a dashboard.
|
||||
|
||||
```ts theme={null}
|
||||
const tickers = await client.fetchPerpsTickers();
|
||||
// tickers: PerpsTicker[]
|
||||
```
|
||||
|
||||
where `PerpsTicker` is:
|
||||
|
||||
<CodeGroup>
|
||||
```ts Type theme={null}
|
||||
type PerpsTicker = {
|
||||
instrumentId: PerpsInstrumentId;
|
||||
symbol: string;
|
||||
indexPrice: DecimalString;
|
||||
markPrice: DecimalString;
|
||||
lastPrice: DecimalString;
|
||||
midPrice: DecimalString;
|
||||
openInterest: DecimalString;
|
||||
fundingRate: DecimalString;
|
||||
nextFunding: EpochMilliseconds;
|
||||
volume24h?: DecimalString;
|
||||
openPrice?: DecimalString;
|
||||
timestamp?: EpochMilliseconds;
|
||||
};
|
||||
```
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"instrumentId": 1,
|
||||
"symbol": "BTC-PERP",
|
||||
"indexPrice": "65000.00",
|
||||
"markPrice": "65012.50",
|
||||
"lastPrice": "65010.00",
|
||||
"midPrice": "65011.25",
|
||||
"openInterest": "125.4",
|
||||
"fundingRate": "0.0001",
|
||||
"nextFunding": 1766124000000,
|
||||
"volume24h": "2450000",
|
||||
"openPrice": "64250.00",
|
||||
"timestamp": 1766120400000
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
Fetch one ticker when you already know which instrument your integration is
|
||||
tracking.
|
||||
|
||||
```python theme={null}
|
||||
ticker = await client.fetch_perps_ticker(instrument_id=instrument.id)
|
||||
# ticker: PerpsTicker
|
||||
```
|
||||
|
||||
Fetch all tickers to build a market list or refresh a dashboard.
|
||||
|
||||
```python theme={null}
|
||||
tickers = await client.fetch_perps_tickers()
|
||||
# tickers: tuple[PerpsTicker, ...]
|
||||
```
|
||||
|
||||
Use the returned ticker for current price, open interest, and funding state.
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"instrument_id": 1,
|
||||
"symbol": "BTC-PERP",
|
||||
"index_price": "65000.00",
|
||||
"mark_price": "65012.50",
|
||||
"last_price": "65010.00",
|
||||
"mid_price": "65011.25",
|
||||
"open_interest": "125.4",
|
||||
"funding_rate": "0.0001",
|
||||
"next_funding": 1766124000000,
|
||||
"volume_24h": "2450000",
|
||||
"open_price": "64250.00",
|
||||
"timestamp": 1766120400000
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Fetch all tickers to build a market list or refresh a dashboard.
|
||||
|
||||
```bash theme={null}
|
||||
curl "https://api.perpetuals.polymarket.com/v1/info/tickers"
|
||||
```
|
||||
|
||||
Filter by instrument ID when you only need one ticker.
|
||||
|
||||
```bash theme={null}
|
||||
curl -G "https://api.perpetuals.polymarket.com/v1/info/tickers" \
|
||||
--data-urlencode "instrument_id=1"
|
||||
```
|
||||
|
||||
The response is an array of ticker snapshots.
|
||||
|
||||
```json theme={null}
|
||||
[
|
||||
{
|
||||
"instrument_id": 1,
|
||||
"symbol": "BTC-PERP",
|
||||
"index_price": "65000.00",
|
||||
"mark_price": "65012.50",
|
||||
"last_price": "65010.00",
|
||||
"mid_price": "65011.25",
|
||||
"open_interest": "125.4",
|
||||
"funding_rate": "0.0001",
|
||||
"next_funding": 1766124000000,
|
||||
"timestamp": 1766120400000
|
||||
}
|
||||
]
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Fetch the Order Book
|
||||
|
||||
Use the order book before choosing an order price or size. It shows available
|
||||
liquidity at the requested depth.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
Choose how many price levels to request. Supported depths are `10`, `100`,
|
||||
`500`, and `1000`. When omitted, the SDK requests `100` levels.
|
||||
|
||||
```ts theme={null}
|
||||
// depth: PerpsBookDepth
|
||||
const depth = 100;
|
||||
```
|
||||
|
||||
Fetch the book for the selected instrument. Bids and asks are returned as price
|
||||
levels with decimal string prices and quantities.
|
||||
|
||||
```ts theme={null}
|
||||
const book = await client.fetchPerpsBook({
|
||||
instrumentId: instrument.id,
|
||||
depth,
|
||||
});
|
||||
|
||||
const bestBid = book.bids[0];
|
||||
const bestAsk = book.asks[0];
|
||||
|
||||
// book: PerpsBook
|
||||
// bestBid: PerpsBookLevel | undefined
|
||||
// bestAsk: PerpsBookLevel | undefined
|
||||
```
|
||||
|
||||
where `PerpsBook` and `PerpsBookLevel` are:
|
||||
|
||||
<CodeGroup>
|
||||
```ts Type theme={null}
|
||||
type PerpsBook = {
|
||||
instrumentId: PerpsInstrumentId;
|
||||
bids: PerpsBookLevel[];
|
||||
asks: PerpsBookLevel[];
|
||||
timestamp: EpochMilliseconds;
|
||||
sequence: number;
|
||||
};
|
||||
|
||||
type PerpsBookLevel = {
|
||||
price: DecimalString;
|
||||
quantity: DecimalString;
|
||||
};
|
||||
```
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"instrumentId": 1,
|
||||
"bids": [
|
||||
{ "price": "65010.00", "quantity": "0.75" },
|
||||
{ "price": "65009.50", "quantity": "1.2" }
|
||||
],
|
||||
"asks": [
|
||||
{ "price": "65012.50", "quantity": "0.6" },
|
||||
{ "price": "65013.00", "quantity": "1.1" }
|
||||
],
|
||||
"timestamp": 1766120400000,
|
||||
"sequence": 123456
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
Choose how many price levels to request. Supported depths are `10`, `100`,
|
||||
`500`, and `1000`. When omitted, the SDK requests `100` levels.
|
||||
|
||||
```python theme={null}
|
||||
depth = 100
|
||||
```
|
||||
|
||||
Fetch the book for the selected instrument. Bids and asks are returned as price
|
||||
levels with decimal string prices and quantities.
|
||||
|
||||
```python theme={null}
|
||||
book = await client.fetch_perps_book(
|
||||
instrument_id=instrument.id,
|
||||
depth=depth,
|
||||
)
|
||||
|
||||
best_bid = book.bids[0] if book.bids else None
|
||||
best_ask = book.asks[0] if book.asks else None
|
||||
|
||||
# book: PerpsBook
|
||||
# best_bid: PerpsBookLevel | None
|
||||
# best_ask: PerpsBookLevel | None
|
||||
```
|
||||
|
||||
Use `book.bids` and `book.asks` for bid and ask price levels.
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"instrument_id": 1,
|
||||
"bids": [
|
||||
{ "price": "65010.00", "quantity": "0.75" },
|
||||
{ "price": "65009.50", "quantity": "1.2" }
|
||||
],
|
||||
"asks": [
|
||||
{ "price": "65012.50", "quantity": "0.6" },
|
||||
{ "price": "65013.00", "quantity": "1.1" }
|
||||
],
|
||||
"timestamp": 1766120400000,
|
||||
"sequence": 123456
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Fetch the order book for an instrument. Supported depths are `10`, `100`, `500`,
|
||||
and `1000`; when omitted, the API uses `100`.
|
||||
|
||||
```bash theme={null}
|
||||
curl -G "https://api.perpetuals.polymarket.com/v1/info/book" \
|
||||
--data-urlencode "instrument_id=1" \
|
||||
--data-urlencode "depth=100"
|
||||
```
|
||||
|
||||
The response returns bids and asks as `[price, quantity]` levels.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"instrument_id": 1,
|
||||
"bids": [
|
||||
["65010.00", "0.75"],
|
||||
["65009.50", "1.2"]
|
||||
],
|
||||
"asks": [
|
||||
["65012.50", "0.6"],
|
||||
["65013.00", "1.1"]
|
||||
],
|
||||
"timestamp": 1766120400000,
|
||||
"sequence": 123456
|
||||
}
|
||||
```
|
||||
|
||||
Each `bids` and `asks` level is `[price, quantity]`.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## List Candles
|
||||
|
||||
Use candles when your workflow needs time-bucketed price history for charts,
|
||||
backtests, or trading signals.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
The SDK paginates candle history. When `start` is omitted, it starts from the
|
||||
past 24 hours.
|
||||
|
||||
```ts theme={null}
|
||||
import { PerpsKlineInterval } from "@polymarket/client";
|
||||
|
||||
const pages = client.listPerpsCandles({
|
||||
instrumentId: instrument.id,
|
||||
interval: PerpsKlineInterval.OneMinute,
|
||||
});
|
||||
|
||||
for await (const page of pages) {
|
||||
for (const candle of page.items) {
|
||||
// candle: PerpsCandle
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
where `PerpsCandle` is:
|
||||
|
||||
<CodeGroup>
|
||||
```ts Type theme={null}
|
||||
type PerpsCandle = {
|
||||
timestamp: EpochMilliseconds;
|
||||
open: DecimalString;
|
||||
high: DecimalString;
|
||||
low: DecimalString;
|
||||
close: DecimalString;
|
||||
volume: DecimalString;
|
||||
trades: number;
|
||||
};
|
||||
```
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"timestamp": 1766120400000,
|
||||
"open": "65000.00",
|
||||
"high": "65025.00",
|
||||
"low": "64980.00",
|
||||
"close": "65010.00",
|
||||
"volume": "42.5",
|
||||
"trades": 18
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
The SDK paginates candle history. When `start` is omitted, it starts from the
|
||||
past 24 hours.
|
||||
|
||||
```python theme={null}
|
||||
pages = client.list_perps_candles(
|
||||
instrument_id=instrument.id,
|
||||
interval="1m",
|
||||
)
|
||||
|
||||
async for page in pages:
|
||||
for candle in page.items:
|
||||
# candle: PerpsCandle
|
||||
pass
|
||||
```
|
||||
|
||||
Each candle contains one OHLCV bucket.
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"timestamp": 1766120400000,
|
||||
"open": "65000.00",
|
||||
"high": "65025.00",
|
||||
"low": "64980.00",
|
||||
"close": "65010.00",
|
||||
"volume": "42.5",
|
||||
"trades": 18
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Fetch candles for an instrument and interval. `start_timestamp` is required;
|
||||
`end_timestamp` is optional. The API returns at most 1000 candles per request.
|
||||
|
||||
```bash theme={null}
|
||||
curl -G "https://api.perpetuals.polymarket.com/v1/info/klines" \
|
||||
--data-urlencode "instrument_id=1" \
|
||||
--data-urlencode "interval=1m" \
|
||||
--data-urlencode "start_timestamp=1766120400000"
|
||||
```
|
||||
|
||||
The response returns candles in `data` and a `more` flag for continuation.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"data": [
|
||||
[1766120400000, "65000.00", "65025.00", "64980.00", "65010.00", "42.5", 18]
|
||||
],
|
||||
"more": false
|
||||
}
|
||||
```
|
||||
|
||||
Each candle is `[timestamp, open, high, low, close, volume, trades]`.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## List Trades
|
||||
|
||||
Use public trades when recent executions matter more than aggregated candles.
|
||||
This is useful for trade tape views and execution analysis.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
The SDK paginates trade history, including cursor handling and boundary
|
||||
deduplication.
|
||||
|
||||
```ts theme={null}
|
||||
const pages = client.listPerpsTrades({
|
||||
instrumentId: instrument.id,
|
||||
});
|
||||
|
||||
for await (const page of pages) {
|
||||
for (const trade of page.items) {
|
||||
// trade: PerpsPublicTrade
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
where `PerpsPublicTrade` is:
|
||||
|
||||
<CodeGroup>
|
||||
```ts Type theme={null}
|
||||
type PerpsPublicTrade = {
|
||||
tradeId: PerpsTradeId;
|
||||
instrumentId: PerpsInstrumentId;
|
||||
side: PerpsSide;
|
||||
price: DecimalString;
|
||||
quantity: DecimalString;
|
||||
timestamp: EpochMilliseconds;
|
||||
hash?: TxHash;
|
||||
};
|
||||
```
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"tradeId": 987654,
|
||||
"instrumentId": 1,
|
||||
"side": "long",
|
||||
"price": "65010.00",
|
||||
"quantity": "0.25",
|
||||
"timestamp": 1766120400000,
|
||||
"hash": "0x1111111111111111111111111111111111111111111111111111111111111111"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
The SDK paginates trade history, including cursor handling and boundary
|
||||
deduplication.
|
||||
|
||||
```python theme={null}
|
||||
pages = client.list_perps_trades(instrument_id=instrument.id)
|
||||
|
||||
async for page in pages:
|
||||
for trade in page.items:
|
||||
# trade: PerpsTrade
|
||||
pass
|
||||
```
|
||||
|
||||
Each trade contains one public execution.
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"trade_id": 987654,
|
||||
"instrument_id": 1,
|
||||
"side": "long",
|
||||
"price": "65010.00",
|
||||
"quantity": "0.25",
|
||||
"timestamp": 1766120400000,
|
||||
"hash": "0x1111111111111111111111111111111111111111111111111111111111111111"
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Fetch recent public trades for an instrument. `start_timestamp` and
|
||||
`end_timestamp` are optional. The API returns at most 100 trades per request.
|
||||
|
||||
```bash theme={null}
|
||||
curl -G "https://api.perpetuals.polymarket.com/v1/info/trades" \
|
||||
--data-urlencode "instrument_id=1"
|
||||
```
|
||||
|
||||
The response returns trades in `data` and a `more` flag for continuation.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"trade_id": 987654,
|
||||
"instrument_id": 1,
|
||||
"side": "long",
|
||||
"price": "65010.00",
|
||||
"quantity": "0.25",
|
||||
"timestamp": 1766120400000,
|
||||
"hash": "0x1111111111111111111111111111111111111111111111111111111111111111"
|
||||
}
|
||||
],
|
||||
"more": false
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## List Funding History
|
||||
|
||||
Use funding-rate history when estimating carry costs or explaining why Perps
|
||||
prices differ from the index over time.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
The SDK paginates funding-rate history.
|
||||
|
||||
```ts theme={null}
|
||||
const pages = client.listPerpsFundingHistory({
|
||||
instrumentId: instrument.id,
|
||||
});
|
||||
|
||||
for await (const page of pages) {
|
||||
for (const fundingRate of page.items) {
|
||||
// fundingRate: PerpsFundingRate
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
where `PerpsFundingRate` is:
|
||||
|
||||
<CodeGroup>
|
||||
```ts Type theme={null}
|
||||
type PerpsFundingRate = {
|
||||
fundingRate: DecimalString;
|
||||
timestamp: EpochMilliseconds;
|
||||
};
|
||||
```
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"fundingRate": "0.0001",
|
||||
"timestamp": 1766120400000
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
The SDK paginates funding-rate history.
|
||||
|
||||
```python theme={null}
|
||||
pages = client.list_perps_funding_history(instrument_id=instrument.id)
|
||||
|
||||
async for page in pages:
|
||||
for funding_rate in page.items:
|
||||
# funding_rate: PerpsFundingRate
|
||||
pass
|
||||
```
|
||||
|
||||
Each funding-rate entry contains one historical observation.
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"funding_rate": "0.0001",
|
||||
"timestamp": 1766120400000
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Fetch historical funding rates for an instrument. `start_timestamp` and
|
||||
`end_timestamp` are optional. The API returns at most 100 funding-rate entries
|
||||
per request.
|
||||
|
||||
```bash theme={null}
|
||||
curl -G "https://api.perpetuals.polymarket.com/v1/info/funding" \
|
||||
--data-urlencode "instrument_id=1"
|
||||
```
|
||||
|
||||
The response returns funding rates in `data` and a `more` flag for continuation.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"funding_rate": "0.0001",
|
||||
"timestamp": 1766120400000
|
||||
}
|
||||
],
|
||||
"more": false
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@@ -0,0 +1,78 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Overview
|
||||
|
||||
> Start here for Polymarket perpetual markets
|
||||
|
||||
Polymarket Perps are perpetual contracts that track an underlying asset such as
|
||||
an index, commodity, crypto asset, or equity. Perps trade continuously and do not
|
||||
expire, so traders can open, manage, and close leveraged positions without
|
||||
waiting for a market resolution event.
|
||||
|
||||
<Note>
|
||||
Polymarket Perps is in early access. Access requires a valid [Perps referral
|
||||
link or code](/perps/referral-program).
|
||||
</Note>
|
||||
|
||||
## How Perps Work
|
||||
|
||||
A Perps trade starts as an order in the order book. When it fills, it becomes a
|
||||
position whose value changes as the tracked market moves, until the trader closes
|
||||
it or the system closes it because the account can no longer support the risk.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Prices" icon="chart-line">
|
||||
A Perps market has a traded price from the order book and reference prices
|
||||
used by the system. The index price tracks the underlying asset, while the
|
||||
mark price is used for account equity, margin checks, and liquidation risk.
|
||||
</Card>
|
||||
|
||||
<Card title="Trading Positions" icon="arrow-right-arrow-left">
|
||||
Trading a Perps market creates or changes a position. A long position benefits
|
||||
when the tracked asset rises, and a short position benefits when it falls.
|
||||
Orders trade through the order book; fills update the account's position,
|
||||
balance, and history.
|
||||
</Card>
|
||||
|
||||
<Card title="Margin And Liquidation" icon="shield">
|
||||
Perps require collateral to support open positions. That collateral is the
|
||||
account's margin: the buffer that covers losses while a position is open. If
|
||||
account equity falls too far relative to the required margin, the position can
|
||||
be liquidated to close exposure.
|
||||
</Card>
|
||||
|
||||
<Card title="Funding Payments" icon="repeat">
|
||||
Funding payments keep the contract price close to the index price. When a
|
||||
market trades above its index price, long positions generally pay short
|
||||
positions. When it trades below its index price, shorts generally pay longs.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Building on Perps
|
||||
|
||||
If you are here to see what you can build on top of Polymarket Perps, common use
|
||||
cases include:
|
||||
|
||||
* Trading bots that react to market signals
|
||||
* Market making systems that quote Perps markets
|
||||
* Portfolio dashboards that track balances and positions
|
||||
* Risk monitors that track margin and liquidation risk
|
||||
* Market data products that analyze books, trades, and funding payments
|
||||
|
||||
## Next Steps
|
||||
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Concepts" icon="book" href="/perps/concepts">
|
||||
Learn the shared terms used across Perps docs.
|
||||
</Card>
|
||||
|
||||
<Card title="Learn About Trading" icon="book-open" href="/perps/learn-about-trading/overview">
|
||||
Understand the market mechanics behind Perps.
|
||||
</Card>
|
||||
|
||||
<Card title="Place Your First Trade" icon="bolt" href="/perps/place-your-first-trade">
|
||||
Build a first end-to-end Perps trading flow.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,245 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Place Your First Trade
|
||||
|
||||
> Learn how to prepare a Perps account and submit a first buy order
|
||||
|
||||
This guide walks through the shortest safe path to a first Perps trade. You will
|
||||
set up a Perps account, add collateral, and place a small buy order.
|
||||
|
||||
You need a Polymarket account with pUSD available before you start. Create one at
|
||||
[polymarket.com](https://polymarket.com).
|
||||
|
||||
<Note>
|
||||
Building directly against the API? Start with [Authenticated
|
||||
Sessions](/perps/authenticated-sessions), then use [Fund Your
|
||||
Account](/perps/fund-your-account) and [Trading](/perps/trading).
|
||||
</Note>
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
<Steps>
|
||||
<Step title="Install the SDK">
|
||||
Install the Unified TypeScript SDK with the package manager of your choice.
|
||||
|
||||
<CodeGroup>
|
||||
```bash pnpm theme={null}
|
||||
pnpm add @polymarket/client@beta viem
|
||||
```
|
||||
|
||||
```bash npm theme={null}
|
||||
npm install @polymarket/client@beta viem
|
||||
```
|
||||
|
||||
```bash yarn theme={null}
|
||||
yarn add @polymarket/client@beta viem
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<Note>
|
||||
This page uses Viem for wallet signing. See the [TypeScript tooling
|
||||
guide](/dev-tooling/typescript#wallet-integrations) for other wallet library
|
||||
integrations.
|
||||
</Note>
|
||||
</Step>
|
||||
|
||||
<Step title="Create a Secure Client">
|
||||
Create a `SecureClient` with the wallet and signer that owns the Perps account.
|
||||
Include a Relayer API key so the SDK can submit gasless transactions.
|
||||
|
||||
```ts theme={null}
|
||||
import { createSecureClient, relayerApiKey } from "@polymarket/client";
|
||||
import { privateKey } from "@polymarket/client/viem";
|
||||
|
||||
const client = await createSecureClient({
|
||||
wallet: process.env.POLYMARKET_WALLET_ADDRESS!,
|
||||
signer: privateKey(process.env.PRIVATE_KEY!),
|
||||
apiKey: relayerApiKey({
|
||||
key: process.env.RELAYER_API_KEY!,
|
||||
address: process.env.RELAYER_API_KEY_ADDRESS!,
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
Create a [Relayer API key](https://polymarket.com/settings?tab=api-keys) from
|
||||
polymarket.com → Settings → API Keys.
|
||||
</Step>
|
||||
|
||||
<Step title="Fund the Account">
|
||||
Set up the approvals required for Perps collateral deposits, then deposit pUSD
|
||||
from the user's Polymarket wallet into the Perps account. The minimum Perps
|
||||
deposit is 10 pUSD. Amounts use raw pUSD base units, so 10 pUSD is
|
||||
`10_000_000n`.
|
||||
|
||||
```ts theme={null}
|
||||
await client.setupTradingApprovals();
|
||||
|
||||
const deposit = await client.depositToPerps({
|
||||
amount: 10_000_000n,
|
||||
});
|
||||
|
||||
await deposit.wait();
|
||||
```
|
||||
|
||||
`deposit.wait()` confirms that the chain transaction settled. Perps may take a
|
||||
moment to credit the account after that. See [Fund Your
|
||||
Account](/perps/fund-your-account) for the full funding workflow.
|
||||
</Step>
|
||||
|
||||
<Step title="Open a Perps Session">
|
||||
Open a Perps session for private reads and trading.
|
||||
|
||||
```ts theme={null}
|
||||
const session = await client.openPerpsSession();
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Choose a Market">
|
||||
Fetch the available Perps instruments and choose the market you want to trade.
|
||||
|
||||
```ts theme={null}
|
||||
const instruments = await client.fetchPerpsInstruments();
|
||||
const instrument = instruments.find(
|
||||
(instrument) => instrument.symbol === "SP500-USD",
|
||||
);
|
||||
|
||||
if (instrument === undefined) {
|
||||
throw new Error("Instrument not found.");
|
||||
}
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Place the Order">
|
||||
Place a long buy order for `1` quantity unit of `SP500-USD` with an explicit
|
||||
limit price of `100` USD per quantity unit and immediate-or-cancel execution.
|
||||
|
||||
```ts theme={null}
|
||||
import { OrderSide, PerpsTimeInForce } from "@polymarket/client";
|
||||
|
||||
const order = await session.placeOrder({
|
||||
instrumentId: instrument.id,
|
||||
side: OrderSide.BUY,
|
||||
quantity: "1",
|
||||
price: "100",
|
||||
timeInForce: PerpsTimeInForce.IOC,
|
||||
});
|
||||
|
||||
// order.id: PerpsOrderId
|
||||
```
|
||||
|
||||
The returned order includes the accepted order state. See
|
||||
[Trading](/perps/trading) for direction, order behavior, cancellation, and state
|
||||
reconciliation.
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
<Steps>
|
||||
<Step title="Install the SDK">
|
||||
Install the Unified Python SDK with the package manager of your choice.
|
||||
|
||||
<CodeGroup>
|
||||
```bash uv theme={null}
|
||||
uv add polymarket-client
|
||||
```
|
||||
|
||||
```bash pip theme={null}
|
||||
pip install polymarket-client
|
||||
```
|
||||
|
||||
```bash poetry theme={null}
|
||||
poetry add polymarket-client
|
||||
```
|
||||
</CodeGroup>
|
||||
</Step>
|
||||
|
||||
<Step title="Create a Secure Client">
|
||||
Create an `AsyncSecureClient` with the wallet and signer that owns the Perps
|
||||
account. Include a Relayer API key so the SDK can submit gasless transactions.
|
||||
|
||||
```python theme={null}
|
||||
import os
|
||||
|
||||
from polymarket import AsyncSecureClient, RelayerApiKey
|
||||
|
||||
client = await AsyncSecureClient.create(
|
||||
private_key=os.environ["PRIVATE_KEY"],
|
||||
wallet=os.environ["POLYMARKET_WALLET_ADDRESS"],
|
||||
api_key=RelayerApiKey(
|
||||
key=os.environ["RELAYER_API_KEY"],
|
||||
address=os.environ["RELAYER_API_KEY_ADDRESS"],
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
Create a [Relayer API key](https://polymarket.com/settings?tab=api-keys) from
|
||||
polymarket.com → Settings → API Keys.
|
||||
</Step>
|
||||
|
||||
<Step title="Fund the Account">
|
||||
Set up the approvals required for Perps collateral deposits, then deposit pUSD
|
||||
from the user's Polymarket wallet into the Perps account. The minimum Perps
|
||||
deposit is 10 pUSD. Amounts use raw pUSD base units, so 10 pUSD is `10_000_000`.
|
||||
|
||||
```python theme={null}
|
||||
await client.setup_trading_approvals()
|
||||
|
||||
deposit = await client.deposit_to_perps(amount=10_000_000)
|
||||
|
||||
await deposit.wait()
|
||||
```
|
||||
|
||||
`deposit.wait()` confirms that the chain transaction settled. Perps may take a
|
||||
moment to credit the account after that. See [Fund Your
|
||||
Account](/perps/fund-your-account) for the full funding workflow.
|
||||
</Step>
|
||||
|
||||
<Step title="Open a Perps Session">
|
||||
Open a Perps session for private reads and trading.
|
||||
|
||||
```python theme={null}
|
||||
session = await client.open_perps_session()
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Choose a Market">
|
||||
Fetch the available Perps instruments and choose the market you want to trade.
|
||||
|
||||
```python theme={null}
|
||||
instruments = await client.fetch_perps_instruments()
|
||||
instrument = next(
|
||||
(item for item in instruments if item.symbol == "SP500-USD"),
|
||||
None,
|
||||
)
|
||||
|
||||
if instrument is None:
|
||||
raise RuntimeError("Instrument not found.")
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Place the Order">
|
||||
Place a long buy order for `1` quantity unit of `SP500-USD` with an explicit
|
||||
limit price of `100` USD per quantity unit and immediate-or-cancel execution.
|
||||
|
||||
```python theme={null}
|
||||
result = await session.place_order(
|
||||
instrument_id=instrument.id,
|
||||
side="BUY",
|
||||
quantity="1",
|
||||
price="100",
|
||||
time_in_force="ioc",
|
||||
)
|
||||
|
||||
# result.order.id: PerpsOrderId
|
||||
```
|
||||
|
||||
The returned order includes the accepted order state. See
|
||||
[Trading](/perps/trading) for direction, order behavior, cancellation, and state
|
||||
reconciliation.
|
||||
</Step>
|
||||
</Steps>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@@ -0,0 +1,86 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Rate Limits
|
||||
|
||||
> IP rate limits, action rate limits, and WebSocket limits for Perps integrations
|
||||
|
||||
Perps uses separate rate-limit buckets for different traffic types. Hitting one
|
||||
bucket does not consume another bucket, so request volume, account trading
|
||||
actions, and WebSocket traffic should be monitored separately.
|
||||
|
||||
## How Limits Work
|
||||
|
||||
Use the error type to identify which bucket rejected the request or message.
|
||||
|
||||
| Bucket | Scope | Applies To | Error |
|
||||
| ---------------------- | -------------- | ---------------------------------- | --------------------------------------------------------------------- |
|
||||
| IP | IP address | HTTP request volume | HTTP `429` or `ip_rate_limited` |
|
||||
| Action | Perps account | Order placement and trade actions | `action_rate_limited` |
|
||||
| WebSocket message | IP address | Inbound WebSocket messages | `message_rate_limited` |
|
||||
| WebSocket subscription | WebSocket link | Active subscriptions on one socket | Per-channel subscription error when the subscription cap is exhausted |
|
||||
|
||||
## IP Rate Limits
|
||||
|
||||
Every IP address gets **1,000 weighted tokens per minute**. Each HTTP request
|
||||
consumes tokens equal to its request weight.
|
||||
|
||||
Use scoped requests when possible. Broad, unfiltered reads consume more of the IP
|
||||
budget than narrow reads.
|
||||
|
||||
| Request Pattern | Weight |
|
||||
| ------------------------------ | --------------------------------------------- |
|
||||
| Lightweight reads | 1 |
|
||||
| Broad unfiltered reads | Up to 20 |
|
||||
| Order book depth 10 | 2 |
|
||||
| Order book depth 100 | 5 |
|
||||
| Order book depth 500 | 10 |
|
||||
| Order book depth 1000 | 20 |
|
||||
| Batch order actions | `1 + floor(n / 20)`, where `n` is order count |
|
||||
| Account orders by ID | 1 |
|
||||
| Account orders without ID | 10 |
|
||||
| Open orders by instrument | 1 |
|
||||
| Open orders without instrument | 20 |
|
||||
|
||||
## Action Rate Limits
|
||||
|
||||
Every account has an action budget from its current limit tier. The default tier
|
||||
is **5,000 action tokens per minute** with an open-order cap of **1,000**.
|
||||
|
||||
Action limits are account-scoped, not IP-scoped. Batching can reduce IP weight,
|
||||
but it does not reduce the number of order actions consumed.
|
||||
|
||||
| Action | Action Cost |
|
||||
| ------------------- | --------------------------- |
|
||||
| Place one order | 1 token |
|
||||
| Place 10 orders | 10 tokens |
|
||||
| Auto-cancel request | 10 tokens |
|
||||
| Open-order count | Limited by account tier cap |
|
||||
|
||||
Legacy request-rate fields on limit-tier responses are not used for request-rate
|
||||
enforcement. Use the IP bucket for request volume and the action bucket for
|
||||
account trading activity.
|
||||
|
||||
## WebSocket Limits
|
||||
|
||||
WebSocket connections have separate limits for connection count, active
|
||||
subscriptions, and inbound messages.
|
||||
|
||||
| Limit | Scope | Value |
|
||||
| ---------------------- | ---------- | ---------------------------------- |
|
||||
| Concurrent connections | IP address | 50 WebSocket connections |
|
||||
| Active subscriptions | Connection | 100 active subscriptions |
|
||||
| Inbound messages | IP address | 1,000 messages per minute |
|
||||
| Subscribe message | Message | 1 message token |
|
||||
| Unsubscribe message | Message | 1 message token |
|
||||
| Trade post message | Message | Same batch-size weighting as trade |
|
||||
| Other post messages | Message | 1 message token |
|
||||
|
||||
## Integration Guidance
|
||||
|
||||
* Scope reads whenever possible. For example, request one instrument's open orders instead of all open orders.
|
||||
* Batch order placement when it reduces request volume, but do not expect batching to reduce action-token usage.
|
||||
* Treat `429`, `ip_rate_limited`, `action_rate_limited`, and `message_rate_limited` as retryable after backoff.
|
||||
* Track active WebSocket subscriptions per connection so reconnects do not accidentally exceed the subscription cap.
|
||||
* If you operate many users behind shared infrastructure, monitor IP usage separately from account action usage.
|
||||
@@ -0,0 +1,987 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Realtime Updates
|
||||
|
||||
> Stream public Perps market data
|
||||
|
||||
Stream public market data as prices, books, trades, candles, tickers, and market
|
||||
statistics change.
|
||||
|
||||
<Note>
|
||||
Private order, fill, and account-state reconciliation is covered in [Reconcile
|
||||
Trade State](/perps/trading#reconcile-trade-state).
|
||||
</Note>
|
||||
|
||||
Start with the stream that matches the view you are building. Subscribe to the
|
||||
updates you need, read events while the view is active, then stop the stream when
|
||||
the view no longer needs live data.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
Subscribe from a `PublicClient` and iterate over the merged event stream.
|
||||
|
||||
```ts theme={null}
|
||||
import { createPublicClient } from "@polymarket/client";
|
||||
|
||||
const client = createPublicClient();
|
||||
|
||||
const stream = await client.subscribe([
|
||||
{ topic: "perps.bbo", instrumentId: 1 },
|
||||
{ topic: "perps.trades", instrumentId: 1 },
|
||||
]);
|
||||
|
||||
for await (const event of stream) {
|
||||
switch (event.type) {
|
||||
case "bbo":
|
||||
// event: PerpsBboEvent
|
||||
break;
|
||||
case "trade":
|
||||
// event: PerpsTradeEvent
|
||||
break;
|
||||
}
|
||||
|
||||
if (shouldClose) {
|
||||
await stream.close();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The stream yields typed events for each subscription and can be closed when the
|
||||
live view no longer needs updates.
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
Subscribe from an `AsyncPublicClient` and iterate over the merged event stream.
|
||||
|
||||
```python theme={null}
|
||||
from polymarket import AsyncPublicClient
|
||||
from polymarket.streams import PerpsBboSpec, PerpsTradesSpec
|
||||
|
||||
client = AsyncPublicClient()
|
||||
|
||||
stream = await client.subscribe(
|
||||
[
|
||||
PerpsBboSpec(instrument_id=1),
|
||||
PerpsTradesSpec(instrument_id=1),
|
||||
]
|
||||
)
|
||||
|
||||
async for event in stream:
|
||||
if event.type == "bbo":
|
||||
# event: PerpsBboEvent
|
||||
pass
|
||||
elif event.type == "trade":
|
||||
# event: PerpsTradeEvent
|
||||
pass
|
||||
|
||||
if should_close:
|
||||
await stream.close()
|
||||
```
|
||||
|
||||
The stream yields typed events for each subscription and can be closed when the
|
||||
live view no longer needs updates.
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Connect to the Perps WebSocket production URL.
|
||||
|
||||
```text theme={null}
|
||||
wss://ws.perpetuals.polymarket.com/v1/ws
|
||||
```
|
||||
|
||||
The example below opens a JavaScript WebSocket client, subscribes to public
|
||||
market-data updates, then unsubscribes and closes the connection.
|
||||
|
||||
```ts theme={null}
|
||||
const ws = new WebSocket("wss://ws.perpetuals.polymarket.com/v1/ws");
|
||||
const channels = ["bbo::1", "trades::1", "klines::1::1m"];
|
||||
|
||||
ws.addEventListener("open", () => {
|
||||
ws.send(
|
||||
JSON.stringify({
|
||||
id: 1,
|
||||
req: "sub",
|
||||
chs: channels,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
ws.addEventListener("message", (event) => {
|
||||
const message = JSON.parse(event.data);
|
||||
// message: public market data frame
|
||||
});
|
||||
|
||||
function unsubscribeAndClose() {
|
||||
ws.send(
|
||||
JSON.stringify({
|
||||
id: 2,
|
||||
req: "unsub",
|
||||
chs: channels,
|
||||
}),
|
||||
);
|
||||
ws.close();
|
||||
}
|
||||
```
|
||||
|
||||
Use `req: "sub"` to subscribe and `req: "unsub"` with the same `chs` values to
|
||||
unsubscribe. Each request may include an `id` for request-response matching.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Best Bid and Offer
|
||||
|
||||
Use best bid and offer updates for top-of-book quotes.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
Subscribe to best bid and offer updates for one instrument.
|
||||
|
||||
```ts theme={null}
|
||||
const bbo = await client.subscribe([{ topic: "perps.bbo", instrumentId: 1 }]);
|
||||
|
||||
for await (const event of bbo) {
|
||||
// event: PerpsBboEvent
|
||||
}
|
||||
```
|
||||
|
||||
After subscribing, the stream yields `PerpsBboEvent` objects like this.
|
||||
|
||||
<CodeGroup>
|
||||
```ts Type theme={null}
|
||||
type PerpsBboEvent = {
|
||||
topic: "perps.bbo";
|
||||
type: "bbo";
|
||||
channel: string;
|
||||
timestamp: number;
|
||||
sequence: number;
|
||||
payload: {
|
||||
instrumentId: number;
|
||||
bidPrice: string;
|
||||
bidQuantity: string;
|
||||
askPrice: string;
|
||||
askQuantity: string;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"topic": "perps.bbo",
|
||||
"type": "bbo",
|
||||
"channel": "bbo::1",
|
||||
"timestamp": 1767225600000,
|
||||
"sequence": 1234567890,
|
||||
"payload": {
|
||||
"instrumentId": 1,
|
||||
"bidPrice": "99.50",
|
||||
"bidQuantity": "10.00",
|
||||
"askPrice": "100.50",
|
||||
"askQuantity": "10.00"
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
Subscribe to best bid and offer updates for one instrument.
|
||||
|
||||
```python theme={null}
|
||||
from polymarket.streams import PerpsBboSpec
|
||||
|
||||
bbo = await client.subscribe(PerpsBboSpec(instrument_id=1))
|
||||
|
||||
async for event in bbo:
|
||||
# event: PerpsBboEvent
|
||||
pass
|
||||
```
|
||||
|
||||
After subscribing, the stream yields `PerpsBboEvent` objects like this.
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"topic": "perps.bbo",
|
||||
"type": "bbo",
|
||||
"channel": "bbo::1",
|
||||
"timestamp": 1767225600000,
|
||||
"sequence": 1234567890,
|
||||
"payload": {
|
||||
"instrument_id": 1,
|
||||
"bid_price": "99.50",
|
||||
"bid_quantity": "10.00",
|
||||
"ask_price": "100.50",
|
||||
"ask_quantity": "10.00"
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Subscribe to best bid and offer updates for one instrument.
|
||||
|
||||
```json Subscribe theme={null}
|
||||
{
|
||||
"id": 1,
|
||||
"req": "sub",
|
||||
"chs": ["bbo::<instrument_id>"]
|
||||
}
|
||||
```
|
||||
|
||||
After subscribing, the stream emits BBO update frames like this.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"ch": "bbo::1",
|
||||
"ts": 1767225600000,
|
||||
"sq": 1234567890,
|
||||
"data": {
|
||||
"iid": 1,
|
||||
"bp": "99.50",
|
||||
"bq": "10.00",
|
||||
"ap": "100.50",
|
||||
"aq": "10.00"
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Order Book
|
||||
|
||||
Use order book updates for depth across bid and ask price levels.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
Subscribe to order book updates for one instrument.
|
||||
|
||||
```ts theme={null}
|
||||
const book = await client.subscribe([{ topic: "perps.book", instrumentId: 1 }]);
|
||||
|
||||
for await (const event of book) {
|
||||
// event: PerpsBookEvent
|
||||
}
|
||||
```
|
||||
|
||||
After subscribing, the stream yields `PerpsBookEvent` objects like this.
|
||||
|
||||
<CodeGroup>
|
||||
```ts Type theme={null}
|
||||
type PerpsBookEvent = {
|
||||
topic: "perps.book";
|
||||
type: "book";
|
||||
channel: string;
|
||||
timestamp: number;
|
||||
sequence: number;
|
||||
payload: {
|
||||
instrumentId: number;
|
||||
bids: Array<{ price: string; quantity: string }>;
|
||||
asks: Array<{ price: string; quantity: string }>;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"topic": "perps.book",
|
||||
"type": "book",
|
||||
"channel": "book::1",
|
||||
"timestamp": 1767225600000,
|
||||
"sequence": 1234567890,
|
||||
"payload": {
|
||||
"instrumentId": 1,
|
||||
"bids": [{ "price": "100.00", "quantity": "10.00" }],
|
||||
"asks": [{ "price": "101.00", "quantity": "8.00" }]
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
Subscribe to order book updates for one instrument.
|
||||
|
||||
```python theme={null}
|
||||
from polymarket.streams import PerpsBookSpec
|
||||
|
||||
book = await client.subscribe(PerpsBookSpec(instrument_id=1))
|
||||
|
||||
async for event in book:
|
||||
# event: PerpsBookEvent
|
||||
pass
|
||||
```
|
||||
|
||||
After subscribing, the stream yields `PerpsBookEvent` objects like this.
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"topic": "perps.book",
|
||||
"type": "book",
|
||||
"channel": "book::1",
|
||||
"timestamp": 1767225600000,
|
||||
"sequence": 1234567890,
|
||||
"payload": {
|
||||
"instrument_id": 1,
|
||||
"bids": [{ "price": "100.00", "quantity": "10.00" }],
|
||||
"asks": [{ "price": "101.00", "quantity": "8.00" }]
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Subscribe to order book updates for one instrument.
|
||||
|
||||
```json Subscribe theme={null}
|
||||
{
|
||||
"id": 2,
|
||||
"req": "sub",
|
||||
"chs": ["book::<instrument_id>"]
|
||||
}
|
||||
```
|
||||
|
||||
After subscribing, the stream emits book update frames like this.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"ch": "book::1",
|
||||
"ts": 1767225600000,
|
||||
"sq": 1234567890,
|
||||
"data": {
|
||||
"b": [["100.00", "10.00"]],
|
||||
"a": [["101.00", "8.00"]]
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Trades
|
||||
|
||||
Use trades to update recent-print lists, last-trade displays, or execution-based
|
||||
analytics.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
Subscribe to public trade updates for one instrument.
|
||||
|
||||
```ts theme={null}
|
||||
const trades = await client.subscribe([
|
||||
{ topic: "perps.trades", instrumentId: 1 },
|
||||
]);
|
||||
|
||||
for await (const event of trades) {
|
||||
// event: PerpsTradeEvent
|
||||
}
|
||||
```
|
||||
|
||||
After subscribing, the stream yields `PerpsTradeEvent` objects like this.
|
||||
|
||||
<CodeGroup>
|
||||
```ts Type theme={null}
|
||||
type PerpsTradeEvent = {
|
||||
topic: "perps.trades";
|
||||
type: "trade";
|
||||
channel: string;
|
||||
timestamp: number;
|
||||
sequence: number;
|
||||
payload: {
|
||||
tradeId: number;
|
||||
instrumentId: number;
|
||||
side: "long" | "short";
|
||||
price: string;
|
||||
quantity: string;
|
||||
timestamp: number;
|
||||
hash?: string;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"topic": "perps.trades",
|
||||
"type": "trade",
|
||||
"channel": "trades::1",
|
||||
"timestamp": 1767225600000,
|
||||
"sequence": 1234567890,
|
||||
"payload": {
|
||||
"tradeId": 1,
|
||||
"instrumentId": 1,
|
||||
"side": "long",
|
||||
"price": "100.00",
|
||||
"quantity": "10.00",
|
||||
"timestamp": 1767225600000,
|
||||
"hash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
Subscribe to public trade updates for one instrument.
|
||||
|
||||
```python theme={null}
|
||||
from polymarket.streams import PerpsTradesSpec
|
||||
|
||||
trades = await client.subscribe(PerpsTradesSpec(instrument_id=1))
|
||||
|
||||
async for event in trades:
|
||||
# event: PerpsTradeEvent
|
||||
pass
|
||||
```
|
||||
|
||||
After subscribing, the stream yields `PerpsTradeEvent` objects like this.
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"topic": "perps.trades",
|
||||
"type": "trade",
|
||||
"channel": "trades::1",
|
||||
"timestamp": 1767225600000,
|
||||
"sequence": 1234567890,
|
||||
"payload": {
|
||||
"trade_id": 1,
|
||||
"instrument_id": 1,
|
||||
"side": "long",
|
||||
"price": "100.00",
|
||||
"quantity": "10.00",
|
||||
"timestamp": 1767225600000,
|
||||
"hash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Subscribe to public trade updates for one instrument.
|
||||
|
||||
```json Subscribe theme={null}
|
||||
{
|
||||
"id": 3,
|
||||
"req": "sub",
|
||||
"chs": ["trades::<instrument_id>"]
|
||||
}
|
||||
```
|
||||
|
||||
After subscribing, the stream emits trade update frames like this.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"ch": "trades::1",
|
||||
"ts": 1767225600000,
|
||||
"sq": 1234567890,
|
||||
"data": {
|
||||
"tid": 1,
|
||||
"iid": 1,
|
||||
"side": "long",
|
||||
"p": "100.00",
|
||||
"qty": "10.00",
|
||||
"ts": 1767225600000,
|
||||
"hash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Tickers
|
||||
|
||||
Use ticker updates for the current mark, index, last price, open interest, and
|
||||
funding state.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
Subscribe to ticker updates for one instrument or all active instruments.
|
||||
|
||||
<CodeGroup>
|
||||
```ts Subscribe to one market theme={null}
|
||||
const tickers = await client.subscribe([
|
||||
{ topic: "perps.tickers", instrumentId: 1 },
|
||||
]);
|
||||
```
|
||||
|
||||
```ts Subscribe to all markets theme={null}
|
||||
const tickers = await client.subscribe([{ topic: "perps.tickers" }]);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
```ts theme={null}
|
||||
for await (const event of tickers) {
|
||||
// event: PerpsTickerEvent
|
||||
}
|
||||
```
|
||||
|
||||
Omit `instrumentId` to subscribe to ticker updates for all active instruments.
|
||||
|
||||
After subscribing, the stream yields `PerpsTickerEvent` objects like this.
|
||||
|
||||
<CodeGroup>
|
||||
```ts Type theme={null}
|
||||
type PerpsTickerEvent = {
|
||||
topic: "perps.tickers";
|
||||
type: "ticker";
|
||||
channel: string;
|
||||
timestamp: number;
|
||||
sequence: number;
|
||||
payload: {
|
||||
instrumentId: number;
|
||||
indexPrice: string;
|
||||
markPrice: string;
|
||||
lastPrice: string;
|
||||
midPrice: string;
|
||||
openInterest: string;
|
||||
fundingRate: string;
|
||||
nextFunding: number;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"topic": "perps.tickers",
|
||||
"type": "ticker",
|
||||
"channel": "tickers::1",
|
||||
"timestamp": 1767225600000,
|
||||
"sequence": 1234567890,
|
||||
"payload": {
|
||||
"instrumentId": 1,
|
||||
"indexPrice": "100.00",
|
||||
"markPrice": "100.00",
|
||||
"lastPrice": "100.00",
|
||||
"midPrice": "100.00",
|
||||
"openInterest": "10.00",
|
||||
"fundingRate": "0.0001",
|
||||
"nextFunding": 1767225600000
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
Subscribe to ticker updates for one instrument or all active instruments.
|
||||
|
||||
<CodeGroup>
|
||||
```python Subscribe to one market theme={null}
|
||||
from polymarket.streams import PerpsTickersSpec
|
||||
|
||||
tickers = await client.subscribe(PerpsTickersSpec(instrument_id=1))
|
||||
```
|
||||
|
||||
```python Subscribe to all markets theme={null}
|
||||
from polymarket.streams import PerpsTickersSpec
|
||||
|
||||
tickers = await client.subscribe(PerpsTickersSpec())
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
```python theme={null}
|
||||
async for event in tickers:
|
||||
# event: PerpsTickerEvent
|
||||
pass
|
||||
```
|
||||
|
||||
Omit `instrument_id` to subscribe to ticker updates for all active instruments.
|
||||
|
||||
After subscribing, the stream yields `PerpsTickerEvent` objects like this.
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"topic": "perps.tickers",
|
||||
"type": "ticker",
|
||||
"channel": "tickers::1",
|
||||
"timestamp": 1767225600000,
|
||||
"sequence": 1234567890,
|
||||
"payload": {
|
||||
"instrument_id": 1,
|
||||
"index_price": "100.00",
|
||||
"mark_price": "100.00",
|
||||
"last_price": "100.00",
|
||||
"mid_price": "100.00",
|
||||
"open_interest": "10.00",
|
||||
"funding_rate": "0.0001",
|
||||
"next_funding": 1767225600000
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Subscribe to ticker updates for one instrument or all active instruments.
|
||||
|
||||
<CodeGroup>
|
||||
```json Subscribe to one market theme={null}
|
||||
{
|
||||
"id": 4,
|
||||
"req": "sub",
|
||||
"chs": ["tickers::<instrument_id>"]
|
||||
}
|
||||
```
|
||||
|
||||
```json Subscribe to all markets theme={null}
|
||||
{
|
||||
"id": 5,
|
||||
"req": "sub",
|
||||
"chs": ["tickers::all"]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
After subscribing, the stream emits ticker update frames like this.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"ch": "tickers::1",
|
||||
"ts": 1767225600000,
|
||||
"sq": 1234567890,
|
||||
"data": {
|
||||
"iid": 1,
|
||||
"idx": "100.00",
|
||||
"mark": "100.00",
|
||||
"last": "100.00",
|
||||
"mid": "100.00",
|
||||
"oi": "10.00",
|
||||
"fr": "0.0001",
|
||||
"nxf": 1767225600000
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Statistics
|
||||
|
||||
Use statistics for 24-hour volume, opening price, and the rolling kline window.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
Subscribe to 24-hour statistics for one instrument or all active instruments.
|
||||
|
||||
<CodeGroup>
|
||||
```ts Subscribe to one market theme={null}
|
||||
const statistics = await client.subscribe([
|
||||
{ topic: "perps.statistics", instrumentId: 1 },
|
||||
]);
|
||||
```
|
||||
|
||||
```ts Subscribe to all markets theme={null}
|
||||
const statistics = await client.subscribe([{ topic: "perps.statistics" }]);
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
```ts theme={null}
|
||||
for await (const event of statistics) {
|
||||
// event: PerpsStatisticEvent
|
||||
}
|
||||
```
|
||||
|
||||
Omit `instrumentId` to subscribe to statistics updates for all active instruments.
|
||||
|
||||
After subscribing, the stream yields `PerpsStatisticEvent` objects like this.
|
||||
|
||||
<CodeGroup>
|
||||
```ts Type theme={null}
|
||||
type PerpsStatisticEvent = {
|
||||
topic: "perps.statistics";
|
||||
type: "statistic";
|
||||
channel: string;
|
||||
timestamp: number;
|
||||
sequence: number;
|
||||
payload: {
|
||||
instrumentId: number;
|
||||
volume: string;
|
||||
openPrice: string;
|
||||
klines: Array<{
|
||||
timestamp: number;
|
||||
open: string;
|
||||
high: string;
|
||||
low: string;
|
||||
close: string;
|
||||
volume: string;
|
||||
trades: number;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"topic": "perps.statistics",
|
||||
"type": "statistic",
|
||||
"channel": "statistics::1",
|
||||
"timestamp": 1767225600000,
|
||||
"sequence": 1234567890,
|
||||
"payload": {
|
||||
"instrumentId": 1,
|
||||
"volume": "1000.00",
|
||||
"openPrice": "100.50",
|
||||
"klines": [
|
||||
{
|
||||
"timestamp": 1767225600000,
|
||||
"open": "100.00",
|
||||
"high": "105.00",
|
||||
"low": "99.00",
|
||||
"close": "102.00",
|
||||
"volume": "500.00",
|
||||
"trades": 42
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
Subscribe to 24-hour statistics for one instrument or all active instruments.
|
||||
|
||||
<CodeGroup>
|
||||
```python Subscribe to one market theme={null}
|
||||
from polymarket.streams import PerpsStatisticsSpec
|
||||
|
||||
statistics = await client.subscribe(PerpsStatisticsSpec(instrument_id=1))
|
||||
```
|
||||
|
||||
```python Subscribe to all markets theme={null}
|
||||
from polymarket.streams import PerpsStatisticsSpec
|
||||
|
||||
statistics = await client.subscribe(PerpsStatisticsSpec())
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
```python theme={null}
|
||||
async for event in statistics:
|
||||
# event: PerpsStatisticEvent
|
||||
pass
|
||||
```
|
||||
|
||||
Omit `instrument_id` to subscribe to statistics updates for all active
|
||||
instruments.
|
||||
|
||||
After subscribing, the stream yields `PerpsStatisticEvent` objects like this.
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"topic": "perps.statistics",
|
||||
"type": "statistic",
|
||||
"channel": "statistics::1",
|
||||
"timestamp": 1767225600000,
|
||||
"sequence": 1234567890,
|
||||
"payload": {
|
||||
"instrument_id": 1,
|
||||
"volume": "1000.00",
|
||||
"open_price": "100.50",
|
||||
"klines": [
|
||||
{
|
||||
"timestamp": 1767225600000,
|
||||
"open": "100.00",
|
||||
"high": "105.00",
|
||||
"low": "99.00",
|
||||
"close": "102.00",
|
||||
"volume": "500.00",
|
||||
"trades": 42
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Subscribe to 24-hour statistics for one instrument or all active instruments.
|
||||
|
||||
<CodeGroup>
|
||||
```json Subscribe to one market theme={null}
|
||||
{
|
||||
"id": 6,
|
||||
"req": "sub",
|
||||
"chs": ["statistics::<instrument_id>"]
|
||||
}
|
||||
```
|
||||
|
||||
```json Subscribe to all markets theme={null}
|
||||
{
|
||||
"id": 7,
|
||||
"req": "sub",
|
||||
"chs": ["statistics::all"]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
After subscribing, the stream emits statistics update frames like this.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"ch": "statistics::1",
|
||||
"ts": 1767225600000,
|
||||
"sq": 1234567890,
|
||||
"data": {
|
||||
"iid": 1,
|
||||
"vol": "1000.00",
|
||||
"open": "100.50",
|
||||
"klines": [
|
||||
[1767225600000, "100.00", "105.00", "99.00", "102.00", "500.00", 42]
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Candles
|
||||
|
||||
Use candles to update charts with live OHLCV data.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="TypeScript">
|
||||
Subscribe to candle updates for one instrument and interval.
|
||||
|
||||
```ts theme={null}
|
||||
import { PerpsKlineInterval } from "@polymarket/client";
|
||||
|
||||
const candles = await client.subscribe([
|
||||
{
|
||||
topic: "perps.candles",
|
||||
instrumentId: 1,
|
||||
interval: PerpsKlineInterval.OneMinute,
|
||||
},
|
||||
]);
|
||||
|
||||
for await (const event of candles) {
|
||||
// event: PerpsCandleEvent
|
||||
}
|
||||
```
|
||||
|
||||
The public stream supports `1m`, `5m`, `15m`, `1h`, `4h`, `1d`, and `1w`
|
||||
candle intervals.
|
||||
|
||||
After subscribing, the stream yields `PerpsCandleEvent` objects like this.
|
||||
|
||||
<CodeGroup>
|
||||
```ts Type theme={null}
|
||||
type PerpsCandleEvent = {
|
||||
topic: "perps.candles";
|
||||
type: "candle";
|
||||
channel: string;
|
||||
timestamp: number;
|
||||
sequence: number;
|
||||
payload: {
|
||||
instrumentId: number;
|
||||
interval: "1m" | "5m" | "15m" | "1h" | "4h" | "1d" | "1w";
|
||||
candles: Array<{
|
||||
timestamp: number;
|
||||
open: string;
|
||||
high: string;
|
||||
low: string;
|
||||
close: string;
|
||||
volume: string;
|
||||
trades: number;
|
||||
}>;
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"topic": "perps.candles",
|
||||
"type": "candle",
|
||||
"channel": "klines::1::1m",
|
||||
"timestamp": 1767225600000,
|
||||
"sequence": 1234567890,
|
||||
"payload": {
|
||||
"instrumentId": 1,
|
||||
"interval": "1m",
|
||||
"candles": [
|
||||
{
|
||||
"timestamp": 1767225600000,
|
||||
"open": "100.00",
|
||||
"high": "105.00",
|
||||
"low": "99.00",
|
||||
"close": "102.00",
|
||||
"volume": "500.00",
|
||||
"trades": 42
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Tab>
|
||||
|
||||
<Tab title="Python">
|
||||
Subscribe to candle updates for one instrument and interval.
|
||||
|
||||
```python theme={null}
|
||||
from polymarket.streams import PerpsCandlesSpec
|
||||
|
||||
candles = await client.subscribe(
|
||||
PerpsCandlesSpec(
|
||||
instrument_id=1,
|
||||
interval="1m",
|
||||
)
|
||||
)
|
||||
|
||||
async for event in candles:
|
||||
# event: PerpsCandleEvent
|
||||
pass
|
||||
```
|
||||
|
||||
The public stream supports `1m`, `5m`, `15m`, `1h`, `4h`, `1d`, and `1w`
|
||||
candle intervals.
|
||||
|
||||
After subscribing, the stream yields `PerpsCandleEvent` objects like this.
|
||||
|
||||
```json Example theme={null}
|
||||
{
|
||||
"topic": "perps.candles",
|
||||
"type": "candle",
|
||||
"channel": "klines::1::1m",
|
||||
"timestamp": 1767225600000,
|
||||
"sequence": 1234567890,
|
||||
"payload": {
|
||||
"instrument_id": 1,
|
||||
"interval": "1m",
|
||||
"candles": [
|
||||
{
|
||||
"timestamp": 1767225600000,
|
||||
"open": "100.00",
|
||||
"high": "105.00",
|
||||
"low": "99.00",
|
||||
"close": "102.00",
|
||||
"volume": "500.00",
|
||||
"trades": 42
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="API">
|
||||
Subscribe to candle updates for one instrument and interval.
|
||||
|
||||
```json Subscribe theme={null}
|
||||
{
|
||||
"id": 8,
|
||||
"req": "sub",
|
||||
"chs": ["klines::<instrument_id>::1m"]
|
||||
}
|
||||
```
|
||||
|
||||
The public stream supports `1m`, `5m`, `15m`, `30m`, `1h`, `4h`, `6h`, `12h`,
|
||||
`1d`, and `1w` candle intervals.
|
||||
|
||||
After subscribing, the stream emits kline update frames like this.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"ch": "klines::1::1m",
|
||||
"ts": 1767225600000,
|
||||
"sq": 1234567890,
|
||||
"data": [[1767225600000, "100.00", "105.00", "99.00", "102.00", "500.00", 42]]
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
@@ -0,0 +1,84 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Referral Program
|
||||
|
||||
> Earn a share of Perps trading fees from traders you refer
|
||||
|
||||
Refer traders to Polymarket Perps and earn a share of the trading fees they pay.
|
||||
Each account has one Perps referral code. Share your Perps link, and when a new
|
||||
trader opens Perps through it, your code is applied to their account
|
||||
automatically.
|
||||
|
||||
<Note>
|
||||
This is the first version of the Perps referral program. The mechanics,
|
||||
attribution rules, and program details are set for launch and may change as
|
||||
the program expands.
|
||||
</Note>
|
||||
|
||||
## How It Works
|
||||
|
||||
Every Perps account has one referral code. Your referral code and your Perps
|
||||
invite code are the same string, so the same link invites traders and credits you
|
||||
for the referral.
|
||||
|
||||
```text theme={null}
|
||||
https://polymarket.com/perps?c={code}
|
||||
```
|
||||
|
||||
When someone opens Perps through your link, your code is applied to their account
|
||||
automatically. You start earning on the trading fees they generate after they are
|
||||
attributed to your code.
|
||||
|
||||
A referral code can be applied only once. An account keeps the first code it is
|
||||
given and cannot switch to a different code later. You also cannot apply your own
|
||||
code.
|
||||
|
||||
## Rewards
|
||||
|
||||
You earn **20% of the trading fees** paid by every Perps trader you refer. There
|
||||
is no cap on how much a single referred trader can earn you.
|
||||
|
||||
| Detail | Perps referral program |
|
||||
| ------------- | --------------------------------------------------- |
|
||||
| Reward | 20% of trading fees paid by referred Perps traders |
|
||||
| Recipient | The referrer |
|
||||
| Trader bonus | No separate bonus is paid to the trader you invite |
|
||||
| Per-user cap | No cap on how much one referred trader can earn you |
|
||||
| Payout timing | Weekly |
|
||||
|
||||
## Code Limits
|
||||
|
||||
A standard Perps referral code can be used by up to **15 people**. After 15
|
||||
traders sign up through your code, anyone who opens your link sees a referral
|
||||
expired state.
|
||||
|
||||
If you are running a larger campaign and need more than 15 uses, reach out to the
|
||||
Polymarket team to discuss a higher limit.
|
||||
|
||||
## Payouts
|
||||
|
||||
Referral earnings are paid out weekly. You can see referral payouts in your
|
||||
Perpetuals portfolio history.
|
||||
|
||||
## Find and Track Your Code
|
||||
|
||||
Your referral code is available from your profile and on Perps market pages, so
|
||||
you can copy and share it while you trade.
|
||||
|
||||
The referrals dashboard shows how the program is performing for your account:
|
||||
|
||||
* Sign-ups against your code limit
|
||||
* Total trading volume from referred traders
|
||||
* Total referral earnings
|
||||
* Per-referral details, including the trader, sign-up time, and earnings
|
||||
|
||||
## Perps vs. Prediction Market Referrals
|
||||
|
||||
The Perps referral program is separate from the prediction market referral
|
||||
program. They use different codes and track earnings independently.
|
||||
|
||||
Referring a Perps trader does not affect your prediction market referrals, and a
|
||||
prediction market referral does not affect your Perps referrals. Each program
|
||||
shows up in its own place.
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user