TL;DR
GET /v1/users/{userId}/home/solar-forecast— hourly PV production forecast for today and tomorrow, plus the weather behind itPUT /v1/users/{userId}/home/location— set the home's coordinates (a prerequisite for any forecast)PUT /v1/users/{userId}/home/solar-forecast—{ "enabled": true | false }to enable (and regenerate) or disable the forecast- Two hard prerequisites: a home location and at least one producing device (a solar inverter or electric meter). Without both, no forecast is ever generated
- Production and forecast values are kWh per hour; all timestamps are UTC (
...Z) - Forecast generation runs asynchronously after the location is set — expect a short delay before
GETreturns data - Missing prerequisites return distinct, actionable errors (
409/404) instead of an empty body
The Solar Forecast endpoints expose clever-PV's PV production forecast for a user's home: the expected solar production for the rest of today and for tomorrow, broken down per hour, alongside the weather data the model is based on. They also let you set the home's location and turn the forecast on or off.
This is the same forecast shown in the clever-PV app. It is intended for partner integrations that want to display a production curve, compare forecast against actual production, or align loads with expected solar surplus.
Solar Forecast vs. Energy Forecast
Both forecasts read from the same home (location, producing device, enabled flag), but return different data at different resolutions:
| Solar Forecast (this page) | Energy Forecast | |
|---|---|---|
| Endpoint | GET …/home/solar-forecast | GET …/home/energy-forecast |
| Granularity | Hourly | Quarter-hourly (15-minute slots) |
| Coverage | Measured production so far today + forecast for today/tomorrow | Forward-looking only — current slot through tomorrow; no elapsed-today or measured data |
| Data returned | PV production (measured + forecast) and the weather behind it (clouds, rain, snow, icon) | Price, PV production, household consumption, battery state of charge, grid import/feed-in |
| Typical use | Display a production curve, compare forecast vs. actual, show weather context | Anticipate price windows, plan around battery/grid behaviour, align loads with solar surplus |
| Manages location/toggle | Yes — PUT …/home/location, PUT …/home/solar-forecast | No — reuses Solar Forecast's location and enabled flag |
If you need weather or a production-vs-actual comparison, use Solar Forecast. If you need price, consumption, battery or grid figures, use Energy Forecast. Both can be called independently once the shared prerequisites are met.
Prerequisites
A forecast can only be produced once both of the following are true:
- The home has a location. Set it with
PUT …/home/location. The coordinates drive the weather lookup that the forecast is built on. - The home has at least one producing device — a solar inverter or an electric meter — onboarded. Without a production source, the forecast is never generated (there is nothing to model or train on).
After the location is set, generation runs in the background. The forecast is not available instantly: GET returns 404 solarForecastNotAvailable until the first forecast has been produced, then 200.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
PUT | /v1/users/{userId}/home/location | Set the home's geographic location |
PUT | /v1/users/{userId}/home/solar-forecast | Enable (and regenerate) or disable the forecast |
GET | /v1/users/{userId}/home/solar-forecast | Get the hourly PV production forecast for the home |
The home is resolved server-side from the authenticated end-user. The {userId} path segment is required for routing and auditing, but the home is not chosen by the caller.
Set the home location
PUT /v1/users/{userId}/home/location
Sets the home's coordinates (and optional address). This is the first step before a forecast can be generated — setting the location triggers the weather lookup and, if a producing device is present, the forecast generation.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
latitude | number | yes | Decimal degrees, -90 to 90. |
longitude | number | yes | Decimal degrees, -180 to 180. |
street | string | no | Informational only; not used by the forecast. |
postalCode | string | no | Informational only. |
city | string | no | Informational only. |
Code
Returns 204 No Content on success. Out-of-range coordinates return 400 with a validation error keyed by latitude / longitude.
Enable or disable the forecast
PUT /v1/users/{userId}/home/solar-forecast
Code
| Field | Type | Required | Notes |
|---|---|---|---|
enabled | bool | yes | true to enable, false to disable. |
Returns 204 No Content.
- Disable (
false) stops the forecast and removes the weather link and cached forecast data for the home. - Enable (
true) turns the forecast back on and re-triggers generation from the home's stored location, so the forecast is rebuilt. (Enabling does nothing useful if no location has ever been set — set the location first.)
Because disabling tears down the weather link, simply flipping
enabledback totruewithout a stored location will not produce a forecast. As long as the location is still set, enabling re-runs generation automatically.
Get the forecast
GET /v1/users/{userId}/home/solar-forecast
Code
200 OK
Code
Top-level fields
| Field | Type | Description |
|---|---|---|
enabled | bool | Whether the forecast is currently enabled for the home. |
trainingDays | int | Days of historical data the model has trained on so far. |
maxTrainingDays | int | Target number of training days the model works towards (default 10). |
sunrise | string | Sunrise for the home's location, UTC ISO-8601 (...Z). |
sunset | string | Sunset for the home's location, UTC ISO-8601 (...Z). |
meanError | number | Mean relative forecast error (0–1); lower is more accurate. |
production | array | Measured PV production so far today, per hour. |
forecastToday | array | Forecasted PV production for today, per hour. |
forecastTomorrow | array | Forecasted PV production for tomorrow, per hour. |
weatherToday | array | Hourly weather underlying today's forecast. |
weatherTomorrow | array | Hourly weather underlying tomorrow's forecast. |
Production / forecast point
| Field | Type | Description |
|---|---|---|
time | string | Start of the hour, UTC ISO-8601 (...Z). |
value | number? | PV energy for that hour in kWh. null when no value is available for the hour. |
Weather point
| Field | Type | Description |
|---|---|---|
time | string | Start of the hour, UTC ISO-8601 (...Z). |
clouds | int | Cloud cover in percent (0–100). |
weatherIconId | int | Weather icon identifier from the weather provider. |
rain | number | Rain volume for the hour, in millimetres. |
snow | number | Snow volume for the hour, in millimetres. |
todayandtomorroware relative to the home's timezone, but every timestamp in the response is UTC (...Z). Convert client-side for display.
Typical flow
PUT …/home/locationwith the home's coordinates →204.- The forecast is generated in the background. Until it is ready,
GET …/home/solar-forecastreturns404 solarForecastNotAvailable— poll periodically. - Once ready,
GET …/home/solar-forecastreturns200with the production and forecast series. - To opt the user out,
PUT …/home/solar-forecast{ "enabled": false }. To opt back in, send{ "enabled": true }(the forecast regenerates from the stored location).
Error responses
All errors follow RFC 7807 (application/problem+json) using the partner-friendly ConnectApiProblemDetails shape (type + errorCode + traceId + optional detail).
| Status | errorCode | Meaning |
|---|---|---|
400 | validationError | PUT …/home/location with out-of-range latitude/longitude, or a malformed body. |
401 | — | Missing or invalid bearer token. |
403 | — | Token lacks the connect_api scope. |
404 | missingHome | The authenticated user has no home. |
404 | solarForecastNotAvailable | GET — the forecast is enabled and prerequisites are met, but it has not been generated yet. Retry shortly. |
409 | homeLocationRequired | GET — no home location is set. Call PUT …/home/location first. |
409 | solarProducerRequired | GET — the home has no producing device (inverter/meter); a forecast cannot be generated. |
409 | solarForecastDisabled | GET — the forecast is disabled. Enable it to regenerate. |
429 | — | Global IP rate limit (100 requests / 10 seconds). |
500 | internalError | Unhandled server error. |
Example 409
Code
Important notes
- Two prerequisites, two distinct errors: a missing location returns
409 homeLocationRequired; a missing producing device returns409 solarProducerRequired. Resolve the one you get before retrying. - Generation is asynchronous: after setting the location,
GETreturns404 solarForecastNotAvailableuntil the first forecast is built. Poll rather than assuming it is ready immediately. - Units:
productionandforecast*values are in kWh per hour. Weatherrain/snoware in millimetres. - UTC only: All timestamps are UTC (
...Z). "Today" / "tomorrow" windows are derived from the home's timezone, but the response is not localised. nullis valid: Anullvaluemeans no figure is available for that hour (e.g. night-time, or a past hour with no measurement). It is not an error.- Enable regenerates: Disabling removes the weather link and cached data; enabling re-runs generation from the stored location. There is no way to "re-enable without regenerating".