# 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.
>
> https://danadresse.dk/en/guides/zapier · verified 2026-11-02
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](/en/integrationer/zapier). Here you get the exact field mapping, a pitfall with lists, and a version with error handling.

> [!NOTE]
> Webhooks by Zapier is a premium app at Zapier and needs a paid Zapier plan.

## 1. Webhooks by Zapier: GET

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

| Field | Value |
|---|---|
| URL | `https://api.danadresse.dk/datavask/adgangsadresser` |
| Query String Params | `betegnelse` = the address field from the trigger |
| Headers | `X-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 Zapier | Content |
|---|---|
| Kategori | `A`, `B` or `C` for the best match |
| Resultater Adresse Id | The access address UUID |
| Resultater Adresse Vejnavn / Husnr | Street and house number |
| Resultater Adresse Postnr / Postnrnavn | Postcode 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.

```js id=code-by-zapier run=no
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:

| Code | Meaning |
|---|---|
| `quota_exceeded` | The 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_key` | The key is wrong or missing |
| `key_blocked`, `origin_not_allowed` | The 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](/dashboard/usage).

## Test the call

```bash id=test-call run=live expect="kategori"
curl -s "https://api.danadresse.dk/datavask/adgangsadresser?betegnelse=Strandvejen%20100%2C%202900%20Hellerup" \
  -H "X-Api-Key: $DANADRESSE_API_KEY"
```

## Next steps

- [Make](/en/guides/make) and [n8n](/en/guides/n8n)
- [Limits, quotas and 429](/en/guides/graenser-og-429)
- Short recipe: [/en/integrationer/zapier](/en/integrationer/zapier)
