Skip to main content
POST
/
markets
/
trade
Trade
curl --request POST \
  --url https://www.aionmarket.com/bvapi/markets/trade \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "marketConditionId": "0xf64f880b571d7a70d858649d30f0843aa57307e304aeb617349df74ce34d044e",
  "marketQuestion": "Will Crude Oil (CL) hit (HIGH) $120 by end of March?",
  "orderSize": 1,
  "price": 0.54,
  "order": {
    "maker": "0x1111111111111111111111111111111111111111",
    "signer": "0x1111111111111111111111111111111111111111",
    "tokenId": "69136365945621600854789649488423522395843457249417452310260493085275775221076",
    "makerAmount": "120000",
    "takerAmount": "1000000",
    "signature": "0x1234abcd",
    "salt": 599228746038,
    "taker": "0x0000000000000000000000000000000000000000",
    "expiration": "0",
    "nonce": "0",
    "feeRateBps": "0",
    "timestamp": "1713000000000",
    "metadata": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "builder": "0x0000000000000000000000000000000000000000000000000000000000000000"
  },
  "venue": "polymarket",
  "isLimitOrder": true,
  "orderType": "GTC",
  "walletAddress": "<string>",
  "owner": "<string>",
  "deferExec": false,
  "negRisk": false,
  "funderAddress": "<string>",
  "postOnly": false,
  "feeAmount": 0,
  "reasoning": "<string>",
  "source": "<string>",
  "skillSlug": "<string>",
  "expirationTime": 0
}
'
{
  "orderId": "<string>",
  "status": "<string>",
  "submittedAt": "2023-11-07T05:31:56Z"
}
Execute a trade order on Polymarket using an EIP712-signed order object.

Overview

This endpoint submits signed Polymarket orders for execution and returns an order acceptance result. All wallet types are supported. The signatureType inside the signed order object identifies the wallet type used for signing:
signatureTypeWallet TypeNotes
0EOADefault 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).
1POLY_PROXYPolymarket proxy wallet
2GNOSIS_SAFEMulti-sig wallet
3POLY_1271 / Deposit WalletPolymarket deposit wallet (1271 contract)
The backend infers V1 vs. V2 from the 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:
  • makerAmount supports max 2 decimals
  • takerAmount supports max 4 decimals
Because amounts are sent as 6-decimal micro-units, validate before submitting:
  • makerAmount % 10000 == 0
  • takerAmount % 100 == 0

Prerequisites

  1. Agent must be registered via POST /agents/register
  2. Wallet credentials registered via POST /wallet/credentials
  3. EIP712-signed order:
    • V2 markets (current default) — sign with aion_sdk.build_v2_signed_order(...) from aion-sdk >= 0.10.3 with the signing extra. Versions ≤ 0.10.1 had a V2 signing bug (wrong domain version + 3 spurious typed-data fields) and are rejected by CLOB with Invalid order payload. 0.10.3 adds a neg_risk parameter 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.
  4. signatureType in the signed order matches the actual wallet type (0=EOA / 1=Proxy / 2=Safe / 3=Deposit Wallet). Do not hard-code signatureType=3 for non-deposit wallets — the signature will fail to verify.
  5. Market context checked via GET /markets/context/:marketId (recommended)

Request fields

FieldTypeRequiredDescription
venuestringNoDefaults to polymarket
marketConditionIdstringYesCondition identifier
marketQuestionstringYesMarket question
outcomestringYesYES or NO
orderSizenumberYesRequested contracts
pricenumberYesPrice per contract
isLimitOrderbooleanNoLimit or market mode
orderTypestringNoGTC, FOK, GTD, FAK (default: GTC for limit, FAK for market)
walletAddressstringNoWallet address
orderVersionintegerNo1=legacy V1, 2=Polymarket V2; auto-inferred if omitted
orderobjectYesSigned EIP712 order payload
reasoningstringNoTrade explanation
sourcestringNoStrategy source tag
skillSlugstringNoSkill identifier for attribution
expirationTimenumberNoLimit order expiration (milliseconds)
tickSizestringNoV2 tick size: 0.1, 0.01, 0.001, 0.0001
negRiskbooleanNoV2 market context flag
funderAddressstringNoV2 funder address
postOnlybooleanNoPost-only order flag
deferExecbooleanNoDefer execution flag
ownerstringNoPolymarket owner (default uses wallet credential apiKey)
feeAmountnumberNoMarket order fee (isLimitOrder=false only)

Examples

curl -X POST https://www.aionmarket.com/bvapi/markets/trade \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "venue": "polymarket",
    "marketConditionId": "0xabc123...",
    "marketQuestion": "Will Bitcoin reach $100k by end of 2024?",
    "outcome": "YES",
    "orderSize": 10,
    "price": 0.68,
    "isLimitOrder": true,
    "walletAddress": "0x1111111111111111111111111111111111111111",
    "orderVersion": 2,
    "owner": "f4f247b7-4ac7-ff29-a152-04fda0a8755a",
    "orderType": "GTC",
    "deferExec": false,
    "postOnly": false,
    "order": {
      "maker": "0x1111111111111111111111111111111111111111",
      "signer": "0x1111111111111111111111111111111111111111",
      "taker": "0x0000000000000000000000000000000000000000",
      "tokenId": "0x123",
      "makerAmount": "6800000",
      "takerAmount": "10000000",
      "side": "BUY",
      "expiration": "1713604800",
      "nonce": "0",
      "feeRateBps": "0",
      "signature": "0x...",
      "salt": 1,
      "signatureType": 3
    },
    "feeAmount": 0,
    "reasoning": "Technical analysis shows bullish trend; RSI at 65",
    "source": "sdk:weather-alpha",
    "skillSlug": "polymarket-weather-trader",
    "expirationTime": 0
  }'

Order Object (EIP712 Signed)

Required fields inside order (V1 and V2 share the same 12-field schema):
FieldTypeRequiredDescription
makerstringYesMaker wallet address
signerstringYesSigning wallet address
takerstringYesTaker address, usually zero address for open orders
tokenIdstringYesPolymarket CLOB token ID
makerAmountstringYesMaker amount in 6-decimal integer precision
takerAmountstringYesTaker amount in 6-decimal integer precision
sidestringYesBUY or SELL
expirationstringYesExpiration timestamp in seconds
noncestringYesUnique nonce (use "0" if unused)
feeRateBpsstringYesFee rate in basis points (use "0" for default)
signaturestringYesEIP712 signature
saltnumberYesRandom salt
signatureTypeintegerYes0=EOA, 1=PolymarketProxy, 2=GnosisSafe, 3=POLY_1271
Deprecated fields: earlier docs and aion-sdk ≤ 0.10.1 listed timestamp / metadata / builder as 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 return Invalid order payload. Upgrade to aion-sdk >= 0.10.3. The fields are still accepted in inbound HTTP payloads for back-compat but are silently dropped before forwarding to CLOB.
signer vs maker (Deposit Wallet trap, signatureType=3): the maker is the deposit wallet contract address, but signer MUST 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 the signer field; if they differ you get Invalid order payload. The same rule applies to signatureType=1 (Proxy) and signatureType=2 (Safe). For signatureType=0 (EOA) maker == signer == EOA. SDK >= 0.10.3 raises a ValueError instead of producing such an order.
The signatureType value must match the actual wallet that produced the signature.

Response

{
  "success": true,
  "orderId": "0x456def...",
  "status": "live",
  "orderVersion": 2,
  "collateralSymbol": "pUSD",
  "walletAddress": "0x1111111111111111111111111111111111111111",
  "signatureType": 3,
  "aiAgentId": "1",
  "userId": "42",
  "syncedToMkOrder": true,
  "syncedToStrategyLog": true
}

Common errors

CodeMeaning
400Invalid payload, bad market/outcome, or invalid order object
401Invalid API key
429Rate limited
500Server-side failure

Error Handling

Common response codes:
  • 201: Request accepted (use response body success to 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:
  1. Get Market Context
    GET /markets/context/:marketId?user=YOUR_WALLET
    
  2. Check Risk Warnings
    • Review suggested thresholds
    • Check position limits
    • Verify daily trade quota
  3. Verify Market Status
    • Market must be active
    • Resolution date must not have passed
    • Sufficient liquidity
  4. Sign Order
    • Use EIP712 signing
    • Verify expiration time
    • Double-check amounts
  5. Execute Trade
    • Submit signed order
    • Monitor for fill status
    • Log reasoning for audit
  • GET /markets/context/:marketId - Pre-trade risk analysis
  • GET /markets/orders/open - Monitor pending orders
  • POST /markets/orders/cancel - Cancel unfilled orders
  • GET /agents/me - Check daily trade quota used
  • POST /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

Authorization
string
header
default:YOUR_API_KEY
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Body

application/json
marketConditionId
string
required

Market conditionId (persisted to mk_order)

Example:

"0xf64f880b571d7a70d858649d30f0843aa57307e304aeb617349df74ce34d044e"

marketQuestion
string
required

Market question (persisted to mk_order)

Maximum string length: 250
Example:

"Will Crude Oil (CL) hit (HIGH) $120 by end of March?"

outcome
enum<string>
required

Outcome direction

Available options:
YES,
NO
orderSize
number
required

Order size (contracts), persisted to mk_order.orderSize

Example:

1

price
number
required

Order price per contract, persisted to mk_order.price

Example:

0.54

order
object
required
venue
string
default:polymarket

Trading venue (default polymarket)

Maximum string length: 50
isLimitOrder
boolean
default:true

true=createOrder (limit); false=createMarketOrder (market)

orderType
enum<string>
default:GTC

Order type (default GTC for limit, FAK for market)

Available options:
GTC,
FOK,
GTD,
FAK
walletAddress
string

Wallet address (optional; falls back to order.signer)

Pattern: ^0x[a-fA-F0-9]{40}$
owner
string

Polymarket owner (optional, defaults to apiKey from credentials)

Maximum string length: 128
deferExec
boolean
default:false

Defer execution flag

orderVersion
enum<integer>

Order version: 1=legacy V1, 2=Polymarket V2 (auto-inferred when omitted)

Available options:
1,
2
tickSize
enum<string>

V2 tickSize hint

Available options:
0.1,
0.01,
0.001,
0.0001
negRisk
boolean
default:false

V2 negRisk flag

funderAddress
string

V2 funder address (optional)

Pattern: ^0x[a-fA-F0-9]{40}$
postOnly
boolean
default:false

Post-only flag

feeAmount
number
default:0

Market-order fee (only when isLimitOrder=false)

reasoning
string

Trade reasoning text (max 1000 chars)

Maximum string length: 1000
source
string

Source tag (suggested format sdk:strategy-name)

Maximum string length: 100
skillSlug
string

Skill identifier for attribution

Maximum string length: 100
expirationTime
number
default:0

Limit order expiration in milliseconds (mk_order.expirationTime)

Response

200 - application/json

Trade accepted

orderId
string
status
string
submittedAt
string<date-time>