# Finland Company Data & KYB: Y-tunnus Lookup + Bankruptcy (`datacraft-studio/finland-company-enrichment`) Actor

Look up a Finnish Y-tunnus in the PRH and YTJ open data for KYB and lead generation. Legal name, company form, status, addresses, TOL/NACE, VAT, prepayment and employer registers, plus bankruptcy, liquidation and restructuring. Board members are not in the open data.

- **URL**: https://apify.com/datacraft-studio/finland-company-enrichment.md
- **Developed by:** [Yahya Nouali](https://apify.com/datacraft-studio) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 company enricheds

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

## Finland Company Data & KYB

Look up a Finnish **Y-tunnus** and get a KYB dossier from the Finnish Patent and Registration Office (PRH) and the Business Information System (YTJ) open data API: legal name and parallel names, company form, registration status and dates, street and postal addresses, TOL 2008 activity code with a derived NACE class, VAT (ALV), prepayment (ennakkoperintä), and employer (työnantaja) registers, plus bankruptcy (konkurssi), liquidation (selvitystila), and restructuring (saneeraus) when the register has marked them.

The actor is built for lead enrichment and counterparty checks. You pay only when a company is found, or when a monitor run sees a real change. Invalid Y-tunnus values, unknown companies, and lookup errors are free. The first monitor pass stores a baseline and is not charged.

This is not an official PRH or YTJ service. Data is reused under [Creative Commons Attribution 4.0 International (CC BY 4.0)](https://creativecommons.org/licenses/by/4.0/). Attribute PRH / YTJ. Do not use their logos.

**Board members, managing directors, other role holders, and business bans are not in the PRH open data.** Those details are on a paid trade register extract. This actor does not request them, and monitor mode cannot alert on a board change.

Private traders (toiminimi) are outside this API. The API does not return email addresses or phone numbers.

### Use cases

- KYB onboarding of a Finnish customer or supplier
- Enrich a lead list of Y-tunnus values with legal name, city, and TOL/NACE
- Check VAT, prepayment, and employer registration before you invoice
- Watch a portfolio for bankruptcy, liquidation, restructuring, address, name, or register changes

### Input

| Field | Default | Limit | Meaning |
| --- | --- | --- | --- |
| `businessIds` | Nokia `0112038-9` in the console prefill | — | Y-tunnus. Also accepts `01120389` and `FI01120389`. Mod-11 (weights 7, 9, 10, 5, 8, 4, 2) is checked first. Remainder 1 is invalid. |
| `companyNames` | empty | at least 2 characters | Optional YTJ name search. Exact current, parallel, auxiliary, or previous names win. Partial matches are flagged for review. |
| `mode` | `enrich` | `enrich` or `monitor` | Enrich returns a dossier. Monitor stores a snapshot and returns only later changes. |
| `monitorKeyValueStoreName` | `finland-kyb-snapshots` | 1–63 characters | Named key-value store. Keep it stable across runs. |
| `maxItems` | `100` | 1–10,000 | Cap on processed Y-tunnus values and name hits. |
| `maxNameMatches` | `3` | 1–20 | Name-search hits returned per query. |
| `minRequestIntervalMs` | `300` | 0–10,000 | Pause between calls. PRH shares about **300 requests per minute across all API users**. |

`organizationNumbers` is accepted as an alias of `businessIds`.

Name search reads at most **3 pages** (300 companies, the API page size is 100) when the first page has no exact name. A broad query such as `Oy` is truncated and marked for review.

#### Monitor

Watched fields: status, legal name, bankruptcy, liquidation, restructuring, address, TOL code, VAT, prepayment, employer, and trade-register status. The baseline row is stored and not delivered. An unchanged check is free. A change is charged as `change-detected` and is not also charged as `company-enriched`.

#### Example

```json
{
  "businessIds": ["0112038-9", "FI01120389"],
  "companyNames": ["Nokia Oyj"],
  "mode": "enrich"
}
```

### Output

Each found company includes the Y-tunnus, VAT number `FI` + 8 digits, EUID when present, names, company form, business-ID status, trade-register status, registration and dissolution dates, addresses, TOL code and description, derived NACE (`70100` → `70.10`), the three tax registers, and any open bankruptcy, liquidation, or restructuring situation. `boardMembersAvailable` is always `false`.

Risk is a triage flag, not a credit score:

- **high** — open bankruptcy, liquidation, or restructuring; ceased; removed; or an invalidated business ID
- **review** — not yet registered, or a name search that was not a single exact match
- **clear** — none of those signals

A run summary row records counts and the prices that were applied. Misses are in the dataset with an empty `chargedEvents` list.

### Pricing

Pay per event. Prices are in USD.

| Event | Price | When |
| --- | --- | --- |
| `company-enriched` | 0.004 | Enrich mode, and the Y-tunnus or name resolved to a company |
| `change-detected` | 0.015 | Monitor mode, and a watched field changed after the baseline |

Not charged: invalid check digits, unknown companies, request errors, duplicate Y-tunnus values in the same run, the monitor baseline, and unchanged monitor checks. There is no third or synthetic event.

### Source

| | |
| --- | --- |
| API | `https://avoindata.prh.fi/opendata-ytj-api/v3/companies` |
| Access | Open, no API key |
| Licence | CC BY 4.0 (confirmed on the OpenAPI document, 25 October 2026) |
| Situation codes | `KONK` bankrupt, `SELTILA` liquidation, `SANE` restructuring |

Trade-register status values `0`–`4` on live records match the trade-register entry types: unregistered, registered, removed, start-up not registered, and ceased.

### Local run

```bash
npm install
npm test
npm run smoke
npm run build
npm start
```

`npm run smoke` looks up Nokia (`0112038-9`) against the live API.

Memory for the published actor is **512 MB** minimum and default (maximum 1024 MB).

### Integrations: Make, Zapier, n8n

You can call this Actor from no-code tools through Apify's official integrations. Use its Actor ID `bBVRcgOBybzgj3pA0`, and connect each tool with OAuth or your Apify API token. Never put the token in the Actor input.

- **Make**: in the Apify app, add **Run an Actor** and set *Run synchronously* to Yes. Then add **Get Dataset Items** with the run's default dataset ID, and map the rows to Google Sheets, a CRM or Slack. For long runs, use the **Watch Actor Runs** trigger instead.
- **Zapier**: the Apify app has the **Run Actor** action. A synchronous run has a 30-second hard timeout, so for larger lists start the run and use the **Finished Actor Run** trigger with **Fetch Dataset Items**.
- **n8n**: install the official node `@apify/n8n-nodes-apify`. It is a verified community node on n8n Cloud; on self-hosted n8n, add it under Settings > Community Nodes. Use **Run an Actor and Get Dataset**, or the Apify trigger for finished runs.

Example input:

```json
{"mode": "enrich", "businessIds": ["0112038-9"]}
```

#### Scheduled monitor to Slack or Sheets

1. Save a monitor input as an Actor task and keep the same store name on every run:

```json
{
  "mode": "monitor",
  "businessIds": [
    "0112038-9"
  ],
  "monitorKeyValueStoreName": "finland-kyb-snapshots"
}
```

2. In Apify Console > **Schedules**, run the task on a cron such as `0 7 * * 1` (every Monday at 07:00), with your timezone selected.
3. On the task's **Integrations** tab, add Slack or an HTTP webhook on *Run succeeded*. You can also use Make **Watch Actor Runs**, Zapier **Finished Actor Run** or the n8n Apify trigger.
4. Fetch the dataset items and keep only the change rows: `recordType` is `"company"` (monitor runs only output changed companies). The first run only stores the baseline and is free.

#### HTTP API

This call runs the Actor and returns the dataset rows in one request. Synchronous runs time out after 300 seconds, so use `/runs` for big lists.

```bash
curl -X POST "https://api.apify.com/v2/acts/bBVRcgOBybzgj3pA0/run-sync-get-dataset-items" \
  -H "Authorization: Bearer <YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"mode": "enrich", "businessIds": ["0112038-9"]}'
```

### Suomeksi

Tämä Actor hakee suomalaisen yrityksen julkiset perustiedot Patentti- ja rekisterihallituksen (PRH) ja yritys- ja yhteisötietojärjestelmän (YTJ) avoimesta rajapinnasta. Tunniste on Y-tunnus. Kelpaavat muodot ovat `0112038-9`, `01120389` ja ALV-numero `FI01120389`. Tarkistemerkki lasketaan painoilla 7, 9, 10, 5, 8, 4, 2. Jakojäännös 1 ei ole kelvollinen Y-tunnus.

Haku palauttaa nimen, rinnakkaisnimet, aputoiminimet ja aiemmat nimet, yritysmuodon, Y-tunnuksen ja kaupparekisterin tilan, rekisteröintipäivät, katu- ja postiosoitteen, TOL 2008 -toimialan (ja siitä johdetun NACE-luokan), arvonlisäverovelvollisuuden, ennakkoperintärekisterin, työnantajarekisterin sekä avoimeen dataan merkityn konkurssin, selvitystilan ja saneerauksen.

**Hallituksen jäseniä, toimitusjohtajaa, muita vastuuhenkilöitä ja liiketoimintakieltoa ei ole PRH:n avoimessa datassa.** Ne saa vain maksullisesta kaupparekisteriotteesta. Tämä Actor ei hae niitä, eikä muutosten seuranta voi havaita hallitusmuutosta.

Yksityiset elinkeinonharjoittajat (toiminimet) eivät kuulu rajapintaan. Rajapinta ei palauta sähköpostiosoitteita eikä puhelinnumeroita.

Tila `enrich` palauttaa yrityksen tiedot. Tila `monitor` tallentaa vertailukuvan nimettyyn avain-arvovarastoon. Ensimmäinen tarkistus on maksuton baseline. Myöhempi ajo veloitetaan vain, jos jokin seurattu kenttä on muuttunut.

Hinnoittelu on tapahtumakohtainen: löydetty yritys **0,004 USD** (`company-enriched`), havaittu muutos **0,015 USD** (`change-detected`). Virheellistä Y-tunnusta, tuntematonta yritystä, hakuvierettä, baselinea ja muuttumatonta tarkistusta ei veloiteta. Kolmatta tapahtumaa ei ole.

Lähde on Creative Commons Nimeä 4.0 Kansainvälinen (CC BY 4.0). Mainitse lähteenä PRH / YTJ. Älä käytä PRH:n tai YTJ:n logoa äläkä esitä palvelua viranomaisen palveluna.

Muisti julkaistussa Actorissa on 512 MB.

# Changelog

This Actor's version history is a separate document: https://apify.com/datacraft-studio/finland-company-enrichment/changelog.md

# Actor input Schema

## `businessIds` (type: `array`):

Finnish business IDs. 0112038-9, 01120389, and the VAT form FI01120389 are accepted. The mod-11 check digit is verified before any request. Invalid IDs are returned and not charged.

## `companyNames` (type: `array`):

Optional names to search in YTJ. An exact current, parallel, auxiliary, or previous name wins. Otherwise the top matches are returned and flagged for review.

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

Enrich returns a dossier per company. Monitor stores a snapshot in the named key-value store and returns only changes. The first monitor run is a free baseline.

## `monitorKeyValueStoreName` (type: `string`):

Named key-value store for monitor snapshots. Use the same name on later runs. Deleting it starts a new free baseline.

## `maxItems` (type: `integer`):

Maximum number of Y-tunnus values and name matches to process.

## `maxNameMatches` (type: `integer`):

How many name-search hits to return per company name.

## `minRequestIntervalMs` (type: `integer`):

Pause between calls to avoindata.prh.fi. The open API is shared at about 300 requests per minute across all users.

## Actor input object example

```json
{
  "businessIds": [
    "0112038-9"
  ],
  "companyNames": [],
  "mode": "enrich",
  "monitorKeyValueStoreName": "finland-kyb-snapshots",
  "maxItems": 100,
  "maxNameMatches": 3,
  "minRequestIntervalMs": 300
}
```

# Actor output Schema

## `overview` (type: `string`):

Enriched companies, unmatched queries, and the run summary.

# 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 = {
    "businessIds": [
        "0112038-9"
    ],
    "companyNames": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("datacraft-studio/finland-company-enrichment").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 = {
    "businessIds": ["0112038-9"],
    "companyNames": [],
}

# Run the Actor and wait for it to finish
run = client.actor("datacraft-studio/finland-company-enrichment").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 '{
  "businessIds": [
    "0112038-9"
  ],
  "companyNames": []
}' |
apify call datacraft-studio/finland-company-enrichment --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,datacraft-studio/finland-company-enrichment"
        }
    }
}
```

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/bBVRcgOBybzgj3pA0/builds/Tle05q9lpEwX4Zzeo/openapi.json
