For developers

UK TPS/CTPS screening as an API.

UK TPS/CTPS screening behind a REST API, live today. Built for RevOps and product engineers who would rather integrate than re-implement TPS plumbing. Sign in, create a key, and your first test call works in minutes.

Listed on the HubSpot App MarketplaceFree to install. Screening starts once you subscribe

What it does

Single and bulk lookups

One endpoint, one number or up to 1,000 per request, answered in the same response.

Your own suppression list

Keep the opt-outs you have collected yourself on your account, next to the register checks. Add, list and remove numbers with the same key.

Audit-ready response logs

Every screen result is stored and addressable by id. Pull it back later in a format the ICO is happy to look at.

Quick example

Base URL: https://api.tpsclear.co.uk

Request

POST https://api.tpsclear.co.uk/v1/screen
Authorization: Bearer tpsc_live_xxx  # use tpsc_test_* in CI/sandbox
Content-Type: application/json

{
  "phoneNumbers": ["+447777000001", "+447777000002"],
  "campaignRef": "spring-outbound-2026"
}

campaignRef: Optional reference stored on the audit record for this call, e.g. a campaign or client identifier. Max 120 characters. When supplied it is echoed at the top level of the response beside results. A single number can also be sent as "phone": "+44..".

Response

{
  "results": [
    {
      "phoneNumber": "+447777000001",
      "tpsListed": false,
      "ctpsListed": false,
      "status": "clean",
      "checkedAt": "2026-05-08T10:21:01Z"
    },
    {
      "phoneNumber": "+447777000002",
      "tpsListed": true,
      "ctpsListed": false,
      "status": "tps-listed",
      "checkedAt": "2026-05-08T10:21:01Z"
    }
  ]
}

Endpoints

You should not need a 200-page reference to screen a phone number.

EndpointPurpose
POST /v1/screenSingle or bulk lookup. Synchronous response with TPS and CTPS status per number.
GET /v1/screen/{id}Fetch a past screen result by id for audit purposes.
GET /v1/usageCurrent-window usage for your key plus rolling 30-day totals for your account.
POST /v1/keys/rotateMint a replacement token for your key and (by default) revoke the old one immediately.
GET /v1/suppressionsYour own do-not-call list: the total count and the 100 most recent entries. A number on the list comes back from POST /v1/screen with status suppressed, is not screened and uses no lookup.
POST /v1/suppressionsAdd up to 10,000 numbers per request as {"numbers": [..]}. Numbers already on the list are ignored. A list holds up to 100,000.
DELETE /v1/suppressionsRemove one number, sent as {"number": "+44.."} in the body. Suppression calls use no lookups.

Suppression list responses

GET    -> { "count": 42, "suppressions": [ { "phoneNumber": "+441134960001", "note": "Asked not to be called", "createdAt": "2026-09-18T11:02:00Z" } ] }
POST   -> { "ok": true, "added": 2, "invalid": [], "total": 44 }
DELETE -> { "ok": true }

Every key ships with a reference doc and a Postman collection.

Retrieve a screening record

Every POST /v1/screen response carries an X-Request-Id header. That id addresses the stored audit record: pull it back any time with a GET. Records belong to your account; an id that does not exist, or belongs to someone else, returns 404.

summary.unknown counts every number that came back without a register verdict, which includes numbers rejected as invalid UK numbers before any lookup was made. providerFailures is the subset where the check was attempted and the register lookup failed; those are refunded and are worth retrying. summary.suppressed counts numbers held back by your suppression list; they are not looked up and not charged.

GET https://api.tpsclear.co.uk/v1/screen/6f1d2c9a-4b3e-4f2a-9c1d-8e7b6a5f4d3c
Authorization: Bearer tpsc_live_xxx

Response

{
  "id": "6f1d2c9a-4b3e-4f2a-9c1d-8e7b6a5f4d3c",
  "createdAt": "2026-05-08T10:21:01Z",
  "environment": "live",
  "lookups": 2,
  "campaignRef": "spring-outbound-2026",
  "summary": { "clean": 1, "tpsListed": 1, "ctpsListed": 0, "unknown": 0, "suppressed": 0 },
  "providerFailures": 0,
  "results": [ ...same shape as the original response... ]
}

Check usage

One GET tells you where your key stands in the current fair-use window and what your account has consumed over the last 30 days. Reading usage never consumes any of it.

GET https://api.tpsclear.co.uk/v1/usage
Authorization: Bearer tpsc_live_xxx

Response

