# Bars

> OHLCV bars of any ticker, at any timeframe, raw or split- and dividend-adjusted.

Source: https://getmarkethistory.com/docs/bars

A bar is one OHLCV record: open, high, low, close, volume, VWAP and trade count over one
interval. Each source stores its finest timeframe (`/api/v1/timeframes?source=stocks` lists it);
any coarser timeframe is built from it when you ask, in UTC-aligned buckets.

## Query

curl:

```bash
curl -sD - "https://getmarkethistory.com/query/v1/bars/stocks/SPY/1d?start=2024-01-02&end=2024-01-31&adjust=all" \
  -H "Authorization: Bearer $MARKET_HISTORY_KEY"
```

Python client:

```python
from markethistory import Client

mh = Client()  # reads MARKET_HISTORY_KEY

df = mh.frame("stocks", "SPY", "1d", start="2024-01-02", end="2024-01-31", adjust="all")
df[["open", "high", "low", "close", "volume"]].head()
```

Plain `requests`:

```python
import json
import os

import requests

url = "https://getmarkethistory.com/query/v1/bars/stocks/SPY/1d"
params = {"start": "2024-01-02", "end": "2024-01-31", "adjust": "all"}
headers = {"Authorization": f"Bearer {os.environ['MARKET_HISTORY_KEY']}"}

rows = []
while True:
    r = requests.get(url, params=params, headers=headers, timeout=60)
    r.raise_for_status()  # see /docs/errors for what each status means
    rows += [json.loads(line) for line in r.text.splitlines() if line]
    print(r.headers["X-Row-Count"], "rows,", r.headers["X-Bars-Charged"], "bars")
    if "X-Next-Cursor" not in r.headers:
        break
    params["cursor"] = r.headers["X-Next-Cursor"]
```

Response (shape and headers as served; values illustrative):

```http
HTTP/2 200
content-type: application/x-ndjson
x-row-count: 25
x-bars-charged: 100
x-query-ms: 38

{"close":458.21,"gap_fill_method":0,"high":462.37,"is_gap":false,"low":455.87,"open":461.53,"symbol":"SPY","symbol_id":1529,"timestamp":"2024-01-02T00:00:00Z","trade_count":701844,"volume":123623727.6,"vwap":458.996}
{"close":454.24,"gap_fill_method":0,"high":457.31,"is_gap":false,"low":453.78,"open":457.92,"symbol":"SPY","symbol_id":1529,"timestamp":"2024-01-03T00:00:00Z","trade_count":690121,"volume":103585820.9,"vwap":455.402}
```

`GET /query/v1/bars/{source}/{ticker}/{timeframe}`, with a key.

| Parameter      | Meaning                                                                                   |
| -------------- | ----------------------------------------------------------------------------------------- |
| `source`       | The dataset (`stocks`, `fx`, `crypto`, …). `/api/v1/sources` lists them.                  |
| `ticker`       | The symbol, as `/api/v1/symbols` lists it.                                                |
| `timeframe`    | `1s`, `1m`, `5m`, `1h`, `1d`, … The stored one or any coarser one.                        |
| `start`, `end` | Inclusive range (RFC 3339 or a bare date; a bare `end` is that whole UTC day).            |
| `adjust`       | `raw` (default), `splits` or `all` (splits and cash dividends). `stocks` only.            |
| `columns`      | Only these columns, comma-separated.                                                      |
| `limit`        | Rows per page: default 1,000, maximum 100,000.                                            |
| `cursor`       | `X-Next-Cursor` from the previous page.                                                   |
| `format`       | `jsonl` (default), `json`, `csv`, `parquet`, `arrow` or `mbt1`. Every one costs the same. |

Pages run oldest first. Follow `X-Next-Cursor` (or the `Link` header) until it is absent. The
client's `frame()` and `table()` do it for you and fetch Parquet, so a long range arrives as
typed columns ([install it](https://getmarkethistory.com/docs/quickstart#4-into-pandas) with the `pandas` and `arrow`
extras).

`adjust=` rewrites `open`, `high`, `low`, `close`, `vwap` and `volume` from the published
[corporate actions](https://getmarkethistory.com/docs/corporate-actions#adjusted-bars); the stored bars stay raw. Keep the
raw bars when you need to reproduce a backtest exactly: an adjusted history changes each time a
new split or dividend lands.

:::note[What a `1d` bar of US equities is]
A UTC day of minute bars, pre- and after-hours included. Its close is the last trade before
00:00 UTC (20:00 New York in summer, 19:00 in winter), not the 16:00 closing print. In winter the
last after-hours hour of a Friday falls on Saturday UTC, which makes a small Saturday bar. Drop
it, or build daily bars from `1h` in New York time; the
[moving-average guide](https://getmarkethistory.com/docs/guides/moving-average) does both.
:::

## Free sample

Hourly bars of any ticker over the last five years, with no key. With no dates you get the newest
100; with `start`, `end` or `cursor` it pages like the billed path, at most 5,000 bars a page.
Other timeframes and `adjust=` are a 400 there.

curl:

```bash
curl -sD - "https://getmarkethistory.com/api/v1/bars/stocks/AAPL/1h"
```

Python client:

```python
from markethistory import Client

page = Client().preview("stocks", "AAPL")  # no key
page.to_pandas().tail()
```

Plain `requests`:

```python
import json

import requests

url = "https://getmarkethistory.com/api/v1/bars/stocks/AAPL/1h"
params = {}
headers = {}  # the free sample needs no key

rows = []
while True:
    r = requests.get(url, params=params, headers=headers, timeout=60)
    r.raise_for_status()  # see /docs/errors for what each status means
    rows += [json.loads(line) for line in r.text.splitlines() if line]
    if "X-Next-Cursor" not in r.headers:
        break
    params["cursor"] = r.headers["X-Next-Cursor"]
```

Response:

```http
HTTP/2 200
content-type: application/x-ndjson
x-row-count: 100
x-preview-limit: 100
x-preview-from: 2021-11-01T07:20:48Z
x-data-through: 2026-10-31T04:58:00Z

{"close":348.4375,"gap_fill_method":0,"high":348.47,"is_gap":false,"low":347.94,"open":347.98,"symbol":"AAPL","symbol_id":41,"timestamp":"2026-10-22T22:00:00Z","trade_count":1656,"volume":151877.0,"vwap":348.2574253059383}
{"close":348.6,"gap_fill_method":0,"high":348.75,"is_gap":false,"low":348.1428,"open":348.4,"symbol":"AAPL","symbol_id":41,"timestamp":"2026-10-22T23:00:00Z","trade_count":1679,"volume":40918.0,"vwap":348.491937076299}
```

## Columns

`timestamp` (the bar's open, UTC), `open`, `high`, `low`, `close`, `volume`, `vwap`,
`trade_count`, `symbol` and `symbol_id`. `is_gap` and `gap_fill_method` are always `false` and
`0`: a missing interval is absent, never filled. Types and encodings are in
[Data & formats](https://getmarkethistory.com/docs/formats).

## Price

One bar is one bar. A page rounds up to a block of 100, and an empty page is free. A free
account's monthly bars pay for `1h` only; every other timeframe needs
[bought bars](https://getmarkethistory.com/docs/limits#buying-bars).
