# Go-live checklist for your address integration

> Go through keys, limits, error handling, caching, data and monitoring before your Danadresse integration goes into production.
>
> https://danadresse.dk/en/guides/go-live-tjekliste · verified 2026-11-02
Most of what goes wrong in production is not the calls themselves but everything around them: a test key that made it into production, a key sitting in a public page without a domain lock, or an address field that goes blank when a limit is hit.

This list collects the points worth checking before you go live. Each point links to a guide with the details.

## Keys

- **Use a live key.** Test keys (`dawa_test_…`) are counted per IP address at the free plan's level, and they cannot call `/api/v1/enrich/…`. See [Test keys and sandbox](/en/guides/testnoegler-sandbox).
- **One key per environment and service.** Then you can rotate or revoke one without hitting the others, and the dashboard shows which one is in use.
- **The key lives in a secret store**, not in the code and not in Git. See [Rotate API keys](/en/guides/roter-noegler).
- **Keys in web pages are locked to your domains** under **Tilladte domæner** (allowed domains). Remember both `firma.dk` and `www.firma.dk`. See [Browser keys and allowed domains](/en/guides/browser-noegler-domaener).
- **Server code sends the key in the header** `X-Api-Key`, not as `api_key` in the URL.

## Limits

- **You know your expected usage** per month and per minute and have picked a plan that fits. See the plans on the [front page](/#pricing).
- **On Hobby the quota is a ceiling.** After 2,000 calls you are served from a grace buffer up to 2,400 calls (header `X-Quota-Grace: true`). After that the API answers `429 quota_exceeded` for the rest of the month.
- **On a paid plan you have set a budget cap**, if overage must not run freely. It is set under [Billing](/dashboard/billing#budget). Without a cap, calls beyond the quota are billed as overage.
- **Batch jobs keep their pace** below the per-minute limit (360 on Hobby, 1,700 on Basis, 7,000 on Pro). See [Monitor usage](/en/guides/overvaag-forbrug#per-minute-headroom).
- **The full dataset is fetched with replication**, not with thousands of single calls. See [First extract](/en/guides/replikering-foerste-udtraek).

## Error handling

- **Every call has a timeout**, e.g. 10 seconds.
- **You only retry what can succeed**: `429` on the per-minute limit, `503`, `502`, `504` and network errors, with backoff and `Retry-After`. Never `401`, `403`, `400` or `quota_exceeded`. See [Retries and backoff](/en/guides/retries-og-backoff).
- **You branch on `code`**, not on the error text. See [The error format](/en/guides/fejlformat).
- **The user can carry on if the API does not answer.** An address field in a checkout must accept manual input, and the order must go through.

## Performance

- **Autocomplete has a debounce** of 150 to 250 ms and cancels stale calls. See [Hand-built DAWA autocomplete](/en/guides/migrer-egen-dawa-autocomplete).
- **Lookups that do not change are cached**, e.g. postcodes and municipalities. Error responses are never cached. See [Caching address lookups](/en/guides/caching).
- **List calls are paginated** with `side` and `per_side`. See [Pagination](/en/guides/paginering).

## Data

- **You store the address id**, not just the text. See [Store the address id](/en/guides/gem-adresse-id).
- **You have a plan for addresses that get retired.** See [status, darstatus and retired addresses](/en/guides/status-og-darstatus).
- **The attribution is on your pages**: "Contains data from Klimadatastyrelsen (CC BY 4.0)". See [Data licence, attribution and personal data](/en/guides/licens-og-gdpr).
- **Only the address is sent to the API**, never names, emails or phone numbers.

## Monitoring

- **You log `X-RateLimit-Remaining`** and get an alert at 80 percent of the monthly quota. On Hobby you also alert when `X-Quota-Grace: true` shows up: the quota is then used and the grace buffer has started.
- **You react to `X-Danadresse-Key-Status`**. If it is set, the key is flagged as possibly leaked.
- **You know where to find service status**: the [status page](/status). Changes to the API are in the [changelog](/changelog). Questions and bug reports go through [support](/en/support).

## Migrated from DAWA?

- **No DAWA URLs are left** in code or configuration, and CI fails if they come back. See [Find DAWA calls with migrate-cli](/en/guides/find-dawa-kald-med-migrate-cli).
- **You have checked the list of known differences** against the endpoints and fields you use. See [Move from DAWA](/en/guides/migrer-fra-dawa#5-known-gaps).
- **JSONP has the key in the URL**, if your frontend uses `callback`. A `<script>` tag cannot send `X-Api-Key`, so use `api_key` with a domain-locked browser key, or switch to `fetch`.

## Run a final check

The script runs with the key you are going live with. It warns if it is a test key, makes one call and shows how much room there is:

```python id=preflight run=live expect="autocomplete: 200"
import os

import requests

key = os.environ["DANADRESSE_API_KEY"]
if key.startswith("dawa_test_"):
    print("WARNING: this is a test key. Use a live key in production.")

r = requests.get(
    "https://api.danadresse.dk/autocomplete",
    params={"q": "Rådhuspladsen 1", "per_side": 1},
    headers={"X-Api-Key": key},
    timeout=10,
)
print(f"autocomplete: {r.status_code}")
print("monthly quota:", r.headers.get("X-RateLimit-Limit"), "- left:", r.headers.get("X-RateLimit-Remaining"))
print("per minute:   ", r.headers.get("X-RateLimit-Minute-Limit"))
status = r.headers.get("X-Danadresse-Key-Status")
if status:
    print(f"WARNING: the key is flagged as {status}")
if r.status_code != 200:
    print(r.text)
    raise SystemExit(1)
```

When everything is green, run the smoke test from [Move from DAWA](/en/guides/migrer-fra-dawa#3-run-a-smoke-test) with the endpoints your code uses.
