Sådan validerer du et CVR-nummer

Et gyldigt CVR-nummer skal bestå to tjek: det skal have det rigtige format med korrekt kontrolciffer, og det skal tilhøre en virksomhed, der findes og stadig er aktiv. Det første klarer du lokalt, det andet med ét API-kald.

1. Tjek formatet med modulus 11

Et CVR-nummer har 8 cifre og starter ikke med 0. Gang hvert ciffer med vægtene 2, 7, 6, 5, 4, 3, 2, 1, og læg resultaterne sammen. Summen skal gå op i 11.

Eksempel for 10403782: 1·2 + 0·7 + 4·6 + 0·5 + 3·4 + 7·3 + 8·2 + 2·1 = 77, og 77 / 11 = 7. Nummeret er altså gyldigt.

python
WEIGHTS = (2, 7, 6, 5, 4, 3, 2, 1)

def is_valid_cvr(cvr: str) -> bool:
    cvr = cvr.replace(" ", "")
    if len(cvr) != 8 or not cvr.isdigit() or cvr[0] == "0":
        return False
    return sum(int(d) * w for d, w in zip(cvr, WEIGHTS)) % 11 == 0

is_valid_cvr("10403782")  # True  (Vestas Wind Systems A/S)
is_valid_cvr("12345678")  # False

2. Bekræft at virksomheden findes

Et nummer kan have korrekt kontrolciffer uden at være tildelt. Slå det op:

bash
curl https://apicvr.dk/api/v1/10403782
json
{
  "vat": 10403782,
  "name": "VESTAS WIND SYSTEMS A/S",
  "status": "NORMAL",
  "startdate": "...",
  "enddate": null,
  "bankrupt": false,
  "companydesc": "Aktieselskab",
  ...
}

Findes nummeret ikke, svarer API'et med HTTP 404:

json
{"detail": {"error": "NOT_FOUND", "status": 404, "message": null}}

3. Tjek at den er aktiv

En virksomhed kan findes i CVR, selvom den er ophørt eller gået konkurs. Kig på enddate (sat, når virksomheden er ophørt), bankrupt og status. Her er hele flowet i JavaScript:

javascript
const WEIGHTS = [2, 7, 6, 5, 4, 3, 2, 1];

function isValidCvr(input) {
  const cvr = String(input).replace(/\s/g, "");
  if (!/^[1-9]\d{7}$/.test(cvr)) return false;
  const sum = [...cvr].reduce((acc, d, i) => acc + Number(d) * WEIGHTS[i], 0);
  return sum % 11 === 0;
}

async function checkCvr(cvr) {
  if (!isValidCvr(cvr)) return { valid: false, reason: "checksum" };
  const res = await fetch(`https://apicvr.dk/api/v1/${cvr}`);
  if (res.status === 404) return { valid: false, reason: "not_found" };
  const company = await res.json();
  const active = !company.enddate && !company.bankrupt;
  return { valid: true, active, name: company.name };
}

Gode råd

Ofte stillede spørgsmål

Er alle CVR-numre, der består modulus 11, tildelt?

Nej. Modulus 11 fanger tastefejl, men kun et opslag i CVR kan bekræfte, at nummeret tilhører en virksomhed.

Er CVR-nummer og momsnummer det samme?

For danske virksomheder er momsnummeret som regel CVR-nummeret med DK foran, fx DK10403782.

Hvad svarer API'et ved et ugyldigt format?

Indeholder nummeret andet end cifre, svarer API'et med HTTP 422. Findes nummeret ikke, svarer det med HTTP 404 og fejlkoden NOT_FOUND.