Initial SolarEdge Optimizer Home Assistant App

This commit is contained in:
2026-08-10 09:04:35 +02:00
commit f2887a0ab4
38 changed files with 4253 additions and 0 deletions
@@ -0,0 +1,498 @@
# SolarEdge Monitoring API reference
Local working reference for the SolarEdge Monitoring API. This file summarizes
the official March 2026 documentation in a compact, implementation-oriented
form. The [official PDF](https://knowledge-center.solaredge.com/sites/kc/files/se_monitoring_api.pdf)
remains the authoritative source.
## Base URL and authentication
```text
https://monitoringapi.solaredge.com
```
All requests use `GET` over HTTPS and pass the API key as the `api_key` query
parameter:
```text
GET /site/{siteId}/overview?api_key={apiKey}
Accept: application/json
```
Only JSON is supported. CSV and XML support were removed in March 2026.
The local server-side configuration is:
```dotenv
SOLAREDGE_API_KEY=...
SOLAREDGE_SITE_ID=...
```
Never expose the API key in browser code, an `EXPO_PUBLIC_` variable, logs, or a
repository. SolarEdge recommends using a site-level key where possible and
rotating keys periodically.
## Dates, time zones, encoding, and units
- Date: `YYYY-MM-DD`
- Date and time: `YYYY-MM-DD hh:mm:ss`
- All dates and times use the site's local time zone.
- URL query values, including spaces in date-times, must be URL encoded.
- Text is UTF-8.
- Physical measurements use metric units; temperatures are Celsius.
- Common time units are `QUARTER_OF_AN_HOUR`, `HOUR`, `DAY`, `WEEK`, `MONTH`,
and `YEAR`. Each endpoint defines which values it accepts.
- A time-series value can be `null` or entirely absent when no measurement is
available.
## Limits and errors
SolarEdge uses standard HTTP status codes.
| Status | Meaning |
| --- | --- |
| `403` | Invalid parameter range, endpoint-specific limit exceeded, or access to a requested site is forbidden. |
| `404` | Resource does not exist. |
| `429` | Daily request quota or concurrency limit exceeded. |
Global limits from the March 2026 documentation:
- 300 requests per account token.
- 300 requests per specific site ID and source IP.
- At most 3 concurrent API calls from the same source IP.
- Bulk endpoints accept at most 100 comma-separated site IDs.
- A bulk call consumes one quota unit for every site included in the call.
The package client automatically limits itself to three concurrent requests.
It does not track daily quotas or split date ranges automatically.
## Endpoint index
`{siteIds}` means a comma-separated list of at most 100 site IDs.
| Area | Endpoint | Typed client method |
| --- | --- | --- |
| Sites | `GET /sites/list` | `listSites()` |
| Sites | `GET /site/{siteId}/details` | `getSiteDetails()` |
| Sites | `GET /site/{siteId}/dataPeriod` | `getSiteDataPeriod()` |
| Sites | `GET /sites/{siteIds}/dataPeriod` | Use `get<T>()` |
| Energy | `GET /site/{siteId}/energy` | `getSiteEnergy()` |
| Energy | `GET /sites/{siteIds}/energy` | Use `get<T>()` |
| Energy | `GET /site/{siteId}/timeFrameEnergy` | Use `get<T>()` |
| Energy | `GET /sites/{siteIds}/timeFrameEnergy` | Use `get<T>()` |
| Power | `GET /site/{siteId}/power` | `getSitePower()` |
| Power | `GET /sites/{siteIds}/power` | Use `get<T>()` |
| Overview | `GET /site/{siteId}/overview` | `getSiteOverview()` |
| Overview | `GET /sites/{siteIds}/overview` | Use `get<T>()` |
| Meters | `GET /site/{siteId}/powerDetails` | `getSitePowerDetails()` |
| Meters | `GET /site/{siteId}/energyDetails` | `getSiteEnergyDetails()` |
| Flow | `GET /site/{siteId}/currentPowerFlow` | `getCurrentPowerFlow()` |
| Storage | `GET /site/{siteId}/storageData` | Use `get<T>()` |
| Environment | `GET /site/{siteId}/envBenefits` | Use `get<T>()` |
| Equipment | `GET /equipment/{siteId}/list` | `listSiteEquipment()` |
| Equipment | `GET /site/{siteId}/inventory` | `getSiteInventory()` |
| Equipment | `GET /equipment/{siteId}/{serialNumber}/data` | Use `get<T>()` |
| Meters | `GET /site/{siteId}/meters` | Use `get<T>()` |
## Site endpoints
### List sites
```text
GET /sites/list
```
Returns sites available to an account-level key. A site-level key may not be
able to use this endpoint meaningfully.
| Parameter | Required | Default | Description |
| --- | --- | --- | --- |
| `size` | No | `100` | Page size, maximum 100. |
| `startIndex` | No | `0` | Zero-based first result. |
| `searchText` | No | - | Searches name, notes, address, city, zip, and country. Full-address search is no longer supported. |
| `sortProperty` | No | - | `name`, `country`, `state`, `city`, `address`, `zip`, `status`, `peakPower`, `installationDate`, `amount`, or `maxSeverity`. |
| `sortOrder` | No | `ASC` | `ASC` or `DESC`. |
| `Status` | No | `Active,Pending` | `Active`, `Pending`, `Disabled`, or `All`. The parameter name begins with uppercase `S`. |
Site objects can contain:
- `id`, `accountId`, `name`, `status`, `type`, and `notes`
- `peakPower`, `currency`, `installationDate`, and `ptoDate`
- `location` with country, state, city, address, address2, zip, and time zone
- `alertQuantity` and `alertSeverity` for account-level keys
- `publicSettings` with public name and visibility
- API-specific `uris`
The PDF examples use `Sites.list`, while the live JSON API currently returns
`sites.site`. The package follows the live response and exposes `{ count, site }`.
### Site details
```text
GET /site/{siteId}/details
```
Returns one site object with the same core metadata as the site list. Response
root: `details`.
### Site data period
```text
GET /site/{siteId}/dataPeriod
GET /sites/{siteIds}/dataPeriod
```
Returns the first and last available production timestamps. For a site that is
not transmitting, `startDate` and `endDate` can be `null`.
Single-site response root:
```json
{
"dataPeriod": {
"startDate": "YYYY-MM-DD hh:mm:ss",
"endDate": "YYYY-MM-DD hh:mm:ss"
}
}
```
The bulk response adds `count` and a `list` whose entries include `id`.
## Energy endpoints
### Energy time series
```text
GET /site/{siteId}/energy
GET /sites/{siteIds}/energy
```
| Parameter | Required | Description |
| --- | --- | --- |
| `startDate` | Yes | Start date in `YYYY-MM-DD`. |
| `endDate` | Yes | End date in `YYYY-MM-DD`. |
| `timeUnit` | No | Defaults to `DAY`; accepts `QUARTER_OF_AN_HOUR`, `HOUR`, `DAY`, `WEEK`, `MONTH`, or `YEAR`. |
Limits:
- `DAY`: at most one year.
- `QUARTER_OF_AN_HOUR` or `HOUR`: at most one month.
- The PDF does not state an additional range limit for week, month, or year.
Response root `energy` contains `timeUnit`, `unit`, and `values`. Each value has
`date` and a numeric or `null` `value`. The regular energy endpoint matches the
Site Dashboard calculation.
The bulk response adds `count` and a `list` of `{ id, values }`.
### Total energy for a date range
```text
GET /site/{siteId}/timeFrameEnergy
GET /sites/{siteIds}/timeFrameEnergy
```
| Parameter | Required | Description |
| --- | --- | --- |
| `startDate` | Yes | Start date in `YYYY-MM-DD`. |
| `endDate` | Yes | End date in `YYYY-MM-DD`. |
Maximum range: one year.
Response root `timeFrameEnergy` contains `energy` and `unit`. The bulk response
contains `unit`, `count`, and `{ id, energy }` entries.
This endpoint reports on-grid energy. On storage or backup sites it may differ
from the Site Dashboard; use `/energy` when dashboard-equivalent values are
required.
### Detailed energy by meter
```text
GET /site/{siteId}/energyDetails
```
| Parameter | Required | Description |
| --- | --- | --- |
| `startTime` | Yes | Start in site-local `YYYY-MM-DD hh:mm:ss`. |
| `endTime` | Yes | End in site-local `YYYY-MM-DD hh:mm:ss`. |
| `timeUnit` | No | Defaults to `DAY`; accepts all six common time units. |
| `meters` | No | Comma-separated `PRODUCTION`, `CONSUMPTION`, `SELFCONSUMPTION`, `FEEDIN`, and/or `PURCHASED`. |
Limits:
- `QUARTER_OF_AN_HOUR` or `HOUR`: at most one month.
- `DAY`: at most one year.
- `WEEK`, `MONTH`, or `YEAR`: no documented period limit.
Response root `energyDetails` contains `timeUnit`, `unit`, and `meters`. Each
meter has `type` and `values`; a missing measurement may omit `value` entirely.
## Power endpoints
### Site power
```text
GET /site/{siteId}/power
GET /sites/{siteIds}/power
```
| Parameter | Required | Description |
| --- | --- | --- |
| `startTime` | Yes | Start in site-local `YYYY-MM-DD hh:mm:ss`. |
| `endTime` | Yes | End in site-local `YYYY-MM-DD hh:mm:ss`. |
Maximum range: one month. Resolution is 15 minutes. Response root `power`
contains `timeUnit`, `unit`, and `values`. Missing values can be `null`.
The bulk response adds `count` and a list of `{ id, values }`.
### Detailed power by meter
```text
GET /site/{siteId}/powerDetails
```
| Parameter | Required | Description |
| --- | --- | --- |
| `startTime` | Yes | Start in site-local `YYYY-MM-DD hh:mm:ss`. |
| `endTime` | Yes | End in site-local `YYYY-MM-DD hh:mm:ss`. |
| `meters` | No | Comma-separated `PRODUCTION`, `CONSUMPTION`, `SELFCONSUMPTION`, `FEEDIN`, and/or `PURCHASED`. |
Maximum range: one month. Response root `powerDetails` contains a fixed
`QUARTER_OF_AN_HOUR` time unit, the measurement unit, and per-meter series.
A missing measurement may omit `value` entirely.
## Overview and live power flow
### Site overview
```text
GET /site/{siteId}/overview
GET /sites/{siteIds}/overview
```
Response root `overview` contains:
- `lastUpdateTime`
- `currentPower.power`
- `lastDayData.energy`
- `lastMonthData.energy`
- `lastYearData.energy`
- `lifeTimeData.energy` and lifetime revenue
- Revenue fields can also appear in the period summaries.
The bulk response contains `count` and a list with `id` on every overview.
### Current power flow
```text
GET /site/{siteId}/currentPowerFlow
```
If unsupported, the API may return an empty power-flow object. Otherwise,
`siteCurrentPowerFlow` contains:
- `unit`
- `connections` entries with `from` and `to`
- `GRID` and `LOAD`
- Optional `PV`
- Optional `STORAGE`
Every component provides `status` (`Active`, `Idle`, or `Disabled`) and a
positive `currentPower`. Direction comes from `connections`, not the sign.
Storage can additionally provide `chargeLevel`, `critical`, and `timeLeft`.
## Storage data
```text
GET /site/{siteId}/storageData
```
| Parameter | Required | Description |
| --- | --- | --- |
| `startTime` | Yes | Start in site-local `YYYY-MM-DD hh:mm:ss`. |
| `endTime` | Yes | End in site-local `YYYY-MM-DD hh:mm:ss`. |
| `serials` | No | Comma-separated battery serial numbers. Defaults to every battery at the site. |
Maximum range: seven days.
Response root `storageData` contains `batteryCount` and `batteries`. A battery
contains `serialNumber`, `nameplate`, `modelNumber`, `telemetryCount`, and
`telemetries`. Telemetry can include:
- `timeStamp`
- `power` (positive means charging, negative means discharging)
- `batteryState`: `0` invalid, `1` standby, `2` thermal management, `3` enabled,
`4` fault
- Lifetime energy charged and discharged
- Full-pack energy available
- Internal temperature
- AC grid charging energy
- State of charge from 0 to 100 percent
The documentation warns that some lifetime battery energy values are aggregated
and can be incomplete when telemetry is missing. They are not revenue-grade.
## Environmental benefits
```text
GET /site/{siteId}/envBenefits
```
| Parameter | Required | Description |
| --- | --- | --- |
| `systemUnits` | No | Case-sensitive `Metrics` or `Imperial`. |
Response root `envBenefits` contains `gasEmissionSaved` (`units`, `co2`, `so2`,
and `nox`), `treesPlanted`, and `lightBulbs`.
## Equipment endpoints
### Components list
```text
GET /equipment/{siteId}/list
```
Returns inverters and SMIs with `name`, `manufacturer`, `model`, and
`serialNumber`.
The PDF example shows a top-level `list`; the live API currently wraps the
result in `reporters` with `count` and `list`. The package follows the live
response.
### Inventory
```text
GET /site/{siteId}/inventory
```
Response root `Inventory` can contain arrays for:
- `inverters`
- `thirdPartyInverters`
- `smiList`
- `meters`
- `sensors`
- `gateways`
- `batteries`
Fields vary by device type. Common fields include names, manufacturer, model,
serial number (`SN` or `serialNumber`), firmware versions, communication method,
connected device serials, connected optimizer count, and battery nameplate
capacity.
### Inverter technical data
```text
GET /equipment/{siteId}/{serialNumber}/data
```
| Parameter | Required | Description |
| --- | --- | --- |
| `startTime` | Yes | Start in site-local `YYYY-MM-DD hh:mm:ss`. |
| `endTime` | Yes | End in site-local `YYYY-MM-DD hh:mm:ss`. |
Maximum range: seven days.
Response root `data` contains `count` and inverter telemetry. Unsupported fields
are omitted. Depending on inverter type and firmware, telemetry can contain:
- Timestamp, inverter mode, and operation mode
- Total active power, DC voltage, power limit, total energy, temperature, and
ground-fault resistance
- Per-phase current, voltage, frequency, apparent power, active power, reactive
power, and power factor
- Phase-to-neutral and phase-to-phase voltages where applicable
Inverter modes include normal states such as off, sleeping, starting, MPPT,
throttled, shutdown, fault, and standby, plus several locked states. Operation
mode `0` is on-grid, `1` is off-grid using PV or battery, and `2` is off-grid
with a generator present.
## Meter lifetime data
```text
GET /site/{siteId}/meters
```
| Parameter | Required | Description |
| --- | --- | --- |
| `startTime` | Yes | Start in site-local `YYYY-MM-DD hh:mm:ss`. |
| `endTime` | Yes | End in site-local `YYYY-MM-DD hh:mm:ss`. |
| `timeUnit` | No | Defaults to `DAY`; accepts all six common time units. |
| `meters` | No | Comma-separated `Production`, `Consumption`, `FeedIn`, and/or `Purchased`. |
Response root `meterEnergyDetails` contains `timeUnit`, `unit`, and `meters`.
Each meter includes `meterSerialNumber`, `connectedSolaredgeDeviceSN`, `model`,
`meterType`, and lifetime-energy `values` by timestamp.
## Bulk endpoint behavior
Bulk endpoints use comma-separated IDs directly in the path:
```text
GET /sites/1,4,8/overview
```
- Maximum 100 site IDs.
- Responses normally contain `count` and `list` inside the endpoint root.
- Each list item includes the site `id`.
- If the key lacks permission for any requested site, the entire request can
fail with `403`.
- Dates are interpreted in each site's own time zone.
## March 2026 removals and changes
Do not build new integrations against these removed endpoints or capabilities:
- Site Image
- Installer Logo Image
- Equipment Change Log
- Account List
- Sensor List and Sensor Data
- API Versions: Current and Supported
- CSV and XML response formats
- `CreationTime` site-list sorting
- Full-address matching in `searchText`
## Package usage
```ts
import { createSolarEdgeClientFromEnv } from "@solar-dash/solaredgeapi";
const client = createSolarEdgeClientFromEnv();
const [overview, powerFlow] = await Promise.all([
client.getSiteOverview(),
client.getCurrentPowerFlow(),
]);
```
For an endpoint without a typed method, use the authenticated generic reader:
```ts
type EnvironmentalBenefitsResponse = {
envBenefits: {
gasEmissionSaved: {
units: string;
co2: number;
so2: number;
nox: number;
};
treesPlanted: number;
lightBulbs: number;
};
};
const siteId = process.env.SOLAREDGE_SITE_ID;
if (!siteId) {
throw new Error("Missing SOLAREDGE_SITE_ID");
}
const response = await client.get<EnvironmentalBenefitsResponse>(
`/site/${siteId}/envBenefits`,
{ systemUnits: "Metrics" },
);
```