# EU Company Status Watch (`mikee368/eu-company-status-watch`) Actor

Watch French BODACC notices and UK Companies House for dissolution and insolvency-style status changes. Screening / public-register aid, not legal advice. Private.

- **URL**: https://apify.com/mikee368/eu-company-status-watch.md
- **Developed by:** [Mike Berckmoes](https://apify.com/mikee368) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$3.00 / 1,000 status changes

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

Watch **French BODACC** notices and **UK Companies House** for dissolution and insolvency-style status changes. France uses the free BODACC open-data API (no key). The UK uses the Companies House streaming API and an ETag profile check when you supply your own free API key.

This Actor is a **screening / public-register aid, not legal advice**. It does not replace a bailiff, an insolvency practitioner, or an official Companies House filing search.

### What does EU Company Status Watch do?

It re-checks a list of French and UK companies and writes **one row when a watched status appears or changes**.

1. You pass companies (`name`, `number`, `country`) and a `watchlistId`.
2. France is read from [BODACC annonces commerciales](https://bodacc-datadila.opendatasoft.com/api/explore/v2.1/catalog/datasets/annonces-commerciales/records). A saved ETag sends `If-None-Match` on the next run.
3. The UK, when `companiesHouseApiKey` is set, reads the [Companies House streaming API](https://stream.companieshouse.gov.uk/companies) for at most **90 seconds** (default **75**, inside the 60–90 second window), saves the stream **timepoint**, then ETag-checks `GET /company/{number}` for any GB company the stream did not already update.
4. The **first baseline** for a company is stored and is **not charged**. A later fingerprint change (notice id or `company_status`) is a `status-change` event.

Unchanged re-checks, error rows and not-found rows are **not charged**.

### Why use EU Company Status Watch?

- One scheduled run covers a French SIREN list and, with your own key, a UK company-number list.
- Daily re-checks that see the same notice or the same Companies House status finish without a `status-change` charge.
- The company cap (`maxCompanies`, default 50) is repeated in the run status message, so a long list cannot silently grow the bill.
- The run uses **256 MB**. The Companies House stream stops at the cap and resumes from the saved timepoint.
- Schedule it, call it from the Apify API, or download the dataset as JSON, CSV, Excel or HTML.

### What data can EU Company Status Watch extract?

| Field | Meaning |
|---|---|
| `source` | `FR_BODACC` or `UK_COMPANIES_HOUSE` |
| `status` | Normalised: `dissolved`, `insolvency`, `liquidation`, `notFound`, `error`, … |
| `statusDetail` | Raw BODACC nature or Companies House `company_status` |
| `noticeId` | BODACC publication number or stream timepoint |
| `eventType` | `first-seen` (free baseline), `status-change` (charged), `notFound` or `error` |
| `charged` | `true` only for a `status-change` row |
| `disclaimer` | Repeated on every row |

### How to watch a company

1. Open the Actor and add companies in **Companies to watch**. Use `FR` with a SIREN, or `GB` with a company number.
2. For UK companies, paste your free Companies House API key. Without it, GB companies are skipped and the run still finishes.
3. Set **Watchlist ID** to a stable name if you have more than one schedule. Leave **Max companies per run** at 50 unless the list is shorter.
4. Start the run. The first baseline is free. Later changes show up as `status-change` rows.
5. Schedule the saved task on weekday mornings. A 304 or an identical fingerprint should finish in a few seconds.

### How much does a status change cost?

Pricing is pay per event. The event name is **`status-change`** and the price is **$0.003 per changed row**.

- The **first baseline** for a company is free.
- An **unchanged** re-check is free and is not written again while **Only new** is on.
- An **error** row and a **notFound** row are free.
- There is no charge for starting the Actor. Platform compute is separate and the run is pinned to **256 MB**.

`maxCompanies` (default 50, maximum 200) is the per-run cap. The status message names that cap and how many companies were actually watched. `maxItems` caps how many rows are pushed.

### Input

See the **Input** tab for the full schema.

```json
{
  "companies": [
    {"name": "RENAULT", "number": "780129987", "country": "FR"},
    {"name": "Example Ltd", "number": "00445790", "country": "GB"}
  ],
  "companiesHouseApiKey": "YOUR_FREE_KEY",
  "watchlistId": "crm-eu",
  "onlyNew": true,
  "mode": "status-change",
  "lookbackDays": 14,
  "maxCompanies": 50,
  "maxItems": 50,
  "maxStreamSeconds": 75
}
```

`maxStreamSeconds` defaults to 75 and cannot go above 90. The latest Companies House timepoint is saved on the watchlist so the next run continues.

### Output

You can download the dataset in JSON, HTML, CSV or Excel.

```json
{
  "source": "FR_BODACC",
  "country": "FR",
  "name": "RENAULT",
  "registrationNumber": "780129987",
  "status": "liquidation",
  "eventType": "first-seen",
  "charged": false,
  "noticeId": "BXA2026001"
}
```

A later notice for the same company is `eventType: "status-change"` and `charged: true`.

### Tips

- Keep one `watchlistId` per schedule. **Reset watchlist state** drops stored ETags, timepoints and seen notices for that id.
- Leave the Companies House stream at the default. It stops inside 60–90 seconds and the timepoint is stored.
- A long company list should stay within `maxCompanies`. The status message reports the cap when the run ends.

### FAQ, disclaimers and support

Official BODACC and Companies House records can name people involved in a proceeding. This Actor copies public register fields only. It does not collect private account data, and it is not a credit rating.

Personal data is protected by the GDPR in the European Union and by other laws elsewhere. Use the rows as a screening aid when you have a legitimate reason to look up a company you already hold. If you are unsure, ask your lawyers.

Questions and bugs belong on the **Issues** tab. Programmatic runs use the **API** tab.

### Sources and terms

- BODACC / DILA open data, Licence Ouverte. No key.
- Companies House REST and streaming API: free key, Open Government Licence, rate limits. You bring the key.

# Actor input Schema

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

List of companies as strings (name or number) or objects with name, number / siren / companyNumber, and country (FR or GB). France uses BODACC (no key). The UK uses Companies House when companiesHouseApiKey is set.

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

Free UK Companies House key (same as eu-company-register-lookup). Required to watch GB company numbers via the streaming API and ETag profile checks. Stored as a secret; never logged.

## `watchlistId` (type: `string`):

Named KV state key so several schedules can keep separate seen-notice / ETag / timepoint maps.

## `onlyNew` (type: `boolean`):

On by default. Unchanged re-checks are not pushed and not charged. The first baseline for a company is free either way. Only a later status change is charged.

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

status-change (default): emit when the stored fingerprint (notice id or company_status) changes. first-seen: emit the first watch-worthy event per company, then only changes.

## `lookbackDays` (type: `integer`):

How far back to query BODACC on each run. State still de-duplicates by notice id.

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

Per-run cap. Extra companies are left for a later run and counted in the status message. The run stops at this many companies even if the list is longer.

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

Cap on pushed rows. Only a status-change row is charged. The free baseline, unchanged re-checks, errors and not-found rows are not.

## `maxStreamSeconds` (type: `integer`):

How long to read the Companies House streaming API before saving the timepoint and falling back to ETag profile checks. The hard cap is 90 seconds. The default, 75, sits in the 60–90 second window.

## `resetState` (type: `boolean`):

Drop stored ETags, timepoints and seen notice ids for this watchlistId.

## Actor input object example

```json
{
  "companies": [
    {
      "name": "Example SAS",
      "number": "552032534",
      "country": "FR"
    }
  ],
  "watchlistId": "default",
  "onlyNew": true,
  "mode": "status-change",
  "lookbackDays": 14,
  "maxCompanies": 50,
  "maxItems": 50,
  "maxStreamSeconds": 75,
  "resetState": false
}
```

# Actor output Schema

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

Dataset with one row per change

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

Counts, sources and the screening disclaimer

# 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 SAS",
            "number": "552032534",
            "country": "FR"
        }
    ],
    "watchlistId": "default"
};

// Run the Actor and wait for it to finish
const run = await client.actor("mikee368/eu-company-status-watch").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 SAS",
            "number": "552032534",
            "country": "FR",
        }],
    "watchlistId": "default",
}

# Run the Actor and wait for it to finish
run = client.actor("mikee368/eu-company-status-watch").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 SAS",
      "number": "552032534",
      "country": "FR"
    }
  ],
  "watchlistId": "default"
}' |
apify call mikee368/eu-company-status-watch --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mikee368/eu-company-status-watch"
        }
    }
}
```

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/Ar1vh4zSxKJ4b3Agd/builds/99rkGAHWMvHa3IPL3/openapi.json
