Cleanse addresses in Zapier with Webhooks or Code by Zapier

Call datavask from a Zap with Webhooks by Zapier, pick the right result out of the list, and handle errors and 429 with Code by Zapier.

4 min Level: Beginner ✓ Code tested

Zapier can cleanse an address every time a form is submitted, a lead is created or a row arrives in a spreadsheet. The short recipe is at /en/integrationer/zapier. Here you get the exact field mapping, a pitfall with lists, and a version with error handling.

1. Webhooks by Zapier: GET

Add a step: Webhooks by Zapier → GET. Fill in:

FieldValue
URLhttps://api.danadresse.dk/datavask/adgangsadresser
Query String Paramsbetegnelse = the address field from the trigger
HeadersX-Api-Key = your key

Put the key under Headers rather than api_key in the query string. The URL with its query string is shown in the Zap history.

/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 the result then also has etage, dør and adgangsadresseid. Separate parameters (vejnavn, husnr, etage, dør, postnr) work too.

2. The pitfall: lists get joined

The response has a list, resultater, which can hold several candidates. Zapier shows fields from a list as one value with all items joined by commas. The field Resultater Adresse Postnr can therefore be 2900,2900 if two candidates came back.

Use only the first item. Add Formatter by Zapier → Utilities → Pick from List, choose the field (e.g. Resultater Adresse Id) and Choose: First. Repeat for the fields you need, or use Code by Zapier from step 4, which gives you one object.

Field in ZapierContent
KategoriA, B or C for the best match
Resultater Adresse IdThe access address UUID
Resultater Adresse Vejnavn / HusnrStreet and house number
Resultater Adresse Postnr / PostnrnavnPostcode and city

The cleanse answer has no municipality or coordinates. The Code by Zapier version in step 4 fetches them with one extra call.

3. Filter on category

Add Filter by Zapier: continue only if Kategori is A or B. A is an exact match. B is one safe match with small spelling differences, so write back the official text from the result. C addresses (several candidates or larger differences) need a human to look at them. On a plan with Paths you can send them down their own branch, for example to a Slack message.

4. With error handling: Code by Zapier

The Webhooks step does not give you the status code as a field, and an error response stops the step. To tell error types apart, use Code by Zapier → Run JavaScript instead. Under Input Data, set adresse to the address field and apiKey to the key.

JavaScript#code-by-zapier
const BASE = "https://api.danadresse.dk";
const headers = { "X-Api-Key": inputData.apiKey };
const url = new URL(BASE + "/datavask/adgangsadresser");
url.searchParams.set("betegnelse", inputData.adresse || "");

const res = await fetch(url, { headers });
const body = await res.json().catch(() => ({}));

// Per-minute limit: throw, so Zapier can run the step again later.
if (res.status === 429 && res.headers.get("retry-after")) {
  throw new Error("Danadresse: too many calls per minute, try again");
}
// Other errors, e.g. quota_exceeded or a blocked key: pass the code and the explanation on.
if (!res.ok) {
  return {
    status: res.status,
    fejlkode: body.code || "unknown",
    besked: body.title || "",
    upgrade_url: (body.details && body.details.upgrade_url) || "",
    kategori: "",
  };
}

const top = (body.resultater && body.resultater[0] && body.resultater[0].adresse) || {};
let adg = {};
if (top.id) {
  // The cleanse answer has no municipality or coordinates: one more call for them.
  const r2 = await fetch(BASE + "/adgangsadresser/" + top.id, { headers });
  if (r2.ok) adg = await r2.json();
}
return {
  status: res.status,
  fejlkode: "",
  kategori: body.kategori,
  id: top.id || "",
  vejnavn: top.vejnavn || "",
  husnr: top.husnr || "",
  postnr: top.postnr || "",
  by: top.postnrnavn || "",
  kommune: (adg.kommune && adg.kommune.navn) || "",
  x: adg.adgangspunkt?.koordinater?.[0] ?? "", // longitude
  y: adg.adgangspunkt?.koordinater?.[1] ?? "", // latitude
};

Zapier runs the code inside an async function, so top-level await and return are valid there. After the step you have flat fields such as kategori, postnr and fejlkode that you can filter on directly. On an error, besked holds the API's plain-language explanation.

fejlkode can be, for example:

CodeMeaning
quota_exceededThe free plan's monthly quota and its 20 % grace are used up. It resets on the 1st of next month; upgrade_url links to the upgrade page
invalid_api_key, missing_api_keyThe key is wrong or missing
key_blocked, origin_not_allowedThe key is blocked or locked to domains. Use a server key without a domain lock

If your Zapier plan has Autoreplay turned on, Zapier reruns failed steps later. That suits the per-minute limit. It does not help with a used-up monthly quota.

5. Usage

Each Zap run is one call with Webhooks, two with the Code by Zapier version. Refused calls (429) are not counted. If your Zap runs on an import with many rows, you can hit the per-minute limit of 360 calls per minute on the free plan. Check your usage under Usage.

Test the call

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 →