API
With a key in hand, three commands put a file on your disk. The first block below is copy-pasteable as-is.
Sixty seconds
Replace the key on line 1 with your own (shown once on the page right after payment); paste the rest as-is.
# 1. your key, from the page you saw right after paying export OT_KEY="ck_a1b2c3d4e5f6.xxxxxxxxxxxxxxxxxxxxxxxx" # 2. what can I get? curl -s -H "Authorization: Bearer $OT_KEY" \ https://outcometick.com/v1/meta # 3. find a file, then download it curl -s -H "Authorization: Bearer $OT_KEY" \ "https://outcometick.com/v1/files?asset=btc&dataset=prices" curl -L -H "Authorization: Bearer $OT_KEY" \ "https://outcometick.com/v1/dl/2026-08-12/BTCUSD-prices-2026-08-12.csv.gz" \ -o BTCUSD-prices-2026-08-12.csv.gz
The -L in step 3 matters: the download endpoint answers with a 302 to a short-lived object-storage URL. Files come straight from storage — they never pass through our server.
One line in Python
pandas, DuckDB and wget cannot attach a header to a URL, so the download endpoint also accepts ?api_key=. Be aware it puts the key in browser history and proxy logs — prefer the header wherever you can set one.
import pandas as pd
KEY = "ck_a1b2c3d4e5f6.xxxxxxxxxxxxxxxxxxxxxxxx"
df = pd.read_csv(
"https://outcometick.com/v1/dl/2026-08-12/"
"BTCUSD-prices-2026-08-12.csv.gz?api_key=" + KEY
)
print(df.head())Common tasks
One day, one asset, one interval
Every filter is optional. Use date for a single day, or from / to for a range.
# every BTC 5-minute order book for one day curl -s -H "Authorization: Bearer $OT_KEY" \ "https://outcometick.com/v1/files?date=2026-08-12&asset=btc&interval=5m&dataset=book"
A month of settlement prices, verified on the way in
Each file carries a sha256 identical to the archive manifest. A match proves you have exactly what we published — not merely that the transfer succeeded.
#!/usr/bin/env bash
# a month of BTC settlement prices, downloaded and checksum-verified
set -euo pipefail
export OT_KEY="ck_a1b2c3d4e5f6.xxxxxxxxxxxxxxxxxxxxxxxx"
curl -s -H "Authorization: Bearer $OT_KEY" \
"https://outcometick.com/v1/files?asset=btc&dataset=prices&from=2026-07-14&to=2026-08-12" \
| jq -r '.files[] | "\(.url) \(.name) \(.sha256)"' \
| while read -r url name sha; do
curl -sL -H "Authorization: Bearer $OT_KEY" "$url" -o "$name"
echo "$sha $name" | sha256sum -c -
doneStraight into one DataFrame
import pandas as pd, requests
KEY = "ck_a1b2c3d4e5f6.xxxxxxxxxxxxxxxxxxxxxxxx"
BASE = "https://outcometick.com"
auth = {"Authorization": f"Bearer {KEY}"}
# every 1-minute kline for BTC over a week
r = requests.get(f"{BASE}/v1/files", headers=auth, params={
"asset": "btc", "dataset": "klines", "interval": "1m",
"from": "2026-08-06", "to": "2026-08-12",
})
files = r.json()["files"]
df = pd.concat(
pd.read_csv(f["url"] + "?api_key=" + KEY) for f in files
).sort_values("ts_ms")
print(len(df), "rows")The three endpoints
GET /v1/meta — See what you can get
The dimensions come back already narrowed to your tier — a Polymarket plan never sees Predict.fun. Note the venues do not cover the same assets: Polymarket 8, Predict.fun 3.
{
"firstDay": "2026-06-06", "lastDay": "2026-08-12", "days": 68,
"venues": ["polymarket"],
"assets": ["BNB","BTC","DOGE","ETH","HYPE","SOL","XRP","ZEC"],
"intervals": ["1s","1m","3m","5m","15m","30m","1h","2h","4h","6h","8h","12h","1d","3d","1w","1mo"],
"datasets": { "prices": "…", "book": "…", "klines": "…" }
}GET /v1/files — Find files
Every file in the response carries its own url; hand it straight to your downloader.
| Filters (all optional) | |
|---|---|
| asset | btc / eth / … comma-separated for several, e.g. asset=btc,eth |
| dataset | prices / twap30s / twap60s / book / price_change / last_trade_price / markets / klines |
| interval | 5m and 15m for markets; 1m, 1h, 1d … for klines |
| venue | polymarket / predict |
| date | a single day — same as from=to=that day |
| from / to | a range, at most 92 days per call. Omit both for the latest day |
{
"from": "2026-08-12", "to": "2026-08-12", "days": 1,
"count": 1, "bytes": 1655751,
"files": [{
"date": "2026-08-12",
"name": "BTCUSD-prices-2026-08-12.csv.gz",
"asset": "BTC",
"dataset": "prices",
"interval": null,
"bytes": 1655751,
"sha256": "a8b4f866772578e4…",
"url": "https://outcometick.com/v1/dl/2026-08-12/BTCUSD-prices-2026-08-12.csv.gz"
}]
}GET /v1/dl/:date/:name — Download one file
Answers 302 to a short-lived object-storage URL (valid 15 minutes). Use curl -L, or any client that follows redirects.
When something goes wrong
| 401 | Wrong key, revoked key, or a lapsed subscription. Try the /v1/meta call from step 2 — if that works, the key is fine. |
| 403 date outside… | That day is outside your coverage. The floor field in the response is the earliest date you can request; Pro is the trailing 30 days. |
| 404 file not found in your scope | Either the file does not exist for that day, or it is not part of your tier (e.g. a Polymarket plan asking for a Predict.fun file). List /v1/files for the day to see what is actually there. |
| files returns an empty array | Filters too narrow or misspelled. Drop a filter, or check /v1/meta for the valid values. |
| 429 | Too many requests — back off and retry. |
| 5xx | Temporary; retrying is safe. |
Reading the fields
| feed_ts_ms | Event time: the timestamp upstream put on the report (UTC ms) |
| server_ts_ms | When the upstream server sent it |
| recv_ms | When we received it. All three are kept apart, never merged — so you can measure the capture path |
| value | Price as a float, for convenience |
| full_accuracy_value | The same price as a fixed-point integer string (1e18). Use this to recompute outcomes, not value |
| strike_value | The price to beat for that market. Null when we cannot establish it honestly — never guessed from a nearby tick |
| outcome_prices | The settlement. ["1","0"] means Up won, ["0","1"] means Down won |
Two conventions you need
The settlement rule changed on 2026-08-07
Before it, the instantaneous Chainlink stream decided the outcome; after it, the TWAP streams do (30s lookback for 5-minute markets, 60s for 15-minute). Pick the rule from the market’s own raw.cryptoMarketConfig.twapEnabled rather than from the date — both kinds coexist on the same day.
Frames are stored as received
Out-of-order included; we do not reorder an archive. Sort at query time if you need chronological order. Gaps are likewise not hidden — the paid dataset ships a daily coverage report.