# Rotér API-nøgler uden nedetid

> Skift en API-nøgle uden at et eneste kald fejler, reagér på en lækket eller spærret nøgle, og opbevar nøglen sikkert på din platform.
>
> https://danadresse.dk/guides/roter-noegler · verified 2026-11-02
En API-nøgle skal skiftes, når en medarbejder med adgang stopper, når nøglen har været synlig et sted, den ikke burde (en commit, et log, en skærmdeling), eller når vi har markeret den som mulig lækket. Det er også en god vane at skifte den med faste mellemrum.

Fordi en konto kan have flere aktive nøgler samtidig, kan du skifte uden nedetid: opret den nye, tag den i brug, og tilbagekald først den gamle, når intet bruger den mere.

## 1. Opret en ny nøgle

Gå til [Nøgler](/dashboard/keys), giv den nye nøgle et navn, der siger, hvor den skal bruges (fx `webshop-prod-2026-10`), vælg *live* og klik **Opret**. Nøglen vises kun én gang. Vi gemmer kun et hash af den og kan ikke vise den igen.

Antallet af aktive live-nøgler pr. konto er begrænset:

| Plan | Live-nøgler |
|---|---|
| Hobby | 2 |
| Basis | 8 |
| Pro | 20 |
| Enterprise | 50 |

Testnøgler tæller ikke med. Er du på loftet, kan du ikke oprette en ny live-nøgle (`403 key_cap_reached` fra API'et). Tilbagekald så en nøgle, du ikke bruger, før du går i gang. Har du kun én nøgle i brug, er der altid plads til en til, også på Hobby.

Var den gamle nøgle en browsernøgle med **Tilladte domæner**, så skriv de samme domæner på den nye, før du tager den i brug. Ellers svarer den ikke fra dine sider, eller den bliver set fra mange IP-adresser og markeret som lækket.

## 2. Test den nye nøgle

Kør et kald med den nye nøgle, før den kommer i produktion:

```bash id=test-new-key run=live expect="200"
curl -s -o /dev/null -w "%{http_code}\n" \
  "https://api.danadresse.dk/postnumre/8000" \
  -H "X-Api-Key: $DANADRESSE_API_KEY"
```

`200` betyder, at nøglen virker. `401` betyder, at den er kopieret forkert, ofte med et mellemrum eller et linjeskift for meget.

## 3. Tag den nye nøgle i brug

Læg den nye nøgle i dit secret-lager og genstart eller genudrul din tjeneste. Begge nøgler virker samtidig, så det gør ikke noget, at nogle instanser kører med den gamle et stykke tid.

Det bliver lettere næste gang, hvis koden læser nøglen fra en fil eller en miljøvariabel ved opstart i stedet for at have den i koden:

```python id=load-key run=syntax
import os
from pathlib import Path


def api_noegle() -> str:
    """Læs nøglen fra en secret-fil (Docker/Kubernetes) eller fra en miljøvariabel."""
    sti = os.environ.get("DANADRESSE_API_KEY_FILE")
    if sti:
        return Path(sti).read_text(encoding="utf-8").strip()
    noegle = os.environ.get("DANADRESSE_API_KEY", "").strip()
    if not noegle:
        raise RuntimeError("DANADRESSE_API_KEY eller DANADRESSE_API_KEY_FILE mangler")
    return noegle
```

`.strip()` fjerner det linjeskift, som mange værktøjer sætter i slutningen af en secret-fil.

Hvor nøglen hører hjemme, afhænger af platformen:

| Platform | Sted |
|---|---|
| Lokal udvikling | `.env`-fil, der står i `.gitignore` |
| Docker / Kubernetes | Docker secrets eller et Kubernetes `Secret`, monteret som fil eller miljøvariabel |
| GitHub Actions | Repository- eller environment-secrets |
| Vercel, Netlify og lignende | Projektets miljøvariabler, markeret som hemmelige |
| AWS, Azure, Google Cloud | Secrets Manager eller Parameter Store, Key Vault, Secret Manager |
| PHP på webhotel | En konfigurationsfil uden for webroden, eller en miljøvariabel i virtual host-opsætningen |
| WordPress | En konstant i `wp-config.php`, som ikke ligger i dit repo |
| Browser | Intet kan holdes hemmeligt. Brug en domænelåst browsernøgle |

## 4. Vent, til den gamle nøgle er stille

Kolonnen **Sidste brug** på [Nøgler](/dashboard/keys) viser, hvornår hver nøgle sidst blev brugt. Den opdateres højst én gang i minuttet. Vent, til tidspunktet for den gamle nøgle holder op med at flytte sig. Har du natlige job eller cron-opgaver, så vent et døgn, så de også har kørt med den nye nøgle.

Bliver den gamle nøgle ved med at blive brugt, kører noget stadig med den. Typiske steder er en glemt staging-server, et cron-job, en kollegas lokale `.env` eller en plugin-indstilling i et CMS.

## 5. Tilbagekald den gamle nøgle

Klik **Tilbagekald** ud for den gamle nøgle. Det virker med det samme: næste kald med den får `401 invalid_api_key`. Har du overset et sted i trin 4, vil det sted begynde at fejle nu, så hold øje med dine fejl de næste timer.

## Når en nøgle er lækket eller spærret

Vi holder øje med, fra hvor mange forskellige IP-adresser en live-nøgle bliver brugt på en dag. Er det mange, ligner det en nøgle, der er sluppet ud:

1. Nøglen bliver markeret, svarene får headeren `X-Danadresse-Key-Status: warn`, og du får en mail.
2. Bliver den ved med at blive brugt fra mange IP-adresser efter 72 timer, spærres den. Kald får `403 key_blocked`, og headeren siger `blocked`.

Testnøgler og domænelåste browsernøgler er ikke omfattet, fordi de er beregnet til at blive brugt fra mange steder.

Hvad du gør, afhænger af årsagen:

- **Nøglen sidder i en webside.** De mange IP-adresser er dine besøgende, så nøglen er ikke lækket. Lås den til dine domæner under **Tilladte domæner**. Se [Browsernøgler og tilladte domæner](/guides/browser-noegler-domaener).
- **Nøglen er sluppet ud** (et offentligt repo, en app, en kunde). Følg trin 1 til 5 med det samme, og tilbagekald den gamle nøgle uden at vente på trin 4, hvis du ved, at den er misbrugt.
- **Du ved, hvorfor tallet er højt** (fx en server bag mange skiftende udgående IP-adresser). Brug **Lås op** eller **Nulstil advarsel** på nøglen i dashboardet. Er du på Enterprise, kan du i stedet låse nøglen til dine IP-adresser.

Tjek også, om nøglen ligger i din Git-historik. En nøgle, der er slettet i den seneste commit, ligger stadig i de gamle:

```bash id=search-history run=syntax
git log -p --all -S "dawa_live_" -- . | grep -n "dawa_live_" | head
```

Finder du den, så rotér nøglen. Det er ikke nok at omskrive historikken, fordi kopier af repoet kan findes andre steder.

## Næste skridt

- Låse en nøgle til domæner: [Browsernøgler og tilladte domæner](/guides/browser-noegler-domaener).
- Se nøglestatus i dine logs: [Overvåg forbruget](/guides/overvaag-forbrug).
- Hele listen før produktion: [Go-live-tjekliste](/guides/go-live-tjekliste).
