Overview

Details about how to obtain access tokens using OAuth 2.0

Fetch positions, balances and other account related details.

Place equity and complex option trades including advanced orders.

Fetch quotes, chains and historical data via REST and streaming APIs.

Stream market data and account events in real-time.

Create and update custom watchlists.

Examples, response types, property details and explanations.

Place an OTOCO Order

  • Available in Paper Trading
  • Available in Production
  • Available to Advisors
  • Supported

Place a one-triggers-one-cancels-other order. This order type is composed of three separate orders sent simultaneously. The property keys of each order are indexed.

Please note these specific validations:

  • If all equity orders, second and third orders must have the same symbol.
  • If all option orders, second and third orders must have the same option_symbol.
  • Second and third orders must always have a different type.
  • If sending duration per leg, second and third orders must have the same duration.
POST

Headers

Header Required Values/Example Default
Accept Optional application/xml, application/json application/xml
Authorization Required Bearer {token}

Parameters

Parameter Type Param Type Required Values/Example Default
account_id Path String Required VA000000
Account number
class Form String Required otoco
The kind of order to be placed.
duration Form String Required day
Time the order will remain active. One of: day, gtc, pre, post. Alternatively, it can also be sent per leg (duration[index]) as long as the main duration is omitted.
symbol[index] Form String Required SPY
Underlying security symbol of the options
quantity[index] Form String Required 10
The number of contracts for this leg
type[index] Form String Required limit
The type of order to be placed.
First order, one of: limit, stop, stop_limit
Second order, one of: limit, stop, stop_limit
Third order, one of: limit, stop, stop_limit
option_symbol[index] Form String Required SPY190605C00282000
OCC option symbol of the option to be traded for this leg. Required for option orders.
side[index] Form String Required buy_to_open
The side of the leg.
Equity orders, one of: buy, buy_to_cover, sell, sell_short
Option orders, one of: buy_to_open, buy_to_close, sell_to_open, sell_to_close
price[index] Form String Optional 1.00
Limit price. Required only for limit, stop_limit, debit and credit orders.
stop[index] Form String Optional 1.00
Stop price. Required only for stop and stop_limit orders.
tag Form String Optional my-tag-example-1
Order tag.
Maximum lenght of 255 characters.
Valid characters are letters, numbers and -

Code Example

If you're developing using a paper trading account, change the hostname to https://sandbox.tradier.com
curl -X POST "https://api.tradier.com/v1/accounts/{account_id}/orders" \
     -H 'Authorization: Bearer <TOKEN>' \
     -H 'Accept: application/json' \
     -H 'Content-Type: application/x-www-form-urlencoded' \
     -d 'class=otoco&duration=day&type[0]=limit&price[0]=9.16&option_symbol[0]=SPY190621C00080000&side[0]=buy_to_open&quantity[0]=1&type[1]=limit&price[1]=14.50&option_symbol[1]=SPY190621C00085000&side[1]=sell_to_open&quantity[1]=1&type[2]=stop_limit&price[2]=13.90&stop[2]=14.00&option_symbol[2]=SPY190621C00085000&side[2]=sell_to_open&quantity[2]=1'
// Version 1.8.0_31    
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

import java.io.IOException;

