One API key, one HTTPS request. 1-minute bars for 500 liquid US symbols, extended hours included, 5+ years of history.
No SDK required · any language · works with plain curl
Quickstart
No SDK to install. If you have an HTTP client, you are done.
curl -H "Authorization: Bearer $SQUAWK_API_KEY" \ "https://api.squawkquant.com/v1/bars/1m/AAPL\ ?start=2026-08-19&end=2026-08-19&session=regular"
import os, requests, pandas as pd
r = requests.get(
"https://api.squawkquant.com/v1/bars/1m/AAPL",
params={"start": "2026-08-19", "end": "2026-08-19"},
headers={"Authorization": f"Bearer {os.environ['SQUAWK_API_KEY']}"},
timeout=30,
)
r.raise_for_status()
body = r.json()
df = pd.DataFrame(body["data"]["AAPL"], columns=body["meta"]["columns"])
df[["o", "h", "l", "c"]] /= body["meta"]["price_scale"]const res = await fetch(
"https://api.squawkquant.com/v1/bars/1m/AAPL?start=2026-08-19&end=2026-08-19",
{ headers: { Authorization: `Bearer ${process.env.SQUAWK_API_KEY}` } },
);
if (!res.ok) throw new Error((await res.json()).title);
const { data, meta } = await res.json();
const bars = data.AAPL.map((row) =>
Object.fromEntries(meta.columns.map((c, i) => [c, row[i]])),
);req, _ := http.NewRequest("GET",
"https://api.squawkquant.com/v1/bars/1m/AAPL"+
"?start=2026-08-19&end=2026-08-19", nil)
req.Header.Set("Authorization", "Bearer "+os.Getenv("SQUAWK_API_KEY"))
resp, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer resp.Body.Close()
var out struct {
Data map[string][][]any `json:"data"`
Meta struct{ Columns []string `json:"columns"` } `json:"meta"`
}
json.NewDecoder(resp.Body).Decode(&out) {
"data": {
"AAPL": [
[1787146200, 2266714, 2267334,
2263072, 2263483, 13078, 85,
2264630, "regular"]
]
},
"meta": {
"columns": ["ts","o","h","l","c",
"v","n","vw","session"],
"price_scale": 10000,
"as_of": "2026-08-19T20:00:00Z",
"partial": false,
"count": 390
}
} Features
We don't just hand you data — we tell you where its edges are.
Expected vs actual bar counts, per symbol per day. You can tell "data is missing" apart from "nothing traded that minute" — a prerequisite for honest backtesting.
GET /v1/coverage When a vendor revises a bar we keep the old value, the new value and when we detected it. Most cheap APIs mutate silently and you never learn your cached history went stale.
GET /v1/corrections Intraday analysis wants the price that actually traded. We never rewrite history; splits and dividends ship separately so you can adjust on your own terms.
GET /v1/corporate-actions The calendar gives you pre-market, regular and after-hours bounds for every day, including half days and DST shifts. You never have to hand-roll Eastern-time maths.
GET /v1/calendar Every price is an integer scaled by 10,000. Reconcile us against another vendor bar-by-bar and you will not chase phantom differences caused by rounding.
price_scale: 10000 If a limit truncated your result, meta.partial says so. We never return "200 with an empty array" on failure — an error gets an error status code.
meta.partial FAQ
No. Your subscription covers use inside your own applications and strategies. Reselling or publicly displaying the data to third parties — raw or lightly processed — requires a separate redistribution licence, which is constrained by our upstream vendor agreement. Talk to us first if you need this.
Second and tick data stay inside our own systems. Externally we standardise on 1-minute bars, which is both the product position and what lets us make a completeness promise we can actually keep.
A bar is queryable roughly 5–10 seconds after it closes. Poll once a minute; `meta.as_of` on `/v1/snapshot` tells you the cut-off so you can skip a fetch when nothing new has landed.
Not today — REST only. At 1-minute granularity polling once a minute is entirely sufficient, simpler to operate and far easier to debug. Streaming is on the roadmap.
S&P 500 constituents plus major ETFs, around 500 symbols. Query `GET /v1/symbols` for the live list.
Revoke it instantly from the console. Rotation with a grace period is also supported: old and new secrets both work during the window so you can roll out the new key before retiring the old one — no planned downtime.