TESTNET
Markets
Trade
Lending Vaults
More
User Docs Developer Docs Sdk API Docs Help
Overview
Overview
Architecture
Authentication
Client configuration
Overview
Environments
Installation
Market data
Market data services
Authentication model
Quickstart
Trading
Trading services
Account services
Catalog & precision
Streaming
Accounts & balances
Funding services
Deposits & withdrawals
Realtime client
Errors
Server-side usage
Error handling
  1. Typescript
  2. /
  3. Trading

Trading

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.

Pre-validate for forms
To validate user input without placing anything, use the catalog: 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 same clientOrderId for the same logical order.
  • orders.modify / orders.cancelAll — pass a stable requestId when retrying.
  • Retry only on TransientError (network, timeout, rate limit) — see Error handling.
Previous

Quickstart

Next

Trading services

  • Place an order
  • Attach risk to an order
  • Modify an order
  • Cancel orders
  • Read orders
  • Your trade fills
  • Standalone triggers
  • Retry safely