tastytradeDeveloper Docs

Orders & Order Types

An order in the tastytrade API is a JSON document with two parts: order attributes that apply to the trade as a whole, and a legs array where each leg names a single instrument, a side, and a quantity. All JSON keys are dasherized (for example order-type, price-effect, time-in-force, instrument-type), and prices/values are sent as strings or decimals.

Orders are submitted to POST /accounts/{account_number}/orders. Because orders move real money, always dry-run first against POST /accounts/{account_number}/orders/dry-run (the same JSON body), inspect the returned buying-power-effect/fee-calculation and any warnings, then submit. There is no idempotency-key header and the API does not deduplicate retried submissions, so set your own unique external-identifier on each order (it is echoed back on the order response); if a submission's outcome is uncertain (timeout or 5xx), check GET /accounts/{account_number}/orders with a start-date on or before the day you submitted, in US Eastern time (for example, the previous day), or /orders/live, for that identifier before resubmitting. See Idempotency & retries and the full schema at /reference/orders.

Order attributes

AttributeRequiredMeaning
order-typeYesThe kind of order (see below)
time-in-forceYesHow long the order lives if unfilled
priceYes for Limit / Stop LimitThe limit price
price-effectWith priceDebit (you pay) or Credit (you receive)
stop-triggerYes for Stop / Stop LimitThe trigger price
gtc-dateYes for GTDExpiry date (yyyy-mm-dd)
value / value-effectYes for Notional MarketDollar amount to buy/sell
legsYesArray of leg objects
sourceNoFree-form origin tag

price-effect must agree with the leg action: buying is a Debit, selling is a Credit. Buying for a credit (or selling for a debit) is rejected.

Legs

Each leg names one instrument. All orders need at least one leg. Equity, future, and cryptocurrency orders are limited to 1 leg; equity-option and future-option orders allow up to 4 legs. Two legs may not share the same symbol.

Leg attributeRequiredMeaning
actionYesBuy to Open, Sell to Open, Buy to Close, Sell to Close (or Buy/Sell for single-leg outright futures)
instrument-typeYesEquity, Equity Option, Future, Future Option, or Cryptocurrency
quantityYes (omit for Notional Market)Whole number, or decimal for crypto
symbolYesThe instrument symbol

The action and instrument-type values above are the commonly used ones — the full enums (which also include Allocate, Equity Offering, Fixed Income Security, and Liquidity Pool) are in /reference/orders.

Symbols follow tastytrade symbology: plain tickers for equities (AAPL), OCC-style strings for equity options (AAPL 230818C00197500), leading-slash futures (/CLZ2), future options, and crypto pairs (BTC/USD). Look symbols up via the instruments endpoints — see /reference.

Order types

TypeRule
LimitMust include price and price-effect
MarketNo price/price-effect; single leg; time-in-force not GTC (for cryptocurrency orders the time-in-force rules are the crypto rules instead; the other Market rules still apply)
StopMarket order with a stop-trigger; becomes a market order when the quote hits the trigger
Stop LimitLimit order (price + price-effect) plus a stop-trigger

A Notional Market type also exists for buying a dollar value of crypto or eligible equities (omit quantity). These are the commonly used order types — the full order-type enum (which also includes Marketable Limit and Liquidity Allocation) is in /reference/orders.

{
  "time-in-force": "Day",
  "order-type": "Limit",
  "price": "1.09",
  "price-effect": "Debit",
  "legs": [
    { "instrument-type": "Equity Option", "symbol": "AAPL  230818C00197500", "quantity": 1, "action": "Buy to Open" },
    { "instrument-type": "Equity Option", "symbol": "AAPL  230818C00200000", "quantity": 1, "action": "Sell to Open" }
  ]
}

Time-in-force

TIFMeaning
DayWorks until filled or the market closes
GTCGood 'til canceled — works until filled or canceled
GTDGood 'til date — also requires gtc-date (yyyy-mm-dd)

Some venues also support immediate-or-cancel and extended-hours behaviors; refer to /reference/orders for the values your instrument accepts.

Cryptocurrency orders

Cryptocurrency trading is currently disabled through the API. The release notes record that it was disabled as of release 20260629, until further notice. The rest of this section describes the order shape for when it is enabled; do not build against it before the release notes say it is back.

The is-cryptocurrency-enabled and is-cryptocurrency-closing-only fields returned by GET /accounts/{account_number}/trading-status are per-account flags for whether an account may trade cryptocurrency. They do not say whether the API currently accepts crypto orders.

Cryptocurrency orders use the same POST /accounts/{account_number}/orders endpoint and body as any other order, with instrument-type set to Cryptocurrency and a pair symbol such as BTC/USD.

Finding supported products. GET /instruments/cryptocurrencies returns the active crypto instruments (filter with symbol[]=BTC%2FUSD; URL-encode the /). Use each instrument's symbol field as the leg symbol. An instrument with is-closing-only set to true accepts only closing orders.

