Recent trade tape for a contract
Returns the most recent individual trades for a single (provider, contract_id) pair,
newest first, deduplicated by trade id. Only rows with price > 0 AND price <= 100 AND size > 0 are eligible.
Price unit: price is on the integer-cents scale 0–100 for every provider
(Kalshi, Polymarket, predict.fun, Hyperliquid alike) — it is NOT a 0–1 probability and
NOT already divided into dollars. Multiply size * price / 100 to get USD notional.
price is returned as a float because some venues (e.g. Kalshi) report sub-penny ticks.
Window semantics: the query window is [now - window_seconds, before_or_now]. The
lower bound is always computed from the current server time, not from before —
passing a before older than now - window_seconds can invert the window. If the
primary window yields zero rows, the handler transparently retries with an unbounded
lower bound [0, before_or_now] so contracts with no recent activity still return
their most recent historical trades. has_more reflects an internal over-fetch of
limit + 1 rows, truncated back to limit before serialization.
Rate-limit cost (HEAVY bucket): priced by requested depth — a larger limit
consumes more of your quota.
Caching: responses are cached for 3s per replica (with singleflight coalescing) to
absorb duplicate concurrent requests, and the implicit now upper bound is quantized to
that same 3s so the cache is usable at all. The HTTP response itself is
Cache-Control: private, max-age=5 with no ETag — this route never returns 304.
Responses ≥1KB are gzip-compressed when the client sends Accept-Encoding: gzip.
curl --request GET \
--url https://md.kairos.trade/v1/trades \
--header 'X-Api-Key: <api-key>' \
--header 'X-Api-Secret: <api-key>' \
--header 'X-Client-Id: <api-key>'import requests
url = "https://md.kairos.trade/v1/trades"
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://md.kairos.trade/v1/trades', 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://md.kairos.trade/v1/trades",
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://md.kairos.trade/v1/trades"
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://md.kairos.trade/v1/trades")
.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://md.kairos.trade/v1/trades")
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{
"trades": [
{
"trade_id": "0x9f2a...c11",
"contract_id": "0x8b1c119419f622e21fc576ec8e9c2c07b2c1b09babf0e1f3d1cb9bfc1a8f9c2",
"size": 250,
"price": 62.5,
"outcome": "Yes",
"timestamp": 1737479998.412,
"token_id": "10945...3321",
"taker_address": "0xabc1234567890abcdef1234567890abcdef1234",
"side": "buy"
}
],
"has_more": true,
"oldest_available_ts": 1737479950.001,
"coverage_hours": 0.01
}{
"error": {
"code": "invalid_request",
"message": "limit must be an integer in [1, 500]"
}
}{
"error": {
"code": "unauthorized",
"message": "valid X-Client-Id, X-Api-Key, and X-Api-Secret headers are required"
}
}{
"error": {
"code": "ip_not_whitelisted",
"message": "source IP not in credential whitelist"
}
}{
"error": {
"code": "rate_limited",
"message": "rate limit exceeded"
}
}{
"error": {
"code": "invalid_request",
"message": "market_ids exceeds maximum 200"
}
}{
"error": {
"code": "rate_limiter_unavailable",
"message": "rate limiter temporarily unavailable"
}
}Authorizations
Credential client id (kairos_ck_...). Must be sent together with X-Api-Key and X-Api-Secret.
64-char hex API key. Must be sent together with X-Client-Id and X-Api-Secret.
64-char hex API secret. Must be sent together with X-Client-Id and X-Api-Key.
Query Parameters
Venue identifier, case-insensitive. Resolved against the central provider registry; kalshi_offchain is an alias for kalshi and dome is an alias for polymarket. opinion resolves but is a disabled provider — valid only for historic reads.
kalshi, kalshi_offchain, polymarket, dome, opinion, predictfun, hyperliquid Venue-scoped contract/token identifier to fetch trades for.
Lookback window, in seconds, measured back from the current server time (not from before). Valid range [3600, 86400]; out-of-range or non-integer values are rejected with 400, not clamped.
3600 <= x <= 86400Maximum number of trades to return, newest first. Valid range is [1, 500]; the default is also 500. Drives the rate-limit cost — see the operation description.
1 <= x <= 500Upper bound of the window as a positive Unix timestamp in seconds (exclusive: trades with trade_ts < before). Omit to use the current time. Must be a positive integer or the request is rejected with 400.
x >= 1Response
Trade page for the window, newest first. trades may be empty (and oldest_available_ts null) if the contract has no recorded trades at all, even after the unbounded fallback query.
Trades in the resolved window, newest first, capped at limit entries.
Show child attributes
Show child attributes
True when the number of trades returned equals the requested limit, meaning more trades likely exist beyond this page.
true
Unix timestamp (seconds, fractional) of the oldest trade in the returned page, or null when trades is empty. Reflects the oldest trade in this response, not necessarily the oldest trade ever recorded for the contract.
1737479950.001
Hours between oldest_available_ts and the request time, rounded to 1 decimal place. 0.0 when trades is empty.
0.01
Was this page helpful?
curl --request GET \
--url https://md.kairos.trade/v1/trades \
--header 'X-Api-Key: <api-key>' \
--header 'X-Api-Secret: <api-key>' \
--header 'X-Client-Id: <api-key>'import requests
url = "https://md.kairos.trade/v1/trades"
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://md.kairos.trade/v1/trades', 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://md.kairos.trade/v1/trades",
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://md.kairos.trade/v1/trades"
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://md.kairos.trade/v1/trades")
.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://md.kairos.trade/v1/trades")
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{
"trades": [
{
"trade_id": "0x9f2a...c11",
"contract_id": "0x8b1c119419f622e21fc576ec8e9c2c07b2c1b09babf0e1f3d1cb9bfc1a8f9c2",
"size": 250,
"price": 62.5,
"outcome": "Yes",
"timestamp": 1737479998.412,
"token_id": "10945...3321",
"taker_address": "0xabc1234567890abcdef1234567890abcdef1234",
"side": "buy"
}
],
"has_more": true,
"oldest_available_ts": 1737479950.001,
"coverage_hours": 0.01
}{
"error": {
"code": "invalid_request",
"message": "limit must be an integer in [1, 500]"
}
}{
"error": {
"code": "unauthorized",
"message": "valid X-Client-Id, X-Api-Key, and X-Api-Secret headers are required"
}
}{
"error": {
"code": "ip_not_whitelisted",
"message": "source IP not in credential whitelist"
}
}{
"error": {
"code": "rate_limited",
"message": "rate limit exceeded"
}
}{
"error": {
"code": "invalid_request",
"message": "market_ids exceeds maximum 200"
}
}{
"error": {
"code": "rate_limiter_unavailable",
"message": "rate limiter temporarily unavailable"
}
}
