Precleared

Checks whether a cold email to one address is allowed in the recipient's country before an agent sends it: a verdict, the rule with its legal source, what the footer must include and a signed receipt. Covers the UK, US, Canada, Germany, France, Australia, Ireland and the Netherlands. Free daily allowance, no sign-in.

Documentation

Precleared

Docs Rules Guides Accuracy Get a key

Docs

Contact Check

One call per address. The answer comes back with the rule quoted and a signed receipt.

It sits between the step that finds an address (Hunter, Apollo, Clay) and the step that sends (Gmail, Outlook, Instantly, lemlist). One call per new contact, before the first email. It is not needed for invoices, receipts or other transactional email.

Covers the UK, US, Canada, Germany, France, Australia, Ireland and the Netherlands: UK PECR, US CAN-SPAM, Canadian CASL, German UWG, French CNIL rules, Australia's Spam Act 2003, Ireland's S.I. 336/2011 and the Dutch Telecommunicatiewet.

Australia: the Spam Act lets consent be inferred from a conspicuously published work address when the pitch is relevant to the role, so pass pitch_relevant. Ireland: email to a company mailbox is allowed until the company objects, and a named work address needs a pitch that relates solely to the person's business. Netherlands: prior consent is required for companies as well as people, so only existing customers come back ok_to_email.

Recipes

Step-by-step setups for checking every lead before it reaches your sequencer: all recipes, for Clay, Make, Zapier and n8n, or straight into Instantly, Smartlead, lemlist or Apollo.

Quick start

1. Get a free key. You can also call without one, with a smaller daily allowance.

2. Send the address, who you are and where you got it.

curl https://precleared.dev/api/v1/check \
  -H "Authorization: Bearer pc_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "recipient_email": "jane@acme.co.uk",
    "sender_country": "GB",
    "pitch": "Bookkeeping software for small firms",
    "address_source": "published",
    "company_number": "01234567"
  }'

Note: Python's built-in urllib is refused by our hosting's bot filter. Use requests or httpx, or set a User-Agent header.

Request fields

