Find markets by what their book and tape are doing
Screens the whole live catalogue by spread, resting depth, rolling volume, open interest and price, rather than by text. Numbers are live from the market-vitals cache (sub-second book and tape), joined to the discover cache for titles; a market the discover cache has never seen is still returned, under its id, with hasMetadata: false.
Prices and spread are in cents, money in dollars. At least one metric bound is required — an unfiltered screen is a ranking, not a screen, and is rejected with 400.
spread is ask - bid on one outcome, and a book with only one side cannot be crossed, so it has no spread: any query bounding spread only matches markets quoting both sides. two_sided asks for that explicitly without bounding the width. Bounds are compared on one canonical price scale, so a threshold means the same width on every venue whatever scale that venue publishes.
curl --request GET \
--url https://data.kairos.trade/search/screener \
--header 'X-Api-Key: <api-key>' \
--header 'X-Api-Secret: <api-key>' \
--header 'X-Client-Id: <api-key>'import requests
url = "https://data.kairos.trade/search/screener"
headers = {
"X-Client-Id": "<api-key>",
"X-Api-Key": "<api-key>",
"X-Api-Secret": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {
'X-Client-Id': '<api-key>',
'X-Api-Key': '<api-key>',
'X-Api-Secret': '<api-key>'
}
};
fetch('https://data.kairos.trade/search/screener', 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://data.kairos.trade/search/screener",
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>",
"X-Api-Secret: <api-key>",
"X-Client-Id: <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://data.kairos.trade/search/screener"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-Client-Id", "<api-key>")
req.Header.Add("X-Api-Key", "<api-key>")
req.Header.Add("X-Api-Secret", "<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://data.kairos.trade/search/screener")
.header("X-Client-Id", "<api-key>")
.header("X-Api-Key", "<api-key>")
.header("X-Api-Secret", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://data.kairos.trade/search/screener")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-Client-Id"] = '<api-key>'
request["X-Api-Key"] = '<api-key>'
request["X-Api-Secret"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"markets": [
{
"id": "<string>",
"marketId": "<string>",
"provider": "<string>",
"title": "<string>",
"eventTitle": "<string>",
"image": "<string>",
"icon": "<string>",
"category": "<string>",
"status": "<string>",
"hasMetadata": true,
"outcomeIndex": 123,
"matchedLeg": true,
"outcomeName": "<string>",
"bid": 123,
"ask": 123,
"mid": 123,
"spread": 123,
"price": 123,
"volume24h": 123,
"volume1h": 123,
"liquidity": 123,
"outcomeLiquidity": 123,
"bookAgeSeconds": 123,
"openInterest": 123,
"openInterestNotional": 123,
"updatedAt": "2023-11-07T05:31:56Z"
}
],
"total": 123,
"available": true,
"plan": "<string>",
"limit": 123,
"offset": 123
}{
"detail": "Invalid provider: acme"
}{
"detail": "Not authenticated"
}{
"detail": "Invite required"
}{
"detail": [
{}
]
}{
"error": "Rate limit exceeded: 100 per 1 minute"
}{
"detail": "Invalid provider"
}Authorizations
Credential client id (kairos_ck_...). Must be sent together with X-Api-Key and X-Api-Secret.
64-char hex API key.
64-char hex API secret.
Query Parameters
Cents. Only two-sided books can satisfy a spread bound.
0 <= x <= 100Cents.
0 <= x <= 100Cents, on the matched outcome's mid.
0 <= x <= 100Cents, on the matched outcome's mid.
0 <= x <= 100Dollars traded in the rolling 24h window.
x >= 0Dollars traded in the rolling 1h window.
x >= 0Dollars resting across every outcome, both sides.
x >= 0Dollars resting across every outcome, both sides. Pair with a volume floor to find thin books carrying heavy flow.
x >= 0Dollars resting on the matched outcome alone, both sides.
x >= 0Contracts outstanding.
x >= 0Only markets quoting a bid and an ask. A settled market has no quotes at all, which would otherwise read as infinitely thin.
Drop markets whose top of book has not been published within this many minutes. Settled and delisted markets stop being streamed, so their frozen book would otherwise screen as a live quote — on a live catalogue that is more than half the records. 0 removes the bound and returns them.
The timestamp is the streamer's publish clock, so this detects "nothing is publishing this market any more", not "the venue's book went quiet": a wedged venue connection re-publishing a cached book still stamps now.
x >= 0Repeatable. Restricts the screen to these venues.
volume_24h, volume_1h, spread_desc, spread_asc, liquidity, open_interest 1 <= x <= 5000 <= x <= 10000Response
A page of matching markets, most relevant to the chosen sort first.
Show child attributes
Show child attributes
Matches before paging. -1 means the ordered walk stopped at the page bound and the rest were not counted — render it as "top N", not as a count.
False when the live vitals service could not be reached. Distinct from a screen that matched nothing, which is available with an empty markets.
How the scan ran (index_ordered, index_range, scan). Diagnostic.
Was this page helpful?
curl --request GET \
--url https://data.kairos.trade/search/screener \
--header 'X-Api-Key: <api-key>' \
--header 'X-Api-Secret: <api-key>' \
--header 'X-Client-Id: <api-key>'import requests
url = "https://data.kairos.trade/search/screener"
headers = {
"X-Client-Id": "<api-key>",
"X-Api-Key": "<api-key>",
"X-Api-Secret": "<api-key>"
}
response = requests.get(url, headers=headers)
print(response.text)const options = {
method: 'GET',
headers: {
'X-Client-Id': '<api-key>',
'X-Api-Key': '<api-key>',
'X-Api-Secret': '<api-key>'
}
};
fetch('https://data.kairos.trade/search/screener', 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://data.kairos.trade/search/screener",
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>",
"X-Api-Secret: <api-key>",
"X-Client-Id: <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://data.kairos.trade/search/screener"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-Client-Id", "<api-key>")
req.Header.Add("X-Api-Key", "<api-key>")
req.Header.Add("X-Api-Secret", "<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://data.kairos.trade/search/screener")
.header("X-Client-Id", "<api-key>")
.header("X-Api-Key", "<api-key>")
.header("X-Api-Secret", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://data.kairos.trade/search/screener")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-Client-Id"] = '<api-key>'
request["X-Api-Key"] = '<api-key>'
request["X-Api-Secret"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"markets": [
{
"id": "<string>",
"marketId": "<string>",
"provider": "<string>",
"title": "<string>",
"eventTitle": "<string>",
"image": "<string>",
"icon": "<string>",
"category": "<string>",
"status": "<string>",
"hasMetadata": true,
"outcomeIndex": 123,
"matchedLeg": true,
"outcomeName": "<string>",
"bid": 123,
"ask": 123,
"mid": 123,
"spread": 123,
"price": 123,
"volume24h": 123,
"volume1h": 123,
"liquidity": 123,
"outcomeLiquidity": 123,
"bookAgeSeconds": 123,
"openInterest": 123,
"openInterestNotional": 123,
"updatedAt": "2023-11-07T05:31:56Z"
}
],
"total": 123,
"available": true,
"plan": "<string>",
"limit": 123,
"offset": 123
}{
"detail": "Invalid provider: acme"
}{
"detail": "Not authenticated"
}{
"detail": "Invite required"
}{
"detail": [
{}
]
}{
"error": "Rate limit exceeded: 100 per 1 minute"
}{
"detail": "Invalid provider"
}
