# UK Cold Email PECR Checker — Companies House (`rudra_digital/pecr-gate`) Actor

Screen UK B2B leads against Companies House and identify leads confidently linked to active corporate subscribers. Conservative, evidence-backed results with no scraping or email sending.

- **URL**: https://apify.com/rudra\_digital/pecr-gate.md
- **Developed by:** [Rudra Digital](https://apify.com/rudra_digital) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$10.00 / 1,000 lead checkeds

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 Cold Email PECR Checker — Companies House

**PECR Gate** checks each UK business lead against the **Companies House register** and tells you, row by
row, whether the lead is **confidently linked to an active limited company, LLP or PLC** — the entity types
it confirms — or whether it has no confident register link (for example a sole trader, an unregistered
business or a dissolved company), or needs a human look.
Paste a lead list or a CSV link, get one **structured verdict per lead** with machine-readable reasons.
No scraping, no email sending, no director data.

### ✉️ Why this matters for UK cold email

Under UK **PECR**, the electronic-mail consent/soft-opt-in rule applies to **individual subscribers**,
including **sole traders and certain partnerships**. It does not apply to **corporate subscribers**, which
include **companies, LLPs and Scottish partnerships**. Corporate marketing emails must still **identify the
sender** and provide a **valid contact address for opting out**, and **UK GDPR** may apply where personal
data is used.

PECR Gate deliberately assesses a **narrower set of entity types**: it confirms only active limited
companies, LLPs and PLCs, and sends unsupported forms to **manual review** rather than making a legal
assumption.

Most B2B lead lists mix individual and corporate subscribers with no way to tell them apart. PECR Gate
answers the first question a UK sender needs answered: **is this lead an active company, LLP or PLC on the
register?**

### ✅ What you get for each lead

| Field | What it tells you |
|---|---|
| `verdict` | `CORPORATE_CONFIRMED` · `INDIVIDUAL_OR_UNINCORPORATED` · `NEEDS_REVIEW` |
| `recommended_action` | `PASS` · `DO_NOT_SEND_WITHOUT_CONSENT` · `MANUAL_REVIEW` |
| `reasons` | Codes you can filter on — e.g. `OK_CORPORATE_ACTIVE`, `NO_CH_MATCH`, `NON_CORPORATE_FORM`, `COMPANY_STATUS_UNCERTAIN`, `MULTIPLE_CANDIDATES`, `EMAIL_FREEMAIL_UNVERIFIABLE`, `COMPANY_NUMBER_NOT_FOUND`, `SNAPSHOT_STALE` |
| `company_number`, `registered_name`, `company_type`, `company_status` | The register record the verdict is based on, when one matched |
| `lookup_basis` | Whether the lead was matched by `company_number` or by `business_name` |
| `snapshot_date`, `snapshot_age_days` | **The date of the register data this verdict used**, on every row |
| `billable` | Whether this row is a charged check |

A run summary (`OUTPUT`) gives counts per verdict, the events billed, the data date, and the disclaimer.

### 🔒 Conservative by design

- **Exact matching only.** A near-miss company name never passes. No fuzzy matching, no guessing.
- **Fails closed.** No register match, several companies sharing a name, a company in liquidation or with
  a proposal to strike off, an unsupported company form — none of these can produce `CORPORATE_CONFIRMED`.
- **Honest abstention.** Forms PECR Gate does not confirm — including Scottish partnerships (corporate
  subscribers under PECR), companies limited by guarantee and CICs — return `NEEDS_REVIEW` with a specific
  reason, never a legal assumption either way.
- **Email sanity checks.** Malformed or truncated addresses are flagged. Freemail addresses (Gmail,
  Outlook…) on a confirmed company are marked for review, because we cannot verify who controls them. If
  you supply the lead's website, an own-domain email that contradicts it is flagged.

### 📥 Input

Provide **either** a JSON list **or** a public CSV URL. One row per lead:

| Column | Required | Notes |
|---|---|---|
| `business_name` | Yes, unless `company_number` is given | Trading or registered name |
| `company_number` | Optional | The fastest, most precise match. 8 characters (e.g. `01234567`, `SC123456`). Numbers that lost leading zeros in a spreadsheet are padded. An invalid number is flagged, never guessed, and **not charged** |
| `email` | Optional | Screened for malformed, truncated or freemail addresses |
| `postcode` / `locality` | Optional | Separates companies that share a name (not used when matching by company number) |
| `website` | Optional | Enables the email-domain check |

Blank cells are treated as empty. Optional setting: **maximum data age** (1–45 days) if you need fresher
data than the default 45-day limit.

```json
{
  "leads": [
    { "business_name": "Example Joinery Ltd", "email": "info@examplejoinery.co.uk",
      "postcode": "AB1 2CD", "website": "https://www.examplejoinery.co.uk" },
    { "company_number": "SC123456" },
    { "business_name": "J Smith Plumbing", "email": "jsmithplumbing@gmail.com" }
  ]
}
```

### 📤 Output example

```json
{
  "verdict": "CORPORATE_CONFIRMED",
  "recommended_action": "PASS",
  "reasons": ["OK_CORPORATE_ACTIVE"],
  "billable": true,
  "company_number": "01234567",
  "registered_name": "EXAMPLE JOINERY LIMITED",
  "company_type": "Private Limited Company",
  "company_status": "Active",
  "lookup_basis": "business_name",
  "snapshot_date": "2026-09-01",
  "snapshot_age_days": 13,
  "checked_at": "2026-09-14T10:00:00Z",
  "source": "snapshot",
  "product": "PECR Gate"
}
```

*(Illustrative values.)*

### 🗓️ Data source and freshness

- Data comes from Companies House's monthly **Basic Company Data** product, loaded into a private index and
  **refreshed every month**. Contains Companies House data © Crown copyright, reused under the
  [Open Government Licence v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/).
- **Every row tells you the date of the data it used.** If that data is older than 45 days (or your stricter
  limit), every row is returned as `MANUAL_REVIEW` with reason `SNAPSHOT_STALE`, and **nothing is charged**.
- The monthly file lists live companies. A company dissolved or struck off after the data date can still
  appear until the next refresh — which is why the date is on every row.
- PECR Gate is an independent service and is not affiliated with, endorsed by, or an official product of Companies House. Companies House data is used under the Open Government Licence.

### 💷 Pricing

**$0.01 per successfully checked lead** — 1,000 checked leads cost $10. Platform usage is included; there
is no separate compute charge.

You are **not charged** for:

- invalid rows or invalid company numbers;
- rows returned as `SNAPSHOT_STALE` because the data is too old;
- internal errors, or rows left unchecked when your maximum cost per run is reached;
- runs that fail before checking starts.

A completed check is charged whatever its verdict — including `NEEDS_REVIEW` rows with a specific finding
such as a company in liquidation, or several companies sharing a name — because the register was checked
and the answer is specific. Set a **maximum cost per run** in Apify to cap any run.

### 🤖 Automation and AI agents

Structured JSON in, structured verdicts out, with stable reason codes. Call it from the Apify API, a
schedule, an integration, or an AI agent's tool call, and filter on `recommended_action`. Runs take about
15–20 seconds to start while the register loads, then check leads almost instantly.

### ⚠️ What this Actor does not do

- It **does not tell you an email campaign is lawful.** `CORPORATE_CONFIRMED` confirms the legal-entity
  match only. It does not confirm that an email address belongs to, is controlled by, or is authorised by
  that company.
- It does **not** assess consent, soft opt-in, UK GDPR lawful basis, transparency notices, suppression
  lists, or the content of your emails. Responsibility for your campaign stays with you.
- It does **not** scrape websites, find email addresses, enrich contacts, send email, or return any
  director, officer or PSC data.
- It is **decision support, not legal advice.**

### ❓ FAQ

**Does `CORPORATE_CONFIRMED` mean I can email this lead?**
It means the lead matched an active limited company, LLP or PLC on the register — the corporate-subscriber
types PECR Gate confirms. PECR's consent/soft-opt-in rule for individual subscribers does not apply to
corporate subscribers, but your emails must still identify the sender and give a valid contact address for
opting out, UK GDPR may apply where personal data is used, and the rest of your campaign stays your
responsibility.

**Why is a lead with no register match `INDIVIDUAL_OR_UNINCORPORATED`?**
Sole traders and ordinary partnerships are not on the Companies House register, so a missing match is
treated as a reason for caution (`DO_NOT_SEND_WITHOUT_CONSENT`), never as a licence to send. It is the
conservative reading, not a legal finding: some businesses without a company record — such as Scottish
partnerships — are corporate subscribers, but PECR Gate cannot confirm that from the register.

**Why was a lead marked `NEEDS_REVIEW`?**
Every such row carries a reason — for example the company is in liquidation, several companies share the
name, the company form is outside what PECR Gate confirms, or the email domain contradicts the website.

**Should I use company numbers?**
If you have them, yes: a number identifies one company exactly. If you also supply a name that does not
match the registered name, the row is flagged for review rather than assumed to be the same company.

**Does Rudra Digital store my leads separately?**
No. PECR Gate does not copy your leads into a separate Rudra Digital customer database. Your input and
results are processed within the Apify run and stored in that run's Apify storage, subject to Apify's
applicable retention settings.

# Actor input Schema

## `leads` (type: `array`):

Paste lead rows. Each row needs business\_name or company\_number, plus optional email, postcode, locality, and website. Use this or a CSV URL, not both. Invalid or uncertain checks fail closed to manual review.

## `leads_csv_url` (type: `string`):

A public CSV URL with lead headers. Use this or Your lead list, not both; inaccessible files fail before checks or charges.

## `reverify_snapshot_older_than_days` (type: `integer`):

Optional stricter freshness budget, in days (default and maximum 45). If the Companies House snapshot is older than this, every row is returned as MANUAL\_REVIEW with reason SNAPSHOT\_STALE and is not charged.

## Actor input object example

```json
{
  "leads": [
    {
      "company_number": "00063230"
    }
  ]
}
```

# Actor output Schema

## `results` (type: `string`):

One row per input lead, in input order: verdict, recommended action, reason codes, matched register record, lookup basis, register data date and whether the row was a charged check.

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

Counts per verdict, billed lead-checked events, snapshot date and freshness, and the 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 = {
    "leads": [
        {
            "company_number": "00063230"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("rudra_digital/pecr-gate").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 = { "leads": [{ "company_number": "00063230" }] }

# Run the Actor and wait for it to finish
run = client.actor("rudra_digital/pecr-gate").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 '{
  "leads": [
    {
      "company_number": "00063230"
    }
  ]
}' |
apify call rudra_digital/pecr-gate --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rudra_digital/pecr-gate"
        }
    }
}
```

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/JPmM1clEh2Qab4YmQ/builds/SUi0gHrhTRF9Ddymt/openapi.json