recipient_email or recipient_domain (one is required), sender_country (GB or US, default GB), pitch, address_source (published, bought, scraped, given or unknown; default unknown), recipient_country (two letters), default_recipient_country (two letters, used only when the country can't be worked out; recipient_country always wins), company_number, pitch_relevant, existing_customer (default false), suppressed.

How the country is worked out

  1. recipient_country, if you send it.
  2. The domain's country code, such as .co.uk or .ca.
  3. Companies House: a UK company number found means GB.
  4. The company's website: US and Canadian office addresses are read. If the site shows more than one country, none is assumed.
  5. default_recipient_country, if you send it.
  6. Otherwise the country is unknown.

Response fields

verdict

ok_to_email, consent_needed, blocked or unknown.

confidence

high, medium or low. Medium usually means the legal form came from the website, not the register. When a site shows no company number, Precleared searches Companies House by name and only accepts a match backed by the website or a named officer; those verdicts say legal_form_source "companies_house_search" and carry one step lower confidence.

reasons

The rule that matched, with its text and source, followed by any notes.

rules_applied

The rule keys used. Look them up on /rules.

footer_text

What the email's footer must include when the rule sets requirements, for example who you are, a postal address and a way to opt out. Write your footer to meet it; it is not wording to paste.

next_step

What to do next, in one line.

facts

What we found: masked address, domain, country and where it came from, legal form and its source, company number, name and status, director first name, address type, syntax, mailbox record, disposable and suppressed flags. legal_form_source is unavailable when Companies House could not be searched by name. The UK verdict is unknown: check again in a few minutes, or pass company_number.

receipt

Receipt id, time, request and response hashes, Ed25519 signature, key version and a verify URL.

rules_version

The version of the rule set used. It is also in the receipt.

usage

free_remaining_today and credits_remaining for the caller.

disclaimer

A fixed line. Decision support with sources, not legal advice.

Errors

Every error is JSON with an error code and a plain message.

  • 400 The body is not valid. The message says which field.
  • 401 The key is wrong or has been revoked.
  • 402 payment_required. Today's free checks are used and there are no credits. The body has buy_url, which opens checkout for that key.
  • 429 daily_limit. Keyless use is over for today. The body has get_key_url.
  • 429 rate_limited. Each key may make 60 checks a minute; above that the API answers 429 with retry_after in seconds. Ask support@precleared.dev for a higher limit.

A check has a 25 second limit. If the register or the website is slow, the verdict is unknown with a note.

MCP

The MCP server runs over streamable HTTP at https://precleared.dev/mcp. It has two tools.

  • contact_check takes the same input as the API and returns the same JSON.
  • verify_receipt takes an id and returns the receipt.
{
  "mcpServers": {
    "precleared": {
      "url": "https://precleared.dev/mcp",
      "headers": { "Authorization": "Bearer pc_live_..." }
    }
  }
}

The header is optional. Without a key, the keyless daily allowance applies.

Gateways that pass keys in their own header, such as Smithery, can send X-API-Key: pc_live_... instead.

Add it in one click

Pick your client. Each one points at the same server; add a key later for your own daily allowance and to use packs.

Add to Claude Add to Cursor Add to VS Code

Listed in the Claude directory. One click, no setup, no sign-in.

Claude Code:

claude mcp add --transport http precleared https://precleared.dev/mcp

Claude.ai and the Claude desktop app: Settings, Connectors, Add custom connector, then paste https://precleared.dev/mcp. Leave authentication off for the keyless allowance.

Any other MCP client: use the JSON above. The server speaks streamable HTTP and needs no OAuth.

Use it from your agent framework

Precleared is a plain MCP server over streamable HTTP, so any framework that speaks MCP can use it without an SDK. Five that outbound agents are commonly built on:

Claude API (Anthropic Messages API, MCP connector)

{
  "model": "claude-sonnet-4-5",
  "max_tokens": 1024,
  "mcp_servers": [{ "type": "url", "url": "https://precleared.dev/mcp", "name": "precleared" }],
  "messages": [{ "role": "user", "content": "May I send a cold email to jane@acme.co.uk from the UK? The address is on their website." }]
}

Send with the header anthropic-beta: mcp-client-2025-04-04.

OpenAI Agents SDK (Python)

from agents import Agent, Runner, HostedMCPTool

agent = Agent(
    name="Outreach",
    instructions="Before any cold email, call contact_check and follow its verdict and footer_text.",
    tools=[HostedMCPTool(tool_config={
        "type": "mcp", "server_label": "precleared",
        "server_url": "https://precleared.dev/mcp", "require_approval": "never",
    })],
)
result = Runner.run_sync(agent, "May I email jane@acme.co.uk from the UK? The address is on their website.")
print(result.final_output)

The same tool block works in the Responses API under "tools".

LangGraph / LangChain (Python)

from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent

client = MultiServerMCPClient({
    "precleared": {"url": "https://precleared.dev/mcp", "transport": "streamable_http"},
})
tools = await client.get_tools()
agent = create_react_agent("anthropic:claude-sonnet-4-5", tools)
reply = await agent.ainvoke({"messages": "May I email jane@acme.co.uk from the UK?"})

CrewAI (Python)

from crewai import Agent
from crewai_tools import MCPServerAdapter

with MCPServerAdapter({"url": "https://precleared.dev/mcp", "transport": "streamable-http"}) as tools:
    outreach = Agent(role="Outreach", goal="Only send cold emails Precleared says are allowed", tools=tools)

n8n

  1. Add an "MCP Client Tool" node to your AI Agent.
  2. Endpoint: https://precleared.dev/mcp. Server transport: HTTP Streamable. Authentication: none.
  3. Optional: to use a key, choose header auth and set Authorization to Bearer pc_live_...
  4. The agent now has contact_check and verify_receipt as tools.

Or start from the ready-made template: Check cold email compliance and draft Gmail messages with Precleared.

Apify

Run the Cold Email Compliance Check Actor on the Apify Store. Paste a list of addresses and get one row per address with the verdict, the rule, what the footer must include and a receipt link. It costs $0.03 per address checked, billed by Apify. Invalid addresses, duplicates and checks that fail aren't charged. To use your own daily allowance and packs instead, paste your Precleared key into the Actor's input. AI agents can also run it through Apify's MCP server.

Using Harvey, the open-source AI sales agent? The check is built in. See Precleared in Harvey.

To send a key from any framework, add the header Authorization: Bearer pc_live_... to the server configuration. Without a key, each IP address gets 100 checks a day over MCP, shared by everyone calling from it. A free key gives you your own 100.

Verifying a receipt

Each receipt is signed with Ed25519 over the string request_hash.response_hash. Get the public key from /api/v1/public-key. It is base64 SPKI DER. The key version is in every receipt.

import { createPublicKey, verify } from "node:crypto";

const r = await (await fetch("https://precleared.dev/api/v1/receipt?id=cc_rcpt_...")).json();
const { public_key } = await (await fetch("https://precleared.dev/api/v1/public-key")).json();

const key = createPublicKey({ key: Buffer.from(public_key, "base64"), format: "der", type: "spki" });
const ok = verify(null, Buffer.from(`${r.request_hash}.${r.response_hash}`), key, Buffer.from(r.signature, "base64"));
console.log(ok ? "Signature verified" : "Signature does not match");

Allowances and pricing

  • No key: 100 checks a day over MCP, or 10 over the REST API, shared by everyone calling from the same IP address.
  • Free key: your own 100 checks a day over MCP, or 25 over the REST API.
  • Pack: £39 for 2,000 checks. Used after the daily free checks. Never expire.
  • On the Apify Store: $0.03 per address checked, billed by Apify, or use your own key there.

Days run on UK time. MCP and REST checks come out of the same daily count.

When a pack runs out

Free daily checks carry on as normal. Once those are used and there are no credits left, a check returns 402 payment_required with a buy_url. It opens checkout for that key in one click. The key itself is never put in a URL.

When a check leaves a key with 1 to 200 pack checks, usage also has low_balance: true, a top_up_url and a notice saying how many are left. Packs stack on the same key and never expire. You can also buy one at /buy.

Suppression list

A managed suppression list per key is coming soon. For now, pass suppressed: true when the address is on your own list.

Other resources

openapi.json · llms.txt · /api/v1/rules

Precleared

Decision support with sources, not legal advice.

Docs Rules Guides Accuracy Privacy FAQ Terms support@precleared.dev

Listed on Claude directory Apify Store n8n templates Smithery Glama Claude Market

Precleared is run by Gabriel Imevbore, trading as Precleared, a sole trader based in England. 82A James Carter Road, Mildenhall IP28 7DE, United Kingdom. support@precleared.dev