public class MainClass {
  public static void main(String[] args) throws IOException {
    final HttpUriRequest request = RequestBuilder
        .post("https://api.tradier.com/v1/accounts/{account_id}/orders")
        .addHeader("Authorization", "Bearer <TOKEN>")
        .addHeader("Accept", "application/json")
        .addParameter("class", "otoco")
        .addParameter("duration", "day")
        .addParameter("type[0]", "limit")
        .addParameter("price[0]", "9.16")
        .addParameter("option_symbol[0]", "SPY190621C00080000")
        .addParameter("side[0]", "buy_to_open")
        .addParameter("quantity[0]", "1")
        .addParameter("type[1]", "limit")
        .addParameter("price[1]", "14.50")
        .addParameter("option_symbol[1]", "SPY190621C00085000")
        .addParameter("side[1]", "sell_to_open")
        .addParameter("quantity[1]", "1")
        .addParameter("type[2]", "stop_limit")
        .addParameter("price[2]", "13.90")
        .addParameter("stop[2]", "14.00")
        .addParameter("option_symbol[2]", "SPY190621C00085000")
        .addParameter("side[2]", "sell_to_open")
        .addParameter("quantity[2]", "1")
        .build();

    final HttpResponse response = HttpClientBuilder.create().build().execute(request);
    final String jsonString = EntityUtils.toString(response.getEntity());
    final JsonNode json = new ObjectMapper().readTree(jsonString);
    
    System.out.println(response.getStatusLine().getStatusCode());
    System.out.println(json);
  }
}
# Version 2.5.0p0    
require 'uri'
require 'net/http'

url = URI("https://api.tradier.com/v1/accounts/{account_id}/orders")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <TOKEN>'
request["Accept"] = 'application/json'
request["Content-Type"] = 'application/x-www-form-urlencoded'
request.body = "class=otoco&duration=day&type[0]=limit&price[0]=9.16&option_symbol[0]=SPY190621C00080000&side[0]=buy_to_open&quantity[0]=1&type[1]=limit&price[1]=14.50&option_symbol[1]=SPY190621C00085000&side[1]=sell_to_open&quantity[1]=1&type[2]=stop_limit&price[2]=13.90&stop[2]=14.00&option_symbol[2]=SPY190621C00085000&side[2]=sell_to_open&quantity[2]=1"

response = http.request(request)
puts response.code
puts response.read_body
// Version go1.12      
package main

import (
    "fmt"
    "net/http"
    "net/url"
    "io/ioutil"
    "log"
    "strconv"
    "strings"
)

func main() {
    apiUrl := "https://api.tradier.com/v1/accounts/{account_id}/orders"
    data := url.Values{} 
    data.Set("class", "otoco") 
    data.Set("duration", "day") 
    data.Set("type[0]", "limit") 
    data.Set("price[0]", "9.16") 
    data.Set("option_symbol[0]", "SPY190621C00080000") 
    data.Set("side[0]", "buy_to_open") 
    data.Set("quantity[0]", "1") 
    data.Set("type[1]", "limit") 
    data.Set("price[1]", "14.50") 
    data.Set("option_symbol[1]", "SPY190621C00085000") 
    data.Set("side[1]", "sell_to_open") 
    data.Set("quantity[1]", "1") 
    data.Set("type[2]", "stop_limit") 
    data.Set("price[2]", "13.90") 
    data.Set("stop[2]", "14.00") 
    data.Set("option_symbol[2]", "SPY190621C00085000") 
    data.Set("side[2]", "sell_to_open") 
    data.Set("quantity[2]", "1")

    u, _ := url.ParseRequestURI(apiUrl)
    urlStr := u.String()

    client := &http.Client{}
    r, _ := http.NewRequest("POST", urlStr, strings.NewReader(data.Encode()))
    r.Header.Add("Authorization", "Bearer <TOKEN>")
    r.Header.Add("Accept", "application/json")
    r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
    r.Header.Add("Content-Length", strconv.Itoa(len(data.Encode())))

    resp, _ := client.Do(r)
    responseData, err := ioutil.ReadAll(resp.Body)

    if err != nil {
      log.Fatal(err)
    }

    fmt.Println(resp.Status)
    fmt.Println(string(responseData))
}
// Version 4.6.2.0    
using System;
using System.Net;  
using System.IO;
using System.Text;

