Skip to content

Quick Start Guide

Get up and running with the Danish CVR Registry API in minutes.

Prerequisites

  • ✅ Valid CVR API credentials (How to get them)
  • ✅ Environment variables set up
  • ✅ Network access to http://distribution.virk.dk

Your First API Call

Let's start with the simplest possible query - getting one company record:

curl -u "$CVR_USERNAME:$CVR_PASSWORD" \
  -X POST "http://distribution.virk.dk/cvr-permanent/virksomhed/_search" \
  -H 'Content-Type: application/json' \
  -d '{"size": 1}'

Expected Result

You should see a JSON response with one company record and metadata about the total number of companies (~2.2 million).

Basic Company Lookup

Search by CVR Number

Every Danish company has a unique CVR number. Here's how to look up a specific company:

curl -u "$CVR_USERNAME:$CVR_PASSWORD" \
  -X POST "http://distribution.virk.dk/cvr-permanent/virksomhed/_search" \
  -H 'Content-Type: application/json' \
  -d '{
    "query": {
      "term": {
        "Vrvirksomhed.cvrNummer": "10103940"
      }
    }
  }'

This searches for the Danish Prime Minister's Office (Statsministeriet).

Search by Company Name

curl -u "$CVR_USERNAME:$CVR_PASSWORD" \
  -X POST "http://distribution.virk.dk/cvr-permanent/virksomhed/_search" \
  -H 'Content-Type: application/json' \
  -d '{
    "query": {
      "match": {
        "Vrvirksomhed.navne.navn": "Novo Nordisk"
      }
    },
    "size": 5
  }'

This finds companies with "Novo Nordisk" in their name.

Understanding the Response

A typical response looks like this:

{
  "took": 16,                          // Query execution time (ms)
  "timed_out": false,                  // Whether query timed out
  "_shards": {                         // Elasticsearch shard info
    "total": 6,
    "successful": 6,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,                        // Number of matching documents
    "max_score": 1.0,                  // Relevance score
    "hits": [                          // Array of results
      {
        "_index": "cvr-v-20220630",    // Physical index name
        "_type": "_doc",               // Document type
        "_id": "4004315821",           // Internal document ID
        "_score": 1.0,                 // Relevance score for this doc
        "_source": {                   // The actual company data
          "Vrvirksomhed": {
            "cvrNummer": 10103940,
            "navne": [
              {
                "navn": "Statsministeriet",
                "periode": {
                  "gyldigFra": "2001-01-01",
                  "gyldigTil": null        // null = currently valid
                }
              }
            ]
            // ... more fields
          }
        }
      }
    ]
  }
}

Key Fields Explained

Field Description Example
cvrNummer Unique company identifier 10103940
navne Company names (with validity periods) Array of name objects
virksomhedsstatus Company status "NORMAL", "UNDER KONKURS"
beliggenhedsadresse Physical address Array of address objects
virksomhedsform Company type 80 (ApS), 60 (A/S)

Filtering Results

Get Only Specific Fields

To reduce response size and get only the data you need:

curl -u "$CVR_USERNAME:$CVR_PASSWORD" \
  -X POST "http://distribution.virk.dk/cvr-permanent/virksomhed/_search" \
  -H 'Content-Type: application/json' \
  -d '{
    "query": {
      "match": {
        "Vrvirksomhed.navne.navn": "Novo Nordisk"
      }
    },
    "_source": [
      "Vrvirksomhed.cvrNummer",
      "Vrvirksomhed.navne",
      "Vrvirksomhed.virksomhedsstatus"
    ],
    "size": 5
  }'

Filter by Company Status

Get only active companies:

curl -u "$CVR_USERNAME:$CVR_PASSWORD" \
  -X POST "http://distribution.virk.dk/cvr-permanent/virksomhed/_search" \
  -H 'Content-Type: application/json' \
  -d '{
    "query": {
      "term": {
        "Vrvirksomhed.virksomhedsstatus.status": "NORMAL"
      }
    },
    "size": 10
  }'

