API: Discovery & Meta
Changelog
API version history with breaking-change flags. Returns the v2 release log plus the lifecycle status of v1.
GET
/
changelog
API version history with breaking-change flags
curl --request GET \
--url https://api.example.com/changelog \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.example.com/changelog"
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://api.example.com/changelog', 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://api.example.com/changelog",
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://api.example.com/changelog"
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://api.example.com/changelog")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/changelog")
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{
"data": {
"current_version": "<string>",
"v1_status": "stable",
"releases": [
{
"version": "<string>",
"released_at": "<string>",
"summary": "<string>",
"breaking": false,
"changes": []
}
],
"docs_url": "/v2/docs",
"openapi_url": "/v2/openapi.json"
},
"meta": {
"version": "2.0",
"timestamp": "<string>",
"request_id": "<string>",
"symbol": "<string>",
"spot_price": 123,
"computed_at": "<string>",
"freshness_seconds": 123,
"source": [
"<string>"
],
"exchanges_filtered": [
"<string>"
],
"rate_limit": {},
"extra": {}
},
"success": true
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
},
"meta": {
"version": "2.0",
"timestamp": "<string>",
"request_id": "<string>",
"symbol": "<string>",
"spot_price": 123,
"computed_at": "<string>",
"freshness_seconds": 123,
"source": [
"<string>"
],
"exchanges_filtered": [
"<string>"
],
"rate_limit": {},
"extra": {}
},
"success": false
}{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "No data for BTCUSDT"
},
"meta": {
"version": "2.0",
"timestamp": "2026-04-29T12:00:00Z"
}
}{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request parameters",
"details": {
"errors": []
}
},
"meta": {
"version": "2.0",
"timestamp": "2026-04-29T12:00:00Z"
}
}{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again later."
},
"meta": {
"version": "2.0",
"timestamp": "2026-04-29T12:00:00Z"
}
}Static release log with per-version
Venue IDs and tape units: Venue coverage.
breaking flags. Use
breaking: true as the signal to schedule client re-integration tests.
Poll authenticated GET /v2/changelog for the canonical list (newest
first).
Recent versions
| Version | Date | Summary |
|---|---|---|
| 2.9.0 | 2026-08-30 | Per-venue dealer flow on /v2/tape/flow-by-strike via ?include=by_venue, with a venue_disagreement statistic. Venues disagree on direction for about 70% of multi-venue contracts. |
| 2.8.1 | 2026-08-30 | Responses ~17% smaller (float noise trimmed everywhere). Breaking: /v2/options/pcr intraday now honours days and puts exchange_breakdown behind ?include=. |
| 2.8.0 | 2026-08-28 | Breaking: point-in-time as_of on nine endpoints including the raw options chain; time-heatmap filtered history now signed as-of each frame; market series report short windows. |
| 2.7.1 | 2026-08-26 | GET /v2/options/venue-book spread sorts rank tradeable spreads first and crossed books last. |
| 2.7.0 | 2026-08-24 | Crypto market data and spot ETF flows: candles, open interest, funding, CVD, liquidations, ETF flows, and /v2/market/bundle returning them on one shared time axis. |
| 2.6.11 | 2026-08-24 | Historical depth becomes a plan entitlement. Reported in GET /v2/meta, not yet enforced. |
| 2.6.10 | 2026-08-24 | Dealer-flow served from a pre-computed aggregate instead of rebuilt per request. |
| 2.6.9 | 2026-08-23 | Dealer-flow responses carry their own age; last good series retained six hours. |
| 2.6.8 | 2026-08-22 | Dealer-flow no longer makes the first caller in a window wait out a rebuild. |
| 2.6.7 | 2026-08-21 | Fixed: GET /v2/gex/max-pain?expiry=0dte computed across all expirations. |
| 2.6.6 | 2026-08-21 | 429 responses send Retry-After; OpenAPI spec version matches response meta.version. |
| 2.6.5 | 2026-08-20 | Fixed: GET /v2/gex/strike-expiry-heatmap returned 500 on every request. |
| 2.6.4 | 2026-08-20 | meta.extra.aggregation wording no longer describes how the flow model is derived. |
| 2.6.3 | 2026-08-19 | Fixed: GET /v2/gex/stress-history is now per symbol, not always BTC. |
| 2.6.2 | 2026-08-18 | Breaking: consistency pass on GET /v2/options/oi/by-expiry; raw exchange_breakdown removed. |
| 2.6.1 | 2026-08-18 | ?exchanges= returns real per-venue numbers on every surface that accepts it. |
| 2.6.0 | 2026-08-18 | Breaking: WebSocket gex.levels serves FLOW (not std); per-venue open interest on OI surfaces. |
| 2.5.2 | 2026-08-17 | Thalex + Delta India + Delta Global venues. GET /v2/tape/flow-by-strike. |
| 2.5.1 | 2026-08-17 | Thalex chain and tape always-on. |
| 2.5.0 | 2026-08-04 | Breaking: entitlement failures return 403; monthly request quotas; plan ladder. See Rate limits and Errors. |
| 2.4.0 | 2026-07-31 | Derive venue; SOL/HYPE flow coverage notes. |
| 2.3.0 | 2026-07-30 | Dealer / gamma / delta flow endpoints; tape analytics; WS GEX levels. |
| 2.2.0 | 2026-07-30 | Breaking: default positioning=flow. |
See also
Venue coverage
Rate limits
Flow by strike
Authorizations
Your BackQuant API key (same key as v1)
Headers
Response
Successful Response
Show child attributes
Show child attributes
The meta block returned alongside every v2 response.
Every field after version/timestamp is optional because endpoints
attach different combinations - e.g. /v2/status skips symbol, the
chain endpoint sets extra.filter_hash, etc. Listing them here means
SDKs get a typed accessor for each instead of a generic meta: dict.
Show child attributes
Show child attributes
⌘I
API version history with breaking-change flags
curl --request GET \
--url https://api.example.com/changelog \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.example.com/changelog"
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://api.example.com/changelog', 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://api.example.com/changelog",
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://api.example.com/changelog"
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://api.example.com/changelog")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/changelog")
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{
"data": {
"current_version": "<string>",
"v1_status": "stable",
"releases": [
{
"version": "<string>",
"released_at": "<string>",
"summary": "<string>",
"breaking": false,
"changes": []
}
],
"docs_url": "/v2/docs",
"openapi_url": "/v2/openapi.json"
},
"meta": {
"version": "2.0",
"timestamp": "<string>",
"request_id": "<string>",
"symbol": "<string>",
"spot_price": 123,
"computed_at": "<string>",
"freshness_seconds": 123,
"source": [
"<string>"
],
"exchanges_filtered": [
"<string>"
],
"rate_limit": {},
"extra": {}
},
"success": true
}{
"error": {
"code": "<string>",
"message": "<string>",
"details": {}
},
"meta": {
"version": "2.0",
"timestamp": "<string>",
"request_id": "<string>",
"symbol": "<string>",
"spot_price": 123,
"computed_at": "<string>",
"freshness_seconds": 123,
"source": [
"<string>"
],
"exchanges_filtered": [
"<string>"
],
"rate_limit": {},
"extra": {}
},
"success": false
}{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "No data for BTCUSDT"
},
"meta": {
"version": "2.0",
"timestamp": "2026-04-29T12:00:00Z"
}
}{
"success": false,
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request parameters",
"details": {
"errors": []
}
},
"meta": {
"version": "2.0",
"timestamp": "2026-04-29T12:00:00Z"
}
}{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again later."
},
"meta": {
"version": "2.0",
"timestamp": "2026-04-29T12:00:00Z"
}
}