# Business Creditworthiness Check (`mikee368/business-creditworthiness-check`) Actor

One company per row. An open-data risk indicator from public registers, plus optional Creditsafe and Dun & Bradstreet lookups using your own API credentials. The indicator is not a credit rating. No bureau account is included. Duplicate companies in one input are checked and charged once.

- **URL**: https://apify.com/mikee368/business-creditworthiness-check.md
- **Developed by:** [Mike Berckmoes](https://apify.com/mikee368) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 open-data indicators

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

Check one company with an **open-data risk indicator**, and optionally normalise a **Creditsafe Connect** or **Dun & Bradstreet Direct+** report using **your own** bureau credentials.

The indicator is **not a credit rating**, not a credit score, and not a credit limit. Bureau rows are a normalised subset of a report your contract already allows you to order. This Actor does not include a bureau account.

### What does Business Creditworthiness Check do?

Each company becomes one dataset row.

**Open-data indicator** (no bureau key). The run calls code copied from this repo's register and VAT Actors, then adds open accounts where a free source publishes them:

- Register status, age and legal form from [EU Company Register Lookup](https://apify.com/mikee368/eu-company-register-lookup) (Companies House, French recherche-entreprises, Brønnøysund, GLEIF and the other registers that Actor already supports). A UK row needs your free Companies House key.
- Dutch identity from the free KvK basis profile when you supply your own KvK API key.
- Filed accounts: Companies House `accounts` block (overdue, type, period end). French `finances` (turnover and net result) from recherche-entreprises. The free KvK basis profile does not include annual accounts, and this Actor does not call a paid jaarrekening product.
- VAT existence from [EU TIN & VAT Validator](https://apify.com/mikee368/eu-tin-vat-validator) when you pass a VAT number.
- Insolvency notices, sanctions hits and an ownership profile are **plugs**. They are not fetched unless you pass them or turn on the in-process ownership pack.

**Bureau lookup** (your key). With `creditsafeUsername` and `creditsafeSecret`, the Actor calls the official Connect API: `POST /authenticate`, `GET /companies`, then `GET /companies/{connectId}` with `includeIndicators=true`. With `dnbApiKey` and `dnbConsumerSecret`, it calls `POST /v2/token` (or `/v1/token` if you select v1) and `GET /v1/data/duns/{duns}`. A D\&B lookup needs a 9-digit D-U-N-S number. Company search on D\&B is not called.

No bureau website is scraped.

### What a row shows

- One row can hold the open-data indicator and, when you set mode to `bureau` or `both` and supply credentials, a normalised bureau result.
- The concern points and the signal list are on the row. A dissolved company, an overdue accounts flag, a supplied insolvency notice, or a supplied sanctions hit each add points. Fewer than two known signals is `insufficient`.
- Creditsafe and D\&B credentials are secret input fields. They are not written to the dataset.
- Director names, principal names, and CCJ defendant names from a bureau payload are not copied. The default D\&B blocks omit `principalscontacts`.

### Licensing

Creditsafe and Dun & Bradstreet generally forbid reselling their data, building a competing database, or redistributing a report to someone who is not covered by the customer's contract. This Actor is built around that limit:

- There is no Creditsafe or D\&B account in the code, the image, or the default input.
- The Actor calls only the official HTTP APIs, and only with credentials from the run input.
- The dataset stores a normalised subset (score, limit, payment behaviour, CCJs or other legal events, group structure). The raw report is not stored in the dataset or the key-value store.
- A bureau row is for the customer who supplied the key. It is not a sublicense from this Actor, and it is not a new rating. Customers are responsible for their Creditsafe/D\&B contract allowing this use.
- The open-data indicator uses public registers and free APIs (Companies House, recherche-entreprises, KvK basis profile, VIES, GLEIF). Those rows are labelled `open-data-risk-indicator` and `isCreditRating` is false.
- Sanction lists are not downloaded here. Pass hits from Sanctions Screening Watch. Insolvency Watch can be plugged in later by passing its rows as `insolvencyNotices`. The ownership pack from this repo can run in-process when `includeOwnership` is on.

### What does each row return?

| Field | Meaning |
|---|---|
| `product` | `open-data-risk-indicator`, `bureau-lookup`, or `both` |
| `isCreditRating` | Always false |
| `indicatorBand` | `lower-concern`, `mixed`, `higher-concern`, or `insufficient` |
| `concernPoints` | Sum of the open-data signals. Higher means more concern. It is not a bureau score |
| `signals` | Each signal, the points, and a short reason |
| `register` | Status, legal form, incorporation date, source |
| `accounts` | `filed`, `overdue`, `not-published`, or `not-in-free-profile` |
| `vat` | Existence result when a VAT number was supplied |
| `insolvency` / `sanctions` / `ownership` | `not-run`, or the plug you supplied |
| `bureau` | Normalised Creditsafe or D\&B outcome when that call ran |
| `eventsCharged` | `open-indicator` and/or `bureau-lookup` |

`higher-concern` is a flag to read the signals. It is not a refusal to trade.

### How to run it

1. Add one company under **Companies**. Include `country` and a registration number, VAT number, KvK number, or D-U-N-S.
2. Leave **Mode** on `indicator` for the open-data row. Set `bureau` or `both` only when you also paste your own bureau credentials. In `both` mode, if `open-indicator` is not on the live price list, the indicator is not fetched or charged and the priced bureau lookup still runs and is charged.
3. For a UK company, paste your free Companies House key. For a Dutch company, paste your KvK key.
4. Start the run. Open the dataset.

`maxCompanies` defaults to 1 and cannot exceed 25. A later copy of the same country and id is processed and charged once. Spaces, dots and dashes in a registration number, VAT number, D-U-N-S or KvK number are ignored. Two companies that only share a name are both checked, and a number with no country is not merged.

To plug in the other Actors, set the matching switch and paste their rows:

- `useSuppliedInsolvency` and `insolvencyNotices`
- `useSuppliedSanctions` and `sanctionsHits` (an empty list is an explicit clear; leaving the switch off is not a clear)
- `useSuppliedOwnership` and `ownershipProfile`, or `includeOwnership` to run the ownership pack in this container

`includePsc` is off. Turn it on only when you need UK persons with significant control. Those names are personal data from the public PSC register.

### How much does a check cost?

Pay per event. The live price is `.actor/pricing.json`.

| Event | When it is charged | Price |
|---|---|---|
| `open-indicator` (primary) | One delivered open-data indicator. Not charged when the band is insufficient or the company is not found. | $0.01 |
| `bureau-lookup` | One completed Creditsafe or D\&B lookup | $0.005 |

A missing bureau key, a rejected bureau password, and an invalid input are not charged. A completed bureau call that finds no company is charged, because the lookup ran. Not charged when the band is insufficient or the company is not found.

Apify keeps 20% of the event price. Platform compute is still the developer's cost on pay-per-event. This repo's measured rate is **$0.20 per compute unit** (1 CU = 1 GB-hour): a sanctions check in `actors/BUILD-NOTES.md` showed a compute line of $0.001404 for 0.00702 CU.

This Actor asks for 256 MB (0.25 GB). A run that lasts 60 seconds is `0.25 × 60 / 3600 = 0.004167` CU, about **$0.00083**.

| Price | Kept after 20% | Covers a 256 MB run of |
|---|---|---|
| $0.01 open indicator | $0.008 | about 9.6 minutes |
| $0.005 bureau lookup | $0.004 | about 4.8 minutes |
| Both on one company | $0.012 | about 14 minutes |

A 1-company run is the default. Recorded one-company runs of other Actors in this repo were 9.06 s (`company-ownership-lookup`) and 3.74 s (`eu-company-status-watch`), from `actors/BUILD-NOTES.md`. The offline harness replays fixtures and is not a platform bill.

### Input

See the **Input** tab. Secrets:

- `companiesHouseApiKey`, `kvkApiKey`
- `creditsafeUsername`, `creditsafeSecret` (`creditsafeEnvironment` is `production` or `sandbox`)
- `dnbApiKey`, `dnbConsumerSecret` (`dnbTokenVersion` is `v2` or `v1`)

`dnbOrderReason` is optional. It is not sent when empty. The default D\&B blocks are `companyinfo_L2_v1`, `financialstrengthinsight_L2_v1`, `paymentinsight_L1_v1`, `eventfilings_L3_v1`, and `hierarchyconnections_L1_v1`.

### Output

```json
{
  "product": "open-data-risk-indicator",
  "isCreditRating": false,
  "name": "EXAMPLE HOLDINGS LIMITED",
  "country": "GB",
  "registrationNumber": "99999999",
  "indicatorBand": "lower-concern",
  "concernPoints": 0,
  "accounts": {"status": "filed", "overdue": false, "source": "UK_COMPANIES_HOUSE"},
  "eventsCharged": ["open-indicator"]
}
```

A Creditsafe row adds `bureau.score.commonValue` (A–E), `bureau.creditLimit`, `bureau.paymentBehaviour` when the contract returns a `pbi` indicator, `bureau.negativeEvents`, and `bureau.groupStructure`. A D\&B row adds `bureau.paymentBehaviour.paydex`, `bureau.score.failureScoreClass`, and `bureau.groupStructure.globalUltimate` when those objects are in the payload. A credit limit is copied only when the entitled payload includes one.

### Privacy

Register rows keep the company name, number, status, legal form and address fields the register Actor already returns. They do not copy officer lists. Bureau director and principal names are dropped. UK PSC names are omitted unless `includePsc` is on. Use those names only for a permitted ownership or screening purpose, and do not build a marketing file from them. Questions belong on the Actor's **Issues** tab.

### FAQ

**Is the band a credit score?** No. Read `signals` for the reasons. A bureau score, when present, is the bureau's own figure, copied from your report.

**Can I run this without a Creditsafe or D\&B contract?** Yes. Leave mode on `indicator` and leave the bureau secrets empty.

**Why does D\&B need a D-U-N-S?** The documented data-block call used here is `GET /v1/data/duns/{duns}`. A match/search call is not made.

**Why are Dutch annual accounts missing?** The free basis profile does not publish them. A paid KvK accounts product is not called.

### Related Actors

These are separate Actors. This check does not call them.

- [Supplier Risk Monitor](https://apify.com/mikee368/supplier-risk-monitor) — Re-checks a saved supplier list on a schedule and stores a row when a later run differs. This Actor checks the companies in one run.
- [GDPR & ePrivacy Consent Scanner](https://apify.com/mikee368/gdpr-consent-scan) — Records cookies and trackers set before consent, the cookie banner, and privacy-policy signals on a website. It does not score the company.
- [EU UBO Lookup](https://apify.com/mikee368/eu-ubo-lookup) — Reads beneficial owners where a commercial Actor may, and returns not available where the register is closed. This Actor does not call those UBO registers.
- [US Business Entity Status](https://apify.com/mikee368/us-business-entity-status) — Returns status from New York, Colorado, Connecticut, Oregon, and Pennsylvania open data, and from the Texas Comptroller franchise file. Those US offices are not part of this Actor's register lookup.
- [ISO Certificate Check](https://apify.com/mikee368/iso-certificate-check) — Checks an ISO 9001, 14001, 27001, or 45001 certificate number. A live IAF result uses the customer's own key. Certificate status is not an indicator signal.

# Actor input Schema

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

Companies to check. Each item may include name, country, registrationNumber, vatNumber, duns, connectId, kvkNumber and lei. A string is treated as a name.

## `mode` (type: `string`):

indicator: open-data risk indicator only. bureau: your Creditsafe and/or D\&B credentials only. both: indicator and any bureau whose credentials are set.

## `maxCompanies` (type: `integer`):

How many companies this run checks. The default is 1 so a single-company run stays within the prepared price.

## `companiesHouseApiKey` (type: `string`):

Your free Companies House key. Required for a UK register row and UK accounts. Never a bureau key.

## `kvkApiKey` (type: `string`):

Your free KVK Handelsregister API key for a Dutch basis profile. Annual accounts are not in that free profile and are not requested.

## `creditsafeUsername` (type: `string`):

Username for your own Creditsafe Connect contract. Leave empty to skip Creditsafe.

## `creditsafeSecret` (type: `string`):

Password for your own Creditsafe Connect contract. Stored as a secret. It is not written to the dataset or the log.

## `creditsafeEnvironment` (type: `string`):

Official Creditsafe host. production is connect.creditsafe.com. sandbox is connect.sandbox.creditsafe.com.

## `dnbApiKey` (type: `string`):

Consumer key for your own Dun & Bradstreet Direct+ contract. Leave empty to skip D\&B.

## `dnbConsumerSecret` (type: `string`):

Consumer secret for your own Direct+ contract. Stored as a secret. It is not written to the dataset or the log.

## `dnbTokenVersion` (type: `string`):

v2 calls POST /v2/token (Direct+ Data Blocks). v1 calls POST /v1/token (the partner authentication page). Both use plus.dnb.com.

## `dnbBlockIds` (type: `string`):

Comma-separated Direct+ blockIDs. Empty uses company info, financial strength, payment insight, event filings and hierarchy. principalscontacts is not in the default.

## `dnbOrderReason` (type: `string`):

Optional orderReason from your D\&B contract. Empty means the parameter is not sent.

## `useSuppliedInsolvency` (type: `boolean`):

When on, insolvencyNotices are matched to each company. The Insolvency Watch Actor is not called.

## `insolvencyNotices` (type: `array`):

Rows from the Insolvency Watch Actor (name, registrationNumber, noticeId, publishedAt, status, source). Ignored unless useSuppliedInsolvency is on.

## `useSuppliedSanctions` (type: `boolean`):

When on, sanctionsHits are matched by company name. Sanction lists are not downloaded in this Actor.

## `sanctionsHits` (type: `array`):

Hits from sanctions-screening-watch (name or matchedName, list, uid, score). Ignored unless useSuppliedSanctions is on. An empty list is an explicit clear.

## `useSuppliedOwnership` (type: `boolean`):

When on, ownershipProfile is copied onto the row and the ownership pack is not called.

## `ownershipProfile` (type: `object`):

One company-ownership-lookup shaped profile. Ignored unless useSuppliedOwnership is on.

## `includeOwnership` (type: `boolean`):

Run the company-ownership pack in this container (GLEIF parents, and UK PSC only when includePsc is on). No child Actor is started.

## `includePsc` (type: `boolean`):

When includeOwnership is on, also read Companies House persons with significant control. Those names are personal data. Off by default.

## Actor input object example

```json
{
  "companies": [
    {
      "name": "Example Holdings Limited",
      "country": "GB",
      "registrationNumber": "99999999"
    }
  ],
  "mode": "indicator",
  "maxCompanies": 1,
  "creditsafeEnvironment": "production",
  "dnbTokenVersion": "v2",
  "dnbBlockIds": "",
  "dnbOrderReason": "",
  "useSuppliedInsolvency": false,
  "insolvencyNotices": [],
  "useSuppliedSanctions": false,
  "sanctionsHits": [],
  "useSuppliedOwnership": false,
  "ownershipProfile": {},
  "includeOwnership": false,
  "includePsc": false
}
```

# Actor output Schema

## `dataset` (type: `string`):

One row per company

## `summary` (type: `string`):

Counts for the run

# 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 = {
    "companies": [
        {
            "name": "Example Holdings Limited",
            "country": "GB",
            "registrationNumber": "99999999"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mikee368/business-creditworthiness-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 = { "companies": [{
            "name": "Example Holdings Limited",
            "country": "GB",
            "registrationNumber": "99999999",
        }] }

# Run the Actor and wait for it to finish
run = client.actor("mikee368/business-creditworthiness-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 '{
  "companies": [
    {
      "name": "Example Holdings Limited",
      "country": "GB",
      "registrationNumber": "99999999"
    }
  ]
}' |
apify call mikee368/business-creditworthiness-check --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mikee368/business-creditworthiness-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/qGxBGxB5T4aYxUqXd/builds/5FBXx57pqeFI2dqd2/openapi.json
