Get bars
https://api.tickerbot.io/ v2/ bars/ {ticker}/ {interval}OHLCV bars from 1-second through monthly. The prices underneath the table.
Query parameters
string[]requiredTicker symbol, or a comma-separated list (up to 50) for a bulk response keyed by symbol.
enumrequiredBar interval. 2h/4h roll up hourly bars; 1w/1mo roll up daily bars into calendar weeks (Monday start) and months — the bar's t is the bucket start (UTC), and with asof the last bucket is the week/month to date.
1s | One-second bars. Bars only, active universe, back-filled on demand. |
1m | One minute. The finest stored tier; carries the intraday column subset and ~1,100 of ~13,700 tickers. |
5m | Five-minute bars. Bars only. |
15m | Fifteen-minute bars. Bars only. |
30m | Thirty-minute bars. Bars only. |
1h | One hour. Stored tier, intraday column subset, full universe. |
1d | One day. The full-history, full-column tier — the only grain that carries daily-only columns (SMAs, RSI, fundamentals). |
1w | One week, resampled: state columns take the week’s last observation, bars aggregate, rows keyed by the Monday. |
stringWindow start (inclusive): YYYY-MM-DD, ISO timestamp, or epoch-ms. Combines with to for an explicit window; page within it using cursor. Mutually exclusive with asof and before (400).
stringWindow end (inclusive): a bare YYYY-MM-DD means through the end of that day, same as series. Mutually exclusive with asof and before (400).
stringPoint-in-time: the most recent bar whose period had **closed** at or before that moment. A bare YYYY-MM-DD means that day's close. A full timestamp means the last FINISHED bar — at 10:00 ET on a Wednesday the day's close has not happened, so 1d returns Tuesday's bar. Returns one bar unless you also pass limit, which gives the last limit closed bars. Mutually exclusive with before/cursor (400). Unlimited depth.
booleanDefault true: prices are split-adjusted — restated after each later split, as the tape is, so a series is continuous across a split. false returns the price as it printed that day (a name that later did a 1:10 reverse split reads 21.4 adjusted and 2.14 on the tape), which is what a broker fill or a chart from that time shows. Volume scales the other way. Un-adjusted on read from the splits table; the store is untouched.
enumdefault allSub-hour intervals only. all (default) includes pre- and post-market bars. regular keeps bars whose start is in 09:30–16:00 ET (DST-aware). Why you might want it: the vendor buckets trades by SIP report time, and late-reported off-exchange (Form T) prints on thin names can land 20 min to hours late in a pre-market minute — a $1.70 print at 08:13 ET on a $3.85 stock. Daily high/low are untouched by those. limit counts after the filter; paging still works.
integerdefault 100Most-recent N bars. Max 1000 — an over-cap value is clamped, not an error.
stringReturn the N bars ending strictly before this date/timestamp — back-paging. Mutually exclusive with cursor (they are the same control — a 400 when both are sent).
stringContinuation token from a prior response's next_cursor; sugar for before (sending both is a 400; a blank cursor= counts as absent), and the way to page inside a from/to window.
Returns
as_ofstringServer time this response was assembled (ISO 8601).
tickerstringThe symbol you asked for.
intervalstringThe bar size served.
adjustedbooleanWhether the bars are split-adjusted — `true` unless you passed `adjusted=false`.
sessionstringThe session filter applied: `all` (default) or `regular` (09:30–16:00 ET, sub-hour intervals only).
countnumberBars returned in single-symbol mode; the number of SYMBOLS in bulk mode.
coveragestringWhy the page looks the way it does: `covered` when bars were found, `no_data` when the vendor has none for the window, `not_in_minute_tier` when a sub-hour interval was asked of a symbol the minute store does not carry.
next_cursorstringOpaque token for the next page; `null` on the last page. Absent on bulk (comma-list) requests, which are unpaged. Absent on bulk requests — page bulk symbol-by-symbol.
notestringPresent only when there is something to disclose about how the page was served: the first on-demand fetch for an untiered symbol (explains the latency; later calls are stored), or a `1s` page served from the local store because the provider could not be reached. Bulk responses carry `notes[symbol]` instead.
notesobjectBulk (comma-list) requests only: the per-symbol disclosures, keyed by symbol, in place of `note`.
barsarrayOHLCV bars, chronological, in the compact array shape. Bulk requests key this by symbol instead.
Status codes
200400interval; no, malformed, or more than 50 symbols; invalid or contradictory range controls (asof with before-paging, before with cursor, from/to combined with either, from after to, or a malformed bound); a non-positive-integer limit; or an invalid cursor.401Notes
- Bars are the historical stock data: daily bars run back to each ticker's first day of coverage (2003 for the oldest equities; see Tickers for depth by class), delisted names keep their bars, and intraday bars run from 1-second up. History is not only price:
?asof=on any state read rewinds a whole row, and Series pulls any columns over time on one grid. - Supports point-in-time (
asof) and back-paging (before/limit).1dand1hcover the full universe with full history; sub-hour intervals cover the active universe and back-fill on demand. Pass a comma-separated symbol list for a bulk response keyed by symbol. - Prices are split-adjusted at every interval, and re-adjusted retroactively when a later split lands: a bar from before a 1-for-10 reverse split shows the tape price times 10, so a stock that closed at $2.14 that day reads $21.40 once the split is in. There is no unadjusted option today. To match a fill from your broker, scale by the splits dated after that bar;
/v2/events?kind=splitlists them. - Sub-hour bars (
1sthrough30m) include pre-market and after-hours prints, bucketed by the SIP report time rather than the execution time. On thin names an off-exchange trade can be reported an hour or more after it executed, so a pre-market bar can carry a wick far from where the market was in that minute.1dhigh/low counts regular-session trades only, per SIP rules, so the daily bar never shows those wicks. Compute intraday statistics such as MAE/MFE from regular-session bars (09:30 to 16:00 ET); there is no session filter today. - Bars is its own family on purpose, alongside Series: sub-hour intervals, fetch-on-miss coverage, and the compact chart-ready shape live here. To get OHLCV *joined with* indicator or boolean signals on one grid, read series with
columns=close,rsi_14,…instead. - Available at all intervals. The
asofpoint-in-time param is unlimited-depth — see As-of queries. 2h/4hare rollups of the hourly store and1w/1moof the daily store (calendar buckets,t= bucket start), so they carry the same universe and depth as1hand1d. Added in v2.32.0 — until then only the dashboard chart could draw them.1d/1hcover the full universe with full history. Sub-hour (1m/5m/15m/30m) is pre-loaded for the active universe (the minute tier); a symbol outside it is served on demand: the first call fetches from the provider (~3–10s) and stores the result, later calls are sub-second. Each on-demand request fills up to 31 days ending atto/before/now — page further back withnext_cursor. That first response carries anotesaying so./coveragereports the same asminute_tier.on_demand—included:falsethere is not "no data".1s(1-second) bars are served on demand: from our store when it already covers the request through the latest session, otherwise passed through from the provider and served in the same call (the store is filled by earlier requests, so a full page of older stored bars is never mistaken for the latest ones). Second data is not bulk-backfilled — it accumulates as it is requested. Best paired with a tightbefore+limitwindow. When the vendor pass-through is unavailable, the response says so: anote(single-symbol) /notes[symbol](bulk) flags that the range came from the local store only and may be under-covered.coverageiscovered,no_data(universe-wide interval with nothing for the symbol), ornot_in_minute_tier— a gap is always explicit, never a silent empty array.- Paging is
before+limit, withcursor/next_cursoras sugar. Accepts epoch-ms orYYYY-MM-DD; bars come back oldest-first. - For an explicit historical window, pass
from/to(inclusive; same bound semantics as series) and page inside it withcursor.from/todoes not combine withasof(point-in-time) orbefore(tail-paging) — contradictory range controls are a 400, never a silent pick. - The response echoes
adjustedandsession, so a cached page is self-describing. - Path history: this was
/v2/tickers/{ticker}/bars/{interval}until 2026-09-14. That spelling keeps serving forever as an alias — same handler, same response, no deprecation headers.
More examples
curl "https://api.tickerbot.io/v2/bars/AAPL,MSFT/5m?limit=2" \
-H "Authorization: Bearer YOUR_KEY"{
"as_of": "2026-08-11T22:47:23.948Z",
"interval": "5m",
"count": 2,
"bars": {
"AAPL": [ { "t": 1786487400000, "o": 304.975, "h": 304.984, "l": 304.955, "c": 304.975, "v": 890 },
{ "t": 1786487700000, "o": 304.975, "h": 304.975, "l": 304.975, "c": 304.975, "v": 2622 } ],
"MSFT": [ { "t": 1786487400000, "o": 501.9, "h": 501.9, "l": 501.846, "c": 501.846, "v": 617 },
{ "t": 1786487700000, "o": 501.845, "h": 501.845, "l": 501.82, "c": 501.82, "v": 826 } ]
},
"coverage": { "AAPL": "covered", "MSFT": "covered" }
}