> ## Documentation Index
> Fetch the complete documentation index at: https://docs.metastreams.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# OHLCV candles

> Read one token's candle series at any timeframe, priced or by market cap.

```http theme={null}
GET /v1/tokens/{chain}/{address}/ohlcv
```

Candles come oldest first, one per bucket that traded. A bucket with no trades is left out. The series follows the TradingView contract: `countBack` asks for a bar count and supersedes `from`, while `to` and `timeframe` still bind.

## Path parameters

<ParamField path="chain" type="string" required>
  The [chain slug](/concepts/chains).
</ParamField>

<ParamField path="address" type="string" required>
  The token's address.
</ParamField>

## Query parameters

<ParamField query="timeframe" type="string" default="1m">
  Bucket size. One of `1s`, `5s`, `15s`, `30s`, `1m`, `3m`, `5m`, `15m`, `30m`, `1h`, `4h`, `6h`, `12h`, `1d`, `7d`. A width outside this set has no rows behind it and is refused.
</ParamField>

<ParamField query="metric" type="string" default="marketCap">
  What the OHLC values measure: `price` or `marketCap`.
</ParamField>

<ParamField query="denomination" type="string" default="usd">
  What they are denominated in: `usd` or `native`.
</ParamField>

<ParamField query="from" type="integer">
  Window start in milliseconds, inclusive. Ignored when `countBack` is set. A window holding more than 5000 candles keeps the newest.
</ParamField>

<ParamField query="to" type="integer">
  Window end in milliseconds, exclusive.
</ParamField>

<ParamField query="countBack" type="integer">
  The most recent N buckets at or before `to`, between 1 and 5000. Takes priority over `from`.
</ParamField>

A request that names neither `countBack` nor `from` returns the most recent 500 buckets. To read older candles, repeat the request with `to` set to the earliest `time` you received; see [Paging through candles](/concepts/pagination#paging-through-candles).

## Response

<ResponseField name="candles" type="object[]" required>
  Buckets, oldest first.

  <Expandable title="candle">
    <ResponseField name="time" type="integer" required>
      The bucket's open time, in milliseconds.
    </ResponseField>

    <ResponseField name="open" type="number" required>
      Opening value.
    </ResponseField>

    <ResponseField name="high" type="number" required>
      Highest value.
    </ResponseField>

    <ResponseField name="low" type="number" required>
      Lowest value.
    </ResponseField>

    <ResponseField name="close" type="number" required>
      Closing value.
    </ResponseField>

    <ResponseField name="volume" type="number" required>
      Traded volume, in the requested denomination.
    </ResponseField>
  </Expandable>
</ResponseField>

Candle values are JSON numbers, not the decimal strings the token and trade objects carry. They feed charting libraries, which take numbers.

## Errors

| Code | When |
| - | - |
| `UNSUPPORTED_CHAIN` | `chain` is not a supported slug |
| `VALIDATION_ERROR` | A malformed address, an unknown `timeframe`, `from` greater than `to`, a `countBack` outside 1–5000, or an unknown parameter |

An unknown token answers an empty series, not a `404`.

<RequestExample>
  ```bash cURL theme={null}
  curl "https://{{API_HOST}}/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/ohlcv?timeframe=1h&metric=price&countBack=24" \
    -H "Authorization: Bearer $API_KEY"
  ```

  ```typescript TypeScript theme={null}
  const url = new URL(
    "https://{{API_HOST}}/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/ohlcv",
  );
  url.searchParams.set("timeframe", "1h");
  url.searchParams.set("metric", "price");
  url.searchParams.set("countBack", "24");

  const response = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.API_KEY}` },
  });
  if (!response.ok) throw new Error(`HTTP ${response.status}`);
  const { candles } = await response.json();
  ```

  ```rust Rust theme={null}
  use serde_json::Value;

  let series: Value = reqwest::Client::new()
      .get("https://{{API_HOST}}/v1/tokens/solana/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263/ohlcv")
      .query(&[("timeframe", "1h"), ("metric", "price"), ("countBack", "24")])
      .bearer_auth(std::env::var("API_KEY")?)
      .send()
      .await?
      .error_for_status()?
      .json()
      .await?;

  for candle in series["candles"].as_array().into_iter().flatten() {
      println!("{} {}", candle["time"], candle["close"]);
  }
  ```
</RequestExample>

<ResponseExample>
  ```json Series theme={null}
  {
    "candles": [
      { "time": 1789545600000, "open": 0.0000221, "high": 0.0000224, "low": 0.0000219, "close": 0.0000222, "volume": 2104410.5 },
      { "time": 1789549200000, "open": 0.0000222, "high": 0.0000223, "low": 0.0000215, "close": 0.0000216, "volume": 2981337.2 }
    ]
  }
  ```

  ```json Inverted window theme={null}
  {
    "error": {
      "code": "VALIDATION_ERROR",
      "message": "One or more parameters are invalid.",
      "details": [{ "field": "from", "message": "Must not be greater than `to`." }]
    }
  }
  ```
</ResponseExample>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.