create_order() and post_order() are the py_clob_client methods that place trades on Polymarket. Order placement is a two-step process: first sign the order locally with your wallet, then submit it to the CLOB API. This page covers limit orders with OrderArgs, market orders with MarketOrderArgs, order types (GTC/FOK/FAK), tick size validation, batch orders, and common errors.
For the complete py_clob_client method reference covering all methods, see the py_clob_client Reference. For Kalshi’s equivalent order placement, see the Prediction Market API Reference.
The Two-Step Order Flow
Every order on Polymarket follows this pattern:
- Sign locally —
create_order()orcreate_market_order()signs the order with your private key, producing aSignedOrder - Post to API —
post_order()submits the signed order to the CLOB for matching
# Step 1: Sign
signed = client.create_order(order_args)
# Step 2: Post
response = client.post_order(signed, OrderType.GTC)
This design means your private key never leaves your machine — the API only receives the cryptographic signature.
Limit Orders with OrderArgs
Signatures
client.create_order(order_args: OrderArgs) -> SignedOrder
client.post_order(signed_order: SignedOrder, order_type: OrderType, post_only: bool = False) -> dict
OrderArgs Fields
| Field | Type | Required | Description |
|---|---|---|---|
token_id | str | Yes | The outcome token ID (YES or NO token) |
price | float | Yes | Price per share in USDC (0.01 to 0.99) |
size | float | Yes | Number of shares to buy or sell |
side | str | Yes | BUY or SELL (import from py_clob_client.order_builder.constants) |
expiration | int | No | Unix timestamp for auto-cancellation. Omit for GTC |
post_order() Parameters
| Parameter | Type | Description |
|---|---|---|
signed_order | SignedOrder | The signed order from create_order() |
order_type | OrderType | GTC, FOK, or FAK (see Order Types) |
post_only | bool | If True, rejects if the order would immediately match |
Example — Place a Limit Buy
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import OrderArgs, OrderType
from py_clob_client.order_builder.constants import BUY
client = ClobClient(
"https://clob.polymarket.com",
key="<your-private-key>",
chain_id=137
)
client.set_api_creds(client.create_or_derive_api_creds())
order = OrderArgs(
token_id="<token-id>",
price=0.45,
size=20.0,
side=BUY
)
signed = client.create_order(order)
response = client.post_order(signed, OrderType.GTC)
print(f"Order ID: {response['orderID']}")
print(f"Status: {response.get('status', 'submitted')}")
Example — Place a Limit Sell
from py_clob_client.order_builder.constants import SELL
order = OrderArgs(
token_id="<token-id>",
price=0.65,
size=10.0,
side=SELL
)
signed = client.create_order(order)
response = client.post_order(signed, OrderType.GTC)
Example — Order with Expiration
import time
order = OrderArgs(
token_id="<token-id>",
price=0.40,
size=50.0,
side=BUY,
expiration=int(time.time()) + 3600 # Expires in 1 hour
)
signed = client.create_order(order)
response = client.post_order(signed, OrderType.GTC)
Market Orders with MarketOrderArgs
Market orders execute immediately against resting liquidity at the best available prices.
Signature
client.create_market_order(order_args: MarketOrderArgs) -> SignedOrder
MarketOrderArgs Fields
| Field | Type | Required | Description |
|---|---|---|---|
token_id | str | Yes | The outcome token ID |
amount | float | Yes | For BUY: USDC to spend. For SELL: number of shares to sell |
side | str | Yes | BUY or SELL |
order_type | OrderType | Yes | Must be OrderType.FOK (fill-or-kill) |
fee_rate_bps | int | No | Custom fee rate in basis points |
Example — Buy $25 at Market Price
from py_clob_client.clob_types import MarketOrderArgs, OrderType
from py_clob_client.order_builder.constants import BUY
market_order = MarketOrderArgs(
token_id="<token-id>",
amount=25.0,
side=BUY,
order_type=OrderType.FOK
)
signed = client.create_market_order(market_order)
response = client.post_order(signed, OrderType.FOK)
print(f"Order ID: {response['orderID']}")
Example — Sell 50 Shares at Market Price
from py_clob_client.order_builder.constants import SELL
sell_order = MarketOrderArgs(
token_id="<token-id>",
amount=50.0,
side=SELL,
order_type=OrderType.FOK
)
signed = client.create_market_order(sell_order)
response = client.post_order(signed, OrderType.FOK)
Key difference: OrderArgs uses price + size (price per share × number of shares). MarketOrderArgs uses amount (total USDC to spend for buys, or shares to sell for sells).
Order Types: GTC, FOK, FAK
| Type | Constant | Behavior | Use Case |
|---|---|---|---|
| GTC | OrderType.GTC | Rests on the order book until filled or canceled | Limit orders — you want a specific price |
| FOK | OrderType.FOK | Must fill entirely and immediately, or is rejected | Market orders — you want instant execution |
| FAK | OrderType.FAK | Fills what it can immediately, cancels the rest | Partial fills OK — you want whatever is available now |
from py_clob_client.clob_types import OrderType
# Limit order that rests on the book
client.post_order(signed, OrderType.GTC)
# Market order that fills immediately or fails
client.post_order(signed, OrderType.FOK)
# Aggressive limit order — fill what you can, cancel rest
client.post_order(signed, OrderType.FAK)
Post-Only Orders (Market Makers)
Post-only orders are rejected if they would immediately match against resting orders. This guarantees you’re always the maker (providing liquidity), never the taker.
order = OrderArgs(
token_id="<token-id>",
price=0.49,
size=100.0,
side=BUY
)
signed = client.create_order(order)
response = client.post_order(signed, OrderType.GTC, post_only=True)
# If the best ask is <= 0.49, this order is rejected
# Otherwise, it rests on the book at 0.49
Batch Orders
Place up to 15 orders in a single API call. Essential for market makers updating quotes on both sides.
Signature
client.post_orders(signed_orders: list[SignedOrder], order_type: OrderType) -> dict
Example — Ladder of Buy Orders
from py_clob_client.clob_types import OrderArgs, OrderType
from py_clob_client.order_builder.constants import BUY
orders = []
for price in [0.40, 0.42, 0.44, 0.46, 0.48]:
order = OrderArgs(
token_id="<token-id>",
price=price,
size=50.0,
side=BUY
)
orders.append(client.create_order(order))
response = client.post_orders(orders, OrderType.GTC)
print(f"Batch submitted: {len(orders)} orders")
Example — Two-Sided Quotes
from py_clob_client.order_builder.constants import BUY, SELL
signed_orders = []
# Buy side
for price in [0.48, 0.47, 0.46]:
order = OrderArgs(token_id="<token-id>", price=price, size=100.0, side=BUY)
signed_orders.append(client.create_order(order))
# Sell side
for price in [0.52, 0.53, 0.54]:
order = OrderArgs(token_id="<token-id>", price=price, size=100.0, side=SELL)
signed_orders.append(client.create_order(order))
response = client.post_orders(signed_orders, OrderType.GTC)
print(f"Posted {len(signed_orders)} orders (3 bids + 3 asks)")
Tick Size Validation
Every Polymarket market has a tick_size — the minimum price increment. Orders that don’t align to the tick size are rejected.
| Tick Size | Valid Prices | Example |
|---|---|---|
0.01 | 0.01, 0.02, …, 0.99 | Most markets |
0.001 | 0.001, 0.002, …, 0.999 | High-volume markets |
def align_price(price, tick_size=0.01):
"""Round a price to the nearest valid tick."""
return round(round(price / tick_size) * tick_size, 4)
# Example
raw_price = 0.4537
aligned = align_price(raw_price, tick_size=0.01)
print(f"{raw_price} → {aligned}") # 0.4537 → 0.45
aligned_fine = align_price(raw_price, tick_size=0.001)
print(f"{raw_price} → {aligned_fine}") # 0.4537 → 0.454
To get the tick size for a market, query the Gamma API:
import requests
slug = "bitcoin-above-100k"
resp = requests.get(f"https://gamma-api.polymarket.com/markets?slug={slug}")
market = resp.json()[0]
tick_size = float(market.get("minimum_tick_size", "0.01"))
Neg Risk Markets
Some Polymarket markets are flagged as neg_risk (negative risk). In these markets, holding complementary positions reduces your collateral requirement. Your agent should check this flag when calculating margin.
import requests
# Check if a market is neg_risk
resp = requests.get(f"https://gamma-api.polymarket.com/markets?slug={slug}")
market = resp.json()[0]
is_neg_risk = market.get("neg_risk", False)
if is_neg_risk:
print("Neg-risk market — complementary positions reduce margin")
When using the TypeScript SDK, neg_risk is passed in the options:
const order = await client.createAndPostOrder(
{ tokenID: "TOKEN_ID", price: 0.50, size: 10, side: Side.BUY },
{ tickSize: "0.01", negRisk: true } // Pass neg_risk flag
);
Complete Workflow: Buy, Monitor, Sell
A full trading cycle combining order placement with position and balance checks:
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import (
OrderArgs, MarketOrderArgs, OrderType,
BalanceAllowanceParams, AssetType
)
from py_clob_client.order_builder.constants import BUY, SELL
client = ClobClient(
"https://clob.polymarket.com",
key="<your-private-key>",
chain_id=137
)
client.set_api_creds(client.create_or_derive_api_creds())
token_id = "<token-id>"
# 1. Check balance
balance = client.get_balance_allowance(
BalanceAllowanceParams(asset_type=AssetType.COLLATERAL)
)
usdc = int(balance["balance"]) / 1e6
print(f"Available: ${usdc:.2f} USDC")
# 2. Check order book for pricing
book = client.get_order_book(token_id)
best_ask = float(book.asks[0]["price"]) if book.asks else None
print(f"Best ask: ${best_ask}")
# 3. Place a limit buy below the best ask
if best_ask and usdc > 0:
buy_price = round(best_ask - 0.02, 2) # 2 cents below ask
buy_size = min(100, usdc / buy_price)
order = OrderArgs(
token_id=token_id,
price=buy_price,
size=buy_size,
side=BUY
)
signed = client.create_order(order)
resp = client.post_order(signed, OrderType.GTC)
print(f"Buy order placed: {buy_size:.0f} shares @ ${buy_price}")
# 4. Check positions after fill
positions = client.get_positions()
for pos in positions:
if pos["asset"]["token_id"] == token_id:
size = float(pos["size"])
print(f"Position: {size:.2f} shares")
# 5. Place a sell order at target price
sell_price = 0.70
sell_order = OrderArgs(
token_id=token_id,
price=sell_price,
size=size,
side=SELL
)
signed = client.create_order(sell_order)
resp = client.post_order(signed, OrderType.GTC)
print(f"Sell order placed: {size:.0f} shares @ ${sell_price}")
Common Errors
| Error | Cause | Fix |
|---|---|---|
INSUFFICIENT_BALANCE | Not enough USDC for the order | Check balance with get_balance_allowance() first |
INVALID_TICK_SIZE | Price doesn’t match market’s tick size | Check and align to tick size (0.01 or 0.001) |
ORDER_ALREADY_EXISTS | Duplicate order submission | The SDK generates nonces — ensure you’re calling create_order() fresh each time |
MARKET_NOT_TRADABLE | Market is closed or resolved | Check market status via Gamma API before ordering |
INVALID_SIGNATURE | Auth signature mismatch | Regenerate credentials: client.set_api_creds(client.create_or_derive_api_creds()) |
| FOK order rejected | Not enough liquidity for full fill | Check order book depth or use FAK for partial fills |
UNAUTHORIZED | API credentials not set | Call set_api_creds() before any trading methods |
| Post-only rejected | Order would immediately match | Your price crosses the spread — adjust it |
CLI Equivalent
Place orders via the Polymarket CLI:
# Limit order
polymarket clob create-order \
--token TOKEN_ID \
--side buy \
--price 0.45 \
--size 20
# Market order
polymarket clob market-order \
--token TOKEN_ID \
--side buy \
--amount 25
# Cancel an order
polymarket clob cancel ORDER_ID
# Cancel all orders
polymarket clob cancel-all
See Also
- py_clob_client Complete Reference — Every method documented
- py_clob_client get_order_book() — Check liquidity before placing orders
- py_clob_client get_balance_allowance() — Verify funds before trading
- py_clob_client get_positions() — Track positions after fills
- Prediction Market API Reference — Polymarket vs Kalshi comparison
- Polymarket Rate Limits Guide — Handle 429 errors when placing orders
- Build a Polymarket Trading Bot — Full bot tutorial
- Agent Betting Glossary — Key terms defined
{{ partial “marketplace-cta.html” . }}
This reference is maintained by AgentBets.ai. Found an error or SDK change we missed? Let us know on Twitter.
Not financial advice. Built for builders.