Open government business registers are a surprisingly useful and surprisingly awkward data source. Here is what teams wish they had known before integrating one.
Every so often a feature lands on a developer's plate that sounds trivial and turns out to be a rabbit hole. A common one: "let users verify a company by its registration number." How hard could it be? The data is public. There are official registries. Surely it is just an API call.
It is never just an API call.
Teams that have wrangled official business-registry data across a few jurisdictions tend to come out the other side with a working feature and a list of things they wish someone had told them first. This is that list. For anyone about to touch company data, open corporate registers, or "know your customer" style verification, it might save a week.
Public does not mean easy
The first surprise is that "the data is public" and "the data is accessible" are very different statements.
Most developed countries maintain an official business register. Legally the core data is public: company name, registration number, legal form, status, directors, sometimes ownership and annual filings. But how a developer actually gets at it ranges from "clean open-data API with a documented schema" to "there is a website, good luck." Some countries publish proper open datasets. Others hide everything behind a form with a session cookie and a CAPTCHA, and their idea of an API is a paginated HTML table.
So before anyone promises a feature, it is worth spending an afternoon finding out what the source actually offers for the specific countries in scope. The gap between the best and worst national registers is enormous, and it dictates the whole architecture.
Identifiers are messier than expected
A company registration number looks like it should be a nice clean primary key. Sometimes it is. Often it is not.
Formats differ per country, which is expected, but the annoying part is the near-misses. Numbers get formatted with spaces, dots, or country prefixes inconsistently. The same company can appear under a slightly different legal name in two sources. Historical names linger. A company that changed its form keeps its number but changes almost everything else about itself.
A few habits tend to save pain:
- Store the raw identifier exactly as the source gives it, and a normalized version for matching. Never overwrite the original.
- Normalize aggressively for comparison (strip whitespace, punctuation, casing) but display the canonical source value.
- Treat the registration number plus the country as the real key. The number alone is not globally unique.
// naive normalization that catches most matching bugs
function normalizeRegNo(raw) {
return raw
.toUpperCase()
.replace(/[\s.\-\/]/g, "") // spaces, dots, dashes, slashes
.replace(/^[A-Z]{2}(?=\d)/, ""); // strip a leading country prefix before digits
}
That last line is deliberately conservative. Stripping prefixes is risky, because in some jurisdictions the letters are part of the number, not a country code. Which points to the real lesson.
Model the data around "this is a claim from a source at a point in time"
The mistake teams tend to make early is treating registry data as the truth. It is not. It is what a particular source reported at a particular moment. Sources lag. They disagree. They fix errors. A company can be marked active in one place and struck off in another because one updated last week and the other last quarter.
The moment a schema stops storing company.status = "active" and starts storing status = "active", source = X, retrieved_at = timestamp, everything gets easier. Conflicts become visible instead of silently overwriting each other. The system can show a user where a fact came from and how fresh it is, which turns out to be the single most trust-building thing in the whole feature. People believe "active as of yesterday, per the national register" far more than a bare green checkmark.
This is basically provenance, and for anything verification-flavored, it belongs in the design from day one. Retrofitting provenance onto a schema that assumed single-source truth is miserable.
Freshness is a product decision, not just a technical one
Company data changes: new directors, address changes, dissolutions, name changes. How stale is too stale depends entirely on what the data is used for. Displaying a company profile? Daily or weekly is probably fine. Making a decision that carries legal or financial weight? It needs to be current, and the timestamp should be visible.
The refresh strategy is worth deciding explicitly rather than letting it emerge by accident. Cache hard for read-heavy display, but keep a path to force a fresh pull when it matters. And always surface the "last updated" value to the user. Hiding it does not make the data fresher, it just makes the application silently responsible for its staleness.
Rate limits and being a good citizen
Official registers, and the aggregators that sit on top of them, are often run on modest infrastructure or with genuine per-query costs. Hammering them with unbounded requests is both rude and a good way to get blocked.
- Batch and cache. Do not re-fetch a company that was looked at an hour ago.
- Respect rate limits, and back off politely on errors instead of retrying in a tight loop.
- For bulk data, look for an actual bulk or open-data download rather than scraping record by record. Many registers offer one, and it is almost always the right answer for analytics.
When to build versus when to borrow
Here is the honest conclusion. For a single well-served country with a good open-data API, integrating directly is very doable and worth doing. For multi-country coverage, or for jurisdictions with awkward or paywalled registers, the integration and normalization work adds up fast, and it is often cheaper to use an aggregator or a specialist that has already solved the messy parts.
This is jurisdiction-dependent in a big way. Some countries make it a joy. Estonia, for example, is unusually developer-friendly here: company data, ownership, and filings are openly available and genuinely structured, which is a large part of why so many digital businesses base themselves there. For teams working with entities in a specific country that would rather not build the plumbing themselves, providers who deal with these registers daily, like Capture, handle the formation and verification side and can be a shortcut past a lot of this. Either way, the principles above still apply to whatever the data source returns.
The takeaways
The four things worth remembering:
- Check what the source actually offers before designing anything. Public does not mean accessible.
- Store raw and normalized identifiers, and key on number plus country.
- Model every fact as a claim with a source and a timestamp. Provenance is the feature.
- Surface freshness to the user, and be a polite API citizen.
Company data looks boring from the outside and turns out to be a neat little case study in provenance, data modeling, and the gap between "public" and "usable." For anyone about to go down this road, hopefully this shortens the trip.
What official registers have developers found especially good or especially painful to work with? The war stories tend to pile up in the comments.
Top comments (0)