# Solprognose

> Solinnstråling (GHI) og PV-produksjon time for time, 60 timer frem, for ethvert punkt eller anlegg i Norge. Bulk for inntil 50 anlegg, utvidet prognose til 10 døgn, satellittbasert nowcast og metadata om siste syklus.

Kilde: https://solkart.no/api/dokumentasjon/prognose · Sist oppdatert 2026-09-15 · Base-URL https://api.solkart.no · OpenAPI: https://solkart.no/openapi.json

## Hva du får

Prognosen er EnergiSmarts egen modell for solinnstråling (V2.3b): modellen regnes i 1 km, API-et serverer verdier fra et rutenett på 0,03° (om lag 3 km × 1,7 km) for hele fastlands-Norge, ny syklus hver time, om lag 60 timer frem (59 til 67 tidssteg). Sender du inn anleggets takflater, regner API-et også ut produksjonen per time (DISC-dekomponering og Klucher-transposisjon, temperaturkorreksjon og systemvirkningsgrad; med `precise=true` brukes pvlib med Perez-modellen). Det samme datagrunnlaget driver [sanntidskartet](/) på forsiden.

Nøkkel er valgfri: uten nøkkel får du 24 forespørsler og ett anlegg per døgn fra din IP-adresse. Se [autentisering](/api/dokumentasjon/autentisering) og [kvoter](/api/dokumentasjon/grenser-og-feil).

## GET /api/forecast: innstråling for et punkt

```bash
curl "https://api.solkart.no/api/forecast?lat=59.19&lon=10.90" \
  -H "X-API-Key: $SOLKART_API_KEY"
```

| Parameter | Type | Påkrevd | Standard | Beskrivelse |
|---|---|---|---|---|
| `lat`, `lon` | tall | ja | | WGS84, 57 til 72° N, 4 til 32° Ø |
| `daily` | `true` | nei | av | Serie fra midnatt UTC i stedet for fra siste syklus. Basic eller høyere. |
| `snow` | `1` | nei | av | Legg snøtapsfaktorer fra seNorge på produksjonen (bare med `arrays`). |
| `precise` | `true` | nei | av | Produksjon regnet i pvlib med PVGIS-horisont. Tregere, brukes til validering. |
| `model` | `v23b` \| `v1` | nei | `v23b` | `v1` velger den utgående V1.5-modellen. Fases ut 19. november 2026. |
| `extended` | `true` | nei | av | Videresender til `/api/forecast/extended`. |
| `site` | `jegerveien` | nei | | Forhåndsdefinert anlegg med takflater (se `GET /api/sites`). |

Svar `200`:

```json
{
  "site": "59.19,10.90",
  "latitude": 59.19,
  "longitude": 10.9,
  "grid_index": { "i_lat": 220, "i_lon": 538 },
  "cycle_time": "2026-09-15T16:00:00Z",
  "model": "production_v2_3b",
  "data_mode": "v23b",
  "peak_ghi_wm2": 449.1,
  "daily_ghi_kwh_m2": 2.71,
  "ghi_timeseries": [
    { "hour": 0, "timestamp": "2026-09-15T15:00:00Z", "ghi_wm2": 183.4 },
    { "hour": 1, "timestamp": "2026-09-15T16:00:00Z", "ghi_wm2": 96.2 },
    { "hour": 2, "timestamp": "2026-09-15T17:00:00Z", "ghi_wm2": 21.0 }
  ]
}
```

| Felt | Enhet | Beskrivelse |
|---|---|---|
| `cycle_time` | ISO 8601 UTC | Når prognosen ble kjørt. Ny hver time. |
| `model`, `data_mode` | | Faktisk brukt modell og datamodus etter eventuell fall tilbake. Se [versjonering](/api/dokumentasjon/caching-og-versjonering). |
| `grid_index` | | Cellen i 1 km-rutenettet som ble brukt. |
| `peak_ghi_wm2` | W/m² | Høyeste timeverdi i serien. |
| `daily_ghi_kwh_m2` | kWh/m² | Sum av GHI over hele serien (ikke bare første døgn). |
| `ghi_timeseries[].hour` | | Indeks fra 0, ikke klokkeslett. |
| `ghi_timeseries[].timestamp` | ISO 8601 UTC | **Starten på timen** verdien gjelder. |
| `ghi_timeseries[].ghi_wm2` | W/m² | Middel global horisontal innstråling over timen. |