Quantity and price precision.

  • Quantity may be a decimal for crypto. GET /instruments/quantity-decimal-precisions returns, per instrument type or symbol, a value giving the number of decimal places a quantity may use (0 means whole numbers only). In the reference example BTC/USD has a value of 8, so 0.12345678 is valid and 0.123456789 is not.
  • Price: an opening order's price must follow the instrument's tick-size. A closing order's price may use any number of decimal places up to the highest max-price-precision among the instrument's destination-venue-symbols entries that have routable set to true. See the instruments reference and the rules below.

Order shape. A crypto order has a single leg. Send a decimal quantity as described above, or use a Notional Market order that buys a dollar value and omits quantity. A Notional Market example:

{
  "time-in-force": "IOC",
  "order-type": "Notional Market",
  "value": "10.0",
  "value-effect": "Debit",
  "legs": [
    { "instrument-type": "Cryptocurrency", "symbol": "BTC/USD", "action": "Buy to Open" }
  ]
}

Order rules and limits. The order service's own checks on a cryptocurrency order are listed below. They apply when crypto trading is available to your account and client, and say nothing about whether that is the case today; the notice at the top of this section does. The order types and time-in-force values listed are the ones the order service's code accepts. They are not a guarantee that a given combination is accepted on submission; see the venue rules note after the table.

RuleWhat the order service enforcesRejection code
LegsExactly one legcryptocurrency_single_leg_only
ActionBuy to Open or Sell to Close. Buy to Close is accepted only for orders the service treats as forced.cryptocurrency_invalid_action
Order typeLimit, Market, or Notional Marketcryptocurrency_invalid_type
Time in forceIOC or GTC; any other value is rejected. A Notional Market order must be IOC.tif.cryptocurrency_invalid, cryptocurrency_notional_market_orders_ioc_only
gtc-dateMust not be setcryptocurrency_no_gtc_date
Maximum quantity2,147,483,647 per legorder_limit_check_failed
Minimum notional value$1 for an order with an opening leg; $0.01 for a closing order. The rejection message formats the minimum with no decimals, so for a closing order it reads "$0".below_notional_value_minimum
Maximum notional value$75,000above_notional_value_maximum
Opening priceMust follow the instrument's tick-size (checked when the order has a price)invalid_price_increment
Closing priceAt most the highest routable max-price-precision decimal places (checked when the order has a price). If the instrument has no routable destination-venue-symbols, the limit is the number of decimal places in its tick-size.cryptocurrency_invalid_closing_price
Price band, buyA Limit buy price may be at most 1.20 times the current askcryptocurrency_unreasonable_price_max
Price band, sellA Limit sell price may be at most 1.55 times the current askcryptocurrency_unreasonable_price_max
Price band, minimumA Limit price may not be below 0.25 times the current bidcryptocurrency_unreasonable_price_min

The notional-value limits are checked on the order's notional value as the order service calculates it, for every crypto order type and not only Notional Market. The quantity limit is a fixed ceiling, not a statement of what the instrument accepts; the quantity precision rules above still apply. The quantity limit, the notional limits and the price-band multipliers are fixed values in the order service's code, not account settings. The message for order_limit_check_failed is in the preflight error list; it suggests contacting the trade desk to increase your limits, but the crypto quantity limit is this fixed value, so that advice does not apply to it.

Venue rules and dry-run. The table lists the order service's own checks. On submission the service also matches the order against routing-venue rules that are stored in a database. Those rules can further restrict order type and time in force (each type and each time in force is a separate on/off setting, for example Market, Notional Market, IOC and GTC). The same venue selection also checks that the symbol is routable and checks quantity and price precision. If no venue accepts the order, it is rejected with cryptocurrency_venue_not_found. If a venue matches but no compatible order router is left for it, the rejection is no_router_found ("No compatible order router found."). A dry-run does not run this step, so a dry-run that passes does not guarantee that the order will be accepted on submission. The venue rules are not published, so this page does not say which type and time-in-force combinations are enabled; in particular it does not say whether a Market order with GTC is accepted, even though no crypto check in the table rejects it.

Blocked for API clients. The order service can block an instrument type for API clients. When it does, an order from an OAuth2 client for that type is rejected with a 422, and the entry in error.errors[] is:

{
  "code": "api_forbidden_type",
  "message": "Order contains instrument types that are not currently allowed for API trading: <instrument types>"
}

Orders sent without an OAuth2 client are not checked, and clients the service has allowlisted are exempt. Which types are blocked, and which clients are allowlisted, is service configuration that is not published, so this page does not say whether api_forbidden_type is how crypto is disabled today. The same check can reject specific symbols with the code api_forbidden_symbol.

