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.
- TypeScript
- Python
- curl
const order = await post(
"/v1/gateway/orders",
{
asset_id: assetId,
qty: "2",
qty_unit: "quote",
side: "buy",
type: "market",
},
forUser,
);
order = post(
"/v1/gateway/orders",
{
"asset_id": asset_id,
"qty": "2",
"qty_unit": "quote",
"side": "buy",
"type": "market",
},
for_user,
)
curl -s -X POST https://api.truemarkets.co/v1/gateway/orders \
-H "Authorization: Bearer $ORG_TOKEN" \
-H "TM-On-Behalf-Of: $USER_ID" \
-H "Content-Type: application/json" \
-d '{
"asset_id": "'"$ASSET_ID"'",
"qty": "2",
"qty_unit": "quote",
"side": "buy",
"type": "market"
}'
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.
- TypeScript
- Python
- curl
const orders = await get(
"/v1/gateway/orders?status=active",
forUser,
);
const order = await get(`/v1/gateway/orders/${orderId}`, forUser);
orders = get("/v1/gateway/orders?status=active", for_user)
order = get(f"/v1/gateway/orders/{order_id}", for_user)
curl -s -G https://api.truemarkets.co/v1/gateway/orders \
-H "Authorization: Bearer $ORG_TOKEN" \
-H "TM-On-Behalf-Of: $USER_ID" \
-d status=active
curl -s https://api.truemarkets.co/v1/gateway/orders/$ORDER_ID \
-H "Authorization: Bearer $ORG_TOKEN" \
-H "TM-On-Behalf-Of: $USER_ID"
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.
- TypeScript
- Python
- curl
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,
);
cancel = post(
f"/v1/gateway/orders/{order_id}/cancel",
{},
for_user,
)
signatures = [stamp(p["payload"]) for p in cancel["payloads"]]
post(
f"/v1/gateway/orders/{order_id}/cancel/execute",
{
"signatures": signatures,
"auth_type": "api_key",
},
for_user,
)
curl -s -X POST https://api.truemarkets.co/v1/gateway/orders/$ORDER_ID/cancel \
-H "Authorization: Bearer $ORG_TOKEN" \
-H "TM-On-Behalf-Of: $USER_ID"
# $SIGNATURES is the JSON array your code signed
curl -s -X POST https://api.truemarkets.co/v1/gateway/orders/$ORDER_ID/cancel/execute \
-H "Authorization: Bearer $ORG_TOKEN" \
-H "TM-On-Behalf-Of: $USER_ID" \
-H "Content-Type: application/json" \
-d '{
"signatures": '"$SIGNATURES"',
"auth_type": "api_key"
}'
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_unit | Meaning | Allowed on |
|---|---|---|
quote | amount of the quote asset to spend, "10 USDC of SOL" | market buy |
base | amount of the base asset, "0.01 SOL" | market sell, limit orders |
Follow an order to a final state
- completefilled
- activea limit order, resting
- pendingstill settling
- failed
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
| Status | Meaning |
|---|---|
201 with an empty order_id | The wallet can't fund the buy. quote.issues says why, and no order was created. |
422 with insufficient_balance | The wallet can't fund a sell or a perpetual order. |
422 with quote_stale | The quote expired or the price moved before execute landed. Place the order again. |
403 | The 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 execute | The 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