!!! note "Tidsstempel"
    `10:00:00Z` betyr middelet over 10:00 til 11:00 UTC. Plott punktet midt i timen. Konvensjonen ble endret 7. september 2026; se [konvensjoner](/api/dokumentasjon/konvensjoner).

## POST /api/forecast: produksjon for ditt anlegg

Samme endepunkt med JSON-kropp. Legg til takflatene, så får du produksjon per flate og totalt.

```bash
curl -X POST https://api.solkart.no/api/forecast \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $SOLKART_API_KEY" \
  -d '{
    "latitude": 59.19,
    "longitude": 10.90,
    "daily": true,
    "performance_ratio": 0.9,
    "arrays": [
      { "name": "Tak sør",  "kwp": 8.0, "tilt_deg": 25, "azimuth_deg": 180 },
      { "name": "Tak øst",  "kwp": 4.5, "tilt_deg": 10, "azimuth_deg": 90 }
    ]
  }'
```

| Felt | Type | Påkrevd | Standard | Beskrivelse |
|---|---|---|---|---|
| `latitude`, `longitude` | tall | ja | | Anleggets posisjon |
| `arrays[]` | liste | for produksjon | | Én oppføring per takflate eller streng |
| `arrays[].name` | streng | ja | | Brukes som feltnavn i svaret (`<name>_W`) |
| `arrays[].kwp` | tall | ja | | Installert effekt. Summen per anlegg er begrenset av planen (25 kWp gratis, 150 Basic, 1 000 Pro). |
| `arrays[].tilt_deg` | 0 til 90 | ja | | 0 = flatt, 90 = vegg |
| `arrays[].azimuth_deg` | 0 til 360 | ja | | Kompass: 0 nord, 90 øst, 180 sør, 270 vest |
| `performance_ratio` | 0 til 1 | nei | 0,85 | Systemvirkningsgrad: inverter, kabling, smuss, tilgjengelighet |
| `temp_coeff_pmax` | tall | nei | −0,004 | Temperaturkoeffisient per °C |
| `altitude_m` | tall | nei | | Høyde over havet; brukes bare med `precise=true` |
| `daily`, `snow`, `precise`, `model` | | nei | | Som for GET |

Svar `200` (utdrag):

```json
{
  "site": "59.19,10.90",
  "cycle_time": "2026-09-15T16:00:00Z",
  "model": "production_v2_3b",
  "data_mode": "v23b_daily",
  "peak_ghi_wm2": 449.1,
  "daily_ghi_kwh_m2": 2.71,
  "pv_system": {
    "total_kwp": 12.5,
    "arrays": [ { "name": "Tak sør", "kwp": 8.0, "tilt_deg": 25, "azimuth_deg": 180 }, { "name": "Tak øst", "kwp": 4.5, "tilt_deg": 10, "azimuth_deg": 90 } ],
    "performance_ratio": 0.9,
    "peak_power_w": 7412.5,
    "total_production_kwh": 61.3,
    "engine": "simplified (JS approximation)",
    "horizon_applied": false
  },
  "pv_timeseries": [
    { "hour": 9, "timestamp": "2026-09-16T09:00:00Z", "ghi_wm2": 402.6,
      "Tak sør_W": 4102.3, "Tak øst_W": 1811.9, "total_W": 5914.2, "total_kWh": 5.9142 }
  ]
}
```

| Felt | Enhet | Beskrivelse |
|---|---|---|
| `pv_system.peak_power_w` | W | Høyeste timeeffekt i serien |
| `pv_system.total_production_kwh` | kWh | Sum over hele serien (fra midnatt med `daily`) |
| `pv_system.engine` | | `simplified (JS approximation)` som standard; `pvlib (Perez transposition, …)` med `precise=true` |
| `pv_timeseries[].<name>_W` | W | Effekt per takflate |
| `pv_timeseries[].total_W`, `total_kWh` | W, kWh | Sum for timen |
| `snow` | | Med `snow=1`: `snow_applied`, `reason` (når ikke brukt), `source`, `issued_utc`, `age_hours`, `kommune`, `kommune_distance_km`, `dates`, `geometry_note`, `arrays[].reference_geometry` |

