# GB Biocide Article 95 Supplier Change Signals (`starshaped_bullsnake/gb-biocide-article-95-supplier-change-signals`) Actor

Monitor official HSE GB Article 95 supplier-state changes with a persistent full snapshot.

- **URL**: https://apify.com/starshaped\_bullsnake/gb-biocide-article-95-supplier-change-signals.md
- **Developed by:** [Starshape Tools](https://apify.com/starshaped_bullsnake) (community)
- **Categories:** Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $50.00 / 1,000 gb article 95 supplier change signals

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

## GB Biocide Article 95 Supplier Change Signals

Monitors the Health and Safety Executive's official GB Article 95 workbook and emits machine-readable changes affecting biocide supplier status, regulatory procurement monitoring, and market-access risk. HSE states that the official source is updated regularly.

This is a stateful change-signals Actor rather than a directory export. A first valid live run creates a zero-signal baseline. Later runs compare the complete official workbook with a persistent snapshot and emit only detected changes. An identical workbook emits no signals.

### Signals

- `ENTRY_ADDED`: a previously unseen stable identity first appears as active.
- `ENTRY_SUSPENDED`: an active identity moves to the suspended worksheet.
- `ENTRY_RESTORED`: a suspended identity returns to active.
- `ENTRY_REMOVED`: a previously active or suspended identity disappears from current state and has new matching evidence in removed history.
- `ENTRY_REINSTATED`: an identity with previously observed removal history becomes active.
- `ENTRY_DETAILS_CHANGED`: meaningful non-key attributes change for the same identity and current state, including supplier-role changes.

Disappearance from ACTIVE or SUSPENDED alone never produces `ENTRY_REMOVED`. Unexplained missing identities are retained internally. A material unexplained-missing burst fails closed and retains the previous snapshot.

### Stable identity and source handling

The stable identity is the SHA-256 representation of these normalized source fields:

1. the complete active-substance-name cell;
2. the deterministic sorted set of every CAS identifier;
3. the deterministic sorted set of every EC identifier;
4. Product Type, including an explicit null for genuine blanks; and
5. company name.

Supplier type, reasons, and dates are attributes, not identity fields. Supplier roles are represented as a deterministic set. The Actor does not use fuzzy company matching, infer company renames, forward-fill Product Type, or use worksheet row positions as identity.

The parser reads actual populated worksheet rows rather than relying on Excel Table boundaries. This matters because the observed `Removed entries` worksheet contains valid data below its formal Table range. Literal duplicate public source rows are normalized without creating business signals.

Expected worksheets and headers are validated before comparison. Production acquisition also rejects clearly collapsed parses below internal safety floors of 1,000 ACTIVE rows and 1,500 REMOVED rows; SUSPENDED has no positive minimum because it can legitimately reach zero. A material unresolved-missing anomaly requires both at least 25 identities and at least 2% of the previous current-state population. Fetch, workbook, schema, state, identity, anomaly, Dataset, or output-summary failure prevents snapshot advancement.

`maxItems` limits Dataset output only. It never truncates source acquisition, diffing, removal history, or the persisted snapshot.

### Modes

- `live` discovers the current XLSX link from the official HSE landing page, validates the entire workbook, compares state, writes signals and `OUTPUT`, then commits the snapshot last.
- `sample` runs deterministic transition fixtures through the real normalize and diff logic. It performs no HSE request and never opens the production key-value store.

The sample demonstrates all six signal types. It is suitable for the example run without modifying the live baseline.

### Source and reuse

Source: [The GB Article 95 List — HSE](https://www.hse.gov.uk/biocides/active-substances/uk-article-95-list.htm).

Contains public sector information published by the Health and Safety Executive and licensed under the [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/). Open Government Licence exclusions and third-party rights may apply. No endorsement is implied, and the HSE logo is not used.

# Actor input Schema

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

Compare the live official workbook or run an isolated deterministic sample.

## `signalTypes` (type: `array`):

Optional signal-type filter. The full snapshot is always maintained.

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

Optional case-insensitive company-name substring filters.

## `productTypes` (type: `array`):

Optional exact normalized product-type filters.

## `baselineOnly` (type: `boolean`):

Refresh a valid baseline without emitting business signals.

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

Limits Dataset output only; source acquisition and snapshots remain complete.

## Actor input object example

```json
{
  "mode": "live",
  "baselineOnly": false,
  "maxItems": 1000
}
```

# Actor output Schema

## `summary` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("starshaped_bullsnake/gb-biocide-article-95-supplier-change-signals").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("starshaped_bullsnake/gb-biocide-article-95-supplier-change-signals").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 '{}' |
apify call starshaped_bullsnake/gb-biocide-article-95-supplier-change-signals --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,starshaped_bullsnake/gb-biocide-article-95-supplier-change-signals"
        }
    }
}
```

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/xpDM9SdMtREPwTeDp/builds/JYV8CgKBiYfPhFQ7y/openapi.json