public class MainClass {
  public static void Main (string[] args) {
    var request = (HttpWebRequest)WebRequest.Create("https://api.tradier.com/v1/accounts/{account_id}/orders");
    var requestData = "class=otoco&duration=day&type[0]=limit&price[0]=9.16&option_symbol[0]=SPY190621C00080000&side[0]=buy_to_open&quantity[0]=1&type[1]=limit&price[1]=14.50&option_symbol[1]=SPY190621C00085000&side[1]=sell_to_open&quantity[1]=1&type[2]=stop_limit&price[2]=13.90&stop[2]=14.00&option_symbol[2]=SPY190621C00085000&side[2]=sell_to_open&quantity[2]=1";
    var data = Encoding.ASCII.GetBytes(requestData);
    
    request.Method = "POST";
    request.Headers["Authorization"] = "Bearer <TOKEN>";
    request.Accept = "application/json";
    request.ContentType = "application/x-www-form-urlencoded";
    request.ContentLength = data.Length;

    using (var stream = request.GetRequestStream())
     {
         stream.Write(data, 0, data.Length);
     }

    var response = (HttpWebResponse)request.GetResponse();

    Console.WriteLine (response.StatusCode);
    var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
    Console.WriteLine (responseString);
  }
}
// Version 10.15.2    
const request = require('request');

request({
    method: 'post',
    url: 'https://api.tradier.com/v1/accounts/{account_id}/orders',
    form: {
       'class': 'otoco',
       'duration': 'day',
       'type[0]': 'limit',
       'price[0]': '9.16',
       'option_symbol[0]': 'SPY190621C00080000',
       'side[0]': 'buy_to_open',
       'quantity[0]': '1',
       'type[1]': 'limit',
       'price[1]': '14.50',
       'option_symbol[1]': 'SPY190621C00085000',
       'side[1]': 'sell_to_open',
       'quantity[1]': '1',
       'type[2]': 'stop_limit',
       'price[2]': '13.90',
       'stop[2]': '14.00',
       'option_symbol[2]': 'SPY190621C00085000',
       'side[2]': 'sell_to_open',
       'quantity[2]': '1'
    },
    headers: {
      'Authorization': 'Bearer <TOKEN>',
      'Accept': 'application/json'
    }
  }, (error, response, body) => {
      console.log(response.statusCode);
      console.log(body);
  });
# Version 3.6.1    
import requests

response = requests.post('https://api.tradier.com/v1/accounts/{account_id}/orders',
    data={'class': 'otoco', 'duration': 'day', 'type[0]': 'limit', 'price[0]': '9.16', 'option_symbol[0]': 'SPY190621C00080000', 'side[0]': 'buy_to_open', 'quantity[0]': '1', 'type[1]': 'limit', 'price[1]': '14.50', 'option_symbol[1]': 'SPY190621C00085000', 'side[1]': 'sell_to_open', 'quantity[1]': '1', 'type[2]': 'stop_limit', 'price[2]': '13.90', 'stop[2]': '14.00', 'option_symbol[2]': 'SPY190621C00085000', 'side[2]': 'sell_to_open', 'quantity[2]': '1'},
    headers={'Authorization': 'Bearer <TOKEN>', 'Accept': 'application/json'}
)
json_response = response.json()
print(response.status_code)
print(json_response)
<?php
// Version 7.2.17-0ubuntu0.18.04.1
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://api.tradier.com/v1/accounts/{account_id}/orders');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'class=otoco&duration=day&type[0]=limit&price[0]=9.16&option_symbol[0]=SPY190621C00080000&side[0]=buy_to_open&quantity[0]=1&type[1]=limit&price[1]=14.50&option_symbol[1]=SPY190621C00085000&side[1]=sell_to_open&quantity[1]=1&type[2]=stop_limit&price[2]=13.90&stop[2]=14.00&option_symbol[2]=SPY190621C00085000&side[2]=sell_to_open&quantity[2]=1');

$headers = array();
$headers[] = 'Authorization: Bearer <TOKEN>';
$headers[] = 'Accept: application/json';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close ($ch);
echo $http_code;
echo $result;

Response

{
  "order": {
    "id": 257459,
    "status": "ok",
    "partner_id": "c4998eb7-06e8-4820-a7ab-55d9760065fb"
  }
}