Test keys and the sandbox (dawa_test_)

Use dawa_test_ keys for development and CI without spending your quota, and keep test and production apart.

4 min Level: Beginner ✓ Code tested

A test key starts with dawa_test_ and is meant for development, automated tests and demos. It returns the same address data as a live key, but it is never billed and does not use your account's monthly quota. In return it has some limits, which this guide walks through.

Create a test key

Go to Keys, click Create key and pick test. The key is shown once. Store it in your password manager or in the .env file you use locally.

Test keys do not count towards the key limit. The cap of 2 keys on the Hobby plan applies to live keys only, so you can have one test key per developer or per CI pipeline.

Differences between test and live

Live (dawa_live_…)Test (dawa_test_…)
DataAll endpointsAddress endpoints only (see below)
MeteringPer account (Hobby) or per key (paid plans)Per client IP, with the Hobby plan's limits
Per-minute limitYour plan's limit360 calls a minute per IP
BillingAccording to your planNever
Leak controlYes, flagged when used from many IPsNo
Domain lock (browser key)Yes, if you set domainsYes, if you set domains

Per-IP metering means that two developers on separate internet connections do not share a limit, while two CI jobs behind the same NAT address do. The X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Minute-Remaining headers show the IP's numbers, not the account's. More in Limits, quotas and 429.

What a test key may call

Test keys cover address lookups: every DAWA-compatible path such as /autocomplete, /adresser, /adgangsadresser, /datavask/adresser, /postnumre, /kommuner and /replikering/….

Three groups under /api/v1 fetch data live from public registers with a shared key and are therefore closed to test keys:

  • /api/v1/enrich/… (BBR, DAGI, property, climate and the other enrichments)
  • /api/v1/datavask/parse
  • /api/v1/stats/national

Call them with a test key and you get status 403:

JSON#sandbox-scope-body
{
  "detail": {
    "error": {
      "code": "sandbox_scope",
      "message": "The sandbox/demo key is limited to basic address lookups. Use your own API key for enrich/datavask/stats."
    }
  },
  "error": {
    "code": "sandbox_scope",
    "message": "The sandbox/demo key is limited to basic address lookups. Use your own API key for enrich/datavask/stats."
  }
}

The fix is to use your own live key for those calls. Enrichment works on our own demo pages because those pages send a short-lived token that only holds from them. You cannot use that token from your own code. The public demo key on /widget is a test key too and has the same limits.

If you need to test enrichment in CI, use a separate live key with low traffic and watch it under Usage.

When to use which

TaskKey
Local development of an address field or an importTest
Unit and integration tests in CITest
Demo page or prototypeTest, locked to the domain
Production (web shop, CRM, backend)Live
Calls to /api/v1/enrich/…, /api/v1/datavask/parse, /api/v1/stats/nationalLive
Load testNeither without an agreement. Write to us via support

Never use a test key for production traffic. All your users share the server's IP, so they also share one IP limit at the free tier, and the per-minute limit is reached quickly.

Keep the environments apart

The simplest rule: production gets a live key from the production environment's secrets, every other environment gets a test key. Let the code check this at startup, so a wrong key is caught immediately and not in a customer's checkout.

This script shows which kind of key you have set and makes one call:

Python#key-mode-check
import os
import requests

key = os.environ["DANADRESSE_API_KEY"].strip()
if key.startswith("dawa_test_"):
    print("Test key: metered per IP, never billed")
elif key.startswith("dawa_live_"):
    print("Live key: metered on the account")
else:
    raise SystemExit("Unknown key format. It must start with dawa_test_ or dawa_live_")

r = requests.get(
    "https://api.danadresse.dk/postnumre/2900",
    headers={"X-Api-Key": key},
    timeout=10,
)
r.raise_for_status()
print(r.json()["nr"], r.json()["navn"])
print("Left this month:", r.headers.get("X-RateLimit-Remaining"))

A startup guard in Python that refuses to run production with a test key, and the other way round:

Python#startup-guard-python
import os
import sys

ENV = os.environ.get("APP_ENV", "development")
KEY = os.environ.get("DANADRESSE_API_KEY", "").strip()

if not KEY:
    sys.exit("DANADRESSE_API_KEY is not set")
if ENV == "production" and not KEY.startswith("dawa_live_"):
    sys.exit("Production must use a dawa_live_ key")
if ENV != "production" and KEY.startswith("dawa_live_"):
    sys.exit(f"{ENV} must not use the production key. Use a dawa_test_ key")

The same guard in Node:

JavaScript#startup-guard-node
const env = process.env.NODE_ENV ?? "development";
const key = (process.env.DANADRESSE_API_KEY ?? "").trim();

if (!key) throw new Error("DANADRESSE_API_KEY is not set");
if (env === "production" && !key.startsWith("dawa_live_")) {
  throw new Error("Production must use a dawa_live_ key");
}
if (env !== "production" && key.startsWith("dawa_live_")) {
  throw new Error(`${env} must not use the production key. Use a dawa_test_ key`);
}
export const DANADRESSE_API_KEY = key;

In CI, store the test key as a secret and pass it on as an environment variable. Example for GitHub Actions:

YAML#github-actions
jobs:
  test:
    runs-on: ubuntu-latest
    env:
      APP_ENV: test
      DANADRESSE_API_KEY: ${{ secrets.DANADRESSE_TEST_KEY }}
    steps:
      - uses: actions/checkout@v4
      - run: pip install -r requirements.txt
      - run: pytest

A test key in a browser

A test key can be used in frontend code on a demo page. Set Allowed domains on the key under Keys, as with a live key. Calls from other sites are then refused with 403 origin_not_allowed. See Browser keys and allowed domains.

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 →