.NET SDK
A .NET client for every endpoint, with DAWA's records, field names and errors. Targets .NET Standard 2.0 and .NET 8, and uses no reflection, so it works in trimmed, native AOT and file-based apps. The current version is 1.0.0.
Install
dotnet add package getAddress.Dk.Sdk
Set it up
Register it as a typed HttpClient:
services.AddSingleton(new GetAddressDk.ApiKeys("{your-api-key}", "{your-admin-key}"));
services.AddHttpClient<GetAddressDk.Api>();
Or construct it yourself:
var api = new GetAddressDk.Api(httpClient, new GetAddressDk.ApiKeys("{your-api-key}"));
The API key goes in the api-key query parameter of every request. The admin key is only needed for usage.
Keep both on your server: an API key sent from a web page is refused with 401. When the
HttpClient has no BaseAddress, https://api.getaddress.dk/ is used.
Code that runs in your visitors' browsers (Blazor WebAssembly) uses a domain token instead:
var api = new GetAddressDk.Api(httpClient, GetAddressDk.ApiKeys.DomainToken("{your-domain-token}"));
Names
Records keep DAWA's Danish field names, in PascalCase with æ, ø and å written ae, oe and
aa: dør is Doer, højde is Hoejde, ændret
is Aendret. The JSON names are exactly DAWA's. Each record comes in DAWA's three shapes, picked by the
method name: GetAdresse (struktur=nestet), GetAdresseFlad and
GetAdresseMini. Coordinates are WGS84 unless you pass Srid.Etrs89Utm32 (EPSG:25832).
Autocomplete
DAWA's combined /autocomplete: street names, then access addresses, then addresses as the user types.
var result = await api.Autocomplete("Amagerbrogade 217A");
if (result.IsSuccess)
{
foreach (var suggestion in result.Success)
{
var text = suggestion.Forslagstekst; // what to show in the list
if (suggestion.IsAdresse)
{
var adresse = await api.GetAdresse(suggestion.Data.Id!); // one look-up
}
}
}
DAWA's parameters are on AutocompleteQuery:
await api.Autocomplete(new GetAddressDk.AutocompleteQuery
{
Q = "Amagerbrogade 217A",
Type = GetAddressDk.AutocompleteLevel.Adresse,
Postnr = "2300|2400", // several separated by |, as in DAWA
Fuzzy = true,
PerSide = 10,
});
AdresserAutocomplete, AdgangsadresserAutocomplete, VejnavneAutocomplete and
PostnumreAutocomplete call DAWA's per-resource autocompletes.
Adresser and adgangsadresser
One record by id is one look-up; a search costs one look-up per record returned. See Adresser and Adgangsadresser.
var adresse = await api.GetAdresse("3bba05d4-c8c4-4c90-8a64-a4dff11b9d1b");
var line = adresse.Success!.Adressebetegnelse; // "Amagerbrogade 217A, kl. 5, 2300 København S"
var floor = adresse.Success.Etage; // "kl"
var door = adresse.Success.Doer; // "5"
var found = await api.SearchAdresser(new GetAddressDk.AdresseQuery
{
Postnr = "2300",
Vejnavn = "Amagerbrogade",
Husnr = "217A",
PerSide = 100, // at most 100; Side pages on
});
var adgangsadresse = await api.GetAdgangsadresseMini("099f3e28-4fb8-4c61-86a1-edff5df52409");
Etage = "" or Doer = "" means "has none", as in DAWA.
Reverse geocoding
The access address nearest a point. One look-up.
var nearest = await api.Reverse(12.6137425, 55.6490036); // WGS84
var utm = await api.ReverseMini(724524.37, 6172102.97, GetAddressDk.Srid.Etrs89Utm32);
GeoJSON
var feature = await api.GetAdresseGeoJson("3bba05d4-c8c4-4c90-8a64-a4dff11b9d1b");
var json = feature.Success!.Json; // exactly as sent, for a map library
SearchAdresserGeoJson, SearchAdgangsadresserGeoJson, GetAdgangsadresseGeoJson
and ReverseGeoJson do the same.
Vejnavne and postnumre
Free, and rate limited. See Vejnavne and Postnumre.
var streets = await api.Vejnavne(new GetAddressDk.VejnavnQuery { Postnr = "2300" }); // every street in 2300
var street = await api.GetVejnavn("Amagerbrogade");
var postcodes = await api.Postnumre(); // all of them
var postcode = await api.GetPostnummer("2300");
Usage
Needs the admin key. See Usage.
var today = await api.Usage();
var oneDay = await api.Usage(29, 9, 2026);
var range = await api.Usage(new DateTime(2026, 9, 1), new DateTime(2026, 9, 29));
Result and Failure
Every call returns a Result<T>. When IsSuccess is true, Success holds the
response; otherwise Failed is a Failure. Errors are results, not exceptions.
Failure.Status is the HTTP status (0 when no response arrived) and
Failure.Message says what went wrong. There are two kinds:
- DAWA's errors, with DAWA's status and body.
CodeisQueryParameterFormatError(400),ResourcePathFormatError(404, e.g. an id that is not a UUID) orResourceNotFoundError(404), andDetailslists each parameter and what was wrong with it. - Our refusals, as problem details:
401(no key, an unknown key, or an API key from a web page),403(the key may not do this, or the subscription has ended) and429withRetryAfterSeconds.Codeis the body'scodewhen it has one. See Errors.
var result = await api.GetAdresse(id);
if (!result.IsSuccess)
{
if (result.Failed.IsNotFound) { /* no such address; costs nothing */ }
else if (result.Failed.IsQueryParameterFormatError) { var what = result.Failed.Details[0].Name; }
else if (result.Failed.IsRateLimited) { await Task.Delay(TimeSpan.FromSeconds(result.Failed.RetryAfterSeconds ?? 60)); }
else if (result.Failed.IsUnauthorized) { /* key missing or unknown */ }
else { var message = result.Failed.Message; }
}