# Counterparty Check API: KYB checklist from official registers (`bosco_labs/counterparty-check`) Actor

KYB checklist per company: register status, LEI, insolvency, recent accounts, sanctions (OFAC, UN, UK, EU) on the company and officers, VAT (VIES), IBAN; pass, fail, review or unverified, each sourced. Officers: UK, PL, NO, FR only. Insolvency: UK, PL, FR, DE, NL, NO, FI, EE; elsewhere unverified.

- **URL**: https://apify.com/bosco_labs/counterparty-check.md
- **Developed by:** [Bosco Labs](https://apify.com/bosco_labs) (community)
- **Categories:** Business, AI, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 company checkeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Counterparty Check API: KYB checklist from official registers

**Can I do business with this company?** One call checks a supplier, customer or partner
against official sources and returns a **checklist**: pass, fail, review or unverified per
check, each with its source link and time. Built for **AI agents** doing KYB, vendor onboarding
or "may I pay this party?" checks, and for people who want a fast, sourced first screen. To
screen a vendor list, pass up to 10 companies in `companies`: one checklist per company, same
price each.

**Pricing (pay per event):** $0.05 per company checked, on Apify and on the HTTP API, MCP and x402. An ambiguous name returns
the candidates to pick from and costs nothing; so does a company no source knows.

### What you get

| Check | Source | Pass / fail / review |
|---|---|---|
| `register_status` | National register or GLEIF | active = pass; liquidation, dissolved, bankrupt, deleted = fail; other = review. Active but an unclosed liquidation notice with the company's number = fail; other recent notices = review (Sirene and GLEIF stay active during a liquidation) |
| `lei_status` | GLEIF | ISSUED = pass; LAPSED = review; RETIRED, ANNULLED = fail |
| `insolvency` | Companies House insolvency cases and The Gazette (UK), KRS (PL), BODACC (FR), German and Dutch insolvency registers; register status (NO, FI, EE) | a Companies House insolvency status or case (a members' voluntary liquidation is solvent: pass), a notice in the last 3 years that gives the company's number, or an open proceeding = fail; older notices, notices matched on the name only, arrears, or a UK company gone before our Gazette copy starts = review; struck off or deleted without a procedure shown = unverified |
| `accounts_recent` | Registers, ESEF, SEC | newest year end within 24 months = pass, older = review |
| `sanctions_entity` | OFAC SDN and non-SDN, UN Security Council, UK, EU, US export lists | a listing that carries the company's registration number or LEI = fail; possible name match = review |
| `sanctions_people` | same lists; officers and owners from the UK, Polish, Norwegian and French registers | possible match = review |
| `vat_number`, `vat_name_match`, `vat_country_match` | VIES (EU) | not valid = fail; other name or country = review |
| `iban`, `iban_country_match` | ISO 13616 check digits, SWIFT IBAN Registry | bad check digits = fail; other country = review |
| `wallet_sanctions` | OFAC wallet addresses | listed = fail |

`unverified` always means **not checked** (no source for that country, a source down, no VAT
number known), never "safe". `summary.needs_attention` lists the fail and review checks. There
is **no overall verdict or risk score**: you decide, with the sources in hand.

Besides the checklist the answer carries the company's identity, its latest annual figures,
UK officers and owners, insolvency notices, the US listing and the full sanctions, VAT and
IBAN results.

Coverage by country:

| Country | Register status | Officers screened | Insolvency |
|---|---|---|---|
| UK | Companies House | directors and owners (PSCs) | The Gazette |
| Poland | KRS | board (names the register shows in full) | KRS |
| Norway | Brønnøysund | CEO and board | register status (bankrupt, winding up) |
| France | Sirene | directors (RNE) | BODACC |
| Finland, Estonia | national register | no open source | register status |
| Germany | GLEIF | no open source | insolvenzbekanntmachungen.de |
| Netherlands | GLEIF | no open source | Centraal Insolventieregister |
| Denmark, US, others | GLEIF, SEC | no | unverified |

Sanctions on the company, the LEI, VAT and IBAN work for every country.

### Example

```json
{
  "schema_version": "1",
  "query": "24256790",
  "status": "checked",
  "company": {
    "legal_name": "NOVO NORDISK A/S",
    "country": "DK",
    "registration_number": "24256790",
    "register": "Erhvervsstyrelsen (CVR)",
    "lei": "549300DAQ1CVT6CXN342",
    "lei_status": "ISSUED",
    "status": "active",
    "legal_form": "Aktieselskab",
    "registered_address": "Novo Alle 1, 2880 Bagsværd, DK"
  },
  "checks": [
    {
      "check": "register_status",
      "status": "pass",
      "detail": "Register status: active.",
      "source": "GLEIF",
      "source_url": "https://api.gleif.org/api/v1/lei-records/549300DAQ1CVT6CXN342",
      "checked_at": "2026-11-08T04:12:24+00:00"
    },
    {
      "check": "lei_status",
      "status": "pass",
      "detail": "LEI 549300DAQ1CVT6CXN342 is ISSUED.",
      "source": "GLEIF",
      "source_url": "https://search.gleif.org/#/record/549300DAQ1CVT6CXN342",
      "checked_at": "2026-11-08T04:12:24+00:00"
    },
    {
      "check": "insolvency",
      "status": "unverified",
      "detail": "Insolvency covers the UK, Poland, France, Germany and the Netherlands (insolvency registers) and Norway, Finland and Estonia (register status).",
      "source": null,
      "source_url": null,
      "checked_at": "2026-11-08T04:12:24+00:00"
    },
    {
      "check": "accounts_recent",
      "status": "pass",
      "detail": "Newest annual accounts: year ending 2025-12-31 (11 months ago).",
      "source": "filings.xbrl.org",
      "source_url": "https://filings.xbrl.org/549300DAQ1CVT6CXN342/2025-12-31/ESEF/DK/0/NOVO-2025-12-31-1-en.json",
      "checked_at": "2026-11-08T04:12:24+00:00"
    },
    {
      "check": "sanctions_entity",
      "status": "pass",
      "detail": "No match. Checked: OFAC Consolidated (non-SDN) List 2026-11-04, UN Security Council Consolidated List 2026-11-08, UK Sanctions List 2026-11-03, EU Consolidated Financial Sanctions List 2026-10-23, US Consolidated Screening List (Commerce, State) 2026-11-08, OFAC SDN List 2026-11-06.",
      "source": "OFAC, UN, UK, EU and US export lists",
      "source_url": null,
      "checked_at": "2026-11-08T04:12:24+00:00"
    },
    {
      "check": "sanctions_people",
      "status": "unverified",
      "detail": "No officer or owner names known (UK and Polish registers list them; Polish names are masked).",
      "source": null,
      "source_url": null,
      "checked_at": "2026-11-08T04:12:24+00:00"
    },
    {
      "check": "vat_number",
      "status": "unverified",
      "detail": "VIES is not answering (SERVICE_UNAVAILABLE); try again later",
      "source": "VIES (European Commission), answered by the national tax administration",
      "source_url": "https://ec.europa.eu/taxation_customs/vies/#/vat-validation",
      "checked_at": "2026-11-08T04:12:24+00:00"
    },
    {
      "check": "iban",
      "status": "pass",
      "detail": "DK5000400440116243: structure and check digits valid. Bank code 0040; no bank was contacted.",
      "source": "ISO 13616 check digits (mod 97) and the SWIFT IBAN Registry formats",
      "source_url": "https://www.swift.com/standards/data-standards/iban-international-bank-account-number",
      "checked_at": "2026-11-08T04:12:24+00:00"
    },
    {
      "check": "iban_country_match",
      "status": "pass",
      "detail": "expected DK, number is DK",
      "source": "ISO 13616 check digits (mod 97) and the SWIFT IBAN Registry formats",
      "source_url": "https://www.swift.com/standards/data-standards/iban-international-bank-account-number",
      "checked_at": "2026-11-08T04:12:24+00:00"
    }
  ],
  "summary": {
    "pass": 6,
    "fail": 0,
    "review": 0,
    "unverified": 3,
    "needs_attention": [],
    "unverified_checks": [
      "insolvency",
      "sanctions_people",
      "vat_number"
    ]
  },
  "notice": "Screening aid built from official sources, not a compliance, credit or legal determination. 'unverified' means not checked, never 'safe'. Review every 'fail' and 'review' against the linked source before acting.",
  "latest_financials": {
    "basis": "Consolidated annual report of a listed company (ESEF, IFRS figures).",
    "source": "filings.xbrl.org",
    "period_end": "2025-12-31",
    "currency": "DKK",
    "revenue": 309064000000,
    "net_income": 102434000000,
    "total_assets": 542902000000,
    "source_url": "https://filings.xbrl.org/549300DAQ1CVT6CXN342/2025-12-31/ESEF/DK/0/NOVO-2025-12-31-1-en.json"
  },
  "sanctions": {
    "entity": {
      "query": "NOVO NORDISK A/S",
      "match_found": false,
      "best_score": null,
      "complete": true,
      "summary": "No match >= 85 for 'NOVO NORDISK A/S'. Checked: OFAC Consolidated (non-SDN) List 2026-11-04, UN Security Council Consolidated List 2026-11-08, UK Sanctions List 2026-11-03, EU Consolidated Financial Sanctions List 2026-10-23, US Consolidated Screening List (Commerce, State) 2026-11-08, OFAC SDN List 2026-11-06."
    },
    "people_with_matches": [],
    "people_screened": 0
  },
  "vat": {
    "number": "DK24256790",
    "status": "unverified",
    "valid": null,
    "registered_name": null,
    "name_match": null,
    "country_match": null,
    "source_url": "https://ec.europa.eu/taxation_customs/vies/#/vat-validation"
  },
  "iban": {
    "number": "DK5000400440116243",
    "status": "pass",
    "valid": true,
    "bank_code": "0040",
    "country_match": true,
    "source": "ISO 13616 check digits (mod 97) and the SWIFT IBAN Registry formats"
  },
  "wallets": [],
  "warnings": [
    "EU Consolidated Financial Sanctions List: download failed (HTTP 500); used the copy fetched 2026-11-07T01:57 UTC (list dated 2026-10-23)."
  ],
  "source_url": "https://api.gleif.org/api/v1/lei-records/549300DAQ1CVT6CXN342",
  "retrieved_at": "2026-11-08T04:12:24+00:00",
  "duration_seconds": 28.5
}
```

This example ran while VIES was down: the VAT check says `unverified`, not `pass`.

### Input

```json
{ "query": "24256790", "country": "DK", "vatNumber": "DK24256790", "iban": "DK5000400440116243" }
```

| Field | Meaning |
|---|---|
| `query` | Company name, LEI or registration number (UK, DK, NO, FR, FI, EE, PL), US ticker or CIK. Required |
| `country` | ISO country code to pick the register, e.g. `GB` |
| `vatNumber` | The VAT number the counterparty gave you, e.g. `DK24256790`; empty = the one the register lists, if any |
| `iban` | The IBAN they want to be paid on |
| `walletAddresses` | Crypto addresses they want to be paid on, at most 10 |
| `companies` | Instead of `query`: a list of up to 10 companies, each `{query, country, vatNumber, iban}` |

#### Check a vendor list in one run

```json
{
  "companies": [
    { "query": "Novo Nordisk A/S", "country": "DK", "vatNumber": "DK24256790" },
    { "query": "00445790", "country": "GB" },
    { "query": "Equinor ASA", "country": "NO" }
  ]
}
```

You get one row per company, in the same shape as a single check, and pay the same $0.05 per
company checked. A name that fits several companies (`status: "ambiguous"`, with
`candidates`) and a company no source knows or that does not answer in time
(`status: "failed"`, with a `message`) cost nothing. Up to 10 companies per run; four are
checked at a time, within the registers' rate limits (a UK company takes the longest). Split a
longer list over several runs.

### Use from an AI agent (MCP)

Agents can call this Actor as a tool through the
[Apify MCP server](https://github.com/apify/apify-mcp-server). Add this server URL to your MCP
client (Claude, Cursor, VS Code, ...):

```text
https://mcp.apify.com?tools=bosco_labs/counterparty-check
```

It loads this Actor as a tool, plus the tools that read its results. The hosted server signs you
in with OAuth, or accepts your Apify token as `Authorization: Bearer <APIFY_TOKEN>`.

Example prompt: *"Before we pay them: check supplier Novo Nordisk A/S (CVR 24256790), their VAT
number DK24256790 and IBAN DK5000400440116243."* The agent passes:

```json
{"query": "24256790", "country": "DK", "vatNumber": "DK24256790", "iban": "DK5000400440116243"}
```

**Output for agents:** one row (typically 10-20 KB) with stable `snake_case` fields; read
`summary.needs_attention` and `checks` first. Usually 5-30 seconds (VIES and UK officer lookups
are the slow parts). **Cost:** $0.05 per company checked, billed to the Apify account the MCP
server is signed in with.

Also on the Bosco Labs API (`POST https://api.boscolabs.dev/v1/counterparty-check`, credits or
x402) and its MCP server `https://api.boscolabs.dev/mcp` (tool `counterparty_check`).

### FAQ

**Is this a compliance decision?** No. It is a screening aid built from official sources.
Fuzzy name matching gives false positives (namesakes) and can miss a name written another way.
Review every `fail` and `review` against the linked source, and use your own judgement or
counsel for decisions.

**Why is a check `unverified`?** The source does not cover that country (see the coverage
table), the source did not answer in time, or the input to check is missing (no VAT number).
The detail says which.

**Does the IBAN check prove who holds the account?** No. It checks that the number is well
formed and in the expected country; no bank is contacted.

**How fresh is it?** Registers, GLEIF and VIES are read live. Sanctions lists are at most about
an hour old (each list's own date is in the detail). UK insolvency notices come from a nightly
copy of The Gazette.

**Personal data?** Officer and owner names come from the public registers and are screened only
against sanctions lists, for this check. Nothing about the people is stored. See `LEGAL.md`.

# Actor input Schema

## `query` (type: `string`):

The counterparty to check: a name (e.g. "Novo Nordisk") or an identifier: LEI (20 characters, e.g. "724500Y6DUVHQD6OXN27"), UK company number ("00445790", "SC123456"), Danish CVR ("24256790"), Norwegian org number ("923609016"), French SIREN (9 digits, "552032534") or SIRET (14 digits, "55203253400703"), Finnish Business ID with its dash ("0112038-9"), Estonian registry code (8 digits, "12417834"), US ticker in capitals or with $ ("AAPL", "$brk.b"; foreign companies listed in the US resolve to their home country), SEC CIK ("320193"). The type is detected from format and check digits; an 8-digit number valid in several registers (UK, Danish CVR, Estonian) is settled by asking them, and `country` decides when given. Required, unless you give a `companies` list instead.

## `country` (type: `string`):

ISO 3166 alpha-2 country code to disambiguate, e.g. "DK", "GB", "NO", "FR", "FI", "EE", "NL", "US". With a name it limits the search to that country and, for NO, FR, FI and EE, also searches the national register (most companies there have no LEI); with a number it says which register the number belongs to (e.g. "GB" for a UK number without a leading zero, "EE" for an Estonian registry code, "FI" for a Business ID typed without its dash). Empty = detect from the query.

## `vatNumber` (type: `string`):

The VAT number the counterparty gave you, with its country prefix, e.g. "DK24256790". Checked live in VIES (valid or not, registered name) and matched against the register's name and country. Empty = the VAT number the register lists, if any (Estonia, Poland); otherwise the VAT check is unverified.

## `iban` (type: `string`):

The bank account the counterparty wants to be paid on, e.g. "DK5000400440116243". Checked offline: length, layout and ISO 13616 check digits, bank code, and whether its country matches the company's. No bank is contacted, so it does not prove who holds the account.

## `walletAddresses` (type: `array`):

Wallet addresses the counterparty wants to be paid on, e.g. \["0x7FF9cFad3877F21d41Da833E2F775dB0569eE3D9"]. Each is matched exactly against the addresses OFAC lists. At most 10.

## `companies` (type: `array`):

Check a list of companies in one run instead of `query`: up to 10 companies, each a name or number ("Tesco PLC") or an object with the fields above, e.g. \["Tesco PLC", {"query": "Novo Nordisk A/S", "country": "DK", "vatNumber": "DK24256790"}, {"query": "00445790", "country": "GB"}]. One row per company, priced like a single check ($0.05 per company checked); an ambiguous name, or a company no source knows or that does not answer in time, is a row that costs nothing. Leave `query` empty when you use this.

## Actor input object example

```json
{
  "query": "24256790",
  "country": "DK",
  "vatNumber": "DK24256790"
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "query": "24256790",
    "country": "DK",
    "vatNumber": "DK24256790"
};

// Run the Actor and wait for it to finish
const run = await client.actor("bosco_labs/counterparty-check").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "query": "24256790",
    "country": "DK",
    "vatNumber": "DK24256790",
}

# Run the Actor and wait for it to finish
run = client.actor("bosco_labs/counterparty-check").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "query": "24256790",
  "country": "DK",
  "vatNumber": "DK24256790"
}' |
apify call bosco_labs/counterparty-check --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bosco_labs/counterparty-check"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/vv3AOgRM8vgORUnwU/builds/J5mhtHe0ARMRgguTn/openapi.json
