Skip to main content

For AI voice agents

Check every number before your AI voice agent dials it

Your AI voice agent dials whatever number it is handed, including numbers on Do Not Call lists and numbers that belong to known TCPA litigators.

Phone Scrub checks each number in one API call before the call is created, and returns the line type too, so your agent can skip a landline when it wants a mobile.

10 credits a check when the number is found, nothing when it is unknown.

One number, one pre-dial check
  1. Your agent is about to call +1 201 555 0123
  2. It asks Phone Scrub first: Do Not Call, litigator, line type
  3. Known litigator or Do Not Call: the agent skips the call
  4. Clean mobile number: the agent dials

Phone Scrub answers between your agent picking a number and your server placing the call

It is one extra request in the server that already starts your calls, so nothing changes in the agent itself.

Step 1

Your agent picks the next number

It comes from your call list or your CRM, before any call is created.

Step 2

Your server asks 1Lookup Phone Scrub

One POST with the number, and one JSON answer back.

  • Do Not Call?
  • Litigator?
  • Line type?

Skip the call

The number is on a Do Not Call list or belongs to a known litigator.

Route the number

It is clean, but a landline or VoIP line is not what your script is built for.

Dial the call

A clean number of the line type you want.

Step 1, your agent picks the next number. Step 2, your server asks Phone Scrub. Step 3, your server skips the call, routes the number or dials it.

One POST request with the number returns the answer as JSON

Send the number in phone_number with your API key as a bearer token. The numbers below are made up.

The request

POST /api/v1/phone-scrub
curl -X POST https://app.1lookup.io/api/v1/phone-scrub \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phone_number": "+12015550123"}'
Method and address
POST https://app.1lookup.io/api/v1/phone-scrub
Header
Authorization: Bearer YOUR_API_KEY
Body field
phone_number, with or without a country code
Cost
10 credits when found, 0 when unknown

Create a key in the 1Lookup app, then read the API docs for the other fields.

The response for a known litigator, trimmed to what your agent reads

200 OK
{
  "success": true,
  "data": {
    "classification": {
      "matched": true,
      "phoneTypeCode": "X",
      "phoneTypeLabel": "LITIGATOR",
      "doNotCall": false,
      "litigator": true
    },
    "recommendations": {
      "primary_action": "BLOCK",
      "business_rules": {
        "can_use_contact": false,
        "do_not_call": false,
        "litigator_risk": true
      }
    },
    "metadata": {
      "credits_used": 10,
      "cache_hit": false
    }
  }
}

Five fields in the response tell your agent what to do

A true litigator or doNotCall ends the check. The other three fields decide the rest.

  • litigator

    True when the number belongs to a known litigator, serial complainer or attorney.

    Skip the call every time.

  • doNotCall

    True when the number is on a Do Not Call list.

    Skip the call.

  • phoneTypeLabel

    The line type: MOBILE, LANDLINE, VOIP, LITIGATOR or UNKNOWN.

    Dial only the line types your script is built for.

  • matched

    False when 1Lookup has no record of the number. Nothing is charged.

    Hold the number for review. The suggested action is REVIEW.

  • recommendations.business_rules.can_use_contact

    True only when the number matched and is neither on a Do Not Call list nor a litigator.

    Gate the call on this one boolean when you want a single check.

Each kind of number comes back with a different answer

These are the four results your agent meets most, as they appear in the classification part of the response.

Dial

A clean mobile number

matched: true
phoneTypeLabel: "MOBILE"
doNotCall: false
litigator: false
primary_action: APPROVE

Your agent places the call.

Route

A landline when you want mobile

matched: true
phoneTypeLabel: "LANDLINE"
doNotCall: false
litigator: false
primary_action: APPROVE

The number is clean, so send it to a campaign built for landlines.

Skip

A number on a Do Not Call list

matched: true
phoneTypeLabel: "MOBILE"
doNotCall: true
litigator: false
primary_action: BLOCK

Your agent never dials it.

Skip

A known TCPA litigator

matched: true
phoneTypeLabel: "LITIGATOR"
doNotCall: false
litigator: true
primary_action: BLOCK

Your agent never dials it, whatever else the record says.

Run the check in your server right before it creates the outbound call

This is Node and TypeScript. The same function goes in front of whichever request your platform uses to create a call.

