Skip to main content
Send your first order through the API with its bracket attached, then read the account back and close the position. Use this page once you have a Trading API key and a Demo from the programmatic quickstart. By the end you have placed an order that can’t be sent twice, seen the position and its bracket in the account, and flattened it again.

Before you start

You need your Trading API key in TRDRS_TRADING_API_KEY, the base URL in TRDRS_API_BASE_URL, and your Demo’s PROVIDER and ACCOUNT. The examples trade HYPERLIQUID:BTC, the Bitcoin perpetual your Demo lists, whose prices come from a provider’s public data, so they run in the sandbox with no other login. Futures work the same way while the CME session is open. List the markets an account trades names each one your Demo trades: every dated contract it lists, such as CME:ESZ2026, and the continuous futures they make, such as ES1!, each with the dated contract it trades now in contract and when that changes in rollAt. An order on ES1! trades that contract, so an order placed from a continuous chart trades the month the ticket shows. Futures prices are licensed to each user and need your own login at a provider that carries them (Providers lists which), so futures orders run in production, never in the sandbox. Without that login your Demo lists no futures, and a futures order is refused as market_data_unavailable with cause login_missing. With it, your Demo prices futures from your own market-data session at trdrs, which opens when you chart or trade futures while you’re signed in. A Trading API key opens no session of its own, so a futures order it sends that must fill now is refused as market_data_unavailable while no session is open. The TypeScript SDK isn’t published, so call the routes over HTTP, as the curl examples do. The TypeScript examples show the same calls through the SDK’s client, constructed with your Trading API key, with provider and account holding the same two values.
Every step after the first changes the account. Use your Demo or another account you don’t mind trading.
1

Check that the account can trade

A venue’s own rules can lock an account: a limit its venue set, a drawdown rule breached, or a halt. A locked account refuses every new order, so your screen should show the lock instead of an order button.The account stream carries the lock as its lock event: while tradingLocked is false, no lock blocks a new order. Stream account updates is the route.
2

Place a market order with a take profit and a stop loss

Send the order with exits, its take profit and its stop loss. trdrs records them as the order’s bracket before it sends the entry, and they protect the position the moment it opens. The two make one pair: when one fills, the other is cancelled.Mint clientOrderId once, when you decide to send the order, and reuse it if you have to retry. The engine treats a second request with the same id as the same order, so a timeout can’t turn into two positions.
Each leg here covers the whole order (share is in percent) at an exact price. The example assumes the market near 100,000. On a buy, put the stop loss below the market and the take profit above it, each on the instrument’s tick. The quantity is in bitcoin, in steps of 0.00001. A leg can also sit at a distance from the entry, in a unit such as ticks, and a bracket holds up to three take profits and three stop losses: Protect a position shows both.The response names the order and how it filled:
providerOrderId is the id you use to move or cancel orders on this account, and on a Demo it’s your clientOrderId. bracket is the protection placed with it: keep its id to change or withdraw it later. attached is true where the provider holds the pairs with the entry, as the paper book does.orderType also takes limit with limitPrice, stop with triggerPrice, and stop_limit with both triggerPrice and stopLimitPrice, and it’s market when you leave it out. tif is day or gtc. reduceOnly: true sends an order that can only shrink a position, on a provider that enforces it, and such an order carries no exits.
3

Confirm what the account holds

Read the account snapshot. It returns the balance, the open positions, the working orders and the brackets as they stood at one moment, so the parts always agree with each other.
positions now holds a HYPERLIQUID:BTC row with qty of 0.01: a long position is positive and a short one negative. The take profit and the stop loss rest in orders, and brackets shows them as one bracket around the position. The order worked.
4

Close the position

Flatten the instrument. The engine cancels its working orders first, the take profit and the stop loss included, then closes the position at market, so nothing left resting can open it again.
Read the snapshot again: the position and its orders are gone. Close a position covers the other ways out.

When an order is refused

Every refusal carries a code beside the English error, and most carry params with the details. Show the trader a message chosen by code, and use error only as a fallback. Nothing is placed when an order is refused, so the same clientOrderId can be retried once the cause is fixed. Get what the account may do runs the standing checks before you send, so a ticket can disable what would be refused and say why. Place an order describes each refusal in full.

Test it end to end

Run the steps against your Demo in the sandbox, then check the account is back where it started:
  1. Get what the account may do and confirm opening a position is allowed.
  2. Place the order and keep its providerOrderId.
  3. Send the exact same request again. It answers 409, and the account still holds one position.
  4. Flatten, then read the snapshot and confirm there’s no position and no working order.

Next steps

Protect a position

Set or move the take profit and the stop loss on a position you already hold.

Manage working orders

Move a resting order to a new price, or cancel one or all of them.

Track fills and P&L

Read what filled and what it earned, from history that outlives the session.

Idempotency

See exactly how a retried request is recognized as the same one.