A batch sends many order commands in one request. Each item is decided on its own, as if it had been sent alone, and the response carries one result per item in request order. Use batches to place a quote ladder, refresh quotes, or pull a set of orders with one round trip.
- Batch create · 1 to 20 items · any Pairs
Retry window: 15 minutes. - Batch replace · 1 to 50 items · one Pair
Retry window: 60 seconds from acceptance. - Batch cancel · 1 to 50 items · any Pairs
Retry window: 2 minutes.
How batches work
Every batch follows the same rules:
- Items run in order and stand alone. A rejected item does not stop the next one, and an admitted item is not rolled back when a later one fails.
- Results follow the request. The response lists one result per item, in request order, with
acceptedCountandrejectedCount. requestIdidentifies the batch. It is required, 1 to 64 ASCII letters, numbers,.,_,:,/, or-, and scoped to the account. Repeating the samerequestIdand the same items within the retry window returns the original results and acts on nothing twice. The samerequestIdwith different items is rejected withCONFLICT_IDEMPOTENCY_KEY_REUSEand changes nothing.- Each item counts against your rate limit, as the matching single command does. See Rate limits.
A request that is malformed as a whole, such as one with no items, more items than its limit
(BATCH_TOO_LARGE), or a missing requestId, is rejected before any item runs.
requestId is free again. Repeating an old batch then acts again: a batch
create can place its orders a second time. Read the items back instead of repeating an old batch.Batch create
BatchCreateOrders (POST /v1/orders/batch) places up to 20 orders, on any mix of Pairs.
Each item is a complete order with the same fields and rules as a single create; see Order types and lifecycle. An item
that fails validation is rejected alone, with its own code, and the other items proceed.
Over REST, an item whose quantity or price has a nonzero digit beyond the Pair's scale is rejected
alone with QTY_STEP_SIZE or PRICE_TICK_SIZE and a violation such as items[0].baseQty. Trailing
zeros beyond the scale are accepted.
A client order ID that is already reserved, or that appears twice in the same batch, rejects only
its item with CONFLICT_DUPLICATE_CLIENT_ORDER_ID. When the holder is a known earlier order, the
item's error carries its existingOrderId. See Client order IDs.
{
"requestId": "quote-0193-a",
"items": [
{
"symbol": "BTC-USDT",
"side": "BUY",
"baseQty": "0.25",
"limitGtc": { "price": "64200", "postOnly": true },
"clientOrderId": "mm-bid-17"
},
{
"symbol": "BTC-USDT",
"side": "SELL",
"baseQty": "0.25",
"limitGtc": { "price": "64300", "postOnly": true },
"clientOrderId": "mm-ask-17"
}
]
}Call /orders.v1.OrdersService/BatchCreateOrders. This example assumes a Pair base quantity scale of 8, so 0.25 is 25000000; prices are in units of 1e-9 quote:
{
"requestId": "quote-0193-a",
"items": [
{
"symbolId": 1,
"side": "BUY",
"baseQtyScaled": "25000000",
"limitGtc": { "priceTicks": "64200000000000", "postOnly": true },
"clientOrderId": "mm-bid-17"
},
{
"symbolId": 1,
"side": "SELL",
"baseQtyScaled": "25000000",
"limitGtc": { "priceTicks": "64300000000000", "postOnly": true },
"clientOrderId": "mm-ask-17"
}
]
}Each result echoes clientOrderId and holds exactly one of:
accepted: the neworderId, the resolved base quantity, and any attached-leg trigger IDsrejected: anerrorwith the item'scode
An accepted item is admitted, not filled. Its orders report their lifecycle like any other order.
Batch replace
BatchReplaceOrders (POST /v1/orders/replace-batch) modifies up to 50 orders of
one Pair as a quote refresh. Name the Pair once for the batch (symbol in REST, symbol_id in ConnectRPC). Each item
names a different order by orderId or clientOrderId and sets at least one of a new price, a new
total quantity, or new attached legs, plus an optional newClientOrderId.
Every item follows the default modify rule, AMEND_OR_REPLACE:
- An item that keeps the price, does not raise the total quantity, and keeps the client order ID amends the order in place, with the same
orderIdand its queue priority. - A new price, a larger total quantity, or a new client order ID replaces the order with a
successor that has a new
orderIdand reset queue priority. - A new total quantity at or below the filled quantity ends the order at its filled quantity, with no successor.
To force a replacement, use ModifyOrder with REPLACE_ONLY. See Modify an order.
An item whose order is on another Pair is rejected alone as ORDER_UNKNOWN. Naming the same order
twice rejects the whole batch. Over REST, an item newPrice with a nonzero digit beyond the tick
scale also rejects the whole request, with PRICE_TICK_SIZE and the item's violation, such as items[1].newPrice.
Admission receipt
The response is an admission receipt, returned before the market has applied the items. Its full schema is in the API reference. Read it this way:
batchRequestIdidentifies the batch and is the same for every retry of it. Keep it forGetBatchReplaceStatus.- The batch
statusisADMITTED,PARTIALLY_ADMITTED, orREJECTED. Each result'sstatusisADMITTED, orREJECTEDwith acode. - Match results by
itemIndex, the zero-based position of the item in your request, and treat a missing ID as none. - After
actionTakenAMENDED, keep trackingoldOrderId. AfterREPLACED, trackreplacementOrderId, which only a replaced item carries.
REST uses the short enum names shown; ConnectRPC uses the full Protobuf names, such as BATCH_REPLACE_ADMISSION_STATUS_ADMITTED.
An admitted item can still be refused by the market, for example a replacement that would cross as post-only. The original order then keeps its price and quantity, and no rejected order appears
under the replacement's order ID. Watch the private order updates,
which report REPLACE_REJECTED or AMEND_REJECTED, or read the batch status.
GetBatchReplaceStatus
OrdersReadService.GetBatchReplaceStatus returns each item's progress for a batchRequestId. It is available over ConnectRPC only, so its values use the full Protobuf names, such as BATCH_REPLACE_PHASE_WORKING; the prefix is omitted below.
Item phase | Meaning |
|---|---|
ADMITTED | Admitted and handed to execution |
WORKING | The successor, or the amended order, is active |
REJECTED | Rejected at admission or refused by the market; code says why |
TERMINAL | The successor, or the amended order, has ended |
Each item also carries orderStatus, the current status of its successor or amended order. A NOT_FOUND answer does not prove that the batch was rejected; reconcile the individual orders
instead.
Batch cancel
BatchCancelOrders (POST /v1/orders/cancel-batch) cancels up to 50 orders, on any
Pairs. Each item
names one order by orderId or clientOrderId. Over ConnectRPC, an item can also carry symbol_id;
when set, it must match the order's Pair or the item is rejected as ORDER_UNKNOWN.
Each result has status (ACCEPTED or REJECTED), the resolved orderId, and a code for a
rejection. ACCEPTED means cancellation was requested: the order can still fill until it ends, and
the order's own updates report CANCELED or FILLED. A cancel never applies twice. An item whose
order has already ended is rejected with ORDER_ALREADY_TERMINAL; an item named by a client order ID
more than a minute after its order ended may be rejected with ORDER_UNKNOWN instead.
To cancel by filter instead of by ID, use Cancel all orders.
Partial failure and unknown outcomes
A batch can end without a full answer in two ways:
- An error for the whole request, such as
UNAVAILABLE. For a batch create or batch cancel, some items may already be admitted: Polyester answers with an error while any item is still undecided, even when others went through. - An unknown outcome.
ORDER_CREATE_OUTCOME_UNKNOWN,ORDER_MODIFY_OUTCOME_UNKNOWN, orORDER_CANCEL_OUTCOME_UNKNOWN(REST504) means every item's outcome is unknown, and some may still apply. The same applies when the connection drops before the answer.
Keep the same requestId and items
Do not change the payload or generate a new requestId while you resolve the batch.
Repeat the batch within its retry window
Send the same requestId and items again. Decided items return their original results, and only the
undecided items run, so no item is admitted twice.
Read the orders back if the window has passed
Past the window, do not repeat the batch. Read open orders, look up each item by clientOrderId or orderId, or call GetBatchReplaceStatus for a batch replace.
REQUEST_RECEIPTS_EXHAUSTED means the account already holds its maximum number of recent modify and
batch requests for duplicate detection. Retry once earlier ones expire. All codes are in the error catalogue.
Batches on each interface
- Batch create
REST:POST /v1/orders/batch
ConnectRPC:BatchCreateOrders
SBE WebSocket:BatchCreateOrders(template 7) - Batch replace
REST:POST /v1/orders/replace-batch
ConnectRPC:BatchReplaceOrders
SBE WebSocket:BatchReplaceOrders(template 8) - Batch cancel
REST:POST /v1/orders/cancel-batch
ConnectRPC:BatchCancelOrders
SBE WebSocket:BatchCancelOrders(template 9)
REST takes Pair symbols and decimal strings, except the new quantity in a batch replace item, which
is the scaled integer newQtyScaled. A batch replace item whose newPrice has a nonzero digit
beyond 9 fractional digits fails the whole request with 400 PRICE_TICK_SIZE and that item's
violation, such as items[1].newPrice; trailing zeros are accepted. ConnectRPC takes Pair IDs and
scaled integers; see Scaled integers. Over the SBE WebSocket, the batch correlationId is the idempotency key and the answers are BatchCreateAck, BatchReplaceAck, and BatchCancelAck; see Batch commands.
Full field lists are in the API reference.