# Fejl 400 og 404 – forkerte parametre og ukendte id'er

> Læs details i en 400-fejl, find stavefejl i parametre, der bliver ignoreret uden fejl, og skeln mellem not_found, route_not_found og unknown_entity.
>
> https://danadresse.dk/guides/fejl-400-og-404 · verified 2026-11-02
En 400 betyder, at en parameter har en værdi, API'et ikke kan bruge. En 404 betyder, at stien eller det id, du spørger efter, ikke findes. Begge tæller som et kald på din kvote, så det betaler sig at fange dem i koden. Nøglen bliver tjekket før parametrene, så har du også en nøglefejl, ser du 401 eller 403 først.

## 400 invalid_query_parameter

På DAWA-stierne giver en forkert parameter altid status 400 med `code` `invalid_query_parameter`. `details` er en liste med én post pr. fejl:

```json id=bad-param-body run=no
{
  "type": "QueryParameterFormatError",
  "title": "Invalid query parameter",
  "details": [
    {
      "type": "literal_error",
      "loc": ["query", "format"],
      "msg": "Input should be 'json', 'csv', 'geojson', 'geojsonz' or 'ndjson'",
      "input": "xml",
      "ctx": {"expected": "'json', 'csv', 'geojson', 'geojsonz' or 'ndjson'"}
    }
  ],
  "code": "invalid_query_parameter"
}
```

`loc[1]` er parameterens navn, `msg` er grunden, og `input` er den værdi, du sendte. Skriv dem i din log:

```python id=read-400 run=live expect="invalid_query_parameter"
import os

import requests

r = requests.get(
    "https://api.danadresse.dk/adresser",
    params={"postnr": "8000", "per_side": 5000},
    headers={"X-Api-Key": os.environ["DANADRESSE_API_KEY"]},
    timeout=10,
)
if r.status_code == 400:
    body = r.json()
    print(r.status_code, body["code"])
    for fejl in body["details"]:
        print(f"  {fejl['loc'][-1]} = {fejl['input']!r}: {fejl['msg']}")
```

De almindelige årsager:

| Symptom i `details` | Årsag | Løsning |
|---|---|---|
| `per_side`, `less_than_equal` | `per_side` over grænsen | Højst 1000 på de fleste lister, 100 på `/autocomplete`. Se [Paginering](/guides/paginering) |
| `side`, `greater_than_equal` | `side=0` | Sider starter ved 1 |
| `format` eller `struktur`, `literal_error` | Værdi, der ikke findes | Se [Formater](/guides/formater-json-csv-geojson) |
| `srid`, `x`, `y`, `int_parsing` eller `float_parsing` | Tekst i stedet for tal, fx komma som decimaltegn | Brug punktum: `x=12.5683` |
| `srid`, `value_error`, "srid skal være 4326 (WGS84) eller 25832 (ETRS89/UTM32)" | Et andet koordinatsystem, fx `srid=3857` | Brug `4326` (standard) eller `25832`. Se [Koordinater og srid](/guides/koordinater-srid) |
| `x` eller `y`, `missing` | Reverse uden koordinater | Send både `x` og `y` |
| `entitet`, `missing` | `/replikering/udtraek` uden entitet | `?entitet=adresse` |

På `/api/v1` hedder den tilsvarende fejl `422 validation_error`, og listen står i `error.details`.

### Andre 400-koder

| `code` | Årsag | Løsning |
|---|---|---|
| `invalid_kvh` | `kvh` er ikke præcis 12 tegn | Fyld husnummeret op med `_` foran: `03301407___1` |
| `invalid_kvhx` | `kvhx` er ikke præcis 19 tegn | kvh + etage (3) + dør (4), fyldt op med `_` |
| `invalid_cirkel` | `cirkel` er ikke tre tal, eller radius er uden for 1-50.000 m | `cirkel=længde,bredde,radius` |
| `invalid_polygon` | `polygon` er ikke gyldig GeoJSON, eller har færre end tre punkter | `polygon=[[[længde,bredde],…]]`, URL-kodet |
| `invalid_parameter` | `matrikelnr` uden `ejerlavkode`, eller `husnrfra`/`husnrtil`, der ikke er et husnummer | `details.parameter` nævner parameteren. Send også `ejerlavkode`, eller et husnummer som `5` eller `5A` |

## Stavefejl i parameternavne giver ingen fejl

Et parameternavn, API'et ikke kender, bliver ignoreret, som i DAWA. Kendte filtre filtrerer, også på `/autocomplete` (`postnr`, `kommunekode`, `adgangsadresseid`) og sammen med `cirkel`, `polygon` og `medtagnedlagte`. Men `?postnummer=8000` giver ikke en fejl. Det giver de første 100 adresser i hele landet, fordi filteret aldrig blev brugt. Det samme sker med `?kommune=0101` i stedet for `kommunekode`, `?pr_side=` i stedet for `per_side`, og `format=csv` på endpoints, der kun giver JSON.

Er resultatet for bredt, så tjek navnene mod API-beskrivelsen på `/openapi.json`. Funktionen her gør det automatisk, før den sender kaldet:

