Spring til indhold

Jobs via API

6 min læsning

Alt, hvad du kan i dashboardets Jobs, kan du også fra din egen kode. Base-URL'en er https://api.danskadresseapi.dk.

Nøgle: Send en live-nøgle med scope batch som Authorization: Bearer <nøgle>. En pub-nøgle kan ikke bruges, og planen skal være Pro eller Enterprise.

Endpoints

KaldGør
POST /v1/jobsOpretter et job. Svarer 202 med jobbet og en Location-header
GET /v1/jobsTeamets jobs, nyeste først (?limit= op til 100, ?foer=<tidspunkt> for næste side)
GET /v1/jobs/{id}Status, fremdrift, rækker pr. sekund, forventet tid (eta_sek), job_fejl og raekke_fejl
GET /v1/jobs/{id}/resultatResultatet — ?format=ndjson (standard) eller ?format=csv
GET /v1/jobs/{id}/fejlRækkerne, der ikke gav et (sikkert) svar — ?format=csv (standard) eller ndjson, evt. ?aarsag= og ?sprog=en
POST /v1/jobs/{id}/pauseSætter et job i kø eller i gang på pause — den del, der er i gang, gøres færdig og gemmes
POST /v1/jobs/{id}/genoptagGenoptager et job på pause, hvor det slap. Svarer 202 (evt. med advarsel om kvoten)
DELETE /v1/jobs/{id}Annullerer et job i kø, i gang eller på pause

Kvote: Kun jobbets rækker tæller — hver række, der gav et svar, som ét opslag. Rækker, der fejler, og selve POST-kaldet koster ikke noget. Status, resultat, fejlrækker, pause og annullering tæller ikke i kvoten, men følger planens rate limit.

Opret et job

Der er tre måder at sende filen på:

1. Rå fil — sæt Content-Type efter formatet, og angiv type (og evt. variant og navn) i URL'en:

FormatContent-Type
CSVtext/csv
TSVtext/tab-separated-values
NDJSONapplication/x-ndjson

2. JSON med elementerne — {"type": …, "variant": …, "navn": …, "input": [ … ]} med Content-Type: application/json.

3. JSON med rå data — {"type": …, "format": "csv", "data": "<filens indhold>"}.

variant er adresser eller adgangsadresser for datavask og bygninger eller enheder for BBR. Udelader du den, bruges den første. Filens format er beskrevet i Filformat til jobs.

Svaret er jobbet med status koe. Rækker kvoten ikke til hele jobbet, står der en advarsel i svaret — jobbet stopper så med kvote_stop, når kvoten er brugt. Afvises oprettelsen, står årsagen i error.details.kode — se Når et job fejler — fejlkoder.

Statussvaret

JSON
{
  "id": "7c0e6f0a-3b1d-4f5e-9a51-2d4c8b1e9f20",
  "type": "datavask",
  "variant": "adresser",
  "kilde": "api",
  "navn": "kunder-oktober",
  "status": "koerer",
  "total": 48522,
  "behandlet": 21000,
  "fejl": 140,
  "procent": 43.3,
  "raekker_pr_sek": 1840,
  "eta_sek": 15,
  "afregnede_opslag": 20860,
  "fejlbesked": null,
  "oprettet": "2026-10-04T14:11:31.000Z",
  "startet": "2026-10-04T14:11:32.000Z",
  "faerdig": null,
  "udloeber": null,
  "resultat": null,
  "job_fejl": null,
  "venter_paa_kapacitet": false,
  "venter_kapacitet_siden": null,
  "pauset": null,
  "raekke_fejl": {
    "total": 140,
    "pr_aarsag": { "ikke_tolket": 140 },
    "advarsler": { "total": 512, "pr_aarsag": { "flere_mulige": 380, "intet_match": 132 } },
    "daekket_raekker": 21000
  }
}
  • status — se betydningen i Følg et job og hent resultatet.
  • fejl — antal rækker uden svar. raekke_fejl fordeler dem (og advarslerne) pr. årsag.
  • job_fejl — er null, medmindre jobbet er stoppet af en fejl. Så står koden i job_fejl.kode, og en evt. reference til support i job_fejl.reference.
  • venter_paa_kapacitet — true, mens et kørende job venter med sin næste del, fordi API'et er travlt (almindelige kald går forud; Enterprise-jobs venter først ved højere belastning end Pro-jobs). Jobbet venter højst ca. 2 minutter pr. del, intet går tabt, og venter_kapacitet_siden fortæller, hvornår ventetiden begyndte.
  • pauset — hvornår jobbet blev sat på pause (kun ved status pauset).
  • resultat — links til resultatet, når der er noget at hente.

Hent resultatet

GET /v1/jobs/{id}/resultat virker, når status er faerdig — og giver delresultatet, når status er pauset, fejlet, kvote_stop eller annulleret. Resultatet strømmes del for del, så også store resultater kan hentes.

  • 409 — jobbet er ikke færdigt endnu.
  • 410 — resultatet er udløbet og slettet.

Headerne X-Job-Status og X-Job-Raekker fortæller, hvilken status og hvor mange rækker du fik.

Eksempler

cURL — opret et datavask-job fra en CSV-fil, følg det og hent resultatet:

Bash
# Opret jobbet
curl -X POST "https://api.danskadresseapi.dk/v1/jobs?type=datavask&variant=adresser&navn=kunder" \
  -H "Authorization: Bearer $ADDR_KEY" \
  -H "Content-Type: text/csv" \
  --data-binary @adresser.csv