Preflight stops at the first stage that reports an error. The crypto gatekeeper stage runs before the blocked-type check, so an order it rejects with cryptocurrency_trading_not_supported ("Cryptocurrency trading is not supported.") or cryptocurrency_not_allowed ("Your account is not approved for cryptocurrency trading. Please enable it to trade this product.") never reaches it. The blocked-type check in turn runs before the order-shape and limit checks in the table, so a blocked order is rejected with api_forbidden_type even if it also breaks one of those rules.

A failed pre-submission check comes back as a 422 with a preflight_check_failure code (see Errors); each failure is an entry in error.errors[] with its own code.

Complex orders

Complex (bracket) orders are submitted to POST /accounts/{account_number}/complex-orders and have a type plus an orders array (and, for triggered types, a trigger-order; PAIRS adds ratio-price fields — see below). Supported types are OTOCO, OCO, OTO, and PAIRS. BLAST is deprecated and is not supported in any environment.

  • OTO — the trigger-order goes live immediately; when it fills, its orders (up to 3) are routed. They do not cancel one another.
  • OCO — no trigger-order; the orders go live immediately, and when one fills the other is canceled.
  • OTOCO — a trigger-order plus one to three OCO pairs (2, 4 or 6 orders) that sit in Contingent status until the trigger fills, then route as OCOs.
  • PAIRS — orders worked together as a pairs strategy, triggered by a ratio price: set ratio-price-comparator (gte or lte) and ratio-price-threshold (a decimal serialized as a JSON string, e.g. "150.25"); optionally set ratio-price-is-threshold-based-on-notional to compare on notional value instead of price. A working PAIRS order's threshold and comparator can later be edited via PATCH /accounts/{account_number}/complex-orders/{id} (only PAIRS orders can be edited there).
{
  "type": "OTOCO",
  "trigger-order": {
    "order-type": "Limit", "price": 157.97, "price-effect": "Debit", "time-in-force": "Day",
    "legs": [{ "instrument-type": "Equity", "symbol": "AAPL", "action": "Buy to Open", "quantity": 100 }]
  },
  "orders": [
    { "order-type": "Limit", "price": 198.68, "price-effect": "Credit", "time-in-force": "GTC",
      "legs": [{ "symbol": "AAPL", "instrument-type": "Equity", "action": "Sell to Close", "quantity": 100 }] },
    { "order-type": "Stop", "time-in-force": "GTC", "stop-trigger": 143.06,
      "legs": [{ "symbol": "AAPL", "instrument-type": "Equity", "action": "Sell to Close", "quantity": 100 }] }
  ]
}

The response returns a complex-order.id (used to fetch or cancel the whole bracket) plus individual ids for the trigger and nested orders. Cancel a complex order through its own endpoint using the complex-order id, not a nested order id.

Price restrictions on triggered orders

An OTOCO order is checked to make sure its orders are priced sensibly relative to the trigger-order: in each OCO pair, the profit-taking order has to sit on the profitable side of the trigger order's price, and the stop-loss order on the other side. This check runs for OTOCO only; it is not applied to OTO, OCO, or PAIRS orders. It applies to every order in orders, except that an order in orders that has already reached a terminal status is skipped.

Each order in orders is compared against a reference price, strictly (equal prices are rejected). Credit or debit is taken from the order's price-effect; if it has none (as with the Stop in the example above, which has no price), from its value-effect, and for a single-leg order after that from the leg action (a buy is a debit, a sell is a credit):

Order in orders (credit or debit)Price that is comparedMust be
Credit, Limitpricegreater than the reference price
Credit, Stopstop-triggerless than the reference price
Credit, Stop Limitprice (the limit price, not stop-trigger)less than the reference price
Debit, Limitpriceless than the reference price
Debit, Stopstop-triggergreater than the reference price
Debit, Stop Limitprice (the limit price, not stop-trigger)greater than the reference price

In other words, for a long trigger order the profit order must be priced above the trigger price and the stop-loss below it; for a short trigger order the profit order must be priced below and the stop-loss above. A Market order cannot be used in orders: it has no price to compare, so it fails this check.

The reference price is the trigger order's price for a Limit or Stop Limit trigger order, or its stop-trigger for a Stop trigger order. If the trigger order has no price (a Market order), or if it has already filled, the current mid price of the trigger order's legs is used instead (the last trade price for any leg that has no mid). If a leg has neither, the reference price falls back to 0.01, so an OTOCO with a Market trigger order is rejected when no quote is available for it.

The example above passes: the trigger order buys at 157.97, the profit Limit credit is at 198.68 (above it), and the Stop credit triggers at 143.06 (below it).

An order that breaks these rules is rejected with the preflight error code invalid_triggered_order_price and the message Order price is invalid for this trade.

The same check runs when you replace an order that belongs to an OTOCO with PUT or PATCH on /accounts/{account_number}/orders/{id}. A new trigger order is checked against the existing orders; a new order in orders is checked against the trigger order's price, or against the current mid price once the trigger order has filled.

Related