```python id=check-params run=live expect="postnummer"
import os

import requests

API = "https://api.danadresse.dk"
_spec = requests.get(f"{API}/openapi.json", timeout=10).json()


def unknown_params(path: str, params: dict) -> list[str]:
    """Parameternavne, som endpointet ikke kender (og derfor ville ignorere)."""
    known = {p["name"] for p in _spec["paths"][path]["get"].get("parameters", [])}
    return sorted(set(params) - known - {"api_key"})


def checked_get(path: str, params: dict) -> requests.Response:
    bad = unknown_params(path, params)
    if bad:
        raise ValueError(f"Ukendte parametre på {path}: {bad}")
    return requests.get(API + path, params=params, timeout=10,
                        headers={"X-Api-Key": os.environ["DANADRESSE_API_KEY"]})


print("Ukendte:", unknown_params("/adresser", {"postnummer": "8000", "per_side": 10}))
r = checked_get("/adresser", {"postnr": "8000", "per_side": 1})
print(r.status_code, r.json()[0]["adressebetegnelse"])
```

Hent specifikationen én gang ved opstart, ikke ved hvert kald.

## 404 not_found: id'et eller koden findes ikke

```json id=not-found-body run=no
{
  "type": "ResourceNotFoundError",
  "title": "Adresse 0a3f507a-ec01-32b8-e044-0003ba298018 not found",
  "details": null,
  "code": "not_found"
}
```

Gå listen igennem:

1. **Adgangsadresse-id på et adresse-endpoint.** Id'erne er forskellige. Eksemplet ovenfor er et adgangsadresse-id sendt til `/adresser/{id}`. Brug `/adgangsadresser/{id}`, eller `/adresser?adgangsadresseid=…` for enhederne bag døren. Den anden vej virker: `/adgangsadresser/{id}` med et adresse-id svarer med den adgangsadresse, enheden hører til. Se [Adresse eller adgangsadresse?](/guides/adresse-vs-adgangsadresse)
2. **Id fra et andet system.** Et id, der ikke kommer fra adresseregistret (fx et internt kunde-id eller et id fra et testsystem), findes ikke her.
3. **Reverse uden adresse i nærheden.** `/adgangsadresser/reverse` giver `404` med `"title": "No address within range"`, når der ikke er nogen adresse i nærheden af punktet. Typisk er `x` og `y` byttet om, eller UTM-koordinater er sendt uden `srid=25832`. Se [Koordinater og srid](/guides/koordinater-srid).
4. **Mellemrum eller linjeskift i id'et.** Fjern whitespace, før du sætter id'et ind i URL'en.

Koder uden foranstillede nuller er ikke en årsag: `/kommuner/101` og `kommunekode=101` virker og svarer med `0101`. Berigelser under `/api/v1/enrich/adresser/{id}/…` tager både et adgangsadresse-id og et adresse-id.

Prøv det selv med et adgangsadresse-id på adresse-endpointet:

```bash id=wrong-id-curl run=live expect="not_found"
curl -s "https://api.danadresse.dk/adresser/0a3f507a-ec01-32b8-e044-0003ba298018" \
  -H "X-Api-Key: $DANADRESSE_API_KEY"
```

## 404 route_not_found: stien findes ikke

`route_not_found` betyder, at URL'en ikke passer til noget endpoint:

- **`/api/v1` foran en DAWA-sti.** DAWA-stierne ligger i roden: `https://api.danadresse.dk/adresser`, ikke `/api/v1/adresser`.
- **Gammel sti fra DAWA's dokumentation, som ikke findes her.** Se [Kompatibilitet](/kompatibilitet) for listen over understøttede stier.
- **Stavefejl:** `/adresse` i stedet for `/adresser`, `/postnummer` i stedet for `/postnumre`.

Formatet afhænger af stien. Starter den med en DAWA-sti (`/adresser…`), får du DAWA-formatet. Ellers får du `/api/v1`-formatet:

```json id=route-not-found run=no
{
  "detail": {"error": {"code": "route_not_found", "message": "Not Found"}},
  "error": {"code": "route_not_found", "message": "Not Found"}
}
```

## 404 unknown_entity: forkert replikeringsentitet

`/replikering/udtraek?entitet=…` og `/replikering/{entitet}/haendelser` kender et fast sæt entiteter. Et forkert navn giver `unknown_entity`, og `details.supported` lister dem, der virker:

```json id=unknown-entity run=no
{
  "type": "ResourceNotFoundError",
  "title": "Unknown replication entity 'adressen'",
  "details": {"supported": ["adgangsadresse", "adresse", "…"], "legacy_names": ["adgangsadresser", "adresser", "…"]},
  "code": "unknown_entity"
}
```

Entiteter står i ental: `adresse`, `adgangsadresse`, `postnummer`. De gamle flertalsnavne som `adgangsadresser` accepteres også og står i `details.legacy_names`. Se [Replikering: hændelser](/guides/replikering-haendelser).

## Næste skridt

- [Ingen resultater?](/guides/ingen-resultater) når kaldet lykkes, men listen er tom.
- [Fejlformatet](/guides/fejlformat)
- [Adresse eller adgangsadresse?](/guides/adresse-vs-adgangsadresse)
