Skip to content
Contents

API documentation

With the Robinsontjek API you check people against the Danish Robinson list straight from your own system, before you call or send addressed mail. You send a name and an address and get back exactly what we found for every person.

Every call goes to https://api.robinsontjek.dk and uses JSON. Error messages and match.label come in Danish or English following the Accept-Language header.

What you get for every person

  • match.level: what we found, from 0 (nobody on the list at the address) to 5 (same name and address). See the levels.
  • match.code, match.label and match.on: the same as a code and a text, and what matched.
  • list_version: which edition of the Robinson list we checked against.

You decide which level you go by. For integrations that only want a yes or no, there is also status, computed from your chosen level (stop_level).

Download OpenAPI (JSON)

Base URLhttps://api.robinsontjek.dk
First call
curl https://api.robinsontjek.dk/v2/list-versions/current \
  -H "Authorization: Bearer $ROBINSONTJEK_API_KEY"
Response · 200
{
  "id": "4c8e2a1f-7d3b-4e6a-9b25-1f0c6d8e3a71",
  "source": "cpr",
  "published_on": "2026-10-01",
  "activated_at": "2026-10-02T05:00:00Z"
}

Authentication

Every call needs your API key in the Authorization header:

Authorization: Bearer rl_live_…

You create keys in the app under Settings. Keep the key secret and use it only from your own server, never in a browser or an app.

Test and live

  • rl_live_… checks against the real Robinson list and counts towards your usage.
  • rl_test_… returns fixed, made-up answers, touches no real list and costs nothing. Answers to a test key carry the header X-Robinsontjek-Mode: test.

With a test key, the name decides the answer:

The name contains Answer
Test Blokeret level 5, same name and address
Test Tidligere level 4, previous address
Test Manuel level 1, someone else in the household
anything else with an address we can read level 0

Companies with CVR 99999999 are protected from marketing, and the phone number 99999999 returns a person who is on the list (level 5).

Header
Authorization: Bearer rl_test_4f9c1a7e2b8d6035
Wrong key
HTTP/1.1 401 Unauthorized

{
  "error": {
    "code": "unauthorized",
    "message": "The API key is invalid or revoked.",
    "request_id": "req_4a0f6c2e9b1d"
  }
}

Match levels

Every person gets a level from 0 to 5 in match.level. The level says what we found on the Robinson list at the person's address. The higher the level, the more closely what we found resembles the person.

Level match.code What we found
0 none Nobody on the list at the address
1 household Someone else in the household is on the list
2 surname Same surname at the address
3 given_name Same first name at the address
4 name_building Same name, different flat
5 name_address Same name and address

If we can't read the address, match.level is null and the reason is address_unreadable. match.previous_address is true when the person is on the list at a previous address. It counts as at least level 4. match.on shows which parts matched.

Your level: status and stop_level

You choose the level you go by, once in the app's settings or per call with stop_level on POST /v2/checks. If you don't choose, we use level 1, the most cautious. The level comes back in every answer as stop_level, and from it we compute status for integrations that want a ready answer:

status When
allowed match.level is below your level.
blocked match.level is at your level or above.
manual The address can't be read (match.level is null). Never allowed.

status is a convenience. If you'd rather decide row by row, use match.level.

Reasons

reasons are codes you can translate and show yourself:

Code Means
name_and_address The same name and address are on the list.
name_and_unit The same name in the same flat is on the list.
household Someone else at the address is on the list.
partial_name A similar name is on the list at the address.
previous_address The person is on the list at an address they have moved from.
address_unreadable We could not read the address. Correct it and check again.
address_not_found The address doesn't exist in Denmark as written.
no_name There is no name.
company_protected The company has opted out of marketing in CVR.
phone_unlisted The number is unlisted.
phone_not_found We could not find who has the number.
list_not_ready The Robinson list is being updated. Check again shortly.
A result
{
  "match": {
    "level": 5,
    "code": "name_address",
    "label": "Same name and address",
    "on": ["first_name", "last_name", "address", "unit"],
    "previous_address": false
  },
  "status": "blocked",
  "stop_level": 1,
  "reasons": ["name_and_address"]
}
Address can't be read
{
  "match": {
    "level": null,
    "code": null,
    "label": null,
    "on": [],
    "previous_address": false
  },
  "status": "manual",
  "stop_level": 1,
  "reasons": ["address_unreadable"],
  "address": null
}

Errors

An error always has the same shape: an error object with a fixed code your code can act on, and a message you can show to a person. Include request_id if you write to us about an error.

HTTP code What to do
400 invalid_request The body isn't valid JSON. Fix it.
401 unauthorized The key is missing, wrong or revoked.
402 payment_required The account has no active plan. Write to us.
403 phone_not_enabled Phone lookups are an add-on and aren't enabled for you.
403 company_checks_not_enabled Company checks are an add-on and aren't enabled for you.
404 not_found It doesn't exist, or it belongs to another account.
409 idempotency_in_progress A call with the same Idempotency-Key is running. Try again shortly.
422 invalid_request Something in the request is wrong. details says what.
422 idempotency_conflict The Idempotency-Key was used before for a different call.
429 rate_limited Too many calls. Wait the number of seconds in Retry-After.
503 list_not_ready The Robinson list is being updated. Try again shortly.
500 internal_error Something failed on our side. Try again.
Error · 422
{
  "error": {
    "code": "invalid_request",
    "message": "Person 3 has no address.",
    "details": {
      "field": "people",
      "index": 3
    },
    "request_id": "req_7f2c9a41e0b3"
  }
}

Rate limits and idempotency

Each key can make 600 calls a minute. Go over, and we answer 429 with a Retry-After header that says how many seconds to wait.

