Cleanse addresses in Make with the HTTP module
Set up the HTTP module in a Make scenario against datavask, map the fields correctly, and handle 429 and errors with a router or an error handler.
Make does not need a dedicated Danadresse app. The built-in HTTP module calls the API directly, and with Parse response turned on the response becomes fields you can map onward. The short recipe is at /en/integrationer/make. This guide goes further: exact field mapping, the key in a header, and what to do about errors and 429.
1. Set up the HTTP module
Add HTTP → Make a request after the module that delivers the address (Google Sheets, a webhook, your CRM). Fill in:
| Field | Value |
|---|---|
| URL | https://api.danadresse.dk/datavask/adgangsadresser |
| Method | GET |
| Headers | Name X-Api-Key, Value your key |
| Query String | Name betegnelse, Value the address from the previous module, e.g. {{1.Adresse}} |
| Parse response | Yes |
Send the key as a header rather than as api_key in the query string. The query string appears in the scenario's execution log together with the URL, so anyone with access to the log can see the key. If your HTTP module has a field for API-key authentication, you can store the key there with the header name X-Api-Key.
/datavask/adgangsadresser matches the entrance (street, house number, postcode). To hit a specific flat, use /datavask/adresser: it reads floor and door straight from betegnelse (Strandvejen 100, 2. tv, 2900 Hellerup), and adresse then also has etage, dør and adgangsadresseid. If you have the parts in separate fields, you can send vejnavn, husnr, etage, dør and postnr as separate query parameters instead.
2. Map the fields
With Parse response the response sits under data. resultater is a list with the best match first, and Make counts from 1. Assuming the HTTP module is module number 2:
| You need | Mapping |
|---|---|
| Category (A, B or C) | {{2.data.kategori}} |
| Access address id | {{2.data.resultater[1].adresse.id}} |
| Street name | {{2.data.resultater[1].adresse.vejnavn}} |
| House number | {{2.data.resultater[1].adresse.husnr}} |
| Postcode | {{2.data.resultater[1].adresse.postnr}} |
| City | {{2.data.resultater[1].adresse.postnrnavn}} |
| HTTP status | {{2.statusCode}} |
The response the mapping is based on looks like this:
{
"kategori": "A",
"resultater": [
{
"adresse": {
"id": "0a3f507c-0624-32b8-e044-0003ba298018",
"vejnavn": "Strandvejen",
"adresseringsvejnavn": "Strandvejen",
"husnr": "100",
"supplerendebynavn": null,
"postnr": "2900",
"postnrnavn": "Hellerup",
"status": 1,
"href": "…"
},
"aktueladresse": { "…": "same fields, the current version" },
"vaskeresultat": {
"afstand": 0,
"forskelle": { "vejnavn": 0, "husnr": 0, "postnr": 0, "postnrnavn": 0 },
"ukendtetokens": []
}
}
]
}If resultater is empty, the category is C and every resultater[1] field is empty. Check for that in a filter before writing back.
The cleanse answer has no municipality or coordinates. If you need them, add a second HTTP module with the URL https://api.danadresse.dk/adgangsadresser/{{2.data.resultater[1].adresse.id}} and the same header. Map kommune.kode, kommune.navn and adgangspunkt.koordinater[1] / [2] (longitude, latitude) from its data. That is one extra call per row.
3. Split the flow with a router
Put a Router after the HTTP module with three routes:
- Filter:
{{2.statusCode}}= 200 and{{2.data.kategori}}is A or B → write the address back. A is an exact match. B is one safe match with small spelling differences, so write back the official text from the result, not the input. - Filter:
{{2.statusCode}}= 200 and{{2.data.kategori}}= C → send to manual review (Slack, email, a tab in your sheet). C means several candidates or larger differences; never accept it automatically. - The fallback route: everything else → log the status and the address so you can rerun them.
The router only works if the HTTP module does not stop the scenario on errors. So set Evaluate all states as errors to No in the module's advanced settings. 4xx and 5xx responses then continue as ordinary bundles with a statusCode.
4. 429 and retries
There are two kinds of 429, and they need different handling:
| Code | Header | What to do |
|---|---|---|
rate_limit_per_minute | Retry-After (1-60 seconds) | Too many calls in a minute. Wait and retry |
quota_exceeded | no Retry-After | The free plan's monthly quota and its 20 % grace are used up. Stop until the 1st of next month, or upgrade |
The code is in {{2.data.code}}, because error responses on the DAWA paths have the shape {"type", "title", "details", "code"}. For quota_exceeded, {{2.data.title}} is a plain-language explanation, {{2.data.details.resets_at}} says when the quota resets, and {{2.data.details.upgrade_url}} links to the upgrade page. Refused calls are not counted.
If you would rather let Make retry automatically, leave Evaluate all states as errors on Yes, right-click the HTTP module and choose Add error handler → Break. Set the number of attempts to 3 and the interval to 1 minute. That requires Allow storing of incomplete executions to be on in the scenario settings. Break helps with the per-minute limit, not with a used-up monthly quota.
If the scenario processes many rows at once, add Tools → Sleep for 1 second after the HTTP module. On the free plan the limit is 360 calls per minute.
Test the call
The same call the HTTP module makes, from a terminal:
curl -s "https://api.danadresse.dk/datavask/adgangsadresser?betegnelse=Strandvejen%20100%2C%202900%20Hellerup" \ -H "X-Api-Key: $DANADRESSE_API_KEY"
Next steps
- Zapier and n8n — the same setup in other tools.
- Limits, quotas and 429
- Short recipe: /en/integrationer/make
Related guides
Markdown source Spotted an error? Tell us API-reference (Swagger)