# GET /v2/bars/{ticker}/{interval}

**Get bars**

OHLCV bars from 1-second through monthly. The prices underneath the table.

## Query / path parameters

| Name | In | Type | Required | Description |
|------|----|----|----------|-------------|
| `ticker` | path | string[] | yes | Ticker symbol, or a comma-separated list (up to 50) for a bulk response keyed by symbol. Example: `NVDA`. |
| `interval` | path | string | yes | Bar 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. Enum: `1s`, `1m`, `5m`, `15m`, `30m`, `1h`, `2h`, `4h`, `1d`, `1w`, `1mo`. Example: `1d`. |
| `from` | query | string | no | Window 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). Example: `2026-08-17`. |
| `to` | query | string | no | Window end (inclusive): a bare `YYYY-MM-DD` means through the end of that day, same as series. Mutually exclusive with `asof` and `before` (400). Example: `2026-06-28`. |
| `asof` | query | string | no | Point-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. Example: `2026-06-28`. |
| `adjusted` | query | boolean | no | Default `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. Example: `false`. |
| `session` | query | string | no | Sub-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. Enum: `all`, `regular`. Default: `all`. Example: `regular`. |
| `limit` | query | integer | no | Most-recent N bars. Max 1000 — an over-cap value is clamped, not an error. Default: `100`. Example: `5`. |
| `before` | query | string | no | Return 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). Example: `2026-06-28`. |
| `cursor` | query | string | no | Continuation 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_of` (string) — Server time this response was assembled (ISO 8601).
- `ticker` (string) — The symbol you asked for.
- `interval` (string) — The bar size served.
- `adjusted` (boolean) — Whether the bars are split-adjusted — `true` unless you passed `adjusted=false`.
- `session` (string) — The session filter applied: `all` (default) or `regular` (09:30–16:00 ET, sub-hour intervals only).
- `count` (number) — Bars returned in single-symbol mode; the number of SYMBOLS in bulk mode.
- `coverage` (string) — Why 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_cursor` (string) — Opaque 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.
- `note` (string) — Present 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.
- `notes` (object) — Bulk (comma-list) requests only: the per-symbol disclosures, keyed by symbol, in place of `note`.
- `bars` (array) — OHLCV bars, chronological, in the compact array shape. Bulk requests key this by symbol instead.

## Status codes

- **200** — Success — the response shape is documented under Returns above.
- **400** — Invalid `interval`; 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.
- **401** — Missing or invalid API key.

## Sample response

```json
{
  "as_of": "2026-08-11T22:47:57.964Z",
  "ticker": "NVDA",
  "interval": "1d",
  "count": 5,
  "coverage": "covered",
  "next_cursor": "1785902400000",
  "bars": [
    { "t": 1785902400000, "o": 216.86, "h": 222.22,   "l": 216.4,   "c": 219.22,  "v": 158187404 },
    { "t": 1785988800000, "o": 221.53, "h": 223.63,   "l": 217,     "c": 218.99,  "v": 113940644 },
    { "t": 1786075200000, "o": 221.54, "h": 224.76,   "l": 220.66,  "c": 223.96,  "v": 105669440 },
    { "t": 1786334400000, "o": 223.4,  "h": 224.1379, "l": 216.77,  "c": 217.55,  "v": 115846596 },
    { "t": 1786420800000, "o": 222.17, "h": 222.201,  "l": 216.442, "c": 217.457, "v": 82019024 }
  ]
}
```

## More examples

### Bulk: 5-minute bars for several symbols

Request:

```shell
curl "https://api.tickerbot.io/v2/bars/AAPL,MSFT/5m?limit=2" \
  -H "Authorization: Bearer YOUR_KEY"
```

Response (`200`):

```json
{
  "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" }
}
```

## Notes

- 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](/docs/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](/docs/endpoints/series) pulls any columns over time on one grid.
- Supports point-in-time (`asof`) and back-paging (`before`/`limit`). `1d` and `1h` cover 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=split`](/docs/endpoints/events/query) lists them.
- Sub-hour bars (`1s` through `30m`) 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. `1d` high/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](/docs/endpoints/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 `asof` point-in-time param is unlimited-depth — see [As-of queries](/docs/asof).
- `2h`/`4h` are rollups of the hourly store and `1w`/`1mo` of the daily store (calendar buckets, `t` = bucket start), so they carry the same universe and depth as `1h` and `1d`. Added in v2.32.0 — until then only the dashboard chart could draw them.
- `1d`/`1h` cover 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 at `to`/`before`/now — page further back with `next_cursor`. That first response carries a `note` saying so. [`/coverage`](/docs/endpoints/tickers/coverage) reports the same as `minute_tier.on_demand` — `included:false` there 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 tight `before`+`limit` window. When the vendor pass-through is unavailable, the response says so: a `note` (single-symbol) / `notes[symbol]` (bulk) flags that the range came from the local store only and may be under-covered.
- `coverage` is `covered`, `no_data` (universe-wide interval with nothing for the symbol), or `not_in_minute_tier` — a gap is always explicit, never a silent empty array.
- Paging is `before` + `limit`, with `cursor`/`next_cursor` as sugar. Accepts epoch-ms or `YYYY-MM-DD`; bars come back oldest-first.
- For an explicit historical window, pass `from`/`to` (inclusive; same bound semantics as [series](/docs/endpoints/series/state)) and page inside it with `cursor`. `from`/`to` does not combine with `asof` (point-in-time) or `before` (tail-paging) — contradictory range controls are a 400, never a silent pick.
- The response echoes `adjusted` and `session`, 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.

---

Interactive sandbox + parameter editor: https://tickerbot.io/docs/endpoints/bars/get