Med `daily=true` starter serien ved midnatt UTC, så du kan summere «hittil i dag» direkte. Snøfaktorer settes bare når snødata er ferske (`snow_applied: false` med `reason` ellers).

## POST /api/forecast/bulk: mange anlegg i ett kall

Henter inntil 50 anlegg i én forespørsel. Antall per kall og kWp per anlegg begrenses av planen. Solkart bruker dette selv for alle 15 fylker.

```bash
curl -X POST https://api.solkart.no/api/forecast/bulk \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $SOLKART_API_KEY" \
  -d '{
    "daily": true,
    "performance_ratio": 0.9,
    "systems": [
      { "id": "skole_a", "latitude": 59.91, "longitude": 10.75,
        "arrays": [ { "name": "Tak", "kwp": 75, "tilt_deg": 15, "azimuth_deg": 180 } ] },
      { "id": "lager_b", "latitude": 60.39, "longitude": 5.32,
        "arrays": [ { "name": "Tak", "kwp": 220, "tilt_deg": 5, "azimuth_deg": 180 } ] }
    ]
  }'
```

`systems[]` tar `id`, `latitude`, `longitude`, `arrays`, og valgfritt `performance_ratio` og `temp_coeff_pmax` per anlegg. `daily`, `snow`, `model` og felles `performance_ratio` settes på toppnivå.

Svar `200`:

```json
{
  "cycle_time": "2026-09-15T16:00:00Z",
  "data_mode": "v23b_daily",
  "snow": { "snow_applied": false, "reason": "snow_blob_unavailable" },
  "results": {
    "skole_a": { "latitude": 59.91, "longitude": 10.75,
                 "ghi_timeseries": [ "…" ], "pv_timeseries": [ "…" ],
                 "pv_system": { "total_kwp": 75, "peak_power_w": 41250.0, "total_production_kwh": 310.2 } },
    "lager_b": { "error": "Location outside coverage" }
  }
}
```

Anlegg utenfor dekning får `error` i sitt eget objekt; resten leveres. Svaret caches hos oss til neste syklus (`Cache-Control: public, max-age=…`, `X-Solkart-Cache: HIT|MISS`); kvoten trekkes likevel.

Feil: `400` ved manglende `systems` eller flere enn 50; `403` ved flere anlegg eller kWp enn planen tillater; `429` når anleggskvoten ikke rekker til alle nye koordinater. Da avvises hele kallet; `quota` viser hvor mange som ville fått plass, og `rejected_coords` hvilke. Del opp kallet, eller send bare koordinater du allerede har spurt om i dag.

## GET /api/forecast/extended: ut til 10 døgn

Krever Basic eller høyere. De første om lag 60 timene kommer fra prognosemodellens V1.5-rutenett (`model: production_v1`); resten fra MET Locationforecast med skydekke og temperatur. Tar `lat`/`lon` eller samme JSON-kropp med anlegg som `/api/forecast`; `daily`, `model` og `precise` gjelder ikke her.

```bash
curl "https://api.solkart.no/api/forecast/extended?lat=59.19&lon=10.90" -H "X-API-Key: $SOLKART_API_KEY"
```

Svar `200` (utdrag):

```json
{
  "mode": "extended",
  "total_hours": 232,
  "met_nordic_hours": 58,
  "locationforecast_hours": 174,
  "peak_ghi_wm2": 512.3,
  "total_ghi_kwh_m2": 24.6,
  "timeseries": [
    { "timestamp": "2026-09-15T15:00:00Z", "ghi_wm2": 183.4, "source": "met_nordic_model" },
    { "timestamp": "2026-09-18T06:00:00Z", "ghi_wm2": 41.0, "cloud_fraction": 0.82, "temperature_c": 9.1, "source": "locationforecast" }
  ]
}
```

Timer med `source: "locationforecast"` bærer MET sine tidspunkt; behandle dem som timen som starter da. `502` når MET ikke svarer.

## GET /api/forecast/nowcast: neste 0 til 3 timer

Satellittbasert nowcast fra EUMETSAT-bilder når de er ferske, ellers V2.3b for de samme timene.

```bash
curl "https://api.solkart.no/api/forecast/nowcast?lat=59.19&lon=10.90" -H "X-API-Key: $SOLKART_API_KEY"
```

| Felt | Beskrivelse |
|---|---|
| `source` | `v7_eumetsat_nowcast` eller `v23b_fallback` |
| `satellite_time`, `satellite_lag_min`, `sat_covered` | Bare ved satellitt: bildetidspunkt, alder i minutter, om punktet er dekket |
| `hours[]` | 4 timer fra inneværende time: `time` (bin-start), `ghi_wm2`, `v23b_ghi_wm2`, og ved satellitt `kt` (klarhetsindeks) og `clearsky_wm2` |

`Cache-Control: public, max-age=120`. `503` når ingen kilde er tilgjengelig.

## GET /api/forecast/latest: metadata om siste syklus

Uten nøkkel og uten kvote. Bruk den til å vise «Prognose fra …» og til å oppdage nye sykluser før du henter for mange anlegg.

```json
{
  "cycle_time": "2026-09-15T16:00:00Z",
  "model": "production_v1",
  "n_times": 58,
  "n_lat": 501,
  "n_lon": 934,
  "ghi_max": 449.07,
  "timestamps": [ "2026-09-15T15:00:00.000Z", "2026-09-15T16:00:00.000Z", "…" ]
}
```

Metadataene gjelder V1.5-rutenettet (`model: production_v1`), så `cycle_time` kan avvike fra V2.3b-syklusen `/api/forecast` bruker; bruk `cycle_time` i selve prognosesvaret som fasit. `n_lat` og `n_lon` er rutenettets størrelse (501 × 934 celler). `503` hvis ingen prognose finnes.

## GET /api/sites

Forhåndsdefinerte anlegg som kan brukes med `?site=`. I dag ett: `jegerveien` (Fredrikstad) med sine takflater.

## Eksempler i kode

```javascript
const resp = await fetch("https://api.solkart.no/api/forecast", {
  method: "POST",
  headers: { "Content-Type": "application/json", "X-API-Key": process.env.SOLKART_API_KEY },
  body: JSON.stringify({
    latitude: 59.19, longitude: 10.90, daily: true,
    arrays: [{ name: "Tak", kwp: 10, tilt_deg: 25, azimuth_deg: 180 }],
  }),
});
if (!resp.ok) throw new Error((await resp.json()).error);
const data = await resp.json();
const kWhToday = data.pv_timeseries.reduce((s, e) => s + (e.total_kWh || 0), 0);
console.log(`Prognose fra ${data.cycle_time}: ${kWhToday.toFixed(1)} kWh i dag`);
```

```python
import os, requests

resp = requests.post(
    "https://api.solkart.no/api/forecast",
    headers={"X-API-Key": os.environ["SOLKART_API_KEY"]},
    json={"latitude": 59.19, "longitude": 10.90, "daily": True,
          "arrays": [{"name": "Tak", "kwp": 10, "tilt_deg": 25, "azimuth_deg": 180}]},
    timeout=15,
)
if resp.status_code != 200:
    raise SystemExit(resp.json()["error"])
data = resp.json()
kwh_today = sum(e.get("total_kWh", 0) for e in data["pv_timeseries"])
print(f"Prognose fra {data['cycle_time']}: {kwh_today:.1f} kWh i dag")
```

## Feil

| Status | `error` | Årsak |
|---|---|---|
| `400` | `Location outside Norway coverage (57-72N, 4-32E)` | Koordinat utenfor dekning |
| `400` | `Invalid JSON body` | Kroppen kunne ikke tolkes; svaret inneholder `example` |
| `400` | `GET: provide ?lat=&lon= or ?site=jegerveien. …` | Manglende koordinat |
| `401` | `Invalid API key` / `Daglig forespørsels-grense … brukt opp` | Nøkkel eller kallkvote |
| `403` | `Extended forecast requires Basic tier or higher` / `Daily stitched forecast requires Basic tier or higher` | Plan |
| `403` | `Tier "free" tillater maks 25 kWp per anlegg …` | kWp over planens grense |
| `429` | `Daglig anlegg-kvote brukt opp.` | Anleggskvote; se `quota` |
| `503` | `No forecast data available …` | Prognosen mangler; prøv igjen om noen minutter |

## Modellen bak

V2.3b er trent på 30 år med MET-kvalitetssikrede soldata (1991 til 2020) kombinert med MET Nordic-varselet og maskinlæring, og valideres daglig mot målestasjoner over hele landet. Prognosen er et estimat, ikke en måling. Se [om oss](/om).
