pvnode API

Forecast


Get forecast for a site

GET
https://api.pvnode.com
/v2/forecast/{site_id}

Returns a PV power forecast for a saved site.

Uses the site's stored location, strings, and configuration. 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. The response covers past_days days of archived forecast data followed by forecast_days days of forecast. Note that archived forecast data differs from historical data, which tends to be more accurate.

Get forecast for a site › path Parameters

site_id
​string · required

Get forecast for a site › query Parameters

forecast_days
​

Forecast horizon as days beyond today. 0 = today only, 1 = today + tomorrow, etc. If omitted, returns the maximum allowed by your plan. Hard-capped at 7 (8 days incl. today); further clamped to your plan's limit.

past_days
​integer · min: 0 · max: 30

Past days to include before today. Defaults to 0. Hard-capped at 30; further clamped to your plan's limit.

Default: 0
include
​string[]

Field groups to include in the response. Combine freely (?include=weather&include=irradiance). default = pv_power. Omit default to receive only the requested groups (e.g. weather data only). all returns every available field. strings adds a separate top-level strings array with per-string PV power (long format) — values is unaffected. variability adds a pv_power_min/pv_power_max band (~next 48h) to values and to each strings row; requires a plan with variability access and is never part of all.

Enum values:
default
all
weather
irradiance
clearsky
strings
variability
Default: ["default"]
timezone
​string · enum

Timezone of the returned values/strings timestamps. local (default) = naive site-local ISO 8601 (no offset); read the timezone field to interpret them. utc = RFC 3339 UTC ending in Z, and the response timezone field becomes UTC. Daily dates stay site-local. Use utc for clients without an IANA timezone database (e.g. jq-based integrations).

Enum values:
local
utc
Default: local

Get forecast for a site › Headers

Authorization
​string · required

Bearer token. Format: Bearer YOUR_API_KEY

Default: Bearer YOUR_API_KEY

Get forecast for a site › Responses

Successful Response

site_id
​string · required
timezone
​string · required

IANA timezone of the timestamps, e.g. 'Europe/Berlin'. Becomes 'UTC' when ?timezone=utc is requested.

included
​string[] · required

Groups included in this response — echoes what you requested via include. Requesting all is echoed as ["all"], not expanded.

Example: ["default","weather"]
available
​string[] · required

Every group your current plan is allowed to request on this endpoint — use it to discover what you could ask for beyond what you did. Plan-gated groups appear only once your plan includes them (today: variability), so a client can hide or unlock features without hard-coding plan knowledge. The meta-token all is not listed: it is shorthand for every group here except variability, which always has to be requested explicitly.

Example: ["default","weather","irradiance","clearsky","strings"]
​ForecastDaily[] · required
​ForecastValue[] · required
​

