CVR data for AI agents and LLMs

Language models don't know the current CVR register. Give them two tools instead: one to search by name and one to look up by CVR number. Since CVR-API needs no key, there are no secrets to manage in your agent.

Tool definitions

The definitions use JSON Schema, which most models and agent frameworks understand. Some call the field parameters instead of input_schema. The content is the same.

json
[
  {
    "name": "cvr_lookup",
    "description": "Look up a Danish company by its 8-digit CVR number. Returns name, address, industry, status, owners and management.",
    "input_schema": {
      "type": "object",
      "properties": {
        "cvr": {"type": "string", "description": "8-digit CVR number, e.g. 24256790"}
      },
      "required": ["cvr"]
    }
  },
  {
    "name": "cvr_search",
    "description": "Find Danish companies by name. Tolerates typos. Returns name, cvr_number and industry for each hit.",
    "input_schema": {
      "type": "object",
      "properties": {
        "name": {"type": "string", "description": "Company name or part of it"}
      },
      "required": ["name"]
    }
  }
]

Python handler

When the model calls a tool, run the function and send the result back as text. Production units are dropped because large companies can have hundreds, and they take up a lot of the model's context.

python
import json
import urllib.error
import urllib.parse
import urllib.request

BASE = "https://apicvr.dk/api/v1"

def _get(url):
    try:
        with urllib.request.urlopen(url, timeout=15) as res:
            return json.load(res)
    except urllib.error.HTTPError as err:
        return {"error": err.code}

def run_tool(name, args):
    if name == "cvr_lookup":
        company = _get(f"{BASE}/{args['cvr']}")
        company.pop("p_units", None)  # keep the context small
        return json.dumps(company, ensure_ascii=False)
    if name == "cvr_search":
        hits = _get(f"{BASE}/search/fuzzy/" + urllib.parse.quote(args["name"]) + "?limit=5")
        return json.dumps(hits, ensure_ascii=False)
    return json.dumps({"error": "unknown tool"})

System prompt

text
You have access to CVR-API (https://apicvr.dk), a free JSON API for the
Danish CVR register with no API key. Use cvr_search to find the CVR
number from a name, and cvr_lookup to fetch details. If the "protected"
field is true, the company must not be contacted with marketing.

llms.txt

If your agent reads documentation on its own, point it at https://apicvr.dk/llms.txt. It describes every endpoint briefly in Markdown. llms-full.txt also lists every response field and error code.

Tips

Frequently asked questions

Does it work with every language model?

Yes, with any model or framework that supports tool calling or function calling. The API itself is just HTTP and JSON.

Does the agent need an API key?

No. CVR-API needs no key, so there's nothing to store or rotate.

Can the agent get financial figures?

No, financial statements aren't part of CVR-API. The agent gets company details, owners, management and production units.