# Scotland Care Inspectorate Care Service Portfolio Monitor (`plym-actor-factory/uk-scotland-care-inspectorate-cs-number-status-monitor`) Actor

Watch named Scottish care services by Care Inspectorate CS number; get an event on cancellation, provider change, grade downgrade, enforcement or upheld complaint, from official Care Inspectorate open data. Pay per delivered change - not a directory dump.

- **URL**: https://apify.com/plym-actor-factory/uk-scotland-care-inspectorate-cs-number-status-monitor.md
- **Developed by:** [Daniel Witney](https://apify.com/plym-actor-factory) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 scotland care service event delivereds

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

## Scotland Care Inspectorate Care Service Portfolio Monitor

Watch named **Scottish registered care services by Care Inspectorate service number (CS##########)** against the official **Care Inspectorate care service directory** and its monthly **Care Services Open Datastore**. Get one event when a service on your list is **cancelled or goes inactive, changes provider, has its quality grades downgraded, receives an enforcement or has a complaint upheld**.

**Quick start:** replace the example `csNumbers` with your services, set `sourceMode` = **live**, then save as a Task and schedule it daily or weekly. No API key needed.

**Who this is for:**

- **Local authority and HSCP commissioners and contract managers** (care homes, care at home, housing support, and funded early learning and childcare providers, which must meet the National Standard of grades of good or better)
- **Care home groups, operators, investors and lenders** watching their own estate or acquisition targets
- **Insurers and brokers** covering care providers
- **Placement teams, care-finding and nursery-finder platforms** that badge services as active or well graded

The recurring job: **tell me when a service on my contract or portfolio list is cancelled, changes hands, drops below "good", or receives an enforcement or an upheld complaint**, without re-downloading and diffing the Care Inspectorate files every month.

Billable events (PPE `scotland-care-service-event-delivered` @ $0.02):

| Group | Event | Meaning |
|-------|-------|---------|
| `status` | `STATUS_CHANGED` | Active ↔ Inactive / Cancelled (`adverse=true` unless the new status is Active) |
| `provider` | `PROVIDER_CHANGED` | Provider ID or provider name changed (change of ownership or rebrand) |
| `grades` | `GRADE_CHANGED` | Any key-question grade (1 Unsatisfactory to 6 Excellent) or the minimum grade changed: `GRADE_DOWNGRADE` / `GRADE_UPGRADE` / `GRADE_REVISED` |
| `enforcement` | `ENFORCEMENT_ISSUED` | Datastore count of enforcements issued rose for a financial year |
| `complaints` | `COMPLAINT_UPHELD` | Datastore count of upheld complaints rose for a financial year |
| `directory` | `APPEARED` / `DROPPED` | Service number appeared in, or disappeared from, the directory download |
| `inspections` (opt-in) | `INSPECTION_RECORDED` | Last inspection date changed |
| `attributes` (opt-in) | `NAME_CHANGED` | Service name changed |

Non-billable: `RUN_STATUS` (`FIXTURE_HEALTH`, `MONITOR_IDLE`, `CATCHUP_COMPLETE`, `HEALTH_OK`), first-run baselines and duplicates. A quiet watchlist costs only the platform start fee.

This is **not** a dump of the directory billed per row. It does not read inspection report text. Manager names, emails and phone numbers are never included in the output.

### First run vs later runs

Default `sourceMode=fixture` is a **free health check**: one non-billable `RUN_STATUS` row, not product data.

In live mode, **run 1** stores a baseline for each service (no change events, no product charge). **Run 2 onwards** emits only the differences against that checkpoint. Keep using the same Task so the checkpoint carries over.

### What you get per $0.02 event

Each event is one unique change for a named service. It includes the service name, type, status, provider, minimum grade, an `adverse` flag, before and after values (all key-question grades for a grade change), the effective date, the datastore month and the official source URL. You are never charged for `RUN_STATUS`, baselines, quiet `MONITOR_IDLE` runs, invalid numbers, duplicates or fixture SAMPLE rows.

### Example output (SAMPLE)

SAMPLE: illustrative field shape only, not a real event.

```json
{
  "cs_number": "SAMPLE01",
  "service_name": "EXAMPLE CARE HOME A (SAMPLE)",
  "event_type": "GRADE_CHANGED",
  "event_subtype": "GRADE_DOWNGRADE",
  "previous_value": "min 4 (Good)",
  "new_value": "min 2 (Weak)",
  "adverse": true,
  "datastore_as_of": "2026-08-31",
  "billable": false,
  "sample": true,
  "summary": "SAMPLE (fixture demo data with placeholder entities, not a real event)"
}
```

### Input

- `csNumbers`: Care Inspectorate service numbers, for example `CS2003000168` (the CS prefix is optional). Aliases: `serviceNumbers`, `caseNumbers`.
- `sourceMode`: `fixture` (free health check) or `live` (official Care Inspectorate open data)
- `signalGroups`: any of `directory`, `status`, `provider`, `grades`, `enforcement`, `complaints`, `inspections`, `attributes` (default: the first six)

### Production use

```json
{
  "csNumbers": ["CS2003000168", "CS2003000237", "CS2003001774"],
  "sourceMode": "live",
  "signalGroups": ["directory", "status", "provider", "grades", "enforcement", "complaints"]
}
```

### Source and honesty notes

- **Status and provider:** the official care service directory CSV (`careinspectorate.scot/care-services/directory/download`), read at run time. On 2026-10-06 it held 40,616 unique CS numbers: 10,356 Active, 142 Inactive and 30,118 Cancelled.
- **Grades, enforcements, complaints and last inspection:** the monthly Care Services Open Datastore CSV. The newest month is found automatically from the datastore page. It covers about 10,500 active and inactive services and is usually published one to four weeks after month end, so these events lag the Care Inspectorate's own publication.
- If the datastore cannot be read in a run, status and provider monitoring still runs and the earlier grades are carried forward. The `RUN_STATUS` row records a warning when this happens.
- Durable key: CS number (`CS` followed by 10 digits).
- Licence and attribution: Care Inspectorate (Scotland) open data under the Open Government Licence v3.0. This Actor is not affiliated with or endorsed by the Care Inspectorate.

### Pricing

| Event | USD |
|-------|-----|
| `scotland-care-service-event-delivered` | $0.02 |
| `apify-actor-start` | $0.00005 |

### Limitations

- Check the service's page and latest inspection report on careinspectorate.scot before making contract, funding or placement decisions.
- Counts of enforcements and upheld complaints come from the datastore by financial year. The Actor reports increases; it does not include the enforcement or complaint text.
- Cancelled services normally stay in the directory with status Cancelled. `DROPPED` fires only if a number disappears from the download entirely.
- Covers Scotland only (England is regulated by CQC and Ofsted, Wales by CIW).

# Actor input Schema

## `csNumbers` (type: `array`):

Care Inspectorate service numbers to watch, e.g. CS2003000168 (the CS prefix is optional; 10 digits). Shown on each service page at careinspectorate.scot.

## `serviceNumbers` (type: `array`):

Optional alias merged into the watchlist.

## `caseNumbers` (type: `array`):

Optional alias merged into the watchlist (the directory calls the CS number 'Case Number').

## `signalGroups` (type: `array`):

directory (APPEARED/DROPPED), status (STATUS_CHANGED Active / Inactive / Cancelled), provider (PROVIDER_CHANGED — new provider ID or name), grades (GRADE_CHANGED per key question, 1-6), enforcement (ENFORCEMENT_ISSUED), complaints (COMPLAINT_UPHELD), inspections (INSPECTION_RECORDED, opt-in), attributes (NAME_CHANGED, opt-in). Default: directory+status+provider+grades+enforcement+complaints.

## `maxRunSeconds` (type: `integer`):

Wall-clock budget.

## `maxEvents` (type: `integer`):

Stop after this many unique change events are delivered (RUN_STATUS excluded).

## `resumeFromCheckpoint` (type: `boolean`):

If true, resume service snapshots and seen event_uids from the default Key-Value Store (keep the same Task).

## `sourceMode` (type: `string`):

fixture = free Store/CI health check (no network; one non-billable RUN_STATUS row unless emitFixtureDemoEvents=true). live = official Care Inspectorate directory CSV + monthly Open Datastore CSV (no API key). Fixture demo rows use placeholder entities, are flagged sample=true / isSample=true, billable=false, and are never charged.

## `emitFixtureDemoEvents` (type: `boolean`):

When sourceMode=fixture, emit SAMPLE demo events from local fixtures (placeholder services, never charged). Default false.

## `maxTotalChargeUsd` (type: `number`):

Optional soft budget hint.

## `asOfHint` (type: `string`):

Optional as_of label (defaults to the fetch date).

## `directoryCsvUrl` (type: `string`):

Optional override for the official care service directory CSV download.

## `datastoreCsvUrl` (type: `string`):

Optional override for the monthly Open Datastore CSV (otherwise the newest month is discovered from the datastore page).

## Actor input object example

```json
{
  "csNumbers": [
    "CS2003000168",
    "CS2003000237",
    "CS2003001774",
    "CS2014330627"
  ],
  "signalGroups": [
    "directory",
    "status",
    "provider",
    "grades",
    "enforcement",
    "complaints"
  ],
  "maxRunSeconds": 180,
  "maxEvents": 500,
  "resumeFromCheckpoint": true,
  "sourceMode": "fixture",
  "emitFixtureDemoEvents": false
}
```

# Actor output Schema

## `OUTPUT` (type: `string`):

JSON summary: delivered, charged, runStatus, checkpoint, stats, coverage, attribution

# 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 = {
    "csNumbers": [
        "CS2003000168",
        "CS2003000237",
        "CS2003001774",
        "CS2014330627"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("plym-actor-factory/uk-scotland-care-inspectorate-cs-number-status-monitor").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 = { "csNumbers": [
        "CS2003000168",
        "CS2003000237",
        "CS2003001774",
        "CS2014330627",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("plym-actor-factory/uk-scotland-care-inspectorate-cs-number-status-monitor").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 '{
  "csNumbers": [
    "CS2003000168",
    "CS2003000237",
    "CS2003001774",
    "CS2014330627"
  ]
}' |
apify call plym-actor-factory/uk-scotland-care-inspectorate-cs-number-status-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,plym-actor-factory/uk-scotland-care-inspectorate-cs-number-status-monitor"
        }
    }
}
```

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/ELF6aKIkbcDvT2Lqd/builds/j8t5sggtJAQ9Sc96e/openapi.json