# Følg status (brug id'et fra svaret)
curl "https://api.danskadresseapi.dk/v1/jobs/JOB_ID" \
  -H "Authorization: Bearer $ADDR_KEY"

# Hent resultatet som CSV
curl -o resultat.csv "https://api.danskadresseapi.dk/v1/jobs/JOB_ID/resultat?format=csv" \
  -H "Authorization: Bearer $ADDR_KEY"

# Hent fejlrækkerne
curl -o fejl.csv "https://api.danskadresseapi.dk/v1/jobs/JOB_ID/fejl" \
  -H "Authorization: Bearer $ADDR_KEY"

Python

Python
import os, time, requests

API = "https://api.danskadresseapi.dk"
H = {"Authorization": "Bearer " + os.environ["ADDR_KEY"]}

with open("koordinater.csv", "rb") as f:
    r = requests.post(API + "/v1/jobs", params={"type": "reverse"},
                      headers={**H, "Content-Type": "text/csv"}, data=f)
r.raise_for_status()
job = r.json()

while job["status"] in ("koe", "koerer"):
    time.sleep(3)
    job = requests.get(API + "/v1/jobs/" + job["id"], headers=H).json()

if job["job_fejl"]:
    print("Fejlkode:", job["job_fejl"]["kode"], job["job_fejl"]["besked"])

if job["resultat"]:
    res = requests.get(API + "/v1/jobs/" + job["id"] + "/resultat",
                       params={"format": "csv"}, headers=H)
    open("resultat.csv", "wb").write(res.content)

JavaScript (Node 18+)

JavaScript
const API = "https://api.danskadresseapi.dk";
const H = { Authorization: "Bearer " + process.env.ADDR_KEY };

const opret = await fetch(API + "/v1/jobs", {
  method: "POST",
  headers: { ...H, "Content-Type": "application/json" },
  body: JSON.stringify({
    type: "bbr",
    variant: "bygninger",
    input: ["57a791c4-25b0-4e57-8143-aa5b08efec51", "6c16b07d-acb1-414e-9d24-443340fe382e"],
  }),
});
let job = await opret.json();
if (!opret.ok) throw new Error(job.error.message + " (" + job.error.details?.kode + ")");

while (job.status === "koe" || job.status === "koerer") {
  await new Promise((r) => setTimeout(r, 3000));
  job = await (await fetch(API + "/v1/jobs/" + job.id, { headers: H })).json();
}

const ndjson = await (await fetch(API + "/v1/jobs/" + job.id + "/resultat", { headers: H })).text();
const raekker = ndjson.trim().split("\n").map((l) => JSON.parse(l));

I stedet for at spørge efter status igen og igen kan du abonnere på webhooken job.completed (og job.failed) og hente resultatet, når den kommer. Se Notifikationer og webhooks for jobs.

Annullér et job

Bash
curl -X DELETE "https://api.danskadresseapi.dk/v1/jobs/JOB_ID" \
  -H "Authorization: Bearer $ADDR_KEY"

Jobbet får status annulleret, og det, der nåede at blive behandlet, kan hentes. Er jobbet allerede afsluttet, svarer API'et 409.

Pause og genoptag

Bash
curl -X POST "https://api.danskadresseapi.dk/v1/jobs/JOB_ID/pause" \
  -H "Authorization: Bearer $ADDR_KEY"

curl -X POST "https://api.danskadresseapi.dk/v1/jobs/JOB_ID/genoptag" \
  -H "Authorization: Bearer $ADDR_KEY"

pause virker for et job i kø eller i gang: den del, der er i gang, gøres færdig og gemmes, og jobbet får status pauset. genoptag virker kun for et job på pause (ellers 409) — kvoten tjekkes først, og jobbet fortsætter præcis efter sidste gemte række. Et fejlet, kvote_stop eller annulleret job fortsættes med Fortsæt i dashboardet.

Synkrone batch-kald og kvoten

De synkrone batch-endpoints (fx POST /v1/datavask/adresser/batch) tjekker kvoten for hele batchen, før noget behandles. Er der ikke plads til alle elementerne, svarer API'et 429 — intet er behandlet, og intet er afregnet:

JSON
{
  "error": {
    "type": "quota_exceeded",
    "message": "Batchen har 500 elementer, men der er kun 120 opslag tilbage af kvoten i denne periode. Intet er behandlet eller afregnet. …",
    "code": 429,
    "details": { "antal": 500, "tilbage": 120, "grund": "kvote", "upgrade_url": "https://danskadresseapi.dk/dashboard/fakturering" }
  }
}
  • details.antal — antal elementer, du sendte.
  • details.tilbage — hvor mange opslag der er plads til. Send en mindre batch (højst tilbage elementer), opgradér, eller vent til kvoten nulstilles.
  • Samtidige batch-kald på samme team reserverer hver sin plads, så de tilsammen aldrig går over kvoten. Det kald, der ikke får plads, får 429 med details.reserveret_samtidig (opslag, som de andre kald har reserveret).
  • details.retry_after_seconds og headeren Retry-After er kun med, når kvoten nulstilles inden for en time.

rate_limit_exceeded eller quota_exceeded? Ved rate_limit_exceeded sender du for hurtigt — vent og send samme kald igen uændret. Ved quota_exceeded hjælper det ikke at sende samme kald igen, før kvoten nulstilles — send en mindre batch, eller opgradér.

Et job opfører sig anderledes: det kører, til kvoten er brugt, stopper med status kvote_stop, og delresultatet kan hentes. Derfor er et job ofte det bedste valg til store mængder.

Mere

Var dette nyttigt?