Multi-leg spreads
A spread is a single order with more than one leg. Each leg is one instrument, with its own action, quantity, and symbol, and the whole order shares one order-type, price, and price-effect. This guide shows how to assemble the legs array for common option spreads (verticals, iron condors, strangles) and submit them.
Equity Option and Future Option orders can have up to 4 legs. (Equity, Future, and Cryptocurrency orders are limited to 1 leg.) See Orders and order types for the full order model.
Structure each leg
Every option leg needs four fields:
| Leg attribute | Meaning |
|---|---|
instrument-type | Equity Option for equity option spreads, Future Option for futures option spreads. |
symbol | The OCC option symbol, e.g. AAPL 221118C00157500. Fetch symbols from the option chain (see below). |
quantity | A whole number of contracts. Must be positive. |
action | Buy to Open / Sell to Open (opening) or Buy to Close / Sell to Close (closing). |
Each leg must use a distinct symbol — an order with two legs sharing one symbol is rejected. Find option symbols via the option chain, e.g. GET /option-chains/{symbol}/nested, which groups strikes under each expiration with call and put symbols. See the instruments reference for the full set of chain endpoints.
The order-level price is the net debit or credit across all legs. price-effect is Debit (you pay) or Credit (you receive). A net-credit vertical or condor uses Credit; a net-debit spread uses Debit.
Example: vertical spread
A bear call vertical sells a lower strike and buys a higher strike for a net credit. Both legs share the same expiration and quantity.
{
"time-in-force": "Day",
"order-type": "Limit",
"price": "0.85",
"price-effect": "Credit",
"legs": [
{
"instrument-type": "Equity Option",
"symbol": "AAPL 221118C00155000",
"quantity": 1,
"action": "Sell to Open"
},
{
"instrument-type": "Equity Option",
"symbol": "AAPL 221118C00157500",
"quantity": 1,
"action": "Buy to Open"
}
]
}
Example: iron condor
An iron condor is four legs: a put spread below the price and a call spread above it. The defining (short) strikes sit inside the protective (long) strikes, and the order takes a net credit.
{
"source": "my-api-code",
"order-type": "Limit",
"time-in-force": "Day",
"price": "1.51",
"price-effect": "Credit",
"legs": [
{
"instrument-type": "Equity Option",
"symbol": "TSLA 230714P00210000",
"action": "Buy to Open",
"quantity": 1
},
{
"instrument-type": "Equity Option",
"symbol": "TSLA 230714P00215000",
"action": "Sell to Open",
"quantity": 1
},
{
"instrument-type": "Equity Option",
"symbol": "TSLA 230714C00282500",
"action": "Sell to Open",
"quantity": 1
},
{
"instrument-type": "Equity Option",
"symbol": "TSLA 230714C00290000",
"action": "Buy to Open",
"quantity": 1
}
]
}
Example: strangle
A strangle follows the same idea with two legs instead of four — sell (or buy) an out-of-the-money put and an out-of-the-money call at the same expiration.
Dry-run first, then submit
Always validate a multi-leg order before routing it. POST the same JSON to the dry-run endpoint, inspect the buying-power-effect, fee-calculation, and any warnings, then submit the live order only if it looks right.
POST /accounts/{account_number}/orders/dry-run
Authorization: Bearer ACCESS_TOKEN
User-Agent: my-app/1.0.0
Content-Type: application/json
The live endpoint is POST /accounts/{account_number}/orders. Send your 15-minute OAuth access token from POST /oauth/token in the Authorization header, and always include a User-Agent: product/version header. The API does not deduplicate retried submissions and there is no idempotency-key header, so make retries safe yourself: dry-run first, submit with a unique external-identifier (the order response echoes it back), and if the outcome is uncertain (timeout or 5xx), check GET /accounts/{account_number}/orders (or /orders/live) for that identifier before resubmitting. See Idempotency and retries and Rate limits and backoff.
A failed validation returns 422 with an error payload listing each problem (for example cant_buy_for_credit when buying for a credit). Other HTTP errors follow the usual 400/401/403/404/429/5xx codes — see Errors.
See the full request and response schema in the orders reference. New to the API? Start with Get started.