<!-- Public documentation export; not library implementation source. -->
# Historical bars and countBack

`getBars(symbolInfo, resolution, period, onHistory, onError)` returns OHLCV bars in time order. `period.from` and `period.to` are in Unix seconds, but each bar's `time` is in epoch milliseconds.

## Return the history the chart asks for

The time window is `[from, to)`: it includes `from` and excludes `to`. `countBack` is the number of bars the chart actually needs, so treat it as the main target. If the window has too few bars, add earlier bars when you have them. If the window has more bars than `countBack`, it's fine to return them all; don't cut the response short.

Return bars with unique timestamps in ascending order and OHLC values that make sense. Daily, weekly and monthly bars are stamped at 00:00 UTC on the trading day. Don't use a local session-open time.

## Match historical and realtime boundaries

History and realtime updates must use the same interval boundaries, symbol, and price basis. For UTC-aligned H1 bars, each candle starts at `11:00`, `12:00`, and so on. A tick at `11:06` updates the candle starting at `11:00`; it doesn't start a new hour-long candle at `11:06`.

The chart uses the timestamps your datafeed supplies. It doesn't automatically realign provider candles. Align the provider's aggregation request **before** it calculates OHLCV. Rounding a returned candle's timestamp cannot correct its contents: a candle covering `11:06–12:06` contains different trades or quotes from one covering `11:00–12:00`.

### Example: Polygon minute multipliers

Polygon's `60/minute` aggregation can preserve a request's starting minute. A request starting at `11:06` can therefore produce H1 candles at `11:06`, `12:06`, and so on. For fixed UTC intervals, align the request start to the same boundary used by your live aggregator:

```js
const intervalMs = 60 * 60_000; // H1; use 15 * 60_000 for M15.
const fromMs = period.from * 1000; // getBars uses seconds.
const alignedFromMs = Math.floor(fromMs / intervalMs) * intervalMs;
const inclusiveToMs = period.to * 1000 - 1; // Convert [from, to) for this provider.

// Use alignedFromMs and inclusiveToMs in the provider's aggregate request.
// Keep the returned OHLCV values and candle-start timestamps together.
```

This may request an earlier candle that overlaps `period.from`; account for that when selecting enough history to satisfy `countBack`. Providers can also expand request boundaries or limit the number of base aggregates they scan. Validate the returned timestamps against your exclusive `to`, page as needed, and return bars in ascending order. See [Polygon/Massive's aggregation rules](https://massive.com/blog/aggs-api-updates) for its snapping and stretching behavior.

The [tick-to-candle helper](https://docs.lumencharts.com/charting-library/datafeed/tick-aggregation#match-your-history-boundaries) uses fixed UTC boundaries by default. For exchange-session or calendar-based intervals, use a shared market-calendar policy for historical aggregation and the helper's `bucketStart` callback instead of assuming fixed UTC blocks.

## "No more data" versus "something went wrong"

```js
onHistory([], { noData: true }); // no older data exists
onError('History is temporarily unavailable'); // request failed
```

A temporary error doesn't mean the history has run out. If you return only a few bars, the chart may ask for older data a limited number of times. When your provider pages its results, keep fetching pages until you have enough bars or you've truly reached the start of the data.

## Handle late responses safely

Keep track of which symbol, resolution and request each response belongs to. An old request that finishes late shouldn't overwrite newer data. Cache keys should include the provider and any metadata that changes what a bar means.

[Runnable example](https://docs.lumencharts.com/examples?example=minimal) · [Time and sessions](https://docs.lumencharts.com/charting-library/datafeed#time-units-and-trading-sessions)

---
Documentation page: https://docs.lumencharts.com/charting-library/datafeed/history
