danskadresseapi-sdk
v4.0.1
Published
Officiel JavaScript/TypeScript SDK for DanskAdresseAPI — drop-in DAWA replacement. Taler DAWA-fladen (/dawa) med BBR, statistik og batch som udvidelser, replikering-iterator, webhook-verify og React hooks.
Maintainers
Readme
danskadresseapi-sdk
Officiel JavaScript/TypeScript SDK for DanskAdresseAPI.
SDK'et taler DAWA-fladen (/dawa): samme stier, parametre og svarformer som
det officielle DAWA, som lukker 1. oktober 2026. Svarene er DAWA's egne rene
arrays og objekter. Oven på det giver SDK'et adgang til de udvidelser DAWA aldrig
har haft: BBR, statistik, batch-opslag og struktureret validering.
v4 — DAWA-fladen som standard. Opgraderer du fra v3, så læs Opgradering fra v3.
Installation
bun add danskadresseapi-sdk
# eller: npm install danskadresseapi-sdkQuick start
import { Addr } from 'danskadresseapi-sdk';
const addr = new Addr({ apiKey: process.env.ADDR_KEY! });
// Autocomplete — trinvis som DAWA: vejnavn → husnr → etage/dør
const forslag = await addr.autocomplete({ q: 'Nørrebrog', fuzzy: true });
// Reverse geocoding — x er længdegrad, y er breddegrad
const adresse = await addr.reverse({ x: 12.5571, y: 55.6883 });
// Datavask — rens én ustruktureret adressetekst
const vask = await addr.datavask({ betegnelse: 'Nørrebrogade 1, 2200 København N' });
// → { kategori: 'A' | 'B' | 'C', resultater: [...] }
// Adresse + BBR i ét kald
const medBbr = await addr.adgangsadresser.byId('0a3f5089-b3a7-32b8-e044-0003ba298018', { include: 'bbr' });⚠️ x og y. DAWA's rækkefølge er x = længdegrad, y = breddegrad — omvendt af den
lat/lon, mange er vant til. SDK'et kaster enAddrErrormederr.type === 'koordinater_ombyttet', hvis du sender dem byttet om, i stedet for at give dig en adresse i Østersøen. (Udvidelserne på/v1— batch, geo — bruger fortsatlat/lon, se nedenfor.)
DAWA-fladen
// Adresser og adgangsadresser — rene arrays, DAWA's parameternavne
await addr.adresser.search({ vejnavn: 'Rentemestervej', husnr: '8', postnr: '2400', etage: '2' });
await addr.adresser.byId('0a3f50a0-4661-32b8-e044-0003ba298018', { struktur: 'mini' });
await addr.adgangsadresser.search({ q: 'Sivmosevænget 3', per_side: 10 });
// DAGI — hvert tema har liste, opslag og reverse
await addr.dagi.politikreds('1470');
await addr.dagi.sogne({ per_side: 50 });
await addr.dagi.reverse('sogne', { x: 12.53, y: 55.70 });
await addr.dagi.lookup({ x: 12.53, y: 55.70 }); // alle inddelinger for punktet
// Postnumre og vejnavne
await addr.postnumre.byNr('2400');
await addr.vejnavne.search({ q: 'sivmosvænget', fuzzy: true });
// Reference-data
await addr.reference.vejstykke('101', '5804');
await addr.reference.jordstykke('330452', '10y');
await addr.reference.jordstykker({ ejerlavkode: '330452' }); // filter påkrævet — se nedenfor
await addr.reference.bebyggelser({ type: 'by', kommunekode: '0101' });
// Geo — DAWA's cirkel- og polygon-filtre
await addr.geo.indenForRadius({ x: 12.55, y: 55.68, radiusM: 500 });
await addr.geo.indenForBbox({ vest: 12.5, syd: 55.6, oest: 12.6, nord: 55.7 });
await addr.geo.naermeste({ x: 12.55, y: 55.68 });Jordstykker kræver et filter. Et ufiltreret opslag over samtlige matrikler i landet timer ud. Parameteren hedder
ejerlavkodeuden s — med s ignoreres den, og kaldet bliver ufiltreret.
Trinvis autocomplete
DAWA's autocomplete arbejder i trin. Vælger brugeren et vejnavn-forslag, skal
søgningen fortsætte med forslagets tekst — og næste kald skal have
startfra: 'adgangsadresse', ellers kommer vejnavnene igen for navne, der
findes i mange byer (fx «Strøget»):
const trin1 = await addr.autocomplete({ q: 'Strøget', fuzzy: true });
// → [{ type: 'vejnavn', tekst: 'Strøget ', forslagstekst: 'Strøget', … }, …]
const trin2 = await addr.autocomplete({ q: trin1[0].tekst, startfra: 'adgangsadresse', fuzzy: true });
// → [{ type: 'adgangsadresse', forslagstekst: 'Strøget 1, 7280 Sønder Felding', … }, …]Vis forslagstekst til brugeren. tekst kan indeholde DAWA's pladsholder for
etage og dør ("Rentemestervej 2, , 2400 København NV").
Udvidelser
Det DAWA aldrig har haft, ligger i egne navnerum:
// BBR — bygninger og enheder
await addr.bbr.bygninger.list({ adgangsadresseid: '0a3f5089-b3a7-32b8-e044-0003ba298018' });
await addr.bbr.bygninger.byId('1422c24d-20c0-4bb4-b5ec-1b6d3165db54');
// Flere opslag i én forespørgsel (Pro+) — hver linje/id afregnes som ét kald
await addr.bbr.bygninger.batch(['id1', 'id2']);
await addr.batch.datavask(['Nørrebrogade 1, 2200 København N', 'Strøget 12, 1160 København K']);
await addr.batch.reverse([{ lat: 55.6761, lon: 12.5683 }]);
await addr.batch.dagi([{ lat: 55.6761, lon: 12.5683 }, { postnr: '8000' }]);
// Struktureret validering — siger hvilket felt der er galt
await addr.validate({ vejnavn: 'Nørrebrogade', husnr: '1', postnr: '2200' });
// Afstand mellem to punkter
await addr.geo.distance({ from: { lat: 55.68, lon: 12.55 }, to: { id: '0a3f5089-b3a7-32b8-e044-0003ba298018' } });
// Statistik
await addr.stats.totals();
await addr.stats.kommuner({ limit: 10 });Streaming-iteratorer
// Iterér ALLE matchende adresser (side/per_side håndteres for dig)
for await (const adresse of addr.adresser.all({ kommunekode: '0101' })) {
process(adresse);
}
// Replikering — event-stream (kræver Enterprise)
let cursor = 0;
for await (const event of addr.replikering.adresser.iterate({ cursor })) {
applyEvent(event);
cursor = event.sekvensnummer; // gem cursor lokalt for resume
}Webhook-verify
Separat sub-export så React-bundlere ikke fanger Node-crypto:
import { verifyWebhook } from 'danskadresseapi-sdk/webhooks';
export async function POST(req: Request) {
const raw = await req.text();
const sig = req.headers.get('x-addr-signature') ?? '';
if (!verifyWebhook(raw, sig, process.env.WEBHOOK_SECRET!)) {
return new Response('Invalid signature', { status: 401 });
}
// ...behandl event
}Algoritmen er HMAC-SHA256 over ${unix_t}.${rawBody} med endpoint-secret. Replay-protection: 5 min default tolerance (override via { toleranceSeconds }).
React hooks
import { useAutocomplete } from 'danskadresseapi-sdk/react';
import { Addr } from 'danskadresseapi-sdk';
const addr = new Addr({ apiKey: process.env.NEXT_PUBLIC_ADDR_KEY! });
export function AddressInput() {
const [q, setQ] = useState('');
const [efterVejnavn, setEfterVejnavn] = useState(false);
const { results, loading, error } = useAutocomplete(q, {
client: addr,
per_side: 6,
startfra: efterVejnavn ? 'adgangsadresse' : undefined,
});
return (
<>
<input value={q} onChange={(e) => { setEfterVejnavn(false); setQ(e.target.value); }} />
{loading && <span>Søger...</span>}
{error && <span>{error.message}</span>}
<ul>
{results.map((r, i) => (
<li key={i} onClick={() => {
if (r.type === 'vejnavn') { setEfterVejnavn(true); setQ(r.tekst); }
}}>{r.forslagstekst}</li>
))}
</ul>
</>
);
}Konfiguration
new Addr({
apiKey: 'sk_live_…',
baseUrl: 'https://api.danskadresseapi.dk', // default
timeoutMs: 10_000, // default
retries: 1, // 5xx/netværk auto-retries
userAgentSuffix: 'my-app/1.0.0', // tilføjes efter "danskadresseapi-sdk/X.Y.Z"
});Errors
import { Addr, AddrError } from 'danskadresseapi-sdk';
try {
await addr.adresser.byId('0a3f50a0-0000-0000-0000-000000000000');
} catch (err) {
if (err instanceof AddrError) {
console.log(err.type, err.status, err.requestId, err.details);
// DAWA-fladen: 'ResourceNotFoundError' | 'ResourcePathFormatError' | 'QueryParameterFormatError' | …
// Udvidelserne: 'unauthorized' | 'forbidden' | 'rate_limited' | …
// SDK'et selv: 'koordinater_ombyttet'
}
}Opgradering fra v3
v4 skifter adresseopslagene fra /v1 til /dawa. Det er et brud: svarformen
er DAWA's, og flere parametre har skiftet navn.
| v3 | v4 |
|---|---|
| autocomplete({ q, limit }) | autocomplete({ q, per_side, fuzzy }) — trinvis, se ovenfor |
| reverse({ lat, lon }) | reverse({ x: lon, y: lat }) |
| adresser.search(...) → { count, results } | → rent array; paginér med side/per_side |
| datavask() (POST) | datavask() (GET, samme parametre) |
| dagi.lookup({ lat, lon }) | dagi.lookup({ x, y }) — adgangsadressens svar har alle inddelinger |
| dagi.lookupBatch(points) | batch.dagi(lookups) — v3-kaldet sendte en forkert body og fejlede altid |
| geo.indenForRadius({ lat, lon, radiusM }) | geo.indenForRadius({ x, y, radiusM }) |
| geo.indenForBbox({ syd, vest, nord, oest }) | uændret navngivning, nu som DAWA-polygon |
| geo.naermeste({ lat, lon, limit }) | geo.naermeste({ x, y }) — én adresse |
| reference.jordstykker() | reference.jordstykker({ ejerlavkode }) — filter påkrævet |
| reference.stormodtagere() | fjernet — findes hverken hos os eller i DAWA |
| bbr, stats, validate, geo.distance | uændret (udvidelser) |
Dine eksisterende /v1-kald virker fortsat — API'et er uændret. v4 er kun et
skifte i, hvad SDK'et kalder.
License
MIT
