Orders API
Orders are the primary trading mechanism. Operators place orders on behalf of their players. The matching engine automatically matches compatible buy and sell orders.
Authentication: All routes require X-Api-Key header.
Place Order
Submit a new order to the matching engine.
POST /api/v1/orders
Request Body:
| Field | Type | Required | Description |
|---|---|---|---|
marketId | string | Yes | Market UUID |
outcomeId | string | Yes | Outcome UUID |
playerId | string | Yes | Operator-defined player identifier |
side | string | Yes | BUY or SELL |
type | string | Yes | MARKET or LIMIT |
shares | number | Yes | Number of shares (min: 1, max: 100,000) |
price | number | Conditional | Share price (required for LIMIT orders, range: 0.01–0.99) |
transactionId | string | No | Operator-provided reference/idempotency key |
expiresAt | string (ISO 8601) | No | Order expiration time |
The prediction engine does not check player balances. Your backend must verify that the player can afford the order before submitting it. The cost of a BUY order is shares * price for LIMIT orders.
Example — Limit Buy Order:
curl -X POST https://polymarket.sandbox.playbatman.com/api/v1/orders \
-H "X-Api-Key: your-api-key" \
-H "Content-Type: application/json" \
-d '{
"marketId": "market-uuid",
"outcomeId": "outcome-uuid",
"playerId": "player-123",
"side": "BUY",
"type": "LIMIT",
"shares": 50,
"price": 0.65,
"transactionId": "op-txn-001"
}'
Response (201 Created):
{
"success": true,
"data": {
"order": {
"id": "order-uuid",
"marketId": "market-uuid",
"outcomeId": "outcome-uuid",
"operatorId": "operator-uuid",
"playerId": "player-123",
"side": "BUY",
"type": "LIMIT",
"shares": "50",
"price": "0.65",
"filledShares": "30",
"avgFillPrice": "0.60",
"remainingShares": "20",
"status": "PARTIAL",
"transactionId": "op-txn-001",
"expiresAt": null,
"createdAt": "2026-02-18T22:00:00.000Z",
"updatedAt": "2026-02-18T22:00:00.000Z"
},
"trades": [
{
"id": "trade-uuid",
"marketId": "market-uuid",
"outcomeId": "outcome-uuid",
"buyOrderId": "order-uuid",
"sellOrderId": "counter-order-uuid",
"buyerOperatorId": "operator-uuid",
"sellerOperatorId": "other-operator-uuid",
"price": "0.60",
"shares": "30",
"buyerFee": "0.36",
"sellerFee": "0.36",
"createdAt": "2026-02-18T22:00:00.000Z"
}
],
"status": "PARTIAL",
"filledShares": "30",
"avgFillPrice": "0.60",
"remainingShares": "20"
}
}
Order Matching Behavior
When you place an order:
- LIMIT BUY — Matches against existing sell orders priced at or below your limit price, starting from the lowest ask. Unmatched shares remain in the order book.
- LIMIT SELL — Matches against existing buy orders priced at or above your limit price, starting from the highest bid. Unmatched shares remain in the order book.
- MARKET BUY — Matches against the best available sell orders at any price until the requested shares are filled or liquidity is exhausted.
- MARKET SELL — Matches against the best available buy orders at any price until the requested shares are filled or liquidity is exhausted.
Order Statuses
| Status | Description |
|---|---|
PENDING | Order is in the book, no shares matched yet |
PARTIAL | Some shares matched, remainder still in the book |
FILLED | All shares fully matched |
CANCELLED | Order cancelled by operator or system |
EXPIRED | Order expired (passed expiresAt) |
REJECTED | Order rejected (e.g., no liquidity for market order) |
Cancel Order
Cancel an open order.
DELETE /api/v1/orders/{orderId}
Only orders with status PENDING or PARTIAL can be cancelled.
Example:
curl -X DELETE https://polymarket.sandbox.playbatman.com/api/v1/orders/{orderId} \
-H "X-Api-Key: your-api-key"
Response:
{
"success": true,
"data": {
"id": "order-uuid",
"status": "CANCELLED",
"remainingShares": "0",
...
}
}
Get Order
Retrieve a single order by ID.
GET /api/v1/orders/{orderId}
Response: Same shape as the order object in the Place Order response.
List Orders
List orders for your operator account with optional filters.
GET /api/v1/orders
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
playerId | string | Filter by player ID |
marketId | string | Filter by market |
outcomeId | string | Filter by outcome |
side | string | Filter by side (BUY or SELL) |
type | string | Filter by type (MARKET or LIMIT) |
status | string | Comma-separated statuses |
cursor | string | Pagination cursor |
limit | number | Page size |
Example — Get all open orders for a player:
curl "https://polymarket.sandbox.playbatman.com/api/v1/orders?playerId=player-123&status=PENDING,PARTIAL" \
-H "X-Api-Key: your-api-key"
Response:
{
"success": true,
"data": {
"orders": [ ... ],
"total": 5,
"hasMore": false,
"nextCursor": null
}
}
Validation Rules
| Rule | Details |
|---|---|
Market must be OPEN | Orders rejected if market is in any other status |
| Trading window active | Current time must be between tradingStartsAt and tradingEndsAt |
| Valid outcome | Outcome must belong to the specified market |
| Share range | 1 to 100,000 (configurable) |
| Price range | 0.01 to 0.99 (configurable, LIMIT orders only) |
| SELL position check | Operator must hold enough shares to sell |
playerId required | Must be a non-empty string |
Error Codes
| Code | Description |
|---|---|
ORDER_NOT_FOUND | Order with the given ID does not exist |
ORDER_INVALID_PRICE | Price outside allowed range |
ORDER_INVALID_SHARES | Shares outside allowed range |
ORDER_CANNOT_CANCEL | Order is not in a cancellable status |
ORDER_NO_LIQUIDITY | No matching orders available (market orders) |
MARKET_NOT_OPEN | Market is not open for trading |
POSITION_INSUFFICIENT_SHARES | Not enough shares to sell |