Matching a List of Companies
You have a spreadsheet of companies — customers, suppliers, prospects, a portfolio — and you want the registered entity behind each row. This guide covers what to send per row, what to do when a row comes back empty, and how to tell "we do not have this company" apart from "the query did not describe it".
Match on the right field
Each row usually carries more than a name. Pick the most specific thing you have, because they do not search the same field:
| What you have | Parameter | Notes |
|---|---|---|
| Registration number | nationalId | The strongest match. Combine with countryCode. |
| Website or email domain | website | Matches with or without www. and with or without a scheme. |
| A CompanyData ID from an earlier call | ID | Exact, and free of ambiguity. |
| Only a name | search | Combine with countryCode when you are confident of the country. |
A value in the wrong parameter does not fail — it just looks for the wrong thing. A domain in search looks for a company whose name is that domain, which is why search=aselsan.com finds nothing while website=aselsan.com finds ASELSAN. If a search value is unmistakably a domain or a registration number and no company carries it as a name, the API retries it against the right field for you and says so in meta.warnings; sending it in the right parameter to begin with is one request instead of two.
How name matching behaves
search matches from the start of the stored company name. A leading word or two is enough — Heineken finds Heineken N.V. — but everything you do send has to match:
- Word order matters.
QA Wolfdoes not findWolf Qa Inc. - Inserted words matter.
Lurica Argentinadoes not findLURICA CORP ARGENTINA S.A. - Accents matter.
Telefonicadoes not findTelefónica. - Legal forms are interchangeable for common cases (
BV/B.V.,GmbH,Ltd/Limited), but an unusual suffix is treated as part of the name:Younited SAdoes not findYOUNITED. - Names are stored in the Latin alphabet. A search in Greek or Cyrillic will not match.
When the exact search finds nothing, the API retries on its own before answering, in this order, and tells you which step produced the rows:
- All the words, in any order —
QA Wolf→Wolf Qa Inc. - The name without its legal form —
Randstad France SASU→RANDSTAD FRANCE. - (API keys only) The closest spelling —
Telefonica Germany→Telefónica Germany. - (API keys only) The same name in another country —
Thamesis Consulting+IT→THAMESIS CONSULTING LIMITEDin GB.
Each step is only accepted while its result set is small, so a common word cannot pass for a match, and steps 3 and 4 are skipped for names too short to be distinctive. The rows are real, but a relaxed match is a candidate, not a confirmation — check it (see below) before you use it.
What to do per row
For each row, stop at the first step that returns something:
nationalId+countryCode, if you have a registration number.website, if you have a domain.searchwith the name +countryCode. The API's own retries cover word order, legal forms, spelling and — for API keys — other countries.- If it is still empty,
searchwith the first two or three distinctive words, then the same withoutcountryCode. A UK subsidiary is often registered as a branch of its foreign parent:Hoist Finance UK Limitedis on the register asHoist Finance AB (publ)with a UK address.
Anything that arrived with a SEARCH_MATCHED_* warning, or from step 4, widened the search, so check it before you accept it. Location Type and the headquarter fields tell you whether you have the entity itself, its parent, or a branch — see Corporate Structure.
Read meta.warnings
A successful response can carry a meta.warnings array. It never means the request failed; the rows in data.records are always real results. It means something about the request is worth knowing:
{
"meta": {
"totalCount": 1,
"currentPage": 1,
"totalPages": 1,
"pageSize": 25,
"warnings": [
{
"code": "SEARCH_LOOKS_LIKE_DOMAIN",
"parameter": "search",
"message": "No company is named \"aselsan.com\", so the website field was searched for \"aselsan.com\" instead.",
"hint": "Use website=aselsan.com to search websites directly."
}
]
},
"data": { "records": [ { "Company Name": "ASELSAN ELEKTRONIK SANAYI VE TICARET A S" } ] }
}
Worth acting on when you see them across many rows:
| Code | What it means |
|---|---|
COUNTRY_CODE_NORMALISED | You sent a country name or a lowercase code; it was read as the ISO code. |
COUNTRY_CODE_UNRECOGNISED | The value is not a country code, so nothing can match it. The filter is kept rather than dropped, so the count stays honest. |
NATIONAL_ID_NORMALISED | Separators were stripped to match the stored form. |
SEARCH_LOOKS_LIKE_DOMAIN | No company has that name; website was searched instead. |
SEARCH_LOOKS_LIKE_REGISTRATION_NUMBER | No company has that name; nationalId was searched instead. |
SEARCH_NON_LATIN_SCRIPT | Names are stored in the Latin alphabet. |
SEARCH_MATCHED_ANY_ORDER | Exact search found nothing; these rows contain all the words in some order. |
SEARCH_MATCHED_CORE_NAME | Exact search found nothing; these rows match the name with the legal form left off. |
SEARCH_MATCHED_FUZZY | Exact search found nothing; these are the closest spellings. Verify before use. |
SEARCH_MATCHED_OTHER_COUNTRY | Nothing matched in the country you gave; these rows are registered elsewhere. |
PARAMETER_NOT_APPLIED | The parameter is accepted but does not filter anything on this index. |
Check your parameter names once
A parameter name this endpoint does not have is refused with 400, rather than ignored, because a dropped filter returns the whole database as an apparently valid answer:
{
"error": "Unknown parameter",
"message": "This endpoint does not have the parameter(s): query.",
"unknownParameters": ["query"],
"didYouMean": { "query": "search" },
"documentation": "https://companydata.com/api-docs/search"
}
Run one request by hand before you start a batch. The name of the company field is search, not query or companyName; employee ranges are employeesTotalMin / employeesTotalMax; the country filter is countryCode and takes ISO 3166-1 alpha-2 codes.
Reading a zero honestly
After the ladder above, an empty result is a real answer: we do not have that company. That happens most often with very small or very new businesses outside Western Europe, and with entities registered abroad under a different name. It is worth separating those rows out rather than retrying them — and if a whole segment of your list comes back empty, tell us which segment, because that is coverage feedback we can act on.