curl --request GET \
--url https://calibri.io/api/v2/pythia/public/marketsimport requests
url = "https://calibri.io/api/v2/pythia/public/markets"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://calibri.io/api/v2/pythia/public/markets', 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://calibri.io/api/v2/pythia/public/markets",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$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://calibri.io/api/v2/pythia/public/markets"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://calibri.io/api/v2/pythia/public/markets")
.asString();require 'uri'
require 'net/http'
url = URI("https://calibri.io/api/v2/pythia/public/markets")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body[
{
"amount_precision": 2,
"base_unit": "BTCUSD",
"category": "crypto",
"close_at": "2026-07-22T18:00:00Z",
"ctf_no_token_id": "9876543210987654321098765432109876543210",
"ctf_yes_token_id": "1234567890123456789012345678901234567890",
"description": "Resolves YES if the Coinbase BTC-USD close on 31 Dec 2026 is above $70,000.",
"determination_at": "2026-07-23T10:00:00Z",
"event_id": 12345,
"event_rank": 1,
"event_slug": "btc-above-70k-december-2026",
"event_title": "Will BTC close above $70,000 on 31 Dec 2026?",
"group_item_title": "Above $70,000",
"id": "12",
"image_url": "https://cdn.calibri.io/markets/btc-70k.png",
"liquidity_reward": {
"currency": "usdc",
"daily_rate": "3",
"max_spread": "0.045",
"min_size": "20"
},
"market_id": "54321",
"max_price": "0.99",
"min_amount": "1.00",
"min_price": "0.01",
"name": "Will BTC close above $70k on 2026-12-31?",
"open_at": "2026-07-21T10:00:00Z",
"outcome_labels": [
"<string>"
],
"price_precision": 4,
"price_settlement": {
"candle_start": "2026-07-22T18:00:00Z",
"close": 69200.5,
"granularity_seconds": 300,
"open": 68500.75,
"symbol": "BTC-USD",
"tie": false
},
"price_target": {
"cap_strike": 77500,
"comparator": "gte",
"floor_strike": 75000,
"threshold": 77000
},
"quote_currency": "usdc",
"quote_unit": "usdc",
"resolution_source": "Coinbase BTC-USD",
"result": "yes",
"rules": "Settles on the final Coinbase BTC-USD trade price before 23:59:59 UTC.",
"settlement_panel": {
"description": "First consult these sources",
"entries": [
{
"name": "Coinbase",
"tier": "primary",
"url": "https://www.coinbase.com/price/bitcoin"
}
],
"id": 456,
"inherited_from_series": false,
"name": "Primary Sources",
"terms_url": "https://calibri.io/hub/terms-of-use"
},
"status": "active",
"terms": {
"cap_strike": 77500,
"floor_strike": 70000,
"kind": "threshold",
"measure": {
"at": "2026-09-17T00:00:00Z",
"basis": "close",
"granularity_seconds": 60,
"window_start": "2026-09-16T16:00:00Z"
},
"settles_on": "coinbase_spot",
"strike_type": "greater_equal",
"underlying": {
"source": "coinbase",
"symbol": "BTC-USD"
}
},
"title": "Will BTC close above $70,000 on 31 Dec 2026?"
}
]List markets
Every live market as a flat list, with the same object shape as market detail (pricing fields and CTF ids included). An order — including a signed one — can be built straight from a list response without a per-market follow-up call.
curl --request GET \
--url https://calibri.io/api/v2/pythia/public/marketsimport requests
url = "https://calibri.io/api/v2/pythia/public/markets"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://calibri.io/api/v2/pythia/public/markets', 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://calibri.io/api/v2/pythia/public/markets",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$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://calibri.io/api/v2/pythia/public/markets"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://calibri.io/api/v2/pythia/public/markets")
.asString();require 'uri'
require 'net/http'
url = URI("https://calibri.io/api/v2/pythia/public/markets")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body[
{
"amount_precision": 2,
"base_unit": "BTCUSD",
"category": "crypto",
"close_at": "2026-07-22T18:00:00Z",
"ctf_no_token_id": "9876543210987654321098765432109876543210",
"ctf_yes_token_id": "1234567890123456789012345678901234567890",
"description": "Resolves YES if the Coinbase BTC-USD close on 31 Dec 2026 is above $70,000.",
"determination_at": "2026-07-23T10:00:00Z",
"event_id": 12345,
"event_rank": 1,
"event_slug": "btc-above-70k-december-2026",
"event_title": "Will BTC close above $70,000 on 31 Dec 2026?",
"group_item_title": "Above $70,000",
"id": "12",
"image_url": "https://cdn.calibri.io/markets/btc-70k.png",
"liquidity_reward": {
"currency": "usdc",
"daily_rate": "3",
"max_spread": "0.045",
"min_size": "20"
},
"market_id": "54321",
"max_price": "0.99",
"min_amount": "1.00",
"min_price": "0.01",
"name": "Will BTC close above $70k on 2026-12-31?",
"open_at": "2026-07-21T10:00:00Z",
"outcome_labels": [
"<string>"
],
"price_precision": 4,
"price_settlement": {
"candle_start": "2026-07-22T18:00:00Z",
"close": 69200.5,
"granularity_seconds": 300,
"open": 68500.75,
"symbol": "BTC-USD",
"tie": false
},
"price_target": {
"cap_strike": 77500,
"comparator": "gte",
"floor_strike": 75000,
"threshold": 77000
},
"quote_currency": "usdc",
"quote_unit": "usdc",
"resolution_source": "Coinbase BTC-USD",
"result": "yes",
"rules": "Settles on the final Coinbase BTC-USD trade price before 23:59:59 UTC.",
"settlement_panel": {
"description": "First consult these sources",
"entries": [
{
"name": "Coinbase",
"tier": "primary",
"url": "https://www.coinbase.com/price/bitcoin"
}
],
"id": 456,
"inherited_from_series": false,
"name": "Primary Sources",
"terms_url": "https://calibri.io/hub/terms-of-use"
},
"status": "active",
"terms": {
"cap_strike": 77500,
"floor_strike": 70000,
"kind": "threshold",
"measure": {
"at": "2026-09-17T00:00:00Z",
"basis": "close",
"granularity_seconds": 60,
"window_start": "2026-09-16T16:00:00Z"
},
"settles_on": "coinbase_spot",
"strike_type": "greater_equal",
"underlying": {
"source": "coinbase",
"symbol": "BTC-USD"
}
},
"title": "Will BTC close above $70,000 on 31 Dec 2026?"
}
]Query Parameters
Filter on the published status. resolved covers determined and settled
Filter by base unit
Filter by quote unit
asc (default) or desc
Response
OK
2
"BTCUSD"
"crypto"
"2026-07-22T18:00:00Z"
"9876543210987654321098765432109876543210"
CTFYesTokenID / CTFNoTokenID are the on-chain ERC-1155 position ids for this market's two legs, once atlas has registered the condition. nil (and omitted) until then, because a market that is not CTF-registered has no tokens — emitting "" would read as "registered with an empty id".
Published because a token id IS the market-and-outcome identifier: it is derived from (resolver, questionId, collateral), so it names exactly one outcome of one market and never changes. A signed exchange order carries the token id and NO market field — the token id has already answered "which market, which outcome".
Serving them here is what lets an API client build an order from the market it already fetched, rather than making a second authed per-market call for data that is public, immutable and identical for every member.
"1234567890123456789012345678901234567890"
"Resolves YES if the Coinbase BTC-USD close on 31 Dec 2026 is above $70,000."
DeterminationAt is when the outcome is EXPECTED to become knowable — distinct from close, which is only when trading stops.
Published so a member is told the gap in advance. Kalshi's daily-high temperature markets settle 6–7 hours after close because the authoritative report lands hours after the weather; without this field that reads as a stuck market rather than a documented wait.
Omitted when the outcome is expected at close.
"2026-07-23T10:00:00Z"
12345
EventRank is the operator's manual ordering of this market WITHIN its
event (markets.event_rank), ascending. nil = unranked. It exists because
the natural order of a ladder is not derivable from price: a date ladder
reads chronologically, a strike ladder by strike, and neither matches
probability order. When no market in an event carries a rank, the default
sort falls back to probability descending — the right answer for
candidate-style events.
1
EventSlug / EventTitle are the market's event context, denormalised onto the market itself.
A market is not addressable on its own — there is no markets.slug column, and the app routes /event/{slug}?market={id} — so without these a client holding a market from the flat /markets list cannot build a link or name what it belongs to, and has to go back for the event.
Carried even when the market is already nested inside its event (where it is strictly redundant) so a market object means the same thing wherever it is found. A caller that pulls one out of an event payload and passes it on must not end up with something that has quietly lost its context.
EventID is the durable key; the slug is editable and is for display and routing.
"btc-above-70k-december-2026"
"Will BTC close above $70,000 on 31 Dec 2026?"
GroupItemTitle (markets.group_item_title) is this market's short label WITHIN its event — "Atlanta Hawks", "O/U 2.5". nil means the frontend derives one from the title, which is why an unlabelled contender list currently reads "Will Abiy Ahmed be the next Prime Min…".
"Above $70,000"
ID and Status SHADOW the embedded fields of the same json name. The encoder resolves a tag conflict by depth — shallower wins — so these depth-0 fields are what get emitted.
ID because MarketMeta.ID is an int64 while the engine keys on the string form, and clients key on the string.
"12"
"https://cdn.calibri.io/markets/btc-70k.png"
LiquidityReward is what the market pays makers for resting orders today (UTC). Omitted when no reward period covers today.
Show child attributes
Show child attributes
the ID used in the markets/order book
"54321"
"0.99"
"1.00"
"0.01"
Trading parameters. Only the engine knows these, and only for markets it is currently trading — pointers so a settled market omits them rather than publishing zero values that read as real limits.
"Will BTC close above $70k on 2026-12-31?"
"2026-07-21T10:00:00Z"
OutcomeLabels are the display names of this market's two legs, index 0 the YES leg and index 1 the NO leg, with the ["Yes","No"] default already applied — consumers never have to handle NULL. Naming them turns a proposition into a head-to-head, so the chart draws two labelled lines instead of one and the buy buttons carry the contestant's name.
DISPLAY ONLY. The canonical resolution leg is still YES/NO: settlement, the CTF condition and every ledger row are untouched by a relabel.
4
PriceSettlement is the pair of numbers that decided a price-feed market: the deciding candle's open and close.
Published so a settled window can show what happened — price to beat, final price, the difference, and which way it went — WITHOUT reading the asset price history. That independence is the point: history is recorded best-effort over a websocket, so a gap in it must degrade the chart and not the answer. These numbers came from the exchange candle that actually settled the market.
nil for anything not settled from a candle.
Show child attributes
Show child attributes
PriceTarget is the level this market is judged against, published BEFORE it settles.
The sibling of PriceSettlement and deliberately not the same thing. PriceSettlement is what happened and exists only once a market is decided; this is the question, and it is known the moment the market is listed. A strike ladder needs it: every rung shares one underlying price chart and differs only in where its line sits, so without this the front end has a chart and no idea what to draw on it.
nil for anything not judged against a fixed level — an up/down window's reference is its own opening price, which is PriceSettlement's business.
Show child attributes
Show child attributes
"usdc"
"usdc"
"Coinbase BTC-USD"
"yes"
"Settles on the final Coinbase BTC-USD trade price before 23:59:59 UTC."
SettlementPanel is the PUBLISHED, ordered list of authorities this market's outcome may be determined from, resolved from the market's own override or inherited from its series.
Carried on the public payload deliberately. The panel's whole value is that a member could read it BEFORE they traded — an unpublished rule is not the rule anyone agreed to, and a hierarchy that lives only in the admin tool cannot be quoted back at us in a dispute, which is the one situation it exists for.
nil when no panel governs the market, which is the normal case for anything a machine settles.
Show child attributes
Show child attributes
Status because the published vocabulary is narrower than the column.
MarketMeta.Status is scanned straight from markets.aasm_state, which
carries internal states — escalated in particular announces to everyone
holding a position that two reviewers disagreed. Emitting the embedded
field raw is precisely the leak publicMarketStatus exists to prevent, and
shadowing is what makes that unmissable rather than a step someone can
forget.
active, closed, determined, settled, cancelled, voided "active"
Terms is what this market resolves against, as structured fields — the
conditions rules states in prose: kind, strike_type, floor_strike /
cap_strike, underlying, measure (instant, granularity, basis) and settles_on.
rules is for a person and free to change its wording; terms are what code
reads, so an integrator never parses a title to learn the strike. Kalshi
publishes the same thing as strike_type / floor_strike / cap_strike.
Stored by atlas (markets.terms, derived from the resolution source and its
params — atlas owns that derivation) and decoded here only so the published
schema names every field. Omitted for a market with no automated source.
Show child attributes
Show child attributes
"Will BTC close above $70,000 on 31 Dec 2026?"