Switch from cvrapi.dk to apicvr.dk

apicvr.dk uses almost the same field names as cvrapi.dk, so most integrations can switch by changing the URL and renaming three fields. In return you lose the 50 lookups-a-day quota and the custom User-Agent requirement.

Why switch?

The URLs

text
# cvrapi.dk
https://cvrapi.dk/api?search=24256790&country=dk
https://cvrapi.dk/api?name=novo%20nordisk&country=dk
https://cvrapi.dk/api?phone=44448888&country=dk

# apicvr.dk
https://apicvr.dk/api/v1/24256790
https://apicvr.dk/api/v1/search/company/novo%20nordisk?limit=1
https://apicvr.dk/api/v1/search/phone/44448888

Note that name and phone search on apicvr.dk return a list. Take the first item if you only want one hit like on cvrapi.dk.

Fields with the same name

vat, name, address, zipcode, city, cityname, addressco, protected, phone, email, fax, startdate, enddate, employees, industrycode, industrydesc, companycode, companydesc and version.

Fields that differ

cvrapi.dkapicvr.dkNote
productionunitsp_unitsThe P-number is in p_number.
ownersejereEach owner also has type, cvr, ownership share and voting rights.
creditbankruptbankruptSame meaning.
creditstatus, creditstartdatestatusE.g. NORMAL, UNDERKONKURS or OPHØRT.
zipcode (string)zipcode (number)Cast to string if your code expects it.
–direktion, fuldt_ansvarligeNew fields.

Errors

cvrapi.dk puts the error in an error field. apicvr.dk uses HTTP status codes: 404 when the company doesn't exist and 502 when the CVR register doesn't answer. The code is in detail.error.

Drop-in function in PHP

The function fetches from apicvr.dk and returns the shape your existing code expects, so you can switch without touching the rest of your code.

php
<?php
// Drop-in: returns the same shape your cvrapi.dk code expects.
function cvr_lookup(string $cvr): ?array
{
    $ch = curl_init("https://apicvr.dk/api/v1/" . urlencode($cvr));
    curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15]);
    $body = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($status === 404) {
        return ['error' => 'NOT_FOUND'];
    }
    if ($status !== 200) {
        return ['error' => 'INTERNAL_ERROR'];
    }

    $c = json_decode($body, true);

    // Rename the fields that are named differently on apicvr.dk
    $c['productionunits'] = $c['p_units'];
    $c['owners'] = array_map(fn ($o) => ['name' => $o['name']], $c['ejere']);
    $c['creditbankrupt'] = $c['bankrupt'];
    $c['zipcode'] = (string) $c['zipcode'];

    return $c;
}

$company = cvr_lookup('24256790');
echo $company['name'] . ', ' . $company['zipcode'] . ' ' . $company['city'];

Drop-in function in JavaScript

javascript
async function cvrLookup(cvr) {
  const res = await fetch(`https://apicvr.dk/api/v1/${cvr}`);
  if (res.status === 404) return { error: "NOT_FOUND" };
  if (!res.ok) return { error: "INTERNAL_ERROR" };

  const c = await res.json();
  return {
    ...c,
    productionunits: c.p_units,
    owners: c.ejere.map((o) => ({ name: o.name })),
    creditbankrupt: c.bankrupt,
    zipcode: String(c.zipcode),
  };
}

What apicvr.dk doesn't do

Frequently asked questions

Do I need to set a User-Agent?

No, it's not required. You're welcome to send one that describes your project.

Can I keep my cvrapi.dk code?

Yes, if you use the drop-in function above. It renames the fields so the rest of your code works unchanged.

How many lookups can I make?

There's no fixed daily quota. Keep a reasonable pace, and email [email protected] if you need sustained heavy traffic.