Trade
Submit a new market order or limit order for execution.
Overview
This endpoint submits signed Polymarket orders for execution and returns an order acceptance result. All wallet types are supported. ThesignatureType inside the signed order object identifies the wallet type used for signing:
| signatureType | Wallet Type | Notes |
|---|---|---|
0 | EOA | Default for py-clob-client with a raw private key. Fully supported on V1 and V2 (sign V2 orders with aion_sdk.build_v2_signed_order). |
1 | POLY_PROXY | Polymarket proxy wallet |
2 | GNOSIS_SAFE | Multi-sig wallet |
3 | POLY_1271 / Deposit Wallet | Polymarket deposit wallet (1271 contract) |
verifyingContract used at signing time — V1 and V2 share the same 12-field EIP-712 Order struct. It does not require signatureType=3 to use V2.
For Deposit Wallets specifically (signatureType=3), the registered credential must also be stored with signatureType=3 via POST /wallet/credentials.
For immediate BUY orders (FAK / FOK), Polymarket enforces precision constraints:
makerAmountsupports max 2 decimalstakerAmountsupports max 4 decimals
makerAmount % 10000 == 0takerAmount % 100 == 0
Prerequisites
- Agent must be registered via
POST /agents/register - Wallet credentials registered via
POST /wallet/credentials - EIP712-signed order:
- V2 markets (current default) — sign with
aion_sdk.build_v2_signed_order(...)fromaion-sdk>= 0.10.3 with thesigningextra. Versions ≤ 0.10.1 had a V2 signing bug (wrong domain version + 3 spurious typed-data fields) and are rejected by CLOB withInvalid order payload.0.10.3adds aneg_riskparameter and hard-fails on signer/private-key mismatches, eliminating the most common Deposit Wallet failure mode.py-clob-client(≤ 0.34.6) signs the V1 verifying contract and is also rejected. - V1 markets (legacy) — either signer works;
py-clob-client.create_order(...)is fine.
- V2 markets (current default) — sign with
signatureTypein the signed order matches the actual wallet type (0=EOA /1=Proxy /2=Safe /3=Deposit Wallet). Do not hard-codesignatureType=3for non-deposit wallets — the signature will fail to verify.- Market context checked via
GET /markets/context/:marketId(recommended)
Request fields
| Field | Type | Required | Description |
|---|---|---|---|
venue | string | No | Defaults to polymarket |
marketConditionId | string | Yes | Condition identifier |
marketQuestion | string | Yes | Market question |
outcome | string | Yes | YES or NO |
orderSize | number | Yes | Requested contracts |
price | number | Yes | Price per contract |
isLimitOrder | boolean | No | Limit or market mode |
orderType | string | No | GTC, FOK, GTD, FAK (default: GTC for limit, FAK for market) |
walletAddress | string | No | Wallet address |
orderVersion | integer | No | 1=legacy V1, 2=Polymarket V2; auto-inferred if omitted |
order | object | Yes | Signed EIP712 order payload |
reasoning | string | No | Trade explanation |
source | string | No | Strategy source tag |
skillSlug | string | No | Skill identifier for attribution |
expirationTime | number | No | Limit order expiration (milliseconds) |
tickSize | string | No | V2 tick size: 0.1, 0.01, 0.001, 0.0001 |
negRisk | boolean | No | V2 market context flag |
funderAddress | string | No | V2 funder address |
postOnly | boolean | No | Post-only order flag |
deferExec | boolean | No | Defer execution flag |
owner | string | No | Polymarket owner (default uses wallet credential apiKey) |
feeAmount | number | No | Market order fee (isLimitOrder=false only) |
Examples
- curl
- Python SDK
Order Object (EIP712 Signed)
Required fields insideorder (V1 and V2 share the same 12-field schema):
| Field | Type | Required | Description |
|---|---|---|---|
| maker | string | Yes | Maker wallet address |
| signer | string | Yes | Signing wallet address |
| taker | string | Yes | Taker address, usually zero address for open orders |
| tokenId | string | Yes | Polymarket CLOB token ID |
| makerAmount | string | Yes | Maker amount in 6-decimal integer precision |
| takerAmount | string | Yes | Taker amount in 6-decimal integer precision |
| side | string | Yes | BUY or SELL |
| expiration | string | Yes | Expiration timestamp in seconds |
| nonce | string | Yes | Unique nonce (use "0" if unused) |
| feeRateBps | string | Yes | Fee rate in basis points (use "0" for default) |
| signature | string | Yes | EIP712 signature |
| salt | number | Yes | Random salt |
| signatureType | integer | Yes | 0=EOA, 1=PolymarketProxy, 2=GnosisSafe, 3=POLY_1271 |
Deprecated fields: earlier docs andaion-sdk ≤ 0.10.1listedtimestamp/metadata/builderas V2-only fields. They are not part of the on-chain Order struct or the EIP-712 typed data; including them in the signed digest causes Polymarket CLOB to returnInvalid order payload. Upgrade toaion-sdk >= 0.10.3. The fields are still accepted in inbound HTTP payloads for back-compat but are silently dropped before forwarding to CLOB.
Thesignervsmaker(Deposit Wallet trap,signatureType=3): themakeris the deposit wallet contract address, butsignerMUST be the EOA address that owns it — i.e.Account.from_key(private_key).address. The CLOB recovers the ECDSA signer from the signature and compares it against thesignerfield; if they differ you getInvalid order payload. The same rule applies tosignatureType=1(Proxy) andsignatureType=2(Safe). ForsignatureType=0(EOA)maker == signer == EOA. SDK >= 0.10.3 raises aValueErrorinstead of producing such an order.
signatureType value must match the actual wallet that produced the signature.
Response
Common errors
| Code | Meaning |
|---|---|
400 | Invalid payload, bad market/outcome, or invalid order object |
401 | Invalid API key |
429 | Rate limited |
500 | Server-side failure |
Error Handling
Common response codes:- 201: Request accepted (use response body
successto determine downstream execution result) - 400: Invalid market/outcome or insufficient balance
- 401: Invalid API key or expired
- 429: Rate limited
- 500: Server error
Pre-Trade Checklist
Before placing trade orders:-
Get Market Context
-
Check Risk Warnings
- Review suggested thresholds
- Check position limits
- Verify daily trade quota
-
Verify Market Status
- Market must be active
- Resolution date must not have passed
- Sufficient liquidity
-
Sign Order
- Use EIP712 signing
- Verify expiration time
- Double-check amounts
-
Execute Trade
- Submit signed order
- Monitor for fill status
- Log reasoning for audit
Related Endpoints
GET /markets/context/:marketId- Pre-trade risk analysisGET /markets/orders/open- Monitor pending ordersPOST /markets/orders/cancel- Cancel unfilled ordersGET /agents/me- Check daily trade quota usedPOST /markets/redeem- Claim rewards on settled markets
Best Practices
- Size Appropriately: Start small and scale up
- Set Realistic Prices: High bid-ask spreads reduce match probability
- Monitor Fills: Check order status frequently
- Update Reasoning: Clear logic improves trust
- Cancel Stale Orders: Clean up old orders regularly
- Record Strategy: Track all trades for analysis
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
Market conditionId (persisted to mk_order)
"0xf64f880b571d7a70d858649d30f0843aa57307e304aeb617349df74ce34d044e"
Market question (persisted to mk_order)
250"Will Crude Oil (CL) hit (HIGH) $120 by end of March?"
Outcome direction
YES, NO Order size (contracts), persisted to mk_order.orderSize
1
Order price per contract, persisted to mk_order.price
0.54
Trading venue (default polymarket)
50true=createOrder (limit); false=createMarketOrder (market)
Order type (default GTC for limit, FAK for market)
GTC, FOK, GTD, FAK Wallet address (optional; falls back to order.signer)
^0x[a-fA-F0-9]{40}$Polymarket owner (optional, defaults to apiKey from credentials)
128Defer execution flag
Order version: 1=legacy V1, 2=Polymarket V2 (auto-inferred when omitted)
1, 2 V2 tickSize hint
0.1, 0.01, 0.001, 0.0001 V2 negRisk flag
V2 funder address (optional)
^0x[a-fA-F0-9]{40}$Post-only flag
Market-order fee (only when isLimitOrder=false)
Trade reasoning text (max 1000 chars)
1000Source tag (suggested format sdk:strategy-name)
100Skill identifier for attribution
100Limit order expiration in milliseconds (mk_order.expirationTime)