Vendor Due Diligence: Company, VAT, LEI and Domain Checks avatar

Vendor Due Diligence: Company, VAT, LEI and Domain Checks

Pricing

from $22.80 / 1,000 vendor checks

Go to Apify Store
Vendor Due Diligence: Company, VAT, LEI and Domain 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

Adrian Voss

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

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

CheckSourceWhat it answers
Official company registryPRH (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 numberThe European Commission's own VIES serviceIs this VAT number currently valid, and whose name is it in
LEIGLEIF, the global LEI registryIs the legal entity active, and what is its legal name on the LEI
Domain registrationRDAP, the registry protocol that replaced WHOISWhen was the website domain first registered, and at which registrar
Mail setupCloudflare's public DNS resolverCan the domain receive email at all, and does it publish SPF and DMARC
TLS certificatesThe public Certificate Transparency logsWho 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.

FlagFires when
NOT_FOUND_IN_REGISTRYA registry this actor can reach answered, and has no such company
REGISTRY_INACTIVEThe registry record says dissolved, or GLEIF says the legal entity is INACTIVE
VAT_INVALIDVIES says the VAT number is not currently valid
NAME_MISMATCHThe names on the registry, the VAT registration and the LEI do not agree
DOMAIN_UNDER_180_DAYSThe website domain was first registered less than 180 days ago
NO_MXThe domain publishes no mail servers, so it cannot receive email
NO_DMARCThe 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:

  1. 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 no NOT_FOUND_IN_REGISTRY.
  2. An empty redFlags list is not a clean bill of health. It means nothing was found wrong in what was actually checked. checksRun and checksFound on the same row tell you how much that is worth, and checkNotes says 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

  1. In the Apify Console. Open the actor page and click Start — the companies field is already pre-filled with a working example. Results land in the run's dataset as soon as each item is found.
  2. 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"]}'
  3. 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.

  1. key=value pairs, 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=FI

    Accepted 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.

  2. 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 FI23365096 finds all three.

  3. 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.

CheckNeeds
RegistryA 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
VATA VAT number with its country in front, e.g. FI23365096. Use EL for Greece and XI for Northern Ireland
LEIA 20-character LEI code
Domain, mail setup, certificatesA 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.

queryfoundstatuslegalNameregistryStatusregistryCountryregistrySourceregistrationDateregisteredAddressvatValidvatNameleiStatusleiEntityStatusdomainCreatedAtdomainAgeDaysdomainRegistrarhasMxhasSpfhasDmarctlsIssuertlsValidFromnameMatchredFlagsriskLevelchecksRunchecksFoundregistryCheckStatusvatCheckStatusleiCheckStatusdomainCheckStatusdnsCheckStatustlsCheckStatuscheckNotessourceUrlsinputNameinputDomaininputVatNumberinputLeiinputRegistryIdinputCountryscrapedAt
name=Supercell Oy|domain=supercell.com|vatNumber=FI23365096|lei=743700MSCHABJ4XW2532|registryId=2336509-6|country=FItrueOK<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: false and 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_CHECKED with 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 registryStatus is honestly unknown for every US filer rather than a guessed active.
  • Germany and Spain never return a company name from VIES, even for a perfectly valid number. That is their own data-protection policy. vatValid is 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. active requires an open trade-register entry; a company with a closed one lands on unknown rather than active, and only PRH's own company-situation records (liquidation, bankruptcy) read as dissolved.
  • Some country domains publish no registration service at all. .ie is one of them. Those come back domainCheckStatus: NOT_CHECKED with a note saying so, and no domain age, because nothing is known either way. This is kept strictly separate from NOT_FOUND, which means the registry answered and has no such domain — a supplier invoicing you from an unregistered domain. That case is reported through domainCheckStatus and checkNotes rather 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_DAYS is a lesser flag that needs two others to reach high on 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.