{
  "key": { "last4": "k9Qz", "name": "Acme production" },
  "environment": "live",
  "plan": "beta",
  "window": {
    "limit": 10000,
    "windowSecs": 86400,
    "used": 1240,
    "remaining": 8760,
    "reset": 1751932800
  },
  "last30d": { "calls": 87, "lookups": 21430 }
}

window.used counts lookups, not requests, against the same fixed window the 429 limiter uses; window.reset is the epoch second the window rolls over. On very high-volume accounts last30d may include "approximate": true when the lookup total is summed from a capped sample of calls.

Rotate a key

Rotate the key you are calling with. You get a brand-new token on the same plan and limits, shown once in the response and never again; store it before the connection closes. By default the old key is revoked immediately. Send { "revokeOld": false } to keep the old key alive while you cut services over, then retire it later by rotating with it again.

POST https://api.tpsclear.co.uk/v1/keys/rotate
Authorization: Bearer tpsc_live_xxx
Content-Type: application/json

{
  "revokeOld": true
}

Response

{
  "ok": true,
  "token": "tpsc_live_...full token, shown only once...",
  "tokenPrefix": "tpsc_live_AbC123dEf456",
  "last4": "x7Pq",
  "revokedOld": true,
  "note": "Store this token now; it is shown only once. ..."
}

Auth

Bearer tokens in the Authorization header. Tokens are environment-scoped: tpsc_test_* hits a sandbox that returns deterministic fixtures, tpsc_live_* hits the live register data. Tokens can be rotated self-serve via POST /v1/keys/rotate or revoked on request at any time; revocation takes effect immediately.

Issue your own keys from your account. Sign in with a link emailed to your work address, buy a pack of checks, and create, list or revoke keys yourself. Test keys are free, within a daily fair-use limit, so you can build and debug against fixtures before you buy anything.

If you already run TPSClear inside HubSpot, you can issue keys from the app settings page instead (Settings, Integrations, Connected Apps, TPSClear, the API tab), behind your HubSpot login, with no second set of credentials to manage. A key issued that way follows the subscription on the connected portal, and its lookups count towards the same monthly allowance and daily cap as screening driven from the CRM. A key issued from your account draws on your credit balance instead. Either kind works against the same endpoints.

Recommended practice

  • Store tokens in your platform's secret manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault, Doppler, or the equivalent on your stack). Never commit tokens to source control.
  • Use the test token in CI and staging. Live tokens belong only in production runtime environments.
  • Rotate on staff changes. If a token leaks, revoke first, debug after.

Rate limits and cost

No per-lookup charge on any plan. Every plan includes API access with the same engine; the difference is each plan's fair-use volume. Limits are expressed in lookups, not requests, so a bulk call of 500 numbers counts as 500 against your plan's fair use.

To keep the service stable for everyone, abnormal automated traffic may be rate-limited, and sustained bursts beyond fair use return 429 with a Retry-After header so clients back off cleanly. We also return X-RateLimit-Remaining and X-RateLimit-Reset headers on every response. There is no surprise invoice.

Keys issued from a connected HubSpot portal also draw on that portal's daily screening cap, shared with CRM-side screening. Reaching it returns 429 with {"error": "daily_cap_reached"} until 00:00 UTC. The cap is a spend guard rather than a throttle, so ask us to raise it if your volumes need more headroom.

Audit trail

Every screen call, single or bulk, is persisted with its full result set, the timestamp it was checked, and the token that made the call. Results are retained for a minimum of twelve months. Pull any prior result back via GET /v1/screen/{id} in a format aligned with how the ICO expects evidence of consent-checking to be presented.

Why this matters. Under PECR you need to demonstrate you screened, not just claim it. An addressable log of every check, with timestamps, is the cleanest way to do that.

Build vs buy

You can absolutely build TPS screening yourself. There is no official TPS register API, only a licensed daily file; we explain the landscape in TPS register API: what's available and how to use it. You will need a DMA licence, an SFTP fetch on the daily file, a normaliser, a comparator, retention rules, and a re-screen scheduler. Most teams do this once, regret it, and hand it to a third party on the second renewal.

Read the full build-vs-buy breakdown.

Other CRM integrations

If you would rather not write a single line of integration code, TPSClear runs natively inside HubSpot today; Salesforce, Dynamics 365, Pipedrive, Zoho and Capsule integrations are in build. The API covers everything else right now.

See native CRM integrations.

Get an API key

Sign in with a link emailed to your work address and create a key straight away. A test key is free and screens against fixtures, so you can have your integration working before you spend anything. A live key screens the real TPS and CTPS registers and costs one credit per check.

Checks are sold in prepaid packs from £9, and they last 12 months. Screening from inside a CRM is a monthly plan instead, from £95.