Skip to main content

Place orders for a user

Every order is a POST /v1/gateway/orders with an asset, a size and a type. This page covers the calls you make most: place an order, list and read orders, and cancel one. Every call here carries your organization token and TM-On-Behalf-Of, so it acts on that user’s wallet. Getting started walks through signing and executing a market buy.

Identify the asset​

Send the asset's id from the catalog as asset_id. Older integrations name the asset with base_asset instead. Use asset_id for new code.

Place a market order​

A market order executes now at the best available price, so it takes no price. Size a buy by what you spend, with qty_unit: "quote". Size a sell by what you sell, with qty_unit: "base".

The response carries the quote and the payloads to sign. Nothing moves until you sign them and execute.

Buy 2 USDC worth of an asset
const order = await post(
"/v1/gateway/orders",
{
asset_id: assetId,
qty: "2",
qty_unit: "quote",
side: "buy",
type: "market",
},
forUser,
);

Limit orders​

A limit order rests at your price until it fills or you cancel it, sized with qty_unit: "base". Limit orders aren't available for every asset yet; the create order reference has the current rules.

List and read orders​

GET /v1/gateway/orders lists the user's orders, newest first. Filter with status (comma-separated), and page with limit (up to 100) and the cursor from pagination.next_cursor. An order you created but never executed doesn't appear in the list. Read it by its id.

Resting orders, then one order by its id
const orders = await get(
"/v1/gateway/orders?status=active",
forUser,
);

const order = await get(`/v1/gateway/orders/${orderId}`, forUser);

Cancel an order​

Canceling a resting order is a wallet transaction too, so it works like placing one: the cancel call returns payloads, you sign them, and you execute the cancel.

Cancel a resting order, sign, execute
const cancel = await post(
`/v1/gateway/orders/${orderId}/cancel`,
{},
forUser,
);

const signatures = await Promise.all(
cancel.payloads.map((p) => stamp(p.payload)),
);

await post(
`/v1/gateway/orders/${orderId}/cancel/execute`,
{
signatures,
auth_type: "api_key",
},
forUser,
);

Sizing​

In a pair such as SOL/USDC, the base asset is the one you buy or sell (SOL), and the quote asset is the one you price it in (USDC). qty_unit says which one qty counts. Every quantity is a positive decimal string.

qty_unitMeaningAllowed on
quoteamount of the quote asset to spend, "10 USDC of SOL"market buy
baseamount of the base asset, "0.01 SOL"market sell, limit orders

Follow an order to a final state​

Order status, from create to a final state
createinitialized
  • completefilled
  • activea limit order, resting
  • pendingstill settling
  • failed
cancelcancel_pendingcanceled
final won't changeother read the order again

An order that isn't in a final state can still change, so read it again until it is.

If order_id comes back empty, no order was created, and quote.issues says why. Nothing moves until you execute, so you can retry a create that timed out.

When an order fails​

StatusMeaning
201 with an empty order_idThe wallet can't fund the buy. quote.issues says why, and no order was created.
422 with insufficient_balanceThe wallet can't fund a sell or a perpetual order.
422 with quote_staleThe quote expired or the price moved before execute landed. Place the order again.
403The user isn't in your organization, or the asset isn't available in the country your request comes from. GET /assets/availability shows what's available.
409 with already_submitted on executeThe transaction already landed. Read the order instead of executing again.

Errors has the error body and the rest of the codes.

Perpetuals​

A perpetual, or perp, is a contract that tracks an asset's price and never expires. Perpetuals aren't available for every asset; the ones that are appear in the catalog with type: "perp".

To open a position, send leverage, up to the asset's perp.max_leverage in the catalog. Margin is isolated. With qty_unit: "quote", qty is the margin you commit and the position's size is qty times leverage; with "base", qty is the position's size. To close a position, send reduce_only: true instead.

A trigger object turns the order into a take-profit or stop-loss that fires when the mark price crosses trigger.price. The create order reference has every rule.

Next: What you can trade