CVR lookups in Java

Since Java 11 the standard library has an HTTP client, so a CVR lookup only takes one request and a JSON parser. You don't need an API key.

Look up a company by CVR number

This example uses java.net.http.HttpClient and records from Java 16+. Jackson maps the JSON response onto the records and ignores the fields you left out.

java
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.List;

public class Cvr {
    record Owner(String name, String ownership_range) {}
    record Company(int vat, String name, Integer zipcode, String city,
                   String industrydesc, List<Owner> ejere) {}

    static final HttpClient HTTP = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(10)).build();
    static final ObjectMapper JSON = new ObjectMapper()
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    static Company getCompany(int cvr) throws Exception {
        HttpRequest req = HttpRequest.newBuilder(URI.create("https://apicvr.dk/api/v1/" + cvr)).GET().build();
        HttpResponse<String> res = HTTP.send(req, HttpResponse.BodyHandlers.ofString());
        if (res.statusCode() == 404) return null;
        if (res.statusCode() != 200) throw new RuntimeException("CVR-API svarede " + res.statusCode());
        return JSON.readValue(res.body(), Company.class);
    }

    public static void main(String[] args) throws Exception {
        Company c = getCompany(24256790);
        System.out.println(c.name() + ", " + c.zipcode() + " " + c.city());
        for (Owner o : c.ejere()) System.out.println(o.name() + " " + o.ownership_range());
    }
}

Note: protected is a reserved word in Java. To read the field, annotate the component with @JsonProperty("protected").

Add Jackson

Java has no built-in JSON parser. Jackson is the most common choice. With Maven:

xml
<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.17.2</version>
</dependency>

Search by company name

Fuzzy search returns a slim response with name, cvr_number, industrycode and industrytext, even when the name is slightly misspelled.

java
import com.fasterxml.jackson.core.type.TypeReference;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

record Hit(String name, Integer cvr_number, String industrytext) {}

static List<Hit> search(String name) throws Exception {
    String q = URLEncoder.encode(name, StandardCharsets.UTF_8).replace("+", "%20");
    HttpRequest req = HttpRequest.newBuilder(URI.create("https://apicvr.dk/api/v1/search/fuzzy/" + q)).build();
    String body = HTTP.send(req, HttpResponse.BodyHandlers.ofString()).body();
    return JSON.readValue(body, new TypeReference<List<Hit>>() {});
}

// search("novo nordisk").stream().limit(5)
//     .forEach(h -> System.out.println(h.cvr_number() + " " + h.name()));

Handle errors

StatusMeaning
200The company was found. The body is JSON.
404No company has that CVR number. Body: {"detail": {"error": "NOT_FOUND"}}
422The CVR number isn't a number.
502The CVR register didn't answer. Try again shortly.
Always check protected before using the data for marketing. When it's true, the company has opted out of direct marketing.

Frequently asked questions

Does it work in Spring Boot?

Yes. You can use RestClient or WebClient instead of HttpClient. Spring Boot already ships Jackson, so you only need to define your records.

Which Java version is required?

HttpClient needs Java 11. Records need Java 16. On older versions, use plain classes with getters instead.

Do I need an API key?

No. CVR-API needs no key and no account.