ISO 8601 timestamp of when this forecast was computed. Forecasts are recomputed at fixed slots per day (see your plan's forecast.updates_per_day); repeat requests within the same slot return this same cached result. Site-local with a UTC offset by default, or …Z with ?timezone=utc. Absent on /forecast/inline, which is computed fresh on every call.

Example: 2026-08-07T12:00:00+02:00
​

ISO 8601 timestamp of when to request this site again. Nothing is recomputed on a schedule — forecasts are calculated on demand — so this is the first moment a request would return something newer than what you just got; asking earlier costs a request and returns this same cached result. Update slots are spread evenly across the day starting at site-local midnight, so with forecast.updates_per_day = 1 this is the next local midnight, with 4 it is the next 06:00/12:00/18:00/00:00 boundary. Plans refreshing more than 96×/day are advertised on the 15-minute grid, so this is never sooner than 15 minutes out. Treat it as a recommendation, not a guarantee: a recomputation triggered by another request can make newer data available earlier. Same timezone rules as computed_at; absent on /forecast/inline.

Example: 2026-08-08T00:00:00+02:00
​

Per-string PV power and tilted irradiance (gti/gti_shaded) in long format (one row per timestep per string). Present only when include=strings (or all). Each row carries string_index (positional, always present) and, for saved sites, string_id (stable id — use it to correlate with a string's measurements). Loads directly into a DataFrame; pivot on string_index for wide format. values stays unaffected — total pv_power there is the sum across strings. Tilted irradiance lives here (not in values) because it is orientation-dependent and therefore per-string.


Get forecast without a saved site

POST
https://api.pvnode.com
/v2/forecast/inline

Returns a PV power forecast without requiring a saved site.

Provide the location (latitude + longitude) and optionally strings and config inline. Useful for one-off queries or integrations where managing sites is not needed. Computed fresh on every call (no server-side caching) and counts against your monthly forecast quota.

Get forecast without a saved site › query Parameters

forecast_days
​

Forecast horizon as days beyond today. 0 = today only, 1 = today + tomorrow, etc. If omitted, returns the maximum allowed by your plan. Hard-capped at 7 (8 days incl. today); further clamped to your plan's limit.

past_days
​integer · min: 0 · max: 30

Past days to include before today. Defaults to 0. Hard-capped at 30; further clamped to your plan's limit.

Default: 0
include
​string[]

Field groups to include. See the site endpoint for details.

Enum values:
default
all
weather
irradiance
clearsky
strings
variability
Default: ["default"]
timezone
​string · enum

Timezone of the returned timestamps: local (default) or utc. See the site endpoint for details.

Enum values:
local
utc
Default: local

Get forecast without a saved site › Headers

Authorization
​string · required

Bearer token. Format: Bearer YOUR_API_KEY

Default: Bearer YOUR_API_KEY

Get forecast without a saved site › Request Body

Forecast request without a saved site. Minimum: latitude + longitude.
latitude
​number · min: -89.99 · max: 89.99 · required

Latitude of the site in decimal degrees (WGS84).

Example: 48.8566
longitude
​number · min: -179.99 · max: 179.99 · required

Longitude of the site in decimal degrees (WGS84).

Example: 2.3522
​

PV string definitions. Defaults to a single string (10 kWp, 180° orientation, 30° tilt) if omitted.

​

Site configuration overrides. Omitted fields fall back to current defaults.

Get forecast without a saved site › Responses

Successful Response

site_id
​string · required
timezone
​string · required

IANA timezone of the timestamps, e.g. 'Europe/Berlin'. Becomes 'UTC' when ?timezone=utc is requested.

included
​string[] · required

Groups included in this response — echoes what you requested via include. Requesting all is echoed as ["all"], not expanded.

Example: ["default","weather"]
available
​string[] · required

Every group your current plan is allowed to request on this endpoint — use it to discover what you could ask for beyond what you did. Plan-gated groups appear only once your plan includes them (today: variability), so a client can hide or unlock features without hard-coding plan knowledge. The meta-token all is not listed: it is shorthand for every group here except variability, which always has to be requested explicitly.

Example: ["default","weather","irradiance","clearsky","strings"]
​ForecastDaily[] · required
​ForecastValue[] · required
​

ISO 8601 timestamp of when this forecast was computed. Forecasts are recomputed at fixed slots per day (see your plan's forecast.updates_per_day); repeat requests within the same slot return this same cached result. Site-local with a UTC offset by default, or …Z with ?timezone=utc. Absent on /forecast/inline, which is computed fresh on every call.

Example: 2026-08-07T12:00:00+02:00
​

ISO 8601 timestamp of when to request this site again. Nothing is recomputed on a schedule — forecasts are calculated on demand — so this is the first moment a request would return something newer than what you just got; asking earlier costs a request and returns this same cached result. Update slots are spread evenly across the day starting at site-local midnight, so with forecast.updates_per_day = 1 this is the next local midnight, with 4 it is the next 06:00/12:00/18:00/00:00 boundary. Plans refreshing more than 96×/day are advertised on the 15-minute grid, so this is never sooner than 15 minutes out. Treat it as a recommendation, not a guarantee: a recomputation triggered by another request can make newer data available earlier. Same timezone rules as computed_at; absent on /forecast/inline.

Example: 2026-08-08T00:00:00+02:00
​

Per-string PV power and tilted irradiance (gti/gti_shaded) in long format (one row per timestep per string). Present only when include=strings (or all). Each row carries string_index (positional, always present) and, for saved sites, string_id (stable id — use it to correlate with a string's measurements). Loads directly into a DataFrame; pivot on string_index for wide format. values stays unaffected — total pv_power there is the sum across strings. Tilted irradiance lives here (not in values) because it is orientation-dependent and therefore per-string.