Flood risk: the storm-surge indicator for an address

Understand the climate endpoint: how ground elevation and projected storm surge give a margin, what the levels mean and what the indicator does not cover.

4 min Level: Intermediate ✓ Code tested

Property portals, insurers and buyers ask: does the house sit low compared with the sea? GET /api/v1/enrich/adresser/{id}/climate gives a single number for that question. It is an indicator for storm surge from the sea, built on two open data sources. It is a starting point for a conversation or a closer look. It is not a risk assessment, and it cannot stand alone in an insurance or purchase decision.

Read the whole guide before you show the number to end users. The section on what the indicator does not cover is the most important one.

The call

The endpoint takes an access-address id or an address id with floor and door. Both give the same answer, because the elevation is measured at the entrance:

Shell#climate-curl
curl -s "https://api.danadresse.dk/api/v1/enrich/adresser/0a3f507c-0624-32b8-e044-0003ba298018/climate" \
  -H "X-Api-Key: $DANADRESSE_API_KEY"
JSON#climate-svar
{
  "adresseid": "0a3f507c-0624-32b8-e044-0003ba298018",
  "coordinates": { "lat": 55.7326, "lon": 12.5757 },
  "flood_risk": {
    "level": "moderate",
    "margin_m": 1.51,
    "terrain_m": 3.35,
    "surge_100yr_future_m": 1.84,
    "rationale": "terrain 3.35 m DVR90 vs projected 100-yr storm surge 1.84 m → margin 1.51 m"
  },
  "storm_surge": {
    "coast": "Øresunds_kyst",
    "distance_km": 9.0,
    "sea_level_rise_cm": 27.7,
    "storm_surge_future_cm": { "20yr": 165.5, "50yr": 177.5, "100yr": 184.5 },
    "scenario": { "scenarie": "SSP5-8.5", "periode": "2041-2070", "percentil": "median (50%)" }
  },
  "terrain": { "terraen_kote_m": 3.35, "datum": "DVR90", "model": "DHM/Terræn" },
  "data_source": "DMI Klimaatlas (open) · Datafordeler DHM/Terræn · CC BY 4.0"
}

How the margin is calculated

The indicator compares two numbers:

  1. Ground elevation at the address point, from the Danish Elevation Model (terrain.terraen_kote_m). The height is in metres above DVR90, which roughly equals today's mean sea level.
  2. The projected 100-year storm surge at the nearest coastal stretch with data in DMI's Climate Atlas (storm_surge.storm_surge_future_cm["100yr"], converted to metres in surge_100yr_future_m). The scenario is fixed: SSP5-8.5, the median, the period 2041-2070. It is a high-emissions scenario, chosen because it is used for cautious planning.

margin_m is the ground elevation minus the storm-surge height. A positive margin means the ground lies above the projected water level in a 100-year event. A negative margin means it lies below.

levelCondition
highmargin 0 m or less
elevatedmargin below 1 m
moderatemargin from 1 m to below 2.5 m
lowmargin 2.5 m or more
minimalno coastal stretch with data within 30 km
nulldata is missing. rationale explains why and margin_m is null

The 1 m and 2.5 m thresholds are our own choice for grouping the number. They are not an official classification. Show the margin in metres next to the level.

What the indicator does not cover

  • Cloudbursts and rainwater. Flooding from heavy rain, overloaded sewers and hollows where water collects is not included.
  • Streams, lakes and groundwater. Only the sea is included.
  • Whether the water can get there. The comparison is height against height. Dikes, sluices, dunes and higher ground between the coast and the address are not considered. A low-lying address behind a dike can get high even though it is protected.
  • Distance to the coast. The storm-surge height comes from the nearest data point in the Climate Atlas, which can be several kilometres away (storm_surge.distance_km). The indicator does not tell you how close the address is to the water.
  • The building itself. Ground elevation is measured at the address point. Floor height, basement and plinth are not included.
  • Local waves and wind set-up beyond what is in the Climate Atlas figures.

If the building has had damage registered by the Danish Storm Council, BBR marks it. See stormflodRegistreret in the BBR guide. That is a historical fact and a useful supplement to the projected indicator.

Using it in code

Python#climate-python
import os
import requests

def stormflod(adgangsadresse_id):
    r = requests.get(
        f"https://api.danadresse.dk/api/v1/enrich/adresser/{adgangsadresse_id}/climate",
        headers={"X-Api-Key": os.environ["DANADRESSE_API_KEY"]},
        timeout=20,
    )
    if r.status_code == 503:
        return {"text": "Data temporarily unavailable", "retry_after": r.headers.get("Retry-After")}
    r.raise_for_status()
    f = r.json()["flood_risk"]
    if f["level"] is None:
        return {"text": "Not enough data for an assessment", "detail": f["rationale"]}
    if f["level"] == "minimal":
        return {"text": "Far from the coast (over 30 km)", "level": "minimal"}
    return {
        "text": f'Ground {f["terrain_m"]} m, 100-year storm surge about {f["surge_100yr_future_m"]} m '
                f'(margin {f["margin_m"]:+.2f} m)',
        "level": f["level"],
    }

print(stormflod("0a3f507c-0624-32b8-e044-0003ba298018"))

When you show it to users

  • Say what the number is: "The ground lies 1.5 m above a projected 100-year storm surge (2041-2070)". Avoid words like "safe" or "dangerous".
  • Show the source and the licence. The data comes from DMI's Climate Atlas and the Danish Elevation Model under CC BY 4.0: "Indeholder data fra Klimadatastyrelsen (CC BY 4.0)" and DMI.
  • Point to the official sources for a real assessment, for example the municipality's climate adaptation plan.

Technical notes

  • The response is cached for 24 hours per address. The first call can take a few seconds.
  • Test keys get 403 with sandbox_scope, browser keys 403 with browser_key_scope. Call it from your server.
  • If one of the underlying sources does not answer, terrain or storm_surge can hold a _status field, and flood_risk.level is then null. During Datafordeleren's service windows the call can answer 503 with upstream_unavailable and Retry-After.
  • An unknown id gives 404 with the code not_found.

Next steps

Related guides

Markdown source Spotted an error? Tell us API-reference (Swagger)

Try it with a free key

2,000 calls/month on the free plan. No credit card.

Create account →