Everything on this page requires an authenticated client — see Authentication.
Place an order
const result = await client.orders.create({
symbol: "BTC-USDC",
side: "buy", // "buy" | "sell"
orderType: "limit", // "limit" | "market"
timeInForce: "gtc", // "gtc" | "ioc" | "fok"
price: "64250.5", // decimal string; omit for market orders
qty: "0.25", // decimal string
postOnly: true,
clientOrderId: crypto.randomUUID(),
});Useful optional fields:
| Field | Values | Purpose |
|---|---|---|
clientOrderId | string ≤ 64 chars | Your idempotency key. Retrying with the same id never double-places. |
feeSource | "quote" · "received" | Which asset pays the fee. |
selfTradePreventionMode | "expire_taker" · "expire_maker" · "expire_both" | STP behavior when your own orders would match. |
marketMaxSlippage | distance / bps / none | Market orders only — reject beyond this slippage. |
marketClientRefPrice | decimal string | Market orders only — the reference price slippage is measured from. |
account | "main" · "active" · { subaccountId } | Which account the order belongs to (see Accounts & balances). |
Prices and quantities are validated against the pair's tick size, step size, and minimums before
sending. Excess precision is an error, never silently rounded — "0.123456789" on a pair with
6-decimal quantities throws a CatalogConversionError.
client.catalog.orders.validateSpotOrderDecimalInput(...) returns structured
validation errors, and getSpotOrderConstraints(pair) exposes tick/step/min values
for building UI hints.Attach risk to an order
An order can carry take-profit, stop-loss, or trailing-stop legs that activate when it fills:
await client.orders.create({
symbol: "BTC-USDC",
side: "buy",
orderType: "limit",
timeInForce: "gtc",
price: "64000",
qty: "0.1",
risk: {
takeProfit: { triggerPrice: "70000" },
stopLoss: { triggerPrice: "60000", orderType: "market" },
oco: true, // one-cancels-other between the two legs
},
});Valid risk combinations: takeProfit + stopLoss, takeProfit + trailingStop, or any one of
the three alone. Each leg accepts triggerPriceSource ("last" · "index" · "mark"), an orderType, and a limitPrice; trailing stops take a trailingDistance (absolute distance or
bps), optional activationPrice, and maxSlippage.
Modify an order
Patch price, quantity, client id, or the attached risk of an open order:
await client.orders.modify({
symbol: "BTC-USDC",
orderId: order.orderId, // or clientOrderId: "..."
newPrice: "64100",
newQty: "0.2",
});
// replace or clear attached risk
await client.orders.modify({
symbol: "BTC-USDC",
orderId: order.orderId,
risk: { stopLoss: { triggerPrice: "61000" } },
});
await client.orders.modify({
symbol: "BTC-USDC",
orderId: order.orderId,
clearRisk: true,
});modify generates a requestId automatically; pass your own stable value when you might retry
the same logical modification.
Cancel orders
// One order, by id or client id
await client.orders.cancel({ orderId: order.orderId });
await client.orders.cancel({ clientOrderId: "my-key-123" });
// Bulk, with safeguards
const preview = await client.orders.cancelAll({ symbol: "BTC-USDC", dryRun: true });
console.log(`${preview.orders.length} orders would be cancelled`);
await client.orders.cancelAll({ symbol: "BTC-USDC", side: "buy", maxOrders: 50 });Read orders
// Open orders
const open = await client.orders.listOpen({ symbol: "BTC-USDC" });
// History, paginated
let pageToken = "";
do {
const page = await client.orders.listHistory({ pageToken, limit: 100 });
process(page.orders);
pageToken = page.nextPageToken;
} while (pageToken !== "");
// One order with its trades and transfers
const details = await client.orders.getDetails({ orderId: order.orderId });Live order updates stream over a private channel:
const unsubscribe = client.orders.subscribe({
accountId,
onEvent: (order) => console.log(order.status, order.orderId),
});Your trade fills
const { trades, nextPageToken } = await client.trades.list({ symbol: "BTC-USDC" });
const unsubscribe = client.trades.subscribe({
accountId,
onEvent: (trade) => console.log("filled", trade.qty, "@", trade.price),
});Standalone triggers
Triggers are server-side automations that place a child order when their condition fires. Five
types: stop_loss, take_profit, trailing_stop, twap, and ladder.
const created = await client.triggers.create({
triggerType: "stop_loss",
symbol: "BTC-USDC",
side: "sell",
orderType: "market",
timeInForce: "ioc",
qty: "0.1",
triggerPrice: "60000",
triggerPriceSource: "last",
});
// trailing stop: follow the price at a fixed distance
await client.triggers.create({
triggerType: "trailing_stop",
symbol: "BTC-USDC",
side: "sell",
orderType: "market",
timeInForce: "ioc",
qty: "0.1",
trailingDistance: { kind: "distance", distance: "500" },
activationPrice: "68000",
});Every trigger takes the common child-order fields (symbol, side, orderType, timeInForce, qty, optional limitPrice, postOnly, feeSource, selfTradePreventionMode) plus
type-specific fields — TWAP takes duration/interval controls, ladder takes ladderPriceMin, ladderPriceMax, ladderLevels (2–100), and ladderDistribution. A clientTriggerId is
generated when omitted.
Manage the lifecycle:
await client.triggers.list({ symbol: "BTC-USDC", pageToken: "" });
await client.triggers.modify({ triggerId, triggerPrice: "59500" });
await client.triggers.pause({ triggerId });
await client.triggers.resume({ triggerId });
await client.triggers.cancel({ triggerId });
// Why did it fire / cancel / update?
const { events } = await client.triggers.listEvents({ triggerId });Stream trigger state and lifecycle events with client.triggers.subscribe(...) and client.triggers.subscribeEvents(...).
Retry safely
Mutations are idempotent when you make them so:
orders.create— reuse the sameclientOrderIdfor the same logical order.orders.modify/orders.cancelAll— pass a stablerequestIdwhen retrying.- Retry only on
TransientError(network, timeout, rate limit) — see Error handling.