Reference

Placing orders

Every write goes through one endpoint, POST /api/v1/trading/orders, and the execution_type decides what it does. Opening, closing, cancelling and editing brackets are all the same call with a different body.

The request envelope

Two top-level fields: the account, and the trade.

body shape
{
  "accountId": "<the account this key is bound to>",
  "trade": {
    "execution_type": "MARKET",
    ...
  }
}

accountId must be the account the key was issued against. Sending a different one returns 403 even if you own both accounts. The binding, not the body, decides what a key can touch.

Unrecognised fields are ignored, not rejected

The request is parsed against a fixed schema and anything outside it is dropped silently. A typo in a field name therefore does not produce a helpful error. It produces an order without that setting. Check spelling against the table below before assuming a value was applied.

Execution types

What each one does and the minimum it needs.

execution_typePurposeRequires
MARKETOpen or add to a position immediately at the prevailing price.One sizing field, trade_pair, order_type
LIMITRest an order until price reaches limit_price.One sizing field, trade_pair, order_type, limit_price
BRACKETAttach take-profit / stop-loss legs to a position.bracket_orders (at least one leg)
LIMIT_EDITModify the bracket legs on an existing position. Move a level, or remove a leg.bracket_orders describing the new state
LIMIT_CANCELCancel a resting limit order that has not filled.order_uuid
FLAT_ALLClose open positions at market.order_uuid

Fields of `trade`

The complete accepted set.

FieldTypeNotes
execution_typestringRequired. One of MARKET, LIMIT, BRACKET, LIMIT_EDIT, LIMIT_CANCEL, FLAT_ALL.
trade_pairstring | objectThe instrument, e.g. "BTCUSDC", "EURUSD", "AAPL". The object form { "trade_pair_id": "…" } is also accepted.
order_typestringLONG, SHORT or FLAT. This is the direction of the order.
valuenumberOrder size as notional in USD. One of value / quantity / leverage.
quantitynumberOrder size in the instrument's own unit: base tokens for crypto, shares for equities, lots for forex and commodities.
leveragenumberOrder size as a multiple of the account size. The account's maximum leverage still applies.
limit_pricenumberRequired for LIMIT orders; the price the order rests at.
stop_lossnumberStop-loss trigger price to attach to the order.
take_profitnumberTake-profit trigger price to attach to the order.
order_uuidstringTarget order for LIMIT_CANCEL; the position selector for FLAT_ALL.
position_uuidstringTarget position, where the operation acts on one.
bracket_ordersarrayBracket legs. Each leg accepts stop_loss, take_profit, value, quantity and order_uuid.

Sizing: pick exactly one

value, quantity and leverage are three ways of saying the same thing, and MARKET and LIMIT orders must carry exactly one. Sending none, or sending more than one, is rejected with 'leverage', 'value', or 'quantity' must be provided. BRACKET, LIMIT_CANCEL and FLAT_ALL do not take a top-level size.

Not available through the API

Some things the trading terminal can do are not exposed here. Sending them has no effect. They are dropped with the rest of the unrecognised fields rather than rejected:

  • trailing_stop. Trailing stops can only be set from the terminal.
  • bracket_pct, for closing a percentage of a position. Use value or quantity on the bracket leg instead.
  • STOP_LIMIT, stop_price and stop_condition, for stop limit entries.

Worked payloads

The `trade` object for each common operation. Wrap each in the envelope above.

Market order

MARKET
{
  "execution_type": "MARKET",
  "trade_pair": "BTCUSDC",
  "order_type": "LONG",
  "value": 1000
}

Market order with take-profit and stop-loss

Attaching levels at entry is a single call. The legs ride along on the opening order.

MARKET + levels
{
  "execution_type": "MARKET",
  "trade_pair": "BTCUSDC",
  "order_type": "LONG",
  "value": 1000,
  "take_profit": 72000,
  "stop_loss": 61000
}

Limit order

LIMIT
{
  "execution_type": "LIMIT",
  "trade_pair": "ETHUSDC",
  "order_type": "LONG",
  "value": 1500,
  "limit_price": 3200
}

Omitting limit_price is rejected with limit_price is required for LIMIT orders. Resting orders appear on GET /orders until they fill or are cancelled.

Cancel a resting limit order

Take the orderUuid from GET /orders.

LIMIT_CANCEL
{
  "execution_type": "LIMIT_CANCEL",
  "order_uuid": "a12b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d"
}

Add or change take-profit / stop-loss on an open position

LIMIT_EDITrestates the bracket legs for a position. Send the position's instrument, its direction, its size in base units, and the legs you want in place.

LIMIT_EDIT
{
  "execution_type": "LIMIT_EDIT",
  "trade_pair": "BTCUSDC",
  "order_type": "LONG",
  "quantity": 0.115,
  "bracket_orders": [
    {
      "take_profit": 72000,
      "quantity": 0.115
    },
    {
      "stop_loss": 61000,
      "quantity": 0.115
    }
  ]
}

A leg carrying only an order_uuid, with no take_profit or stop_loss, removes that leg. A leg with no size closes the whole position when it triggers.

LIMIT_EDIT, remove one leg
{
  "execution_type": "LIMIT_EDIT",
  "trade_pair": "BTCUSDC",
  "order_type": "LONG",
  "quantity": 0.115,
  "bracket_orders": [
    {
      "order_uuid": "b23c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e"
    }
  ]
}

Close positions

FLAT_ALL uses order_uuid as a selector. The literal string ALL closes every open position on the account:

FLAT_ALL, everything
{
  "execution_type": "FLAT_ALL",
  "order_uuid": "ALL"
}

To close specific positions, pass their positionUuid values comma-separated:

FLAT_ALL, selected positions
{
  "execution_type": "FLAT_ALL",
  "order_uuid": "0f9d1a2b-3c4d-5e6f-7a8b-9c0d1e2f3a4b,1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d"
}

Keep the list short

The selector rides in a field capped at 256 characters upstream, and a long list is silently truncated rather than rejected. Vanta's own terminal sends at most four position ids per request and batches the rest sequentially. Do the same, or use ALL when you genuinely mean everything.

What you get back

Acceptance, not confirmation of a fill.

200 OK
{
  "success": true,
  "data": {
    "status": "accepted",
    "order_uuid": "d45e6f7a-8b9c-0d1e-2f3a-4b5c6d7e8f90"
  }
}

A 200 means the order was accepted for execution. Confirm the outcome by polling GET /positions and GET /trades. Do not treat the acknowledgement as a fill.