If you have many people, send them together: up to 1,000 in one call to POST /v2/checks, or up to 1,000,000 as a job with POST /v2/check-jobs.

Idempotency-Key

Send the Idempotency-Key header with a unique value, such as a UUID, on POST /v2/checks and POST /v2/check-jobs. If the connection fails and you send the same call again with the same key, you get the first answer back instead of the list being checked a second time.

  • A key is valid for 24 hours.
  • A repeated answer carries the header Idempotent-Replayed: true.
  • The same key with different content returns 422 idempotency_conflict.
Call with Idempotency-Key
curl -X POST https://api.robinsontjek.dk/v2/checks \
  -H "Authorization: Bearer $ROBINSONTJEK_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: b3f1c2de-5a7e-4c41-9d0a-2f6e8a91c7d4" \
  -d '{
    "people": [
      {
        "id": "lead-1042",
        "name": "Anne Marie Jensen",
        "address": "Stationsalleen 48, 1. b, 2770 Kastrup"
      }
    ]
  }'
Too many calls
HTTP/1.1 429 Too Many Requests
Retry-After: 12
RateLimit-Limit: 600
RateLimit-Remaining: 0
RateLimit-Reset: 12

{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Wait a moment and try again.",
    "request_id": "req_1d8e4b07c2a9"
  }
}

Webhooks

Robinsontjek sends a POST to your URL when something happens, so your system doesn't have to keep asking. Create the endpoint in the app under Settings. The signing secret is shown once, when the endpoint is created.

Event Happens when
check_job.completed A job is done. Fetch the results.
check_job.failed A job failed. data.error says why.
saved_list.changed A saved list has changes after a new check.
list_version.activated A new edition of the Robinson list has gone live.

A webhook never carries personal data, only ids and counts. id is unique per delivery, so you can ignore a delivery you have already handled.

Verify the signature

Every delivery has the header Robinsontjek-Signature: t=<timestamp>,v1=<signature>. The signature is the hex HMAC-SHA256, with your secret, of the text <timestamp>.<raw body>.

  1. Read the header and take t and v1.
  2. Compute HMAC-SHA256 of t + "." + raw body with your secret.
  3. Compare with v1 using a constant-time comparison.
  4. Reject deliveries where t is more than 5 minutes old.

Use the raw body, not JSON that was parsed and written again.

Replies and retries

Reply with a 2xx status within 5 seconds. Anything else counts as a failure, and we retry up to 8 times over about a day.

Delivery
POST /hooks/robinsontjek HTTP/1.1
Content-Type: application/json
Robinsontjek-Signature: t=1792057351,v1=5d3c0b8e…

{
  "id": "6f1c0c1e-93b4-4d2a-8e57-2c1f0a9b7d34",
  "type": "check_job.completed",
  "created_at": "2026-10-14T09:42:31Z",
  "data": {
    "check_job_id": "5b1d9e3c-2a4f-4c7e-8d16-0e9f7a2b4c58",
    "status": "done",
    "source": "api",
    "external_ref": "kampagne-oktober",
    "row_count": 1840,
    "allowed_count": 1512,
    "blocked_count": 312,
    "manual_count": 16,
    "finished_at": "2026-10-14T09:42:30Z"
  }
}
Verify the signature
import crypto from "node:crypto";

