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.

4 min Level: Beginner ✓ Code tested

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:

FieldValue
URLhttps://api.danadresse.dk/datavask/adgangsadresser
MethodGET
HeadersName X-Api-Key, Value your key
Query StringName betegnelse, Value the address from the previous module, e.g. {{1.Adresse}}
Parse responseYes

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 needMapping
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:

JSON#response-shape
{
  "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:

  1. 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.
  2. 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.
  3. 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:

CodeHeaderWhat to do
rate_limit_per_minuteRetry-After (1-60 seconds)Too many calls in a minute. Wait and retry
quota_exceededno Retry-AfterThe 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:

Shell#test-call
curl -s "https://api.danadresse.dk/datavask/adgangsadresser?betegnelse=Strandvejen%20100%2C%202900%20Hellerup" \
  -H "X-Api-Key: $DANADRESSE_API_KEY"

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 →