Vendor Due Diligence: Company, VAT, LEI and Domain Checks
Pricing
from $22.80 / 1,000 vendor checks
Vendor Due Diligence: Company, VAT, LEI and Domain Checks
KYB check for a list of suppliers: is this vendor real? One company per row from official registries, VIES VAT validation, GLEIF LEI, domain age, mail setup and TLS certificates, plus fake vendor red flags and a published risk rule. Verify a supplier before paying an invoice.
Pricing
from $22.80 / 1,000 vendor checks
Rating
0.0
(0)
Developer
Adrian Voss
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
A KYB check for a list of suppliers, one company per row. You give whatever you already have about a vendor — a name and a country, a website, a VAT number, an LEI code, a registry number — and you get back one row that answers a single question: is this vendor real, and does the story hold together?
Six checks run in parallel against official and technical sources, and then they are cross-read against each other. That cross-reading is the point. Any one source can tell you a company exists; only putting them side by side tells you that the registry's legal name, the name on the VAT registration and the name on the LEI all disagree, or that a company registered in 1998 is invoicing you from a domain that was bought six weeks ago.
What gets checked
| Check | Source | What it answers |
|---|---|---|
| Official company registry | PRH (Finland), Recherche d'entreprises (France), Brønnøysund (Norway), SEC EDGAR (United States) | Does the company exist, is it still active, when was it registered, what is its registered address |
| EU VAT number | The European Commission's own VIES service | Is this VAT number currently valid, and whose name is it in |
| LEI | GLEIF, the global LEI registry | Is the legal entity active, and what is its legal name on the LEI |
| Domain registration | RDAP, the registry protocol that replaced WHOIS | When was the website domain first registered, and at which registrar |
| Mail setup | Cloudflare's public DNS resolver | Can the domain receive email at all, and does it publish SPF and DMARC |
| TLS certificates | The public Certificate Transparency logs | Who issued the newest certificate for the domain, and when |
Every source is free, official or openly published, and needs no API key of yours. Nothing here is scraped from behind a login.
Red flags and the risk level
Each row carries a redFlags list drawn from a fixed, published set, and a riskLevel computed from
it by a rule you can read rather than a black-box score.
| Flag | Fires when |
|---|---|
NOT_FOUND_IN_REGISTRY | A registry this actor can reach answered, and has no such company |
REGISTRY_INACTIVE | The registry record says dissolved, or GLEIF says the legal entity is INACTIVE |
VAT_INVALID | VIES says the VAT number is not currently valid |
NAME_MISMATCH | The names on the registry, the VAT registration and the LEI do not agree |
DOMAIN_UNDER_180_DAYS | The website domain was first registered less than 180 days ago |
NO_MX | The domain publishes no mail servers, so it cannot receive email |
NO_DMARC | The domain publishes no DMARC record, so it is easy to spoof |
The risk rule. high when any of VAT_INVALID, REGISTRY_INACTIVE or NOT_FOUND_IN_REGISTRY
is present, or when three or more flags of any kind stack up. medium for one or two lesser flags.
low for none.
Two honesty rules the flags obey, and they matter more than the list itself:
- A check that could not run never raises a flag. No VAT number supplied means no
VAT_INVALID. A rate-limited certificate log means no conclusion about certificates. A country with no registry route here means noNOT_FOUND_IN_REGISTRY. - An empty
redFlagslist is not a clean bill of health. It means nothing was found wrong in what was actually checked.checksRunandchecksFoundon the same row tell you how much that is worth, andcheckNotessays in plain English why anything came back empty.
What this actor deliberately does not do
- No sanctions screening and no PEP lists. The commercial consolidated sanctions and politically-exposed-person lists are licensed products, and their licences do not permit redistributing them through a service like this one. Rather than ship a partial or stale copy, this actor leaves that job to a provider you license directly. If you need sanctions screening, this is not the tool, and no combination of settings here will substitute for it.
- No personal data. No directors, no officers, no beneficial owners, no dates of birth. France's own company API returns a directors block on every result and this actor does not read it; there is a unit test asserting the parser never surfaces it.
- No credit scores or financial statements. Nothing here is an opinion about whether a vendor can pay you, only about whether they are who they say they are.
How to use Vendor Due Diligence: Company, VAT, LEI and Domain Checks
- In the Apify Console. Open the actor page and click Start — the
companiesfield is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found. - Via the API. Call it directly with a POST request — no Console needed once you have an API token:
curl "https://api.apify.com/v2/acts/accountable_eel~vendor-due-diligence-check/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"companies":["name=Supercell Oy|domain=supercell.com|vatNumber=FI23365096|lei=743700MSCHABJ4XW2532|registryId=2336509-6|country=FI","name=Doctolib|domain=doctolib.fr|registryId=794598813|country=FR","name=Google Ireland Limited|domain=google.ie|vatNumber=IE6388047V|country=IE"]}'
- On a schedule. Save this actor as an Apify Task with the input you want, then add a Schedule (hourly, daily, weekly) so it runs on its own — no server of your own required.
The checks field lets you switch any of the six off. Doing so narrows what the row says and what
the red flags can see; it does not change the price, because a company is billed once as a bundle.
Input
{"companies": ["name=Supercell Oy|domain=supercell.com|vatNumber=FI23365096|lei=743700MSCHABJ4XW2532|registryId=2336509-6|country=FI","name=Doctolib|domain=doctolib.fr|registryId=794598813|country=FR","name=Google Ireland Limited|domain=google.ie|vatNumber=IE6388047V|country=IE"]}
One company per line. Give whatever you already have about it: a company name plus a country, a website domain, an EU VAT number, an LEI code, or a national registry number. The precise form is name=Acme Oy|domain=acme.fi|country=FI, and a plain line like "Acme Oy acme.fi" is read too. Anything you leave out is simply not checked, and never counts against the company. Accepted formats: name=Supercell Oy|domain=supercell.com|country=FI, name=Doctolib|registryId=794598813|country=FR, Doctolib doctolib.fr, IE6388047V, 5493001KJTIIGC8Y1R12.
Three ways to write a line. All three end up in the same place, so use whichever fits how your data already looks.
-
key=valuepairs, separated by|— the precise form, and what the prefilled example uses:name=Supercell Oy|domain=supercell.com|vatNumber=FI23365096|lei=743700MSCHABJ4XW2532|registryId=2336509-6|country=FIAccepted keys:
name,domain,vatNumber,lei,registryId,country, plus the obvious aliases (company,website,vat,orgnr,businessId,siren,cik,ticker,countryCode). A|or=inside a value is replaced with a space, since no real company name, domain, VAT number, LEI or registry number contains either. -
A plain line — each word is classified by its shape, and whatever is left over, in order, is the company name.
Supercell Oy supercell.com FI23365096finds all three. -
An object, if you are calling from code, Clay, n8n or Make:
{ "name": "Supercell Oy", "website": "https://www.supercell.com", "country": "FI" }
What each check needs. Leave anything out and that check is simply skipped, free, and never counted against the vendor.
| Check | Needs |
|---|---|
| Registry | A country of FI, FR, NO or US, plus a name or a registry number. A Finnish business ID (0000000-0) implies Finland on its own. United States coverage is SEC EDGAR, which needs a ticker or a CIK, not a name |
| VAT | A VAT number with its country in front, e.g. FI23365096. Use EL for Greece and XI for Northern Ireland |
| LEI | A 20-character LEI code |
| Domain, mail setup, certificates | A website domain |
A bare nine-digit number is both a Norwegian organisation number and a plausible French SIREN, so it is never routed without a country. Say which.
Output
One row per vendor. A row where fewer than two checks returned data is still returned in full; it is just not billed.
| query | found | status | legalName | registryStatus | registryCountry | registrySource | registrationDate | registeredAddress | vatValid | vatName | leiStatus | leiEntityStatus | domainCreatedAt | domainAgeDays | domainRegistrar | hasMx | hasSpf | hasDmarc | tlsIssuer | tlsValidFrom | nameMatch | redFlags | riskLevel | checksRun | checksFound | registryCheckStatus | vatCheckStatus | leiCheckStatus | domainCheckStatus | dnsCheckStatus | tlsCheckStatus | checkNotes | sourceUrls | inputName | inputDomain | inputVatNumber | inputLei | inputRegistryId | inputCountry | scrapedAt |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| name=Supercell Oy|domain=supercell.com|vatNumber=FI23365096|lei=743700MSCHABJ4XW2532|registryId=2336509-6|country=FI | true | OK | <vat number valid?> | <lei: is the entity active?> | <receives email?> | <do the names agree?> | 1970-01-01T00:00:00.000Z |
Here is a real row, trimmed to the interesting columns, for the prefilled Finnish example. All six checks answered:
{"query": "name=Supercell Oy|domain=supercell.com|vatNumber=FI23365096|lei=743700MSCHABJ4XW2532|registryId=2336509-6|country=FI","found": true,"legalName": "Supercell Oy","registryStatus": "active","registrySource": "PRH (Finland)","registrationDate": "2010-05-14","registeredAddress": "Jätkäsaarenlaituri 1, 00180 HELSINKI","vatValid": true,"vatName": "Supercell Oy","leiStatus": "LAPSED","leiEntityStatus": "ACTIVE","domainCreatedAt": "1999-01-31T05:00:00Z","domainAgeDays": 10102,"domainRegistrar": "Nom-iq Ltd. dba COM LAUDE","hasMx": true,"hasSpf": true,"hasDmarc": true,"tlsIssuer": "C=US, O=Amazon, CN=Amazon RSA 2048 M01","nameMatch": { "verdict": "match", "score": 1 },"redFlags": [],"riskLevel": "low","checksRun": 6,"checksFound": 6}
Two dataset views ship with the actor: Overview, which is every column, and Red flags, the triage table — risk level, flags, legal name, registry status, VAT validity, the name cross-check, domain age and mail setup. Start in Red flags, sort by risk level, and open Overview only for the rows that earned it.
The nameMatch column carries the comparison itself, not just a verdict: every pair of names, the
score from 0 to 1, and both the original and the compared strings. Accents and company suffixes
(Oy, AB, ASA, GmbH, Ltd, SAS, S.A., A/S, L.P.) are removed before comparing, so
"Supercell Oy" and "Supercell Ltd" match — PRH genuinely registers both names for the same company —
while "Supercell Oy" and "Rovio Entertainment Oyj" do not.
Each check also reports its own outcome in registryCheckStatus, vatCheckStatus, leiCheckStatus,
domainCheckStatus, dnsCheckStatus and tlsCheckStatus: OK, NOT_FOUND, NOT_CHECKED,
BAD_INPUT or REQUEST_FAILED. They are named <check>CheckStatus rather than <check>Status
because registryStatus and leiStatus already mean something else on the row — the company's own
status, and the LEI registration's own status.
Example runs
Three inputs that return real rows, with no key or account of your own. Each one exercises a different part of the actor.
1. Everything at once, on one Finnish company. All six checks have something to go on:
{"companies": ["name=Supercell Oy|domain=supercell.com|vatNumber=FI23365096|lei=743700MSCHABJ4XW2532|registryId=2336509-6|country=FI"]}
This is the prefilled example. It comes back active from PRH with a 2010 registration date and a
Helsinki address, vatValid: true in the same name from VIES, an ACTIVE entity on a LAPSED LEI
registration, a domain first registered in 1999, mail on Google with SPF and DMARC present, and a
current certificate. riskLevel: low. The LAPSED LEI is a good illustration of a deliberate
decision: a lapsed LEI usually means an unpaid annual renewal rather than a dead company, so it does
not raise a flag on its own.
2. A French company by SIREN. France is the one route here that searches by name as well as by number:
{"companies": ["name=Doctolib|domain=doctolib.fr|registryId=794598813|country=FR"]}
3. A VAT number and a domain, with no registry route. Ireland has no registry route here, and
this is what that honestly looks like — registryCheckStatus: NOT_CHECKED, a note saying which
countries are covered, no NOT_FOUND_IN_REGISTRY flag invented, and the VAT, domain, mail and
certificate checks all answering normally:
{"companies": ["name=Google Ireland Limited|domain=google.ie|vatNumber=IE6388047V|country=IE"]}
How a vendor gets billed
One event, vendor-check, charged once per company, and only when at least two checks came back
with real data about it. The reasoning: one source on its own is not a due-diligence answer, and
this actor's whole value is the cross-reading, which needs at least two.
What that means in practice:
- A company where five checks answered and one failed costs the same as one where all six answered. You are paying for the verdict, not per lookup.
- A check with nothing to go on is skipped, reported as
NOT_CHECKED, and free. - A company where only one check answered is returned in full and not billed.
- A company where nothing answered comes back
found: falseand is not billed. - A VAT number that VIES reports as not valid does count as an answer. It is the single most useful thing this actor can tell you, and the check worked — the answer was just no.
Pricing
A company is only billed when at least two checks came back with real data about it, and misses are always free. See "How a vendor gets billed" above for exactly what counts as an answer.
Limits worth knowing before you buy
- Registry coverage is four countries. Finland, France, Norway and the United States. Everything
else is reported as
NOT_CHECKEDwith a note, never as a missing company. The VAT check covers all 27 EU member states plus Northern Ireland, and the LEI check is global, so a German or Italian vendor with a VAT number is still usefully checkable — just not against its national register. - United States coverage is SEC EDGAR only, which means SEC filers. It needs a stock ticker or a
CIK, and it has no name search. A privately held US company will not be found there, and SEC
publishes no dissolution field, so
registryStatusis honestlyunknownfor every US filer rather than a guessedactive. - Germany and Spain never return a company name from VIES, even for a perfectly valid number.
That is their own data-protection policy.
vatValidis still true or false, and the missing name is not a failed check — it just means the name cross-check has one fewer name to work with. - Finnish registry status is deliberately conservative.
activerequires an open trade-register entry; a company with a closed one lands onunknownrather thanactive, and only PRH's own company-situation records (liquidation, bankruptcy) read asdissolved. - Some country domains publish no registration service at all.
.ieis one of them. Those come backdomainCheckStatus: NOT_CHECKEDwith a note saying so, and no domain age, because nothing is known either way. This is kept strictly separate fromNOT_FOUND, which means the registry answered and has no such domain — a supplier invoicing you from an unregistered domain. That case is reported throughdomainCheckStatusandcheckNotesrather than as a red flag, because the published flag list has no member for it. - The public certificate log rate-limits heavy use. A rate-limited company comes back
tlsCheckStatus: REQUEST_FAILED, not as a company with no certificate. - Domain age is about the domain, not the company. A long-established firm that rebranded last
year will show a young domain. That is why
DOMAIN_UNDER_180_DAYSis a lesser flag that needs two others to reachhighon its own.
Frequently asked questions
Does this replace a sanctions screen? No, and it does not attempt to. See "What this actor deliberately does not do" above.
Can I get directors or beneficial owners? No. This actor carries no personal data at all, by design.
Why is a column empty? Look at that check's <check>CheckStatus and at checkNotes on the same
row. Every empty column has a stated reason: nothing supplied, no registry route for that country,
the source said no, or the source could not be reached.
Can I run it on a schedule? Yes — save it as an Apify Task with your vendor list and add a schedule. Re-running a supplier list monthly is how you catch a vendor that was struck off after you onboarded it.
Is a low risk level a guarantee? No. It means nothing was found wrong in what was checked.
Read it together with checksFound.
Use it from Clay, n8n, Make, or an AI agent
This actor runs synchronously over plain HTTP — call it directly from a script, a workflow tool, or an AI agent, no Apify Console needed once you have an API token.
curl "https://api.apify.com/v2/acts/accountable_eel~vendor-due-diligence-check/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST \-H "Content-Type: application/json" \-d '{"companies":["name=Supercell Oy|domain=supercell.com|vatNumber=FI23365096|lei=743700MSCHABJ4XW2532|registryId=2336509-6|country=FI","name=Doctolib|domain=doctolib.fr|registryId=794598813|country=FR","name=Google Ireland Limited|domain=google.ie|vatNumber=IE6388047V|country=IE"]}'
n8n. Add an HTTP Request node: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~vendor-due-diligence-check/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body Content Type JSON, JSON Body {"companies":["name=Supercell Oy|domain=supercell.com|vatNumber=FI23365096|lei=743700MSCHABJ4XW2532|registryId=2336509-6|country=FI","name=Doctolib|domain=doctolib.fr|registryId=794598813|country=FR","name=Google Ireland Limited|domain=google.ie|vatNumber=IE6388047V|country=IE"]} (swap in an expression from an earlier node for a real value).
Clay. Add an "HTTP API" column: Method POST, URL https://api.apify.com/v2/acts/accountable_eel~vendor-due-diligence-check/run-sync-get-dataset-items?token=<YOUR_TOKEN>, Body {"companies":["{{vendor}}"]}, mapping the row's vendor into the companies array.
MCP. In Claude, Cursor, or any MCP client with the Apify MCP server, ask for "Vendor verification API: company, VAT, LEI, domain checks" — the agent will find and run this actor.