// rawBody: the request body exactly as it arrived (a Buffer or string)
function verify(header, rawBody, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${parts.t}.${rawBody}`)
    .digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
  return fresh && expected.length === parts.v1.length &&
    crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}

People

Check people against the Robinson list. Up to 1,000 at a time with the answer straight away, or large lists as a job that runs in the background.

Check people

POST/v2/checks

Checks up to 1,000 people and answers straight away, in the order you sent them. Give each person a name and an address. The address can be one field or split into street, house number, floor, door, postcode and town.

Headers

  • Idempotency-Keystring

    A unique value, such as a UUID. Send the same call again with the same key within 24 hours and you get the first answer back. See Rate limits and idempotency.

Body

  • peoplearray of objectsrequired

    The people to check. At least 1 and at most 1,000.

    Show 12 fields
    • idstring

      Your own reference, such as the id in your CRM. It comes back in the response.

    • namestring

      Full name. Or use first_name and last_name.

    • first_namestring

      First name (and any middle names).

    • last_namestring

      Surname.

    • addressstring

      The whole address in one field, such as Stationsalleen 48, 1. b, 2770 Kastrup. Or use the fields below.

    • streetstring

      Street name.

    • house_numberstring

      House number, with a letter if there is one, such as 12B.

    • floorstring

      Floor, such as st (ground), 1 or kl (basement).

    • doorstring

      Door, such as tv (left), th (right), mf (middle) or b.

    • postal_codestring

      Postcode, four digits.

    • citystring

      Town.

    • phonestring

      Phone number, if you have it. Only used when phone lookups are switched on.

  • stop_levelinteger · 1–5

    Go by a different level than your organisation's for this call only. It changes status, not what we found. See Match levels.

Response200

One result per person, in the same order.

  • list_versionobjectrequired

    The edition of the Robinson list that was checked against.

    Show 4 fields
    • idstring (uuid)required

      The list version's id.

    • sourcestring

      cpr is the Robinson list. customer is your own list of people who asked not to be contacted.

    • published_onstring (date)required

      The date CPR published the list.

    • activated_atstring (date-time)

      When we put the list to use.

  • resultsarray of objectsrequired

    One result per person, in the same order as the request.

    Show 7 fields
    • idstring · can be null

      Your reference from the request.

    • matchobject

      What we found on the Robinson list at the person's address.

      Show 5 fields
      • levelinteger · 0–5 · can be nullrequired

        Level from 0 to 5. null when the address can't be read.

      • codestring · can be nullrequired

        The level as a code: none, household, surname, given_name, name_building or name_address.

      • labelstring · can be null

        The level in words, in Danish or English following Accept-Language.

      • onarray of strings

        The parts that matched: first_name, last_name, address and unit.

      • previous_addressboolean

        true when the person is on the list at a previous address. It counts as at least level 4.

    • statusobjectrequired

      For integrations, computed from your chosen level: allowed (below the level), blocked (at the level or above) or manual (the address can't be read).

    • stop_levelinteger · 0–5

      The level you go by, which status is computed from. 1 by default, the most cautious.

    • reasonsarray of objectsrequired

      Codes that explain the answer. See Reasons.

    • addressobject · can be null

      How we read the address. null if it could not be read.

      Show 10 fields
      • inputstring

        The address as you sent it.

      • okboolean

        true when the address could be read.

      • streetstring · can be null

        Street name.

      • house_numberstring · can be null

        House number.

      • floorstring · can be null

        Floor.

      • doorstring · can be null

        Door.

      • postal_codestring · can be null

        Postcode.

      • citystring · can be null

        Town.

      • formattedstring · can be null

        The address written neatly on one line.

      • confidencestring

        exact, corrected or unresolved (could not be read).

    • phone_lookupobject · can be null

      Phone numbers only: what the directory lookup returned.

      Show 3 fields
      • outcomestring

        found, unlisted or not_found.

      • namestring

        The name behind the number.

      • addressstring

        The address behind the number.

Possible errors401402422429

POST /v2/checks
curl -X POST https://api.robinsontjek.dk/v2/checks \
  -H "Authorization: Bearer $ROBINSONTJEK_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: b3f1c2de-5a7e-4c41-9d0a-2f6e8a91c7d4" \
  -d '{
    "people": [
      {
        "id": "lead-1042",
        "name": "Anne Marie Jensen",
        "address": "Stationsalleen 48, 1. b, 2770 Kastrup"
      },
      {
        "id": "lead-1043",
        "first_name": "Jens",
        "last_name": "Hansen",
        "address": "Vestergade 12 8000 Aarhus"
      }
    ]
  }'
Response · 200 OK
{
  "list_version": {
    "id": "4c8e2a1f-7d3b-4e6a-9b25-1f0c6d8e3a71",
    "source": "cpr",
    "published_on": "2026-10-01",
    "activated_at": "2026-10-02T05:00:00Z"
  },
  "results": [
    {
      "id": "lead-1042",
      "match": {
        "level": 5,
        "code": "name_address",
        "label": "Same name and address",
        "on": ["first_name", "last_name", "address", "unit"],
        "previous_address": false
      },
      "status": "blocked",
      "stop_level": 1,
      "reasons": ["name_and_address"],
      "address": {
        "input": "Stationsalleen 48, 1. b, 2770 Kastrup",
        "ok": true,
        "street": "Stationsalleen",
        "house_number": "48",
        "floor": "1",
        "door": "b",
        "postal_code": "2770",
        "city": "Kastrup",
        "formatted": "Stationsalleen 48, 1. b, 2770 Kastrup",
        "confidence": "exact"
      }
    },
    {
      "id": "lead-1043",
      "match": {
        "level": 0,
        "code": "none",
        "label": "Nobody on the list at the address",
        "on": [],
        "previous_address": false
      },
      "status": "allowed",
      "stop_level": 1,
      "reasons": [],
      "address": {
        "input": "Vestergade 12 8000 Aarhus",
        "ok": true,
        "street": "Vestergade",
        "house_number": "12",
        "floor": null,
        "door": null,
        "postal_code": "8000",
        "city": "Aarhus C",
        "formatted": "Vestergade 12, 8000 Aarhus C",
        "confidence": "corrected"
      }
    }
  ]
}

Create a job

POST/v2/check-jobs

For large lists: up to 1,000,000 people as JSON, or an Excel or CSV file. The job runs in the background. Follow it with »Get a job«, or be told at callback_url or through the check_job.completed webhook.

Headers

  • Idempotency-Keystring

    A unique value, such as a UUID. Send the same call again with the same key within 24 hours and you get the first answer back. See Rate limits and idempotency.

Body

  • peoplearray of objectsrequired

    The people to check. At most 1,000,000.

    Show 12 fields
    • idstring

      Your own reference, such as the id in your CRM. It comes back in the response.

    • namestring

      Full name. Or use first_name and last_name.

    • first_namestring

      First name (and any middle names).

    • last_namestring

      Surname.

    • addressstring

      The whole address in one field, such as Stationsalleen 48, 1. b, 2770 Kastrup. Or use the fields below.

    • streetstring

      Street name.

    • house_numberstring

      House number, with a letter if there is one, such as 12B.

    • floorstring

      Floor, such as st (ground), 1 or kl (basement).

    • doorstring

      Door, such as tv (left), th (right), mf (middle) or b.

    • postal_codestring

      Postcode, four digits.

    • citystring

      Town.

    • phonestring

      Phone number, if you have it. Only used when phone lookups are switched on.

  • callback_urlstring (uri)

    We send a POST here when the job is done.

  • external_refstring

    Your own reference for the job, such as the campaign name. It comes back in responses and webhooks.

Or send a file (multipart/form-data)

  • filestring (binary)required

    An Excel file (xlsx or xls) or a CSV file.

  • column_mappingobject

    Which column is which. Leave it out and we find the columns ourselves.

    Show 15 fields
    • header_rowinteger

      The row with the headings. The first row is 0.

    • nameinteger | string

      The column's number (the first is 0) or its heading.

    • first_nameinteger | string

      The column's number (the first is 0) or its heading.

    • last_nameinteger | string

      The column's number (the first is 0) or its heading.

    • addressinteger | string

      The column's number (the first is 0) or its heading.

    • streetinteger | string

      The column's number (the first is 0) or its heading.

    • house_numberinteger | string

      The column's number (the first is 0) or its heading.

    • floorinteger | string

      The column's number (the first is 0) or its heading.

    • doorinteger | string

      The column's number (the first is 0) or its heading.

    • postal_codeinteger | string

      The column's number (the first is 0) or its heading.

    • cityinteger | string

      The column's number (the first is 0) or its heading.

    • phoneinteger | string

      The column's number (the first is 0) or its heading.

    • cvrinteger | string

      The column's number (the first is 0) or its heading.

    • company_nameinteger | string

      The column's number (the first is 0) or its heading.

    • external_idinteger | string

      The column's number (the first is 0) or its heading.

  • callback_urlstring (uri)

    We send a POST here when the job is done.

  • external_refstring

    Your own reference for the job, such as the campaign name. It comes back in responses and webhooks.

Response202

The job is accepted and queued.

  • idstring (uuid)required

    The job's id.

  • sourcestringrequired

    Where the list came from, such as api, upload or email.

    One of: upload, email, sftp, api, monitor, connector

  • statusstringrequired

    queued, running, done or failed. A file waiting for you in the app is draft or awaiting_payment.

    One of: draft, awaiting_payment, queued, running, done, failed, deleted

  • filenamestring · can be null

    The file's name, when the list came as a file.

  • file_formatstring · can be null

    xlsx, xls or csv.

  • row_countinteger

    Rows in the list.

  • processed_countinteger

    Rows checked so far.

  • allowed_countinteger

    How many are below your level.

  • blocked_countinteger

    How many are at your level or above.

  • manual_countinteger

    How many addresses could not be read.

  • level_countsobject
    Show 7 fields
    • 0integerrequired
    • 1integerrequired
    • 2integerrequired
    • 3integerrequired
    • 4integerrequired
    • 5integerrequired
    • unreadintegerrequired
  • columnsarray of strings

    The file's column headings, while the job is a draft.

  • column_mappingobject

    Which columns were used for what.

    Show 15 fields
    • header_rowinteger

      The row with the headings. The first row is 0.

    • nameinteger | string

      The column's number (the first is 0) or its heading.

    • first_nameinteger | string

      The column's number (the first is 0) or its heading.

    • last_nameinteger | string

      The column's number (the first is 0) or its heading.

    • addressinteger | string

      The column's number (the first is 0) or its heading.

    • streetinteger | string

      The column's number (the first is 0) or its heading.

    • house_numberinteger | string

      The column's number (the first is 0) or its heading.

    • floorinteger | string

      The column's number (the first is 0) or its heading.

    • doorinteger | string

      The column's number (the first is 0) or its heading.

    • postal_codeinteger | string

      The column's number (the first is 0) or its heading.

    • cityinteger | string

      The column's number (the first is 0) or its heading.

    • phoneinteger | string

      The column's number (the first is 0) or its heading.

    • cvrinteger | string

      The column's number (the first is 0) or its heading.

    • company_nameinteger | string

      The column's number (the first is 0) or its heading.

    • external_idinteger | string

      The column's number (the first is 0) or its heading.

  • optionsobject

    What the job checks.

    Show 5 fields
    • check_peopleboolean

      Check people against the Robinson list.

    • check_companiesboolean

      Check companies against the CVR register's marketing protection.

    • check_phonesboolean

      Look up phone numbers.

    • use_private_listboolean

      Also check against your own list of people who asked not to be contacted.

    • stop_levelinteger · 1–5
  • previewarray of objects

    The first 20 rows with their results.

    Show 2 fields
    • cellsarray of strings
    • resultobject
      Show 7 fields
      • idstring · can be null

        Your reference from the request.

      • matchobject

        What we found on the Robinson list at the person's address.

        Show 5 fields
        • levelinteger · 0–5 · can be nullrequired

          Level from 0 to 5. null when the address can't be read.

        • codestring · can be nullrequired

          The level as a code: none, household, surname, given_name, name_building or name_address.

        • labelstring · can be null

          The level in words, in Danish or English following Accept-Language.

        • onarray of strings

          The parts that matched: first_name, last_name, address and unit.

        • previous_addressboolean

          true when the person is on the list at a previous address. It counts as at least level 4.

      • statusobjectrequired

        For integrations, computed from your chosen level: allowed (below the level), blocked (at the level or above) or manual (the address can't be read).

      • stop_levelinteger · 0–5

        The level you go by, which status is computed from. 1 by default, the most cautious.

      • reasonsarray of objectsrequired

        Codes that explain the answer. See Reasons.

      • addressobject · can be null

        How we read the address. null if it could not be read.

        Show 10 fields
        • inputstring

          The address as you sent it.

        • okboolean

          true when the address could be read.

        • streetstring · can be null

          Street name.

        • house_numberstring · can be null

          House number.

        • floorstring · can be null

          Floor.

        • doorstring · can be null

          Door.

        • postal_codestring · can be null

          Postcode.

        • citystring · can be null

          Town.

        • formattedstring · can be null

          The address written neatly on one line.

        • confidencestring

          exact, corrected or unresolved (could not be read).

      • phone_lookupobject · can be null

        Phone numbers only: what the directory lookup returned.

        Show 3 fields
        • outcomestring

          found, unlisted or not_found.

        • namestring

          The name behind the number.

        • addressstring

          The address behind the number.

  • priceobject · can be null

    What the job costs. null on the annual plan.

    Show 3 fields
    • productstring

      The price the job falls under.

      One of: list_small, list_large, custom

    • amount_centsinteger

      The amount in øre (1/100 krone), excluding VAT.

    • currencystring

      Currency, such as DKK.

  • list_versionobject

    The edition of the Robinson list that was checked against.

    Show 4 fields
    • idstring (uuid)required

      The list version's id.

    • sourcestring

      cpr is the Robinson list. customer is your own list of people who asked not to be contacted.

    • published_onstring (date)required

      The date CPR published the list.

    • activated_atstring (date-time)

      When we put the list to use.

  • certificate_tokenstring · can be null

    The check receipt, once the job is done. It can be seen at robinsontjek.dk/en/receipt/<token>.

  • errorstring · can be null

    Why the job failed.

  • delete_afterstring (date-time) · can be null

    When the file and the rows are deleted.

  • created_atstring (date-time)

    When the job was created.

  • finished_atstring (date-time) · can be null

    When the job finished.

Possible errors401422

POST /v2/check-jobs
curl -X POST https://api.robinsontjek.dk/v2/check-jobs \
  -H "Authorization: Bearer $ROBINSONTJEK_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: b3f1c2de-5a7e-4c41-9d0a-2f6e8a91c7d4" \
  -d '{
    "people": [
      {
        "id": "lead-1042",
        "name": "Anne Marie Jensen",
        "address": "Stationsalleen 48, 1. b, 2770 Kastrup"
      },
      {
        "id": "lead-1043",
        "first_name": "Jens",
        "last_name": "Hansen",
        "address": "Vestergade 12 8000 Aarhus"
      }
    ],
    "callback_url": "https://example.com/hooks/robinsontjek",
    "external_ref": "kampagne-oktober"
  }'
Response · 202 Accepted
{
  "id": "5b1d9e3c-2a4f-4c7e-8d16-0e9f7a2b4c58",
  "source": "api",
  "status": "queued",
  "filename": null,
  "file_format": null,
  "row_count": 2,
  "processed_count": 0,
  "allowed_count": 0,
  "blocked_count": 0,
  "manual_count": 0,
  "list_version": {
    "id": "4c8e2a1f-7d3b-4e6a-9b25-1f0c6d8e3a71",
    "source": "cpr",
    "published_on": "2026-10-01",
    "activated_at": "2026-10-02T05:00:00Z"
  },
  "certificate_token": null,
  "created_at": "2026-10-14T09:41:58Z",
  "finished_at": null
}

Get a job

GET/v2/check-jobs/{id}

Shows how far the job has come, and the counts once it is done. certificate_token points to the check receipt, which can be seen at robinsontjek.dk/en/receipt/<token>.

Path

  • idstring (uuid)required

    The job's id.

Response200

The job as it stands.

  • idstring (uuid)required

    The job's id.

  • sourcestringrequired

    Where the list came from, such as api, upload or email.

    One of: upload, email, sftp, api, monitor, connector

  • statusstringrequired

    queued, running, done or failed. A file waiting for you in the app is draft or awaiting_payment.

    One of: draft, awaiting_payment, queued, running, done, failed, deleted

  • filenamestring · can be null

    The file's name, when the list came as a file.

  • file_formatstring · can be null

    xlsx, xls or csv.

  • row_countinteger

    Rows in the list.

  • processed_countinteger

    Rows checked so far.

  • allowed_countinteger

    How many are below your level.

  • blocked_countinteger

    How many are at your level or above.

  • manual_countinteger

    How many addresses could not be read.

  • level_countsobject
    Show 7 fields
    • 0integerrequired
    • 1integerrequired
    • 2integerrequired
    • 3integerrequired
    • 4integerrequired
    • 5integerrequired
    • unreadintegerrequired
  • columnsarray of strings

    The file's column headings, while the job is a draft.

  • column_mappingobject

    Which columns were used for what.

    Show 15 fields
    • header_rowinteger

      The row with the headings. The first row is 0.

    • nameinteger | string

      The column's number (the first is 0) or its heading.

    • first_nameinteger | string

      The column's number (the first is 0) or its heading.

    • last_nameinteger | string

      The column's number (the first is 0) or its heading.

    • addressinteger | string

      The column's number (the first is 0) or its heading.

    • streetinteger | string

      The column's number (the first is 0) or its heading.

    • house_numberinteger | string

      The column's number (the first is 0) or its heading.

    • floorinteger | string

      The column's number (the first is 0) or its heading.

    • doorinteger | string

      The column's number (the first is 0) or its heading.

    • postal_codeinteger | string

      The column's number (the first is 0) or its heading.

    • cityinteger | string

      The column's number (the first is 0) or its heading.

    • phoneinteger | string

      The column's number (the first is 0) or its heading.

    • cvrinteger | string

      The column's number (the first is 0) or its heading.

    • company_nameinteger | string

      The column's number (the first is 0) or its heading.

    • external_idinteger | string

      The column's number (the first is 0) or its heading.

  • optionsobject

    What the job checks.

    Show 5 fields
    • check_peopleboolean

      Check people against the Robinson list.

    • check_companiesboolean

      Check companies against the CVR register's marketing protection.

    • check_phonesboolean

      Look up phone numbers.

    • use_private_listboolean

      Also check against your own list of people who asked not to be contacted.

    • stop_levelinteger · 1–5
  • previewarray of objects

    The first 20 rows with their results.

    Show 2 fields
    • cellsarray of strings
    • resultobject
      Show 7 fields
      • idstring · can be null

        Your reference from the request.

      • matchobject

        What we found on the Robinson list at the person's address.

        Show 5 fields
        • levelinteger · 0–5 · can be nullrequired

          Level from 0 to 5. null when the address can't be read.

        • codestring · can be nullrequired

          The level as a code: none, household, surname, given_name, name_building or name_address.

        • labelstring · can be null

          The level in words, in Danish or English following Accept-Language.

        • onarray of strings

          The parts that matched: first_name, last_name, address and unit.

        • previous_addressboolean

          true when the person is on the list at a previous address. It counts as at least level 4.

      • statusobjectrequired

        For integrations, computed from your chosen level: allowed (below the level), blocked (at the level or above) or manual (the address can't be read).

      • stop_levelinteger · 0–5

        The level you go by, which status is computed from. 1 by default, the most cautious.

      • reasonsarray of objectsrequired

        Codes that explain the answer. See Reasons.

      • addressobject · can be null

        How we read the address. null if it could not be read.

        Show 10 fields
        • inputstring

          The address as you sent it.

        • okboolean

          true when the address could be read.

        • streetstring · can be null

          Street name.

        • house_numberstring · can be null

          House number.

        • floorstring · can be null

          Floor.

        • doorstring · can be null

          Door.

        • postal_codestring · can be null

          Postcode.

        • citystring · can be null

          Town.

        • formattedstring · can be null

          The address written neatly on one line.

        • confidencestring

          exact, corrected or unresolved (could not be read).

      • phone_lookupobject · can be null

        Phone numbers only: what the directory lookup returned.

        Show 3 fields
        • outcomestring

          found, unlisted or not_found.

        • namestring

          The name behind the number.

        • addressstring

          The address behind the number.

  • priceobject · can be null

    What the job costs. null on the annual plan.

    Show 3 fields
    • productstring

      The price the job falls under.

      One of: list_small, list_large, custom

    • amount_centsinteger

      The amount in øre (1/100 krone), excluding VAT.

    • currencystring

      Currency, such as DKK.

  • list_versionobject

    The edition of the Robinson list that was checked against.

    Show 4 fields
    • idstring (uuid)required

      The list version's id.

    • sourcestring

      cpr is the Robinson list. customer is your own list of people who asked not to be contacted.

    • published_onstring (date)required

      The date CPR published the list.

    • activated_atstring (date-time)

      When we put the list to use.

  • certificate_tokenstring · can be null

    The check receipt, once the job is done. It can be seen at robinsontjek.dk/en/receipt/<token>.

  • errorstring · can be null

    Why the job failed.

  • delete_afterstring (date-time) · can be null

    When the file and the rows are deleted.

  • created_atstring (date-time)

    When the job was created.

  • finished_atstring (date-time) · can be null

    When the job finished.

Possible errors404

GET /v2/check-jobs/{id}
curl https://api.robinsontjek.dk/v2/check-jobs/5b1d9e3c-2a4f-4c7e-8d16-0e9f7a2b4c58 \
  -H "Authorization: Bearer $ROBINSONTJEK_API_KEY"
Response · 200 OK
{
  "id": "5b1d9e3c-2a4f-4c7e-8d16-0e9f7a2b4c58",
  "source": "api",
  "status": "done",
  "filename": null,
  "file_format": null,
  "row_count": 1840,
  "processed_count": 1840,
  "allowed_count": 1512,
  "blocked_count": 312,
  "manual_count": 16,
  "list_version": {
    "id": "4c8e2a1f-7d3b-4e6a-9b25-1f0c6d8e3a71",
    "source": "cpr",
    "published_on": "2026-10-01",
    "activated_at": "2026-10-02T05:00:00Z"
  },
  "certificate_token": "rk_9QeT4mXw2LbN7cVz",
  "delete_after": "2026-11-13T09:42:30Z",
  "created_at": "2026-10-14T09:41:58Z",
  "finished_at": "2026-10-14T09:42:30Z"
}

Get results

GET/v2/check-jobs/{id}/results

Results come in pages of up to 10,000. Send next_cursor from the response as cursor in the next call, until it is null.

Path

  • idstring (uuid)required

    The job's id.

Query

  • cursorstring

    next_cursor from the previous page. Leave it out for the first page.

  • limitinteger

    Results per page. At most 10,000.

Response200

A page of results.

  • resultsarray of objects

    The results on this page.

    Show 7 fields
    • idstring · can be null

      Your reference from the request.

    • matchobject

      What we found on the Robinson list at the person's address.

      Show 5 fields
      • levelinteger · 0–5 · can be nullrequired

        Level from 0 to 5. null when the address can't be read.

      • codestring · can be nullrequired

        The level as a code: none, household, surname, given_name, name_building or name_address.

      • labelstring · can be null

        The level in words, in Danish or English following Accept-Language.

      • onarray of strings

        The parts that matched: first_name, last_name, address and unit.

      • previous_addressboolean

        true when the person is on the list at a previous address. It counts as at least level 4.

    • statusobjectrequired

      For integrations, computed from your chosen level: allowed (below the level), blocked (at the level or above) or manual (the address can't be read).

    • stop_levelinteger · 0–5

      The level you go by, which status is computed from. 1 by default, the most cautious.

    • reasonsarray of objectsrequired

      Codes that explain the answer. See Reasons.

    • addressobject · can be null

      How we read the address. null if it could not be read.

      Show 10 fields
      • inputstring

        The address as you sent it.

      • okboolean

        true when the address could be read.

      • streetstring · can be null

        Street name.

      • house_numberstring · can be null

        House number.

      • floorstring · can be null

        Floor.

      • doorstring · can be null

        Door.

      • postal_codestring · can be null

        Postcode.

      • citystring · can be null

        Town.

      • formattedstring · can be null

        The address written neatly on one line.

      • confidencestring

        exact, corrected or unresolved (could not be read).

    • phone_lookupobject · can be null

      Phone numbers only: what the directory lookup returned.

      Show 3 fields
      • outcomestring

        found, unlisted or not_found.

      • namestring

        The name behind the number.

      • addressstring

        The address behind the number.

  • next_cursorstring · can be null

    Send it as cursor to get the next page. null when there are no more.

GET /v2/check-jobs/{id}/results
curl https://api.robinsontjek.dk/v2/check-jobs/5b1d9e3c-2a4f-4c7e-8d16-0e9f7a2b4c58/results?limit=1000 \
  -H "Authorization: Bearer $ROBINSONTJEK_API_KEY"
Response · 200 OK
{
  "results": [
    {
      "id": "lead-1042",
      "match": {
        "level": 5,
        "code": "name_address",
        "label": "Same name and address",
        "on": ["first_name", "last_name", "address", "unit"],
        "previous_address": false
      },
      "status": "blocked",
      "stop_level": 1,
      "reasons": ["name_and_address"],
      "address": {
        "input": "Stationsalleen 48, 1. b, 2770 Kastrup",
        "ok": true,
        "street": "Stationsalleen",
        "house_number": "48",
        "floor": "1",
        "door": "b",
        "postal_code": "2770",
        "city": "Kastrup",
        "formatted": "Stationsalleen 48, 1. b, 2770 Kastrup",
        "confidence": "exact"
      }
    },
    {
      "id": "lead-1043",
      "match": {
        "level": 0,
        "code": "none",
        "label": "Nobody on the list at the address",
        "on": [],
        "previous_address": false
      },
      "status": "allowed",
      "stop_level": 1,
      "reasons": [],
      "address": {
        "input": "Vestergade 12 8000 Aarhus",
        "ok": true,
        "street": "Vestergade",
        "house_number": "12",
        "floor": null,
        "door": null,
        "postal_code": "8000",
        "city": "Aarhus C",
        "formatted": "Vestergade 12, 8000 Aarhus C",
        "confidence": "corrected"
      }
    }
  ],
  "next_cursor": "eyJyb3ciOjEwMDB9"
}

Companies (add-on, by agreement)

Add-on, by agreement. Check companies against the CVR register's marketing protection. If the company is a sole proprietorship, we also check the owner against the Robinson list. The endpoint answers 403 until it is enabled for your account. Write to us if you want it.

Check companies

POST/v2/company-checks

Add-on, by agreement: answers 403 until it is enabled for your account. Send the CVR number or the name of up to 1,000 companies at a time.

Body

  • companiesarray of objectsrequired

    The companies to check. At most 1,000.

    Show 3 fields
    • idstring

      Your own reference. It comes back in the response.

    • cvrstring

      CVR number, eight digits.

    • namestring

      The company's name, if you don't have the CVR number.

Response200

One result per company.

  • resultsarray of objects

    One result per company.

    Show 7 fields
    • idstring · can be null

      Your reference from the request.

    • cvrstring · can be null

      The CVR number.

    • namestring · can be null

      The company's name in CVR.

    • statusobjectrequired

      blocked when the company has opted out of marketing. manual when we can't find it.

      One of: allowed, blocked, manual

    • reasonsarray of objectsrequired

      Codes that explain the answer, such as company_protected.

    • company_formstring · can be null

      Legal form, such as ApS or Enkeltmandsvirksomhed (sole proprietorship).

    • synced_atstring (date-time) · can be null

      When we last fetched the company from CVR.

POST /v2/company-checks
curl -X POST https://api.robinsontjek.dk/v2/company-checks \
  -H "Authorization: Bearer $ROBINSONTJEK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "companies": [
      {
        "id": "acc-301",
        "cvr": "12345678"
      },
      {
        "id": "acc-302",
        "name": "Eksempel Byg ApS"
      }
    ]
  }'
Response · 200 OK
{
  "results": [
    {
      "id": "acc-301",
      "cvr": "12345678",
      "name": "Prøve Handel ApS",
      "status": "blocked",
      "reasons": ["company_protected"],
      "company_form": "ApS",
      "synced_at": "2026-10-14T03:00:00Z"
    },
    {
      "id": "acc-302",
      "cvr": "87654321",
      "name": "Eksempel Byg ApS",
      "status": "allowed",
      "reasons": [],
      "company_form": "ApS",
      "synced_at": "2026-10-14T03:00:00Z"
    }
  ]
}

Phone numbers (add-on, by agreement)

Add-on, by agreement. Look a number up in the directory and check the person behind it against the Robinson list. The endpoint answers 403 until it is enabled for your account, and the price per lookup is agreed with you.

Check phone numbers

POST/v2/phone-checks

Add-on, by agreement: answers 403 until it is enabled for your account. Up to 500 numbers at a time, with or without +45 and spaces. If the number is unlisted, or we can't find who has it, the answer is manual.

Body

  • phonesarray of objectsrequired

    The numbers to look up. At most 500.

    Show 2 fields
    • phonestringrequired

      The phone number, such as +4520202020 or 20 20 20 20.

    • idstring

      Your own reference. It comes back in the response.

Response200

One result per number.

  • list_versionobject

    The edition of the Robinson list that was checked against.

    Show 4 fields
    • idstring (uuid)required

      The list version's id.

    • sourcestring

      cpr is the Robinson list. customer is your own list of people who asked not to be contacted.

    • published_onstring (date)required

      The date CPR published the list.

    • activated_atstring (date-time)

      When we put the list to use.

  • resultsarray of objects

    One result per number.

    Show 7 fields
    • idstring · can be null

      Your reference from the request.

    • matchobject

      What we found on the Robinson list at the person's address.

      Show 5 fields
      • levelinteger · 0–5 · can be nullrequired

        Level from 0 to 5. null when the address can't be read.

      • codestring · can be nullrequired

        The level as a code: none, household, surname, given_name, name_building or name_address.

      • labelstring · can be null

        The level in words, in Danish or English following Accept-Language.

      • onarray of strings

        The parts that matched: first_name, last_name, address and unit.

      • previous_addressboolean

        true when the person is on the list at a previous address. It counts as at least level 4.

    • statusobjectrequired

      For integrations, computed from your chosen level: allowed (below the level), blocked (at the level or above) or manual (the address can't be read).

    • stop_levelinteger · 0–5

      The level you go by, which status is computed from. 1 by default, the most cautious.

    • reasonsarray of objectsrequired

      Codes that explain the answer. See Reasons.

    • addressobject · can be null

      How we read the address. null if it could not be read.

      Show 10 fields
      • inputstring

        The address as you sent it.

      • okboolean

        true when the address could be read.

      • streetstring · can be null

        Street name.

      • house_numberstring · can be null

        House number.

      • floorstring · can be null

        Floor.

      • doorstring · can be null

        Door.

      • postal_codestring · can be null

        Postcode.

      • citystring · can be null

        Town.

      • formattedstring · can be null

        The address written neatly on one line.

      • confidencestring

        exact, corrected or unresolved (could not be read).

    • phone_lookupobject · can be null

      Phone numbers only: what the directory lookup returned.

      Show 3 fields
      • outcomestring

        found, unlisted or not_found.

      • namestring

        The name behind the number.

      • addressstring

        The address behind the number.

Possible errors403

POST /v2/phone-checks
curl -X POST https://api.robinsontjek.dk/v2/phone-checks \
  -H "Authorization: Bearer $ROBINSONTJEK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phones": [
      {
        "id": "lead-77",
        "phone": "+4520202020"
      }
    ]
  }'
Response · 200 OK
{
  "list_version": {
    "id": "4c8e2a1f-7d3b-4e6a-9b25-1f0c6d8e3a71",
    "source": "cpr",
    "published_on": "2026-10-01",
    "activated_at": "2026-10-02T05:00:00Z"
  },
  "results": [
    {
      "id": "lead-77",
      "match": {
        "level": 0,
        "code": "none",
        "label": "Nobody on the list at the address",
        "on": [],
        "previous_address": false
      },
      "status": "allowed",
      "stop_level": 1,
      "reasons": [],
      "phone_lookup": {
        "outcome": "found",
        "name": "Testa Testesen",
        "address": "Prøvevej 12, 8000 Aarhus C"
      }
    }
  ]
}

List version

Which edition of the Robinson list checks run against right now.

Get the current list

GET/v2/list-versions/current

Use it to show the list's date in your own system, or to see whether a new edition has gone live since you last looked.

Response200

The edition checks run against now.

  • idstring (uuid)required

    The list version's id.

  • sourcestring

    cpr is the Robinson list. customer is your own list of people who asked not to be contacted.

  • published_onstring (date)required

    The date CPR published the list.

  • activated_atstring (date-time)

    When we put the list to use.

GET /v2/list-versions/current
curl https://api.robinsontjek.dk/v2/list-versions/current \
  -H "Authorization: Bearer $ROBINSONTJEK_API_KEY"
Response · 200 OK
{
  "id": "4c8e2a1f-7d3b-4e6a-9b25-1f0c6d8e3a71",
  "source": "cpr",
  "published_on": "2026-10-01",
  "activated_at": "2026-10-02T05:00:00Z"
}

Addresses

Read Danish addresses written as free text and get them back split up and corrected. Free of charge.

Read addresses

POST/v2/addresses/resolve

Up to 100 addresses at a time. confidence says whether the address matched exactly (exact), was corrected (corrected) or could not be read (unresolved).

Body

  • addressesarray of stringsrequired

    The addresses as free text. At most 100.

Response200

One reading per address.

  • resultsarray of objects

    One reading per address, in the same order.

    Show 10 fields
    • inputstring

      The address as you sent it.

    • okboolean

      true when the address could be read.

    • streetstring · can be null

      Street name.

    • house_numberstring · can be null

      House number.

    • floorstring · can be null

      Floor.

    • doorstring · can be null

      Door.

    • postal_codestring · can be null

      Postcode.

    • citystring · can be null

      Town.

    • formattedstring · can be null

      The address written neatly on one line.

    • confidencestring

      exact, corrected or unresolved (could not be read).

POST /v2/addresses/resolve
curl -X POST https://api.robinsontjek.dk/v2/addresses/resolve \
  -H "Authorization: Bearer $ROBINSONTJEK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "addresses": ["Stationsalleen 48 1b 2770 Kastrup", "Norregade 7, 1165 Kbh K"]
  }'
Response · 200 OK
{
  "results": [
    {
      "input": "Stationsalleen 48 1b 2770 Kastrup",
      "ok": true,
      "street": "Stationsalleen",
      "house_number": "48",
      "floor": "1",
      "door": "b",
      "postal_code": "2770",
      "city": "Kastrup",
      "formatted": "Stationsalleen 48, 1. b, 2770 Kastrup",
      "confidence": "corrected"
    },
    {
      "input": "Norregade 7, 1165 Kbh K",
      "ok": true,
      "street": "Nørregade",
      "house_number": "7",
      "floor": null,
      "door": null,
      "postal_code": "1165",
      "city": "København K",
      "formatted": "Nørregade 7, 1165 København K",
      "confidence": "corrected"
    }
  ]
}