Cleanse addresses in Power Automate with the HTTP action

Call datavask from a Power Automate flow with the HTTP action, parse the response with a ready-made JSON schema, and handle 429 and empty results.

4 min Level: Beginner ✓ Code tested

A Power Automate flow can cleanse an address every time a new row appears in SharePoint, Dataverse, Excel Online or a Microsoft Forms response. You use the built-in HTTP action, a Parse JSON step and a condition on the category.

1. Add the HTTP action

After your trigger: New step → HTTP. Fill in:

FieldValue
MethodGET
URIhttps://api.danadresse.dk/datavask/adgangsadresser
HeadersX-Api-Key = your key
Queriesbetegnelse = the address field from the trigger (dynamic content)

Use Queries rather than putting the address into the URI. Power Automate then encodes spaces, commas and æøå itself.

Open the action's Settings and turn on Secure Inputs. Otherwise the key appears in plain text in the run history. Inside a solution you can keep the key in an environment variable of type Secret instead of typing it into the action.

2. Parse the response

Add Data Operation → Parse JSON. Content: Body from the HTTP action. Schema:

JSON#parse-schema
{
  "type": "object",
  "properties": {
    "kategori": { "type": "string" },
    "resultater": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "adresse": {
            "type": "object",
            "properties": {
              "id": { "type": "string" },
              "href": { "type": "string" },
              "status": { "type": "integer" },
              "vejnavn": { "type": ["string", "null"] },
              "adresseringsvejnavn": { "type": ["string", "null"] },
              "husnr": { "type": ["string", "null"] },
              "supplerendebynavn": { "type": ["string", "null"] },
              "postnr": { "type": ["string", "null"] },
              "postnrnavn": { "type": ["string", "null"] },
              "virkningstart": { "type": ["string", "null"] },
              "virkningslut": { "type": ["string", "null"] }
            }
          },
          "vaskeresultat": {
            "type": "object",
            "properties": {
              "afstand": { "type": "integer" },
              "ukendtetokens": { "type": "array" }
            }
          }
        }
      }
    }
  },
  "required": ["kategori", "resultater"]
}

Fields such as supplerendebynavn are often null. If the type is only "string", Parse JSON fails on those addresses. Hence ["string", "null"]. If you generate the schema from a sample where the field holds text, the type becomes string only, and the flow later fails on an address where the field is null.

3. Use the fields

resultater is a list with the best match first. Read the fields with expressions:

Text#expressions
first(body('Parse_JSON')?['resultater'])?['adresse']?['id']
first(body('Parse_JSON')?['resultater'])?['adresse']?['postnr']
first(body('Parse_JSON')?['resultater'])?['adresse']?['postnrnavn']
first(body('Parse_JSON')?['resultater'])?['adresse']?['vejnavn']

?['…'] makes the expression return null instead of failing when resultater is empty.

The cleanse answer has the official street, house number, postcode and city, but no municipality or coordinates. If you need them, add a second HTTP action with GET https://api.danadresse.dk/adgangsadresser/{id} (the id from above) and read kommune.kode, kommune.navn and adgangspunkt.koordinater (longitude, latitude) from its body.

Add a Condition on kategori. A is an exact match. B is one safe match with small spelling differences: write it back, using the official text from adresse. C is uncertain (several candidates or larger differences): send it to manual review, for example as a Planner task or an email, and never accept it automatically. Category C with an empty resultater means no candidate was found.

/datavask/adgangsadresser matches the entrance (street, house number, postcode). For the exact 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, send vejnavn, husnr, etage, dør and postnr as separate query parameters instead.

4. Errors and 429

The HTTP action fails on every response of 400 or above. The default retry policy retries on 408, 429 and 5xx. Two kinds of 429 can occur:

  • rate_limit_per_minute with Retry-After (1-60 seconds): too many calls in a minute. A retry helps.
  • quota_exceeded without Retry-After: the free plan's monthly quota and its 20 % grace are used up. Retrying will not help until the 1st of next month. The body says so in plain text, and details has resets_at (when it lifts) and upgrade_url.

Refused calls are not counted, so the retries cost nothing.

Set Retry Policy to Fixed interval, 2 retries, interval PT10S. Then add an action, for example an email to yourself, and set its Configure run after to has failed and has timed out. That way you notice if the key is blocked (401/403) or the quota is used up.

If the flow processes many rows at once, set Concurrency Control on your Apply to each to a low value. Otherwise you hit the per-minute limit.

Test the call

The same call the HTTP action makes, from a terminal:

Shell#test-call
curl -s "https://api.danadresse.dk/datavask/adgangsadresser?betegnelse=R%C3%A5dhuspladsen%201%2C%201550%20K%C3%B8benhavn%20V" \
  -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 →