# Stock Candles

Get historical price candles for stocks or ETFs.

## Endpoint
```
https://api.marketdata.app/v1/stocks/candles/{resolution}/{symbol}/
```
### Method
```
GET
```
## Request Example

### HTTP

**GET** [https://api.marketdata.app/v1/stocks/candles/D/AAPL/?from=2024-01-01&to=2024-01-31](https://api.marketdata.app/v1/stocks/candles/D/AAPL/?from=2024-01-01&to=2024-01-31)

### JavaScript

```js title="app.js"
import { MarketDataClient } from "@marketdata/sdk";

const client = new MarketDataClient();

try {
  const candles = await client.stocks.candles("AAPL", {
    resolution: "D",
    from: "2024-01-01",
    to: "2024-01-31",
  });
  for (const c of candles) {
    console.log(`t=${c.t} o=${c.o} h=${c.h} l=${c.l} c=${c.c} v=${c.v}`);
  }
} catch (error) {
  console.error(error);
}
```

### TypeScript

```typescript title="app.ts"
import { MarketDataClient } from "@marketdata/sdk";
import type { StockCandle } from "@marketdata/sdk";

const client = new MarketDataClient();

try {
  const candles: StockCandle[] = await client.stocks.candles("AAPL", {
    resolution: "D",
    from: "2024-01-01",
    to: "2024-01-31",
  });
  for (const c of candles) {
    console.log(`t=${c.t} o=${c.o} h=${c.h} l=${c.l} c=${c.c} v=${c.v}`);
  }
} catch (error) {
  console.error(error);
}
```

### Python

```python title="app.py"
from marketdata import MarketDataClient

client = MarketDataClient()
candles = client.stocks.candles("AAPL", resolution="D", from_date="2024-01-01", to_date="2024-01-31")
print(candles)
```

### Go

```go title="stockCandles.go"

import (
  "fmt"

  api "github.com/MarketDataApp/sdk-go"
)

func ExampleStockCandlesRequest() {
	candles, err := StockCandles().Resolution("D").Symbol("AAPL").From("2024-01-01").To("2024-01-31").Get()
	if err != nil {
		fmt.Print(err)
		return
	}

	for _, candle := range candles {
		fmt.Println(candle)
	}
}

```

### PHP

```php title="stockCandles.php"
use MarketDataApp\Client;

$client = new Client();
$candles = $client->stocks->candles(
    symbol: "AAPL",
    from: "2024-01-01",
    to: "2024-01-31",
    resolution: "D"
);

// Display formatted candles summary
echo $candles;
```

### Java

```java title="StockCandles.java"
import com.marketdata.sdk.MarketDataClient;
import com.marketdata.sdk.stocks.StockCandlesRequest;
import com.marketdata.sdk.stocks.StockResolution;
import java.time.LocalDate;

try (MarketDataClient client = new MarketDataClient()) {
    var candles = client.stocks().candles(
        StockCandlesRequest.builder(StockResolution.DAILY, "AAPL")
            .from(LocalDate.parse("2024-01-01"))
            .to(LocalDate.parse("2024-01-31"))
            .build());
    candles.values().forEach(System.out::println);
}
```

### Kotlin

```kotlin title="StockCandles.kt"
import com.marketdata.sdk.MarketDataClient
import com.marketdata.sdk.stocks.StockCandlesRequest
import com.marketdata.sdk.stocks.StockResolution
import java.time.LocalDate

MarketDataClient().use { client ->
    val candles = client.stocks().candles(
        StockCandlesRequest.builder(StockResolution.DAILY, "AAPL")
            .from(LocalDate.parse("2024-01-01"))
            .to(LocalDate.parse("2024-01-31"))
            .build())
    candles.values().forEach(::println)
}
```

### C#

```csharp title="StockCandles.cs"
using MarketDataApp;
using MarketDataApp.Stocks;

using var client = await MarketDataClient.CreateAsync();

var candles = await client.Stocks.GetCandlesAsync(
    StockResolution.Daily, "AAPL",
    from: DateOnly.Parse("2024-01-01"), to: DateOnly.Parse("2024-01-31"));
foreach (var candle in candles.Values)
{
    Console.WriteLine(candle);
}
```

## Response Example

```json
{
  "s": "ok",
  "c": [217.68, 221.03, 219.89],
  "h": [222.49, 221.5, 220.94],
  "l": [217.19, 217.1402, 218.83],
  "o": [221.03, 218.55, 220],
  "t": [1569297600, 1569384000, 1569470400],
  "v": [33463820, 24018876, 20730608]
}
```

## Request Parameters

### Required

- **resolution** `string`

  The duration of each candle. *Case-insensitive*.

  **Intraday Resolutions:**
  - Minutely Resolutions: (`minutely`, `1`, `3`, `5`, `15`, `30`, `45`, ...)
  - Hourly Resolutions: (`hourly`, `H`, `1H`, `2H`, ...)

  **Daily Resolutions:**
  - Daily Resolutions: (`daily`, `D`, `1D`, `2D`, ...)
  - Weekly Resolutions: (`weekly`, `W`, `1W`, `2W`, ...)
  - Monthly Resolutions: (`monthly`, `M`, `1M`, `2M`, ...)
  - Yearly Resolutions: (`yearly`, `Y`, `1Y`, `2Y`, ...)

- **symbol** `string`

  The company's ticker symbol.

### Dates

All `date` parameters are optional. By default the most recent candle is returned if no date parameters are provided.

- **from** `date`

  The leftmost candle on a chart (inclusive). From and countback are mutually exclusive. If you use `countback`, `from` must be omitted. Accepted timestamp inputs: ISO 8601, unix, spreadsheet. 

- **to** `date`

  The rightmost candle on a chart (inclusive). Accepted timestamp inputs: ISO 8601, unix, spreadsheet.

- **countback** `number`

  Will fetch a specific number of candles before (to the left of) `to`. From and countback are mutually exclusive. If you use `from`, `countback` must be omitted.

> [!NOTE]
> There is no maximum date range limit on daily candles. When requesting intraday candles of any resolution, no more than 1 year of data can be requested in a single request.

### Optional

- **extended** `boolean`

  Include extended hours trading sessions when returning *intraday* candles. Daily resolutions _never_ return extended hours candles.

  - Daily candles default: `false`.
  - Intraday candles default: `false`.

- **adjustsplits** `boolean`

  Adjust historical data for stock splits. Market Data uses the CRSP methodology for adjustment. Only certain combinations with `adjustdividends` are supported — see [Split and Dividend Adjustments](#split-and-dividend-adjustments).

  - Daily candles default: `true`.
  - Intraday candles default: `false`.

- **adjustdividends** `boolean`

  Adjust historical data for dividends. Market Data uses the CRSP methodology for adjustment. Dividend adjustment is available for daily resolutions only. Unsupported combinations are rejected with an HTTP 400 — see [Split and Dividend Adjustments](#split-and-dividend-adjustments).

  - Daily candles default: `true`.
  - Intraday candles default: `false`.

- **adjustdividends** `boolean`

  Adjust historical data for cash dividends. Market Data uses the CRSP methodology for adjustment.

  - Daily candles default: `true`.
  - Intraday candles default: `false`.

By default, daily candles are fully CRSP-adjusted for both splits and dividends. To retrieve split-adjusted-only data (the most common request), set `adjustdividends=false` and leave `adjustsplits` at its default of `true`.

> [!NOTE]
> There is no dividend-only adjustment. Requesting `adjustsplits=false` while `adjustdividends` remains `true` (its default) is unsupported and returns an HTTP `400` error. Because `adjustdividends` defaults to `true` on daily candles, passing only `adjustsplits=false` resolves to this rejected combination — the response's `errmsg` states exactly this and tells you to also set `adjustdividends=false` explicitly. To retrieve fully raw, unadjusted daily data, you must set both `adjustsplits=false` and `adjustdividends=false` explicitly.

### Split and Dividend Adjustments

Only three price series are supported: **raw**, **split-only**, and **fully adjusted** (CRSP-style). There is no dividend-only series — no data source publishes one — so that combination is rejected with an HTTP 400.

**Daily** — the `adjustsplits=false, adjustdividends=true` combination is rejected. Because `adjustdividends` defaults to `true` on daily candles, this is most commonly triggered by passing `adjustsplits=false` alone. To receive raw prices on daily candles, set **both** `adjustsplits=false` and `adjustdividends=false`.

| `adjustsplits` | `adjustdividends` | Series         | Result       |
|:--------------:|:-----------------:|----------------|--------------|
| `false`        | `false`           | raw            | ✅           |
| `true`         | `false`           | split-only     | ✅           |
| `true`         | `true`            | fully adjusted | ✅ (default) |
| `false`        | `true`            | dividend-only  | ❌ HTTP 400  |

The rejected daily combination returns:

```json
{"s":"error","errmsg":"Unsupported parameter combination: adjustsplits=false with adjustdividends=true. Note: adjustdividends defaults to true on daily candles, so if your request only sets adjustsplits=false (without explicitly setting adjustdividends), dividend adjustment is still being applied via the default. Dividend-only adjustment is not supported. To receive unadjusted prices, set both adjustsplits=false and adjustdividends=false explicitly. To keep CRSP-style full adjustment, omit adjustsplits (or set it to true)."}
```

**Intraday** — any `adjustdividends=true` is rejected regardless of `adjustsplits`, because no intraday data source implements dividend adjustment. The intraday default is `false`, so the error only occurs on an explicit `adjustdividends=true`.

| `adjustsplits` | `adjustdividends` | Series         | Result       |
|:--------------:|:-----------------:|----------------|--------------|
| `false`        | `false`           | raw            | ✅ (default) |
| `true`         | `false`           | split-only     | ✅           |
| `false`        | `true`            | dividend-only  | ❌ HTTP 400  |
| `true`         | `true`            | fully adjusted | ❌ HTTP 400  |

Both rejected intraday combinations return:

```json
{"s":"error","errmsg":"adjustdividends=true is not supported for intraday candles. Dividend adjustment is only available for daily resolutions."}
```

## Response Attributes

### Success

- **s** `string`

  ll always be `ok` when there is data for the candles requested.

- **o** `array[number]`

  Open price.

- **h** `array[number]`

  High price.

- **l** `array[number]`

  Low price.

- **c** `array[number]`

  Close price.

- **v** `array[number]`

  Volume.

- **t** `array[number]`

  Candle time. For intraday candles, this is the candle's start time. For daily and longer resolutions, this is midnight US Eastern Time on the session date. All timestamps use US Eastern Time (America/New_York). See [Response Timezone](https://www.marketdata.app/docs/docs/api/dates-and-times#response-timezone) for details.

### No Data

- **s** `string`

  Status will be `no_data` if no candles are found for the request.

- **nextTime** `number` optional

  Unix time of the next quote if there is no data in the requested period, but there is data in a subsequent period.

### Error

- **s** `string`

  Status will be `error` if the request produces an error response.

- **errmsg** `string`
  An error message.

## Usage Information

### Data Availability

**Real-time data is not available for this endpoint under any plan or entitlement.** The type of candle data you receive depends on your user type and UTP entitlement. This may include 15-minute delayed candles or historical candles (1 day old), depending on the plan or access level.

| User Type        | UTP Entitlement | Candle Type            |
|------------------|-----------------|------------------------|
| Non-Professional | ✅              | 15-min delayed         |
| Non-Professional | ❌              | Historical (1 day old) |
| Professional     | Any             | Historical (1 day old) |
| Unknown          | Any             | Historical (1 day old) |

> [!NOTE]
> **What are entitlements?**
>
> Entitlements are permissions granted by exchanges that allow access to their data. To get 15-minute delayed candles, non-professional users need to sign the [UTP agreement](https://www.marketdata.app/docs/account/entitlements). [Learn more about entitlements](https://www.marketdata.app/docs/account/entitlements).

### Pricing

The cost of using the candle API endpoint is 1 credit per 1000 candles.

| Data Type              | Cost Basis       | Credits Required per Unit |
|------------------------|------------------|---------------------------|
| 15-minute Delayed Data | Per 1000 candles | 1 credit                  |
| Historical Data        | Per 1000 candles | 1 credit                  |
| Real-Time Data         | Not available    | N/A                       |