Working with Other Indices

The CVR API has three main indices:

Participants (People and Organizations)

curl -u "$CVR_USERNAME:$CVR_PASSWORD" \
  -X POST "http://distribution.virk.dk/cvr-permanent/deltager/_search" \
  -H 'Content-Type: application/json' \
  -d '{
    "query": {
      "match": {
        "Vrdeltagerperson.navne.navn": "Peter Schmidt"
      }
    },
    "size": 5
  }'

Production Units (Branch Offices)

curl -u "$CVR_USERNAME:$CVR_PASSWORD" \
  -X POST "http://distribution.virk.dk/cvr-permanent/produktionsenhed/_search" \
  -H 'Content-Type: application/json' \
  -d '{
    "query": {
      "term": {
        "VrproduktionsEnhed.virksomhedsrelation.cvrNummer": "10103940"
      }
    },
    "size": 5
  }'

Common Patterns

Fuzzy Search for Typos

Handle typos in company names:

curl -u "$CVR_USERNAME:$CVR_PASSWORD" \
  -X POST "http://distribution.virk.dk/cvr-permanent/virksomhed/_search" \
  -H 'Content-Type: application/json' \
  -d '{
    "query": {
      "match": {
        "Vrvirksomhed.navne.navn": {
          "query": "Novo Nordysk",
          "fuzziness": "AUTO"
        }
      }
    }
  }'

Combine Multiple Criteria

Find active ApS companies in Copenhagen:

curl -u "$CVR_USERNAME:$CVR_PASSWORD" \
  -X POST "http://distribution.virk.dk/cvr-permanent/virksomhed/_search" \
  -H 'Content-Type: application/json' \
  -d '{
    "query": {
      "bool": {
        "must": [
          {
            "term": {
              "Vrvirksomhed.virksomhedsstatus.status": "NORMAL"
            }
          },
          {
            "term": {
              "Vrvirksomhed.virksomhedsform.virksomhedsformkode": 80
            }
          },
          {
            "term": {
              "Vrvirksomhed.beliggenhedsadresse.kommune.kommuneKode": 101
            }
          }
        ]
      }
    },
    "size": 10
  }'

Error Handling

Result Limit (3000 Documents)

If you request more than 3000 documents, you'll get an error:

{
  "error": {
    "type": "search_phase_execution_exception",
    "reason": "Result window is too large, from + size must be less than or equal to: [3000]"
  },
  "status": 500
}

Solution: Use the scroll API for large datasets (see Advanced Queries).

Authentication Issues

If you see a 401 error, check your credentials:

# Verify environment variables are set
echo "Username: $CVR_USERNAME"
echo "Password: $CVR_PASSWORD"

# Test with explicit credentials (for debugging only)
curl -u "your_actual_username:your_actual_password" \
  -X POST "http://distribution.virk.dk/cvr-permanent/virksomhed/_search" \
  -d '{"size": 1}'

Next Steps

Now that you have basic queries working:

Learn More Query Types

Understand the Data

Production Implementation

Quick Reference

Essential Endpoints

Purpose Endpoint Example Query
Companies /virksomhed/_search Find by CVR number or name
Participants /deltager/_search Find owners, directors
Production Units /produktionsenhed/_search Find branch offices

Key Field Paths

Data Field Path Description
CVR Number Vrvirksomhed.cvrNummer Unique company ID
Company Name Vrvirksomhed.navne.navn Current/historical names
Status Vrvirksomhed.virksomhedsstatus.status Active/dissolved/etc
Company Type Vrvirksomhed.virksomhedsform.virksomhedsformkode ApS=80, A/S=60, etc
Municipality Vrvirksomhed.beliggenhedsadresse.kommune.kommuneKode Location code

Common Status Values

Status Meaning
NORMAL Active company
UNDER KONKURS Under bankruptcy
TVANGSOPLØST Forcibly dissolved
OPLØST EFTER KONKURS Dissolved after bankruptcy