Code example: look up soil contamination
Soil contamination for a cadastral plot
Mapped soil contamination belongs to the plot — not to the individual address. Lookups therefore use owner-district code + cadastral number, exactly like /v1/jordstykker:
curl -H "Authorization: Bearer <key>" \
"https://api.danskadresseapi.dk/v1/jordforurening/2000151/639"The response
{
"ejerlavskode": 2000151,
"matrikelnr": "639",
"kortlagt": true,
"count": 1,
"results": [
{
"lokalitetsnr": "101-00001",
"status": "V2 kortlagt",
"v1_kortlagt": false,
"v2_kortlagt": true,
"lokalitetsnavn": "Søfortvej 5, m.fl., Prøvestenen",
"regionsnavn": "Region Hovedstaden",
"attest_url": "https://jord.miljoeportal.dk/report/?elav=2000151&matrnr=639",
"kilde_opdateret": "2026-04-27"
}
]
}V1 versus V2
| Level | Meaning |
|---|---|
| V1 | The region knows of activities that may have contaminated the plot. Not yet investigated. |
| V2 | Contamination has been documented by investigation. |
A locality can be both; then status reads V1 og V2 kortlagt and both v1_kortlagt and v2_kortlagt are true. Prefer the two booleans over parsing the status string — you avoid parsing Danish, and your code will not break if the regions add a new wording.
A clean plot returns 200, not 404
If the plot has no mapped contamination you still get a response:
{ "ejerlavskode": 2000151, "matrikelnr": "999x", "kortlagt": false, "count": 0, "results": [] }This is deliberate. A 404 could not be told apart from "unknown plot", and for the vast majority of plots "no contamination" is exactly the answer you are looking for.
From address to contamination
If you start from an address, fetch its cadastral reference first:
import os, requests
KEY = os.environ["DANSKADRESSEAPI_KEY"]
H = {"Authorization": f"Bearer {KEY}"}
BASE = "https://api.danskadresseapi.dk"
adr = requests.get(f"{BASE}/v1/adgangsadresser/0a3f5096-6d67-32b8-e044-0003ba298018",
headers=H, timeout=15).json()
elav = adr["ejerlavskode"]
matr = adr["matrikelnr"]
soil = requests.get(f"{BASE}/v1/jordforurening/{elav}/{matr}", headers=H, timeout=15).json()
if not soil["kortlagt"]:
print("No mapped soil contamination on this plot")
else:
for case in soil["results"]:
level = "documented" if case["v2_kortlagt"] else "suspected"
print(f"{case['lokalitetsnr']}: {level} — {case['attest_url']}")Filter across plots
The list endpoint accepts ejerlavskode, regionsnavn and niveau:
curl -H "Authorization: Bearer <key>" \
"https://api.danskadresseapi.dk/v1/jordforurening?regionsnavn=Region%20Midtjylland&niveau=v2&limit=100"niveau=v2 also matches localities that are both V1 and V2.
Good to know
- Data comes from Danmarks Miljøportal (DKjord) and is refreshed nightly.
kilde_opdateretshows when the region last touched that particular case. attest_urlpoints to the official soil contamination certificate — the same document you would otherwise have to track down during a property transaction.- Several addresses on the same plot naturally share the same cases.
- A plot can have multiple localities. Check
countrather than assuming one.
