Climate Normals
Agriculture Weather Credits / request: 5Multi-year monthly averages for a point: temperature, total precipitation, rainy/frost days, GDD and ET0. Weather data © Open-Meteo / OpenWeather / MET Norway.
Documentation
Overview
Multi-year monthly normals for a point: temperature means, monthly precipitation totals, rainy/frost day counts, GDD (base 10 °C) and ET0. Values are interpolated from the 4 surrounding cells. Weather data © Copernicus ERA5 / ERA5-Land (contains modified Copernicus Climate Change Service information) / Open-Meteo / OpenWeather / MET Norway.
Authentication
Every request requires the x-api-key header. Credits used and remaining quota are returned in response headers (x-api-credits-used, x-api-remaining-credits, x-rate-limit-*).
Request
Parameters
| Name | Type | Required | Default | Options | Description |
|---|---|---|---|---|---|
latitude |
number | * Required | — | — | Point latitude -90..90. |
longitude |
number | * Required | — | — | Point longitude -180..180. |
month |
integer | Optional | — | — | 1–12. All 12 months when empty. |
years |
integer | Optional | 2 |
— | How many years back to average. Default 2; larger values are capped by the stored history of 730 days. |
Response
| Name | Type | Description |
|---|---|---|
sampleFrom |
string | Sample window start YYYY-MM-DD. |
sampleTo |
string | Sample window end YYYY-MM-DD. |
gddBaseC |
integer | GDD base temperature °C (10). |
months |
array | Normals for the requested months. |
months[].month |
integer | Month 1–12. |
months[].tminMeanC |
number | Mean daily minimum temperature °C. |
months[].tmaxMeanC |
number | Mean daily maximum temperature °C. |
months[].tmeanMeanC |
number | Mean daily mean temperature °C. |
months[].precipTotalMeanMm |
number | Multi-year mean of monthly total precipitation mm. |
months[].rainyDaysMean |
number | Mean number of rainy days (≥1 mm). |
months[].frostDaysMean |
number | Mean number of frost days (tmin ≤ 0 °C). |
months[].gddMean |
number | Multi-year mean of monthly GDD sum (base 10, cap 30). |
months[].et0TotalMeanMm |
number | Multi-year mean of monthly ET0 sum mm. |
months[].sampleYears |
integer | Number of years with data for that month. |
gridLatitude |
number | Latitude of the 0.1° grid corner around the request (interpolation reference). |
gridLongitude |
number | Longitude of the 0.1° grid corner. |
gridInterpolated |
boolean | true: values bilinearly blended from the 4 surrounding cells. false: single cell. |
sources |
array | Data sources that contributed: copernicus-era5-land, open-meteo, openweather, met-norway. For past days (older than about a week) Copernicus ERA5 / ERA5-Land takes precedence; UV, precipitation probability and the weather code of wet hours / days are derived from ERA5-Land variables, wind gust comes from ERA5 (0.25°); cloud cover and the weather code of dry hours / days are filled from other sources when available. At coastal / sea points ERA5-Land values come from the nearest land grid point. |
disclaimer |
string | Decision-support disclaimer and source attribution. |
Errors
| HTTP | code | Description |
|---|---|---|
400 |
-257 |
latitude/longitude missing or out of range (lat -90..90, lon -180..180). |
400 |
-258 |
fromDate/toDate not YYYY-MM-DD, range exceeds 366 days, or outside the last 2 years / after yesterday. |
400 |
-259 |
granularity/days/hours/metric/op/comparator is invalid. |
429 |
-316 |
Daily new location (cell) limit (50) reached. Previously requested locations keep working; new locations next day (UTC). Retry-After header gives seconds until end of day. |
503 |
-261 |
No stored weather for this location yet. Cells were created; the collector is filling them. Retry shortly. |
401 |
-100 |
x-api-key is missing, empty, malformed, inactive, banned, expired, IP-restricted, or not allowed for this API. |
429 |
-221 |
Per-minute request limit exceeded. Response headers: x-rate-limit-limit, x-rate-limit-remaining, x-rate-limit-reset. |
429 |
— | Package credit quota cannot cover this request. Body may be { error, limit, currentUsage, requestCost } (no code field). |
500 |
-1 |
Unexpected server error. message is a generic error text without technical details. |
Notes
- Success body is { data: { ... } }. Error body is { code, message }. code is an ApiResponseCode enum value (negative integer).
Sample response
{
"data": {
"gridLatitude": 39.90,
"gridLongitude": 32.90,
"gridInterpolated": true,
"sampleFrom": "2024-08-31",
"sampleTo": "2026-08-29",
"gddBaseC": 10,
"months": [
{
"month": 6,
"tminMeanC": 14.6,
"tmaxMeanC": 28.7,
"tmeanMeanC": 21.7,
"precipTotalMeanMm": 33.5,
"rainyDaysMean": 4.5,
"frostDaysMean": 0.0,
"gddMean": 351.2,
"et0TotalMeanMm": 168.4,
"sampleYears": 2
},
{
"month": 7,
"tminMeanC": 17.1,
"tmaxMeanC": 32.4,
"tmeanMeanC": 24.8,
"precipTotalMeanMm": 9.0,
"rainyDaysMean": 1.0,
"frostDaysMean": 0.0,
"gddMean": 458.6,
"et0TotalMeanMm": 195.2,
"sampleYears": 2
}
],
"sources": [
"open-meteo"
],
"disclaimer": "Multi-year monthly averages from Copernicus ERA5 / ERA5-Land, Open-Meteo, OpenWeather and MET Norway. Contains modified Copernicus Climate Change Service information. Decision support only."
}
}
Code samples
const response = await fetch('https://api.apikodu.com/api/v1/climate/normals', {
method: 'GET',
headers: {
'x-api-key': 'YOUR_API_KEY'
}
});
const data = await response.json();
console.log(data);
import requests
headers = {
'x-api-key': 'YOUR_API_KEY'
}
response = requests.get('https://api.apikodu.com/api/v1/climate/normals', headers=headers)
print(response.json())
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY");
var response = await client.GetStringAsync("https://api.apikodu.com/api/v1/climate/normals");
Console.WriteLine(response);
$response = file_get_contents('https://api.apikodu.com/api/v1/climate/normals', false, stream_context_create([
'http' => [
'header' => "x-api-key: YOUR_API_KEY"
]
]));
print_r(json_decode($response, true));
curl -X GET 'https://api.apikodu.com/api/v1/climate/normals' \
-H 'x-api-key: YOUR_API_KEY'
Start building in minutes
Create a free account, get your API key and send your first request in minutes.