# UK Designated Standards & Withdrawal Date Monitor (`thatmike1/uk-designated-standards`) Actor

Check Great Britain low-voltage designated standards, amendment groups, restrictions and withdrawal dates from GOV.UK. Export dated observations and optional changes. Workbook metadata only; unchanged successful checks are billed.

- **URL**: https://apify.com/thatmike1/uk-designated-standards.md
- **Developed by:** [Michal Pšenčík](https://apify.com/thatmike1) (community)
- **Categories:** Business, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.00005 / actor start

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

## UK Designated Standards & Withdrawal Date Monitor

An HTTP-only Apify actor for exact reference checks in the GOV.UK consolidated low-voltage workbook. It covers Great Britain (England, Scotland and Wales) under the Electrical Equipment (Safety) Regulations 2016. Each stored observation contains every matching amendment bundle, dates, notices, restrictions/informative notes and provenance. Unchanged successful checks are useful dated receipts and are billed.

```json
{
    "references": ["EN 50214:2006", "EN IEC 60335-2-11:2022", "EN 50620:2017"],
    "watchName": null,
    "maxRows": 100,
    "requestIntervalMs": 1500
}
```

Use a complete edition/amendment token, never a prefix or search query. References normalize to NFC, uppercase and collapsed whitespace (including NBSP); punctuation and edition years remain. Duplicate normalized inputs receive free SUMMARY outcomes. Unknown keys, controls, URLs and comma-separated input bundles are rejected. The Store default is `EN 50214:2006` alone.

The default dataset contains one complete paid observation per unique matched token, with all matching groups sorted by stable group ID. It includes ended and upcoming groups. It never contains errors, summaries or blank checks. `SUMMARY` and `OUTPUT` in the default key-value store contain free run receipts, every input outcome, duplicates, exact `unattemptedIndexes`, limits, attempts and errors. A no-match is `not_found_in_current_workbook`, never a removal/deletion claim. Explicitly resubmit unattempted references after a cap; there is no cursor.

Public identity contract, version 1: hashes are lowercase SHA256 of UTF-8 canonical JSON (object keys recursively sorted in Unicode codepoint order, no extra whitespace or ASCII escaping, arrays in the stated order). `checkId` hashes `{jurisdiction:"GB",legislationKey:"low-voltage",reference:normalizedReference,normalizationVersion:1}`; `recordId` hashes `{runId,checkId}`. A `groupId` hashes `{jurisdiction:"GB",legislationReference:normalizedLegislation,standardReferences:sortedUniqueTokens}`. `semanticHash` hashes `{matches:semanticGroups,sourceContextText}`; semantic groups omit `sheet` and `rowNumber`. Matches sort by groupId; tokens sort after normalization. `source.documentSha256` hashes the original ODS bytes. Date cells parse strictly from DD/MM/YYYY to Gregorian YYYY-MM-DD, preserving the raw cells and published page-update offset.

Set `watchName` (case-sensitive, 1–64 ASCII letters/digits/underscore/hyphen) to compare confirmed observations with a named watch. Its name is `uk-designated-v1-<first 40 hex characters of SHA256(watchName)>` (57 characters, within Apify's 63-character limit). The manifest retains up to 1,000 identities with no eviction. First checks are `new`; subsequent full receipts are `unchanged`, `timestamp_only` for provenance changes, or `revised` with complete previous semantic values. Row locations and observation time are excluded from semantic hashes. Clearing/correcting dates is a revision; the passage of time alone is not.

Serialize schedules sharing a watch. Serialize owner schedules that share the persisted source-deferral policy; that owner-wide KV record has no transactional update or distributed request queue. The bounded lease detects overlaps but KV has no transactional compare-and-swap, so simultaneous undetectable starts remain unsupported. Same-run checkpoints retain source stops/deferrals, operation reservations and delivery intents. A restart reads the exact record receipt before any further delivery and commits it only if newer than the baseline. Interrupted source discovery fails closed; start a new run. One bounded recovery admission is allowed per run; another interrupted recovery requires a new run. Delivery is at least once across runs; a crash can repeat an observation. Uncertain pushes stop delivery, and are never automatically repushed.

The content API discovers exactly one consolidated ODS; the actor then downloads and parses it once, before any delivery. There are normally two source requests. All requests, redirects and retries pass through `src/http.ts`: one in flight, at least two seconds between starts on a host (or the larger requested interval), public DNS pinned to the connection, approved HTTPS routes only, no proxy/login/browser. Blocks, challenge HTML and 429 stop immediately. Transient errors get at most two retries (2s/5s); Retry-After deferrals persist across runs. PDF notices are linked, never fetched or reconciled.

Hard bounds: 100 inputs, 100 useful rows, 12 attempts, 8 MiB response traffic, 120s work plus up to 30s persistence grace; JSON 1 MiB, compressed ODS 2 MiB, ZIP 20 entries/16 MiB inflated/100:1 expansion, content XML 12 MiB, 10,000 nonempty data rows, ten columns. Standard-reference cells are capped at 256 KiB before tokenization; larger cells fail explicitly. DTD/entities, encrypted/unsafe ZIPs, changed layouts and conflicting duplicate bundles fail explicitly. Each complete check/snapshot is at most 256 KiB and each check has 1–20 groups; oversized results receive free diagnostics, never truncation.

The ODS reader supports text/string cells and calendar-date cells. Typed strings are preserved and checked against display text when present. Typed dates must agree with a DD/MM/YYYY display; a missing display, non-midnight time, timezone, unknown type, numeric/boolean/time cell, formula or inconsistent typed value fails the entire source as `unsupported_layout`. Annotations, unrecognized cell content and data-cell merges also fail explicitly. The known preamble merge and empty repeated padding are supported; covered cells must belong to that merge. Source failures deliver no observations and leave watch baselines unchanged.

Persistence is bounded to 105 KV reads/writes, 100 dataset reads/writes and 16 MiB internal traffic. Reads, lease verification, checkpoints and cleanup all consume that allowance. Named watches deliver at most 50 checks, usually fewer because of these additional safety operations and conservative read reservations. Stateless delivery can also stop before maxRows because readback/metadata and checkpoint operations consume the same budget. On the checked v13 fixture, 100 matched references delivered 93 stateless checks or 17 named-watch checks before storage limits. Extra retries, recovery and larger results can reduce these counts. Check the free receipt for exact remaining inputs. Storage capacity and spending are checked before every irreversible push; dataset readback determines delivery, never chargedCount.

Recommended run settings: **512 MB memory and a 150-second timeout**. Local stress measurements peaked at 222.2 MiB RSS; the provisional 256 MB setting does not provide the required 30% headroom. Hosted runtime and costs still require verification.

Pricing is $0.003 per complete stored watched-token check (all groups, including unchanged) plus the platform's $0.00005 start event per allocated-memory unit. One successful check at 512 MB is $0.00305 in event fees (one start unit). Failed/unmatched checks have no item fee; all-failure runs can incur the start fee. There is no free-first-ten allowance or manual event. Console/platform billing and costs still need prepublication verification.

These are workbook observations, not legal authority, certification or a compliance verdict. There is no EU comparison or Northern Ireland coverage. Every row warns `summary_not_legal_authority`, `pdf_not_reconciled` and `known_ods_pdf_corrigendum_discrepancy`. The ODS and notice 0120/25 differ over the EN 60335-2-27:2013 AC:2021-11 bundle; both ODS groups remain as published. The page caveat about the unadopted EN 60335-1:2012 restriction is preserved. Historical notice coverage is incomplete; missing notice IDs do not have invented URLs. Commercial standards-body withdrawal dates are not used.

Sources: [publication](https://www.gov.uk/government/publications/designated-standards-low-voltage), [content API](https://www.gov.uk/api/content/government/publications/designated-standards-low-voltage). Only public factual metadata is emitted; publisher contact emails are excluded. If users later introduce personal data into downstream workflows, they are responsible for their controller obligations. No paid normative standards text is downloaded.

The ODS reader also enforces one cumulative workbook budget of 16 Mi UTF-16 units: decoded cell text/attributes, expanded spaces, repeated retained values and worksheet names, tokenization, tags, cell slots and groups all consume it. Space counts are reserved before string construction; ignored/blank/duplicate content is never refunded. Conservative structural costs can reject a workbook before its raw size limit. XML depth is capped at 64 and each tag at 128 attributes. Empty row/column repeats use counters and at most ten cell slots; nonempty repeated rows, unsupported spans and orphan covered cells fail explicitly. Custom entities/DTDs are forbidden. An exceeded budget produces `result_too_large` in a failed free SUMMARY/OUTPUT, no observations and no watch-baseline changes; the actor exits nonzero. The current 818-group workbook fits with wide margin.

# Actor input Schema

## `references` (type: `array`):

1–100 full edition/amendment tokens. Exact matches only. Duplicates are free; example EN 50214:2006.

## `watchName` (type: `string`):

Case-sensitive letters, digits, underscores and hyphens, 1–64 characters. Serialize runs using the same namespace; no eviction of its 1000 identities.

## `maxRows` (type: `integer`):

Spending, read/write, traffic and deadline limits can reduce delivery. Resubmit SUMMARY unattemptedIndexes explicitly.

## `requestIntervalMs` (type: `integer`):

Minimum per-host interval; this build also enforces a 2000 ms courtesy floor.

## Actor input object example

```json
{
  "references": [
    "EN 50214:2006"
  ],
  "maxRows": 100,
  "requestIntervalMs": 1500
}
```

# Actor output Schema

## `checks` (type: `string`):

No description

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

No description

## `output` (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 = {
    "references": [
        "EN 50214:2006"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("thatmike1/uk-designated-standards").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 = { "references": ["EN 50214:2006"] }

# Run the Actor and wait for it to finish
run = client.actor("thatmike1/uk-designated-standards").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 '{
  "references": [
    "EN 50214:2006"
  ]
}' |
apify call thatmike1/uk-designated-standards --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,thatmike1/uk-designated-standards"
        }
    }
}
```

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/olzBWITzcTwYWNDAp/builds/4uHh4ekdFTRRgLoiX/openapi.json