pre-dial-check.ts
const PHONE_SCRUB = "https://app.1lookup.io/api/v1/phone-scrub";

type Verdict = { dial: boolean; reason: string };

export async function preDialCheck(
  phone: string,
  allowedLineTypes = ["MOBILE"],
): Promise<Verdict> {
  const res = await fetch(PHONE_SCRUB, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.ONELOOKUP_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ phone_number: phone }),
  });
  // A failed check throws, so the call is never placed.
  if (!res.ok) throw new Error(`Phone Scrub returned ${res.status}`);

  const { data } = await res.json();
  const { matched, phoneTypeLabel, doNotCall, litigator } = data.classification;

  if (litigator) return { dial: false, reason: "known litigator" };
  if (doNotCall) return { dial: false, reason: "on a Do Not Call list" };
  if (!matched) return { dial: false, reason: "no record, hold for review" };
  if (!allowedLineTypes.includes(phoneTypeLabel)) {
    return { dial: false, reason: `line type is ${phoneTypeLabel}` };
  }
  return { dial: true, reason: "clean number" };
}

export async function startOutboundCall(phone: string) {
  const verdict = await preDialCheck(phone);
  if (!verdict.dial) return { skipped: verdict.reason };

  const res = await fetch("https://api.vapi.ai/call", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.VAPI_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      assistantId: process.env.VAPI_ASSISTANT_ID,
      phoneNumberId: process.env.VAPI_PHONE_NUMBER_ID,
      customer: { number: phone }, // E.164, like +12015550123
    }),
  });
  return res.json();
}

What this code does

  • A litigator or Do Not Call number never reaches your voice platform.
  • If the check itself fails, the function throws and no call is placed.
  • Only the line types in allowedLineTypes are dialed, so a landline is never dialed by a mobile script.

The second function creates a call with the request in Vapi's create call reference. For Retell, Bland or your own Twilio stack, call preDialCheck before the request that creates the call.

A check costs 10 credits when the number is found and nothing when it is not

You pay for the answers you get. A number 1Lookup has no record of comes back with matched set to false and costs nothing.

10 credits

A number is found

Do Not Call, litigator and line type come back together.

0 credits

A number is unknown

matched is false and nothing is charged.

About $0.05

One check on the Starter plan

Larger plans cost less per credit.

Checking 1,000 numbers that are all found, by plan
  • Starter$49.50

    About $0.05 a check

  • Growth$35.20

    About $0.04 a check

  • Professional$32.00

    About $0.03 a check

  • Enterprise$19.99

    About $0.02 a check

Developers ask these questions before they add a pre-dial check

Do AI voice agent calls fall under the TCPA?

Yes. In a Declaratory Ruling adopted on 2 February 2024 and announced on 8 February 2024, the FCC ruled that calls made with AI-generated voices are artificial voices under the Telephone Consumer Protection Act. Those calls need the prior express consent of the person called, and prior express written consent when the call is telemarketing. The ruling took effect immediately.

What does Phone Scrub check before my AI voice agent dials?

One call returns three answers: whether the number is on a Do Not Call list, whether it belongs to a known TCPA litigator, serial complainer or attorney, and what kind of line it is (mobile, landline or VoIP). The response also carries a suggested action: APPROVE, REVIEW or BLOCK.

Does the check work with Vapi, Retell and Bland?

Yes. Phone Scrub is an ordinary HTTPS request that your own server makes before it asks Vapi, Retell, Bland or your own Twilio setup to place the call, so it needs nothing from the platform.

What does the API return for a Do Not Call or litigator number?

A Do Not Call number comes back with doNotCall set to true and the suggested action BLOCK. A known litigator comes back with litigator set to true, the line type LITIGATOR and BLOCK. A litigator number is never returned as APPROVE, even when it is not on a Do Not Call list.

How much does a pre-dial check cost?

A check costs 10 credits when the number is found and nothing when 1Lookup has no record of it. On the Starter plan that is about $0.05 a check, so a list of 1,000 numbers costs at most 10,000 credits, about $49.50. Every plan starts with a 7-day free trial.

Does Phone Scrub check numbers outside the US?

No. The scrub is built for US numbers, because the Do Not Call and TCPA litigator lists cover the United States only. A number from another country will not return a useful result.