Orders
Place bets, manage limit orders, and query order history
Place a Bet
POST /api/ext/v1/ordersScope: orders:write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
market_id | string | Yes | Market UUID |
outcome | string | Yes (BUY FOK) | "a" or "b" (first or second outcome) |
amount | number | Yes (BUY) | Bet amount in USDC |
side | string | No | "BUY" (default) or "SELL" |
shares | number | Yes (SELL) | Number of shares to sell |
order_type | string | No | "FOK" (default), "GTC", or "GTD" |
limit_price | number | No | Limit price 0.01–0.99 (required for GTC/GTD) |
token_option | string | No | "yes" or "no" (required for limit orders) |
expiration | integer | No | GTD expiry (Unix seconds) |
take_profit_price | number | No | Auto take-profit price 0.01–0.99 |
stop_loss_price | number | No | Auto stop-loss price 0.01–0.99 |
Order Types
| Type | Description |
|---|---|
| FOK (Fill or Kill) | Market order — fills immediately at best price or cancels entirely |
| GTC (Good Till Cancel) | Limit order — stays on orderbook until filled or manually cancelled |
| GTD (Good Till Date) | Limit order — stays until filled, cancelled, or expiration date |
Example: Market Order (FOK)
{
"market_id": "550e8400-e29b-41d4-a716-446655440000",
"outcome": "a",
"amount": 50
}Example: Limit Order (GTC)
For limit orders, use token_option ("yes" or "no") instead of outcome:
{
"market_id": "550e8400-e29b-41d4-a716-446655440000",
"amount": 100,
"order_type": "GTC",
"limit_price": 0.45,
"token_option": "yes"
}cURL Example — Market Order
API_KEY="po_live_your_api_key"
API_SECRET="your_api_secret"
TIMESTAMP=$(date +%s%3N)
NONCE=$(openssl rand -hex 16)
PATH="/api/ext/v1/orders"
BODY='{"market_id":"550e8400-e29b-41d4-a716-446655440000","outcome":"a","amount":50}'
BODY_HASH=$(echo -n "$BODY" | openssl dgst -sha256 -hex | awk '{print $NF}')
SIGNING_STRING="POST\n${PATH}\n${TIMESTAMP}\n${NONCE}\n${BODY_HASH}"
SIGNATURE=$(echo -ne "$SIGNING_STRING" | openssl dgst -sha256 -hmac "$API_SECRET" -hex | awk '{print $NF}')
curl -s -X POST "https://api.winnova.pro${PATH}" \
-H "Content-Type: application/json" \
-H "X-API-KEY: $API_KEY" \
-H "X-API-TIMESTAMP: $TIMESTAMP" \
-H "X-API-SIGNATURE: $SIGNATURE" \
-H "X-API-NONCE: $NONCE" \
-d "$BODY"Response
HTTP Status: 201 Created
{
"success": true,
"data": {
"order_id": "ord-550e8400-e29b-41d4-a716-446655440001",
"notification_id": "notif-9f8e7d6c"
}
}Error Responses
Status 400 — invalid request body or parameters:
{
"success": false,
"error": "invalid request body"
}Status 400 — insufficient balance:
{
"success": false,
"error": "insufficient balance"
}Status 403 — scope not granted:
{
"success": false,
"error": "forbidden: missing scope orders:write"
}Cancel a Limit Order
DELETE /api/ext/v1/orders/:idScope: orders:write
Cancels an active limit order (status: live). FOK orders cannot be cancelled.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | UUID | Order ID |
cURL Example
ORDER_ID="ord-550e8400-e29b-41d4-a716-446655440001"
API_KEY="po_live_your_api_key"
API_SECRET="your_api_secret"
TIMESTAMP=$(date +%s%3N)
NONCE=$(openssl rand -hex 16)
PATH="/api/ext/v1/orders/${ORDER_ID}"
BODY_HASH=$(echo -n "" | openssl dgst -sha256 -hex | awk '{print $NF}')
SIGNING_STRING="DELETE\n${PATH}\n${TIMESTAMP}\n${NONCE}\n${BODY_HASH}"
SIGNATURE=$(echo -ne "$SIGNING_STRING" | openssl dgst -sha256 -hmac "$API_SECRET" -hex | awk '{print $NF}')
curl -s -X DELETE "https://api.winnova.pro${PATH}" \
-H "X-API-KEY: $API_KEY" \
-H "X-API-TIMESTAMP: $TIMESTAMP" \
-H "X-API-SIGNATURE: $SIGNATURE" \
-H "X-API-NONCE: $NONCE"Response
{
"success": true,
"data": {
"order_id": "ord-550e8400-e29b-41d4-a716-446655440001",
"status": "cancelled"
}
}Error Response
{
"success": false,
"error": "order not found"
}Status 404 — order does not exist or does not belong to you.
List Orders
GET /api/ext/v1/ordersScope: orders:read
Query Parameters
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by order status: pending, signing, submitted, live, matched |
page | integer | Page number (default: 1) |
page_size | integer | Items per page (default: 20, max: 100) |
cURL Example
API_KEY="po_live_your_api_key"
API_SECRET="your_api_secret"
TIMESTAMP=$(date +%s%3N)
NONCE=$(openssl rand -hex 16)
PATH="/api/ext/v1/orders?status=matched&page=1&page_size=20"
BODY_HASH=$(echo -n "" | openssl dgst -sha256 -hex | awk '{print $NF}')
SIGNING_STRING="GET\n${PATH}\n${TIMESTAMP}\n${NONCE}\n${BODY_HASH}"
SIGNATURE=$(echo -ne "$SIGNING_STRING" | openssl dgst -sha256 -hmac "$API_SECRET" -hex | awk '{print $NF}')
curl -s "https://api.winnova.pro${PATH}" \
-H "X-API-KEY: $API_KEY" \
-H "X-API-TIMESTAMP: $TIMESTAMP" \
-H "X-API-SIGNATURE: $SIGNATURE" \
-H "X-API-NONCE: $NONCE"Response
{
"success": true,
"data": {
"orders": [
{
"id": "2c87c1ba-adde-41c8-ae3e-9fa90e922530",
"user_id": "d9f8fb6e-5144-4377-b12a-3a56feb63a7c",
"market_id": "550e8400-e29b-41d4-a716-446655440000",
"outcome": "a",
"amount": 50.00,
"making_amount": 49.999,
"taking_amount": 70.422,
"odds": 0.71,
"potential_profit": 20.42,
"status": "matched",
"side": "BUY",
"order_type": "FOK",
"order_source": "manual",
"order_source_id": null,
"clob_order_id": "0x452134a9...",
"original_size": 50.001,
"size_matched": 70.422,
"clob_price": 0.71,
"tx_hashes": [
"0xc4aa72de..."
],
"settlement_status": "won",
"settlement_amount": 20.42,
"settled_at": "2026-04-04T12:00:00Z",
"submitted_at": "2026-04-04T10:00:00Z",
"matched_at": "2026-04-04T10:00:01Z",
"created_at": "2026-04-04T10:00:00Z",
"updated_at": "2026-04-04T12:00:00Z"
}
],
"total_count": 204,
"page": 1,
"page_size": 20
}
}Error Response
{
"success": false,
"error": "unauthorized"
}Get Order Detail
GET /api/ext/v1/orders/:idScope: orders:read
Returns full order details including status, fill amount, and associated market data.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
id | UUID | Order ID |
cURL Example
ORDER_ID="ord-550e8400-e29b-41d4-a716-446655440001"
API_KEY="po_live_your_api_key"
API_SECRET="your_api_secret"
TIMESTAMP=$(date +%s%3N)
NONCE=$(openssl rand -hex 16)
PATH="/api/ext/v1/orders/${ORDER_ID}"
BODY_HASH=$(echo -n "" | openssl dgst -sha256 -hex | awk '{print $NF}')
SIGNING_STRING="GET\n${PATH}\n${TIMESTAMP}\n${NONCE}\n${BODY_HASH}"
SIGNATURE=$(echo -ne "$SIGNING_STRING" | openssl dgst -sha256 -hmac "$API_SECRET" -hex | awk '{print $NF}')
curl -s "https://api.winnova.pro${PATH}" \
-H "X-API-KEY: $API_KEY" \
-H "X-API-TIMESTAMP: $TIMESTAMP" \
-H "X-API-SIGNATURE: $SIGNATURE" \
-H "X-API-NONCE: $NONCE"Response
{
"success": true,
"data": {
"order": {
"id": "2c87c1ba-adde-41c8-ae3e-9fa90e922530",
"user_id": "d9f8fb6e-5144-4377-b12a-3a56feb63a7c",
"market_id": "550e8400-e29b-41d4-a716-446655440000",
"outcome": "a",
"amount": 50.00,
"making_amount": 49.999,
"taking_amount": 70.422,
"odds": 0.71,
"potential_profit": 20.42,
"status": "matched",
"side": "BUY",
"order_type": "FOK",
"order_source": "manual",
"order_source_id": null,
"clob_order_id": "0x452134a9...",
"original_size": 50.001,
"size_matched": 70.422,
"clob_price": 0.71,
"tx_hashes": [
"0xc4aa72de..."
],
"settlement_status": "won",
"settlement_amount": 20.42,
"settled_at": "2026-04-04T12:00:00Z",
"submitted_at": "2026-04-04T10:00:00Z",
"matched_at": "2026-04-04T10:00:01Z",
"created_at": "2026-04-04T10:00:00Z",
"updated_at": "2026-04-04T12:00:00Z"
}
}
}Error Responses
Status 404 — order not found or not owned by you:
{
"success": false,
"code": "ORDER_NOT_FOUND",
"error": "order not found"
}Get Wallet Info
GET /api/ext/v1/walletScope: orders:read
Returns the on-chain wallet addresses needed for raw CLOB order construction and clob_order_id pre-computation.
Response
{
"success": true,
"data": {
"maker": "0x6509FE08D1d17A0fdEb26fFe8A73b851622BbbFa",
"signer": "0x61BE2D6C64E7aDefF4307dE52B7533e83475716c",
"chain_id": 137,
"signature_type": 2,
"ctf_exchange": "0x4bFb41d5B3570DeFd03C39a9A4D8dE6Bd8B8982E",
"neg_risk_exchange": "0xC5d563A36AE78145C45a50134d48A1215220f80a"
}
}| Field | Description |
|---|---|
maker | Safe wallet address (EIP-712 maker field) |
signer | EOA address (EIP-712 signer field) |
chain_id | 137 (Polygon mainnet) |
signature_type | 2 (PolyGnosisSafe, fixed) |
ctf_exchange | Contract address for non-NegRisk markets |
neg_risk_exchange | Contract address for NegRisk markets |
These addresses are bound to the user account and do not change — safe to cache.
Place Raw CLOB Order
POST /api/ext/v1/orders/rawScope: orders:write
Bypasses server-side price × size calculation and passes CLOB parameters directly to Polymarket. Use this when you need full control over makerAmount/takerAmount or want to pre-compute clob_order_id before submission.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
market_id | string (UUID) | Yes | WinNova market ID |
outcome | string | Yes | "a" or "b" |
token_id | string | Yes | CLOB token ID from token_id_a or token_id_b |
maker_amount | string | Yes | Amount paid, uint256 string (6 decimals, e.g. "2000000" = 2 USDC) |
taker_amount | string | Yes | Amount received, uint256 string (6 decimals) |
side | integer | Yes | 0 = BUY, 1 = SELL |
fee_rate_bps | integer | Yes | Fee rate in basis points — must match CLOB market fee |
order_type | string | No | "FOK" (default), "GTC", "GTD" |
salt | string | No | Order salt [0, 10^12]; set a fixed value to pre-compute clob_order_id |
nonce | string | No | Default "0" |
expiration | string | No | Unix seconds, default "0" (never expires) |
client_order_id | string | No | Idempotency key, max 64 chars |
Price constraint: price = maker_amount / taker_amount must be between 0 and 1.
Getting fee_rate_bps: Query the Polymarket CLOB API before placing the order:
curl "https://clob.polymarket.com/fee-rate?token_id=<token_id>"
# Response: {"base_fee": 1000} → fee_rate_bps = 1000Response
HTTP Status: 201 Created
{
"success": true,
"data": {
"order_id": "5ef1b477-6eb2-46de-bd94-14e0431ddf60",
"notification_id": ""
}
}Error Codes
| Code | Cause |
|---|---|
ORDER_INVALID_SALT | Salt outside [0, 10^12] range |
ORDER_INVALID_MAKER_AMOUNT | maker_amount is not a valid non-negative integer string |
ORDER_INVALID_TAKER_AMOUNT | taker_amount is not a valid non-negative integer string |
Trading Limits
| Limit | Description |
|---|---|
| Single order max | 50,000 USDC per order (enforced by signer-service; orders exceeding this fail) |
| Risk controls | Per-order / daily / monthly / per-minute frequency limits; breach returns 500 (ORDER_FAILED_PLACE_BET) |
| Bonus exemption | Orders using bonus funds (is_bonus) are exempt from risk control checks |