# Historical Data

Historical data delivers past PV yields and weather data for a site. As with the
forecast, you query via the `site_id`; site, strings and configuration come from the
stored site.

```bash
GET /v2/historical/{site_id}
```

In V2, the old V1 endpoints `/recent` and `/history` are **merged into a single
endpoint**.

Timestamps are in the site's **local timezone** by default (see `timezone` in the response).
Pass `?timezone=utc` to receive UTC timestamps ending in `Z` instead.

:::tip
The full parameter and field list is in the [API Reference](/api). This page explains
the concepts.
:::

## Choosing a time range

You specify the time range **either** as a rolling window (`period`) **or** with a fixed
start/end date — not both.

### Rolling window: `period`

`period` follows the pattern `^\d+[dmy]$`:

| Suffix | Meaning                        |
|--------|--------------------------------|
| `d`    | Days (e.g. `7d`)               |
| `m`    | Months (e.g. `3m` = 3 months)  |
| `y`    | Years (e.g. `1y` = 1 year)     |

```bash
GET /v2/historical/{site_id}?period=30d
```

Plain numbers (`30`) are rejected.

### Fixed window: `start_date` / `end_date`

ISO dates (`YYYY-MM-DD`), **both required together**:

```bash
GET /v2/historical/{site_id}?start_date=2026-01-01&end_date=2026-01-31
```

Mixing `period` with `start_date`/`end_date` yields **400**.

## `include` groups

Like the forecast, but **without** `clearsky`:

| Group        | Fields                                                          |
|--------------|-----------------------------------------------------------------|
| `default`    | `pv_power` (PV power in W).                                     |
| `weather`    | Temperature, weather code, wind, humidity, precipitation, snow. |
| `irradiance` | `ghi`, `dhi`, `bni`.                                            |
| `all`        | All groups plus the `strings` block.                           |

:::note
Historical responses contain **no** `daily` aggregate and **no** clear-sky values — only
`values` and (with `strings`/`all`) the per-string `strings` block. The `strings` block
works as in the [forecast](/en/v2/api/forecast).
:::

## Validation & limits

The requested time range is checked against the plan and plausibility:

- `end_date` may be at most **yesterday**.
- `start_date ≤ end_date`.
- Span or start date ≤ your plan limit.

Violations yield **400** with an explanatory message.

| Limit / error               | Behavior                                                                       |
|------------------------------|--------------------------------------------------------------------------------|
| Historical API access        | Without historical access in the plan → **403**.                              |
| Monthly historical limit     | Monthly request limit (per user & endpoint) → **429** when exceeded.          |
| `max_period_days`            | Maximum span per request.                                                     |
| `earliest_start_date`        | Earliest retrievable date.                                                    |

There is **no** caching; every successful request counts toward the monthly limit.

:::tip
You'll find your specific limits on the [Usage & Limits](https://pvnode.com/usage) page.
:::
