TPO
List historical TPO (Market Profile) data
Provide exchange, symbol, and timeframe. Nothing else is required: the
window defaults to the 40 timeframe periods before now.
- With
fromthe window starts there and runs forward, ending attoor afterperiodseconds (40 timeframe periods by default). - Without
fromthe window ends atto(now by default) and runs backwards overperiodseconds or the 40 timeframe periods before it. - The default is measured in wall-clock time, so it holds fewer than 40 periods on an exchange with non-trading days (about 28 for a 1d frame on a weekday-only market).
periodcannot be added to an explicitfrom+towindow.- Supported timeframes are day, week, and month based (1d..31d, 1w..4w, 1M).
- If
fromis not aligned to a timeframe period boundary, the beginning of the next period is used. - The requested range is limited to at most 400 profiles (with
mergeSessions=GROUP_BY_TYPEevery session type of a period counts as a profile); a wider range is rejected with 400too_much_data.
Cost: 25 credits per returned timeframe period (distinct openTradingDay), at least
1000 credits per request. With mergeSessions=GROUP_BY_TYPE one profile per session
type is built for every period at no additional cost.
GET
/
api
/
v1
/
marketdata
/
tpo
List historical TPO (Market Profile) data
curl --request GET \
--url https://public-api.takeprofit.com/api/v1/marketdata/tpo \
--header 'x-api-key: <api-key>'import requests
url = "https://public-api.takeprofit.com/api/v1/marketdata/tpo"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://public-api.takeprofit.com/api/v1/marketdata/tpo', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://public-api.takeprofit.com/api/v1/marketdata/tpo",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://public-api.takeprofit.com/api/v1/marketdata/tpo"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://public-api.takeprofit.com/api/v1/marketdata/tpo")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://public-api.takeprofit.com/api/v1/marketdata/tpo")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"meta": {
"exchange": "BATS",
"symbol": "AAPL",
"timeframe": "1d"
},
"profiles": [
{
"openTradingDay": "2026-09-21T00:00:00Z",
"profileEnd": "2026-09-21T20:00:00Z",
"sessionType": "MAINSESSION",
"rowSize": "0.26",
"pointOfControl": "338.26",
"initialBalanceHigh": "337.74",
"initialBalanceLow": "332.8",
"blocks": [
48600,
50400,
52200,
54000,
55800,
57600,
59400,
61200,
63000,
64800,
66600,
68400,
70200
],
"rows": [
[
"332.8",
[
0
],
"0",
"106"
],
[
"333.06",
[
0
],
"2754",
"4223"
],
[
"333.32",
[
0
],
"7037",
"9217"
],
[
"333.58",
[
0
],
"7783",
"9611"
],
[
"333.84",
[
0
],
"8329",
"15930"
],
[
"334.1",
[
0
],
"9352",
"8254"
],
[
"334.36",
[
0
],
"9777",
"11524"
],
[
"334.62",
[
0
],
"4930",
"2161"
],
[
"334.88",
[
0
],
"7366",
"2128"
],
[
"335.14",
[
0
],
"12193",
"9753"
],
[
"335.4",
[
0
],
"2663",
"1883"
],
[
"335.66",
[
0,
1
],
"10208",
"10787"
],
[
"335.92",
[
0,
1
],
"20081",
"7412"
],
[
"336.18",
[
0,
1,
2
],
"12438",
"4948"
],
[
"336.44",
[
1,
2
],
"21328",
"43779"
],
[
"336.7",
[
1,
2,
3,
4
],
"19068",
"29667"
],
[
"336.96",
[
1,
2,
3,
4
],
"43127",
"21425"
],
[
"337.22",
[
1,
2,
3,
4
],
"20867",
"16892"
],
[
"337.48",
[
1,
2,
3,
4,
5
],
"26492",
"13659"
],
[
"337.74",
[
1,
2,
3,
4,
5,
9
],
"26485",
"10554"
],
[
"338",
[
2,
4,
5,
8,
9,
11
],
"32058",
"16709"
],
[
"338.26",
[
4,
5,
6,
7,
8,
9,
10,
11
],
"34640",
"20544"
],
[
"338.52",
[
5,
6,
7,
8,
9,
10,
11
],
"57464",
"46732"
],
[
"338.78",
[
5,
6,
7,
8,
9,
10,
11,
12
],
"90818",
"36228"
],
[
"339.04",
[
6,
7,
9,
10,
11,
12
],
"43163",
"29151"
],
[
"339.3",
[
11,
12
],
"29120",
"10199"
],
[
"339.56",
[
11,
12
],
"2754",
"3395"
]
]
}
]
}{
"error": {
"code": "invalid_argument",
"message": "query parameter \"exchange\" is required"
}
}{
"error": {
"code": "unauthenticated",
"message": "authentication failed"
}
}{
"error": {
"code": "permission_denied",
"message": "permission denied"
}
}{
"error": {
"code": "not_found",
"message": "security not found"
}
}{
"error": {
"code": "rate_limited",
"message": "rate limit exceeded"
}
}Query Parameters
Public security symbol returned by /api/v1/marketdata/exchanges/{exchange}/securities. TakeProfit security symbol as returned by /api/v1/marketdata/exchanges/{exchange}/securities. In a path segment a slash must be percent-encoded (BTC/USDT is requested as BTC%2FUSDT).
Example:
"AAPL"
Was this page helpful?
⌘I
List historical TPO (Market Profile) data
curl --request GET \
--url https://public-api.takeprofit.com/api/v1/marketdata/tpo \
--header 'x-api-key: <api-key>'import requests
url = "https://public-api.takeprofit.com/api/v1/marketdata/tpo"
headers = {"x-api-key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'x-api-key': '<api-key>'}};
fetch('https://public-api.takeprofit.com/api/v1/marketdata/tpo', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://public-api.takeprofit.com/api/v1/marketdata/tpo",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://public-api.takeprofit.com/api/v1/marketdata/tpo"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://public-api.takeprofit.com/api/v1/marketdata/tpo")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://public-api.takeprofit.com/api/v1/marketdata/tpo")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"meta": {
"exchange": "BATS",
"symbol": "AAPL",
"timeframe": "1d"
},
"profiles": [
{
"openTradingDay": "2026-09-21T00:00:00Z",
"profileEnd": "2026-09-21T20:00:00Z",
"sessionType": "MAINSESSION",
"rowSize": "0.26",
"pointOfControl": "338.26",
"initialBalanceHigh": "337.74",
"initialBalanceLow": "332.8",
"blocks": [
48600,
50400,
52200,
54000,
55800,
57600,
59400,
61200,
63000,
64800,
66600,
68400,
70200
],
"rows": [
[
"332.8",
[
0
],
"0",
"106"
],
[
"333.06",
[
0
],
"2754",
"4223"
],
[
"333.32",
[
0
],
"7037",
"9217"
],
[
"333.58",
[
0
],
"7783",
"9611"
],
[
"333.84",
[
0
],
"8329",
"15930"
],
[
"334.1",
[
0
],
"9352",
"8254"
],
[
"334.36",
[
0
],
"9777",
"11524"
],
[
"334.62",
[
0
],
"4930",
"2161"
],
[
"334.88",
[
0
],
"7366",
"2128"
],
[
"335.14",
[
0
],
"12193",
"9753"
],
[
"335.4",
[
0
],
"2663",
"1883"
],
[
"335.66",
[
0,
1
],
"10208",
"10787"
],
[
"335.92",
[
0,
1
],
"20081",
"7412"
],
[
"336.18",
[
0,
1,
2
],
"12438",
"4948"
],
[
"336.44",
[
1,
2
],
"21328",
"43779"
],
[
"336.7",
[
1,
2,
3,
4
],
"19068",
"29667"
],
[
"336.96",
[
1,
2,
3,
4
],
"43127",
"21425"
],
[
"337.22",
[
1,
2,
3,
4
],
"20867",
"16892"
],
[
"337.48",
[
1,
2,
3,
4,
5
],
"26492",
"13659"
],
[
"337.74",
[
1,
2,
3,
4,
5,
9
],
"26485",
"10554"
],
[
"338",
[
2,
4,
5,
8,
9,
11
],
"32058",
"16709"
],
[
"338.26",
[
4,
5,
6,
7,
8,
9,
10,
11
],
"34640",
"20544"
],
[
"338.52",
[
5,
6,
7,
8,
9,
10,
11
],
"57464",
"46732"
],
[
"338.78",
[
5,
6,
7,
8,
9,
10,
11,
12
],
"90818",
"36228"
],
[
"339.04",
[
6,
7,
9,
10,
11,
12
],
"43163",
"29151"
],
[
"339.3",
[
11,
12
],
"29120",
"10199"
],
[
"339.56",
[
11,
12
],
"2754",
"3395"
]
]
}
]
}{
"error": {
"code": "invalid_argument",
"message": "query parameter \"exchange\" is required"
}
}{
"error": {
"code": "unauthenticated",
"message": "authentication failed"
}
}{
"error": {
"code": "permission_denied",
"message": "permission denied"
}
}{
"error": {
"code": "not_found",
"message": "security not found"
}
}{
"error": {
"code": "rate_limited",
"message": "rate limit exceeded"
}
}