The whole API is one endpoint.
POST SQL, get JSON rows back. The full reference fits on this page: two endpoints, five tables, and an MCP server.
First query
- 01Sign in at app.outcome.sh. Magic-link email, no password and no credit card.
- 02Create a key under API Keys in the dashboard. Keys are shown once.
- 03POST your SQL:
curl -X POST https://api.outcome.sh/v1/execute \
-H "Authorization: Bearer $OUTCOME_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "SELECT max(created_time) AS last_trade FROM trades"}'Playground
The playground runs the same queries in the browser, with the live schema, charts, and an AI analyst. No key required.
MCP
Claude, Cursor, and other MCP clients can explore the schema and run queries through the MCP server.
API keys
Every request authenticates with an API key in the Authorization header. Keys are created and revoked in the dashboard, belong to your team, and spend the team credit balance. The same key works for the execute endpoint and the MCP server.
Authorization: Bearer $OUTCOME_API_KEY- Each key is rate limited to 60 requests per second.
- A leaked key can spend your credits. Revoke it from the API Keys page.
GET /v1/schemais public and needs no key.
Execute a query
Runs a single read-only SQL statement against the warehouse and returns the rows as a JSON array. SELECT, WITH, EXPLAIN, and SHOW are permitted; anything that writes, touches system tables, or reaches external data is rejected before it runs.
Request body
A single read-only SQL statement. Results are capped at 10,000 rows and 15 minutes of execution.
When true, applies the ClickHouse FINAL modifier so markets and trades return merged, deduplicated rows instead of occasional pre-merge duplicates. Slower and scans more; use it only when exact dedup matters.
Example
curl -X POST https://api.outcome.sh/v1/execute \
-H "Authorization: Bearer $OUTCOME_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "SELECT ticker, yes_price FROM markets ORDER BY volume_24h DESC LIMIT 5"}'[
{ "ticker": "KXMENWORLDCUP-26-ES", "yes_price": 0.999 },
{ "ticker": "KXTECHLAYOFFS-26", "yes_price": 0.911 },
{ "ticker": "KXUSAALIENS-27", "yes_price": 0.074 }
]Usage headers
Every successful response reports what the query cost:
Credits charged for this query.
Wall-clock execution time in milliseconds.
Bytes the warehouse scanned to answer the query.
Team balance after the charge. Omitted when the query was not charged.
HTTP/2 200
X-Credits-Used: 3
X-Duration-Ms: 118
X-Bytes-Read: 204811520
X-Credits-Remaining: 49997The live schema
Returns every queryable table with its columns and exact ClickHouse types. Public, no key required. Feed it to a code generator or an agent before it writes SQL.
curl https://api.outcome.sh/v1/schema{
"tables": [
{
"name": "markets",
"columns": [
{ "name": "venue", "type": "LowCardinality(String)" },
{ "name": "ticker", "type": "String" },
{ "name": "yes_price", "type": "Float64" },
...
]
},
...
]
}The tables
Kalshi is live today, more venues are on the way. The venue column tells rows apart, so queries keep working as venues are added.
Outcome is an analytical warehouse, not a trading feed: new markets, trades, and book updates land within five minutes of the venue. Build research and dashboards on it, not HFT.
Types below are simplified. For exact ClickHouse types, use GET /v1/schema.
markets
One row per market, updated continuously while it trades: title, status, current prices, volume, liquidity, and the rules text that defines resolution.
-- What does the market believe right now?
SELECT title, round(yes_price * 100, 1) AS chance
FROM markets
WHERE status = 'open'
ORDER BY volume_24h DESC
LIMIT 5- venuetext
- tickertext
- event_tickertext
- titletext
- yes_sub_titletext
- no_sub_titletext
- statustext
- resulttext
- market_typetext
- strike_typetext
- yes_pricefloat
- no_pricefloat
- yes_bidtext
- yes_asktext
- no_bidtext
- no_asktext
- volumefloat
- volume_24hfloat
- liquiditytext
- yes_liquidityfloat
- no_liquidityfloat
- notional_valuetext
- rules_primarytext
- rules_secondarytext
- open_timetimestamp
- created_timetimestamp
- close_timetimestamp
- expiration_timetimestamp
- expected_expiration_timetimestamp
- updated_timetimestamp
- is_deleteduint8
trades
Every trade at tick level, from a market opening to its resolution. Prices are the YES and NO contract prices in dollars, count is the number of contracts.
-- Replay one market's price path
SELECT created_time, yes_price
FROM trades
WHERE ticker = 'KXMENWORLDCUP-26-ES'
ORDER BY created_time- venuetext
- trade_idtext
- tickertext
- yes_pricefloat
- no_pricefloat
- countfloat
- taker_sidetext
- taker_book_sidetext
- taker_outcome_sidetext
- created_timetimestamp
- is_deleteduint8
orderbooks
The latest order book snapshot per market: best bids and asks on both sides, spreads, available liquidity, and the full depth levels as JSON.
-- Tightest markets right now
SELECT ticker, yes_bid, yes_ask, spread_yes
FROM orderbooks
WHERE spread_yes IS NOT NULL
ORDER BY spread_yes ASC
LIMIT 10- venuetext
- tickertext
- yes_bidfloat
- yes_askfloat
- no_bidfloat
- no_askfloat
- spread_yesfloat
- spread_nofloat
- yes_liquidityfloat
- no_liquidityfloat
- yes_levelstext
- no_levelstext
- updated_timetimestamp
historical_orderbooks
Every order book update, sequenced. The same shape as orderbooks plus a sequence_number, so you can reconstruct the book at any point in time.
-- Liquidity over time for one market
SELECT updated_time, yes_liquidity, no_liquidity
FROM historical_orderbooks
WHERE ticker = 'KXMENWORLDCUP-26-ES'
ORDER BY sequence_number- venuetext
- tickertext
- yes_bidfloat
- yes_askfloat
- no_bidfloat
- no_askfloat
- spread_yesfloat
- spread_nofloat
- yes_liquidityfloat
- no_liquidityfloat
- yes_levelstext
- no_levelstext
- sequence_numberbigint
- updated_timetimestamp
resolved_markets
The final result of every settled market, one row per resolution.
-- Resolution outcomes across all settled markets
SELECT result, count() AS markets
FROM resolved_markets
GROUP BY result- venuetext
- tickertext
- resulttext
The MCP server
A remote MCP server for Claude, Cursor, and any other MCP client: the agent discovers the schema and queries the market itself. Streamable HTTP (protocol 2025-06-18), authenticated with your API key, with the same read-only rules, rate limits, and billing as the execute endpoint. Nothing to install or host.
Connect a client
claude mcp add --transport http outcome https://api.outcome.sh/v1/mcp \
--header "Authorization: Bearer YOUR_API_KEY"Tools
List every public table with its columns and types. Takes no arguments.
Return the schema of a single table by name.
Fetch a bounded sample of rows (up to 100) from one table, optionally restricted to specific columns. The server generates the SQL; no arbitrary queries.
Execute a read-only SQL query with exactly the same rules, limits, and billing as POST /v1/execute. Returns rows plus row count, bytes read, credits used, and duration.
A typical session: list_tables once, a preview or two, then run_query. Billed tools report credits used in their results.
Credits and limits
1,000 credits equal one dollar. Only successful queries are charged: one base credit, plus one credit per 100 MB scanned, plus a time cost that rises steeply past a minute:
| query duration | approx. time cost |
|---|---|
| 1 second | 1 credit · $0.001 |
| 30 seconds | 11 credits · $0.011 |
| 60 seconds | 1,000 credits · $1.00 |
| 5 minutes | 5,000 credits · $5.00 |
Set spend limits and auto reload in Billing.
Errors
Errors return a JSON body with an error message and, where a machine needs to react, a stable code:
{
"error": "team spend limit exceeded",
"code": "team_spend_limit_exceeded"
}The body is malformed, the query is empty, the SQL fails to parse, or the statement is not read-only.
No Authorization header, or the key is wrong or revoked.
The team balance cannot cover the query, or the query ran past its byte budget.
The result is too large. Add a LIMIT or aggregate before returning.
The key exceeded 60 requests per second, or the query would exceed the spend limit set in Billing.
Transient billing outage. Retry with backoff.
The query hit the 15 minute limit.
Start querying
Magic-link sign in, no credit card.
Questions or missing data? Academics and researchers get free credits. Write to support@outcome.sh.