Agent Ready

Phone verification in one API call

Line type, carrier, and TCPA litigator check. Pay as you go. Built for AI agents, CRMs, and dialers.

Request
curl -X POST \
  https://numberbroom.com/api/v1/verify \
  -H "Authorization: Bearer nb_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"phone": "+12025550143"}'
Request
import requests

resp = requests.post(
    "https://numberbroom.com/api/v1/verify",
    headers={"Authorization": "Bearer nb_live_YOUR_KEY"},
    json={"phone": "+12025550143"}
)
result = resp.json()
print(result["lineType"], result["isLitigator"])
Request
const resp = await fetch(
  "https://numberbroom.com/api/v1/verify",
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer nb_live_YOUR_KEY",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ phone: "+12025550143" }),
  }
);
const data = await resp.json();
200 Response
{
  "phone":                 "+12025550143",
  "e164":                  "+12025550143",
  "valid":                 true,
  "lineType":              "mobile",
  "carrier":               "Verizon Wireless",
  "isLitigator":           false,
  "litigator":             "no",
  "activityScore":         82,
  "isLikelyDisconnected":  false,
  "outcome":               "clean",
  "keep":                  true,
  "dncEvaluated":          false,
  "charged":               0.2,
  "creditsRemaining":      24.8
}

Everything in one call

No stitching together three vendors. One endpoint, one price, one response.

Line Type Detection

Mobile, landline, VoIP, toll-free or other, as carrier data reports it. A dead line keeps its type, so activityScore (0 to 100) and isLikelyDisconnected (a score of 30 or below) say whether it is still in use. With no score, both are null: the carrier data has no signal either way, which is not the same as in service.

TCPA Litigator Flag

Known litigators are flagged so you can remove them before dialing. The flag covers numbers tied to TCPA, FDCPA, FCRA and CFPB suits in court filings; it does not say which law, and no database catches every litigator. isLitigator is true or false, and litigator says the same as a word (yes, no or not_checked) for tools that compare text: see GoHighLevel and Google Sheets.

Carrier Identification

Get the actual carrier name for each number. Know who you're calling through.

API Endpoints

Base URL: https://numberbroom.com/api

EndpointAuthDescription
POST /v1/verify API key Verify a single phone number
GET /v1/credits API key Credit balance and lookups remaining. Free -- it spends nothing.
POST /v1/credits/checkout API key A Stripe link that adds credit to the key’s account, for a person to pay. Send amount in dollars.
POST /v1/lists API key Send a whole list as numbers (up to 10,000) for the paid list scrub. Returns the price and a Stripe link for a person to pay.
GET /v1/lists/:jobId API key Where one of your list scrubs stands, with counts and an hour-long download link once it is done
POST /v1/keys Account token Issue a key, with an optional label and dailyLimit. Shown once, never again.
GET /v1/keys Account token List your active keys: id, preview, label, daily limit, last used and lookups today
PATCH /v1/keys Account token Change one key’s label or daily limit, by id
DELETE /v1/keys Account token Revoke one key with ?id=, or every key without it

Authentication

All API calls use a Bearer token in the Authorization header. For /v1/keys endpoints, pass your account token. For all other endpoints, pass your API key:

Authorization: Bearer nb_live_a1b2c3d4e5f6...

Verifying many numbers

There is no batch lookup endpoint. Call /v1/verify once per number, concurrently if you like -- each call is independently priced, rate-limited and refunded. For lists rather than lookups, use the list scrub: same checks, $0.20 a row through 2,000 rows and less past that, one file back. Upload a CSV, TSV, Excel or PDF file, or send the numbers to POST /v1/lists.

Lists and credit from code

POST /v1/lists takes {"numbers": [...], "scrubMode": "full"} (litigator_only keeps landlines, VoIP and disconnected numbers) and answers with the price at list rates and a Stripe Checkout url. A person opens the link and pays by card; nothing is taken from API credit. The scrub runs once payment clears, and GET /v1/lists/:jobId reports its status and counts, with a download link that lasts an hour. Numbers outside the US are not priced or scrubbed: both responses count them as outsideUsRows, and a finished list adds outsideUsDownloadUrl, their rows in a file of their own. When rows were removed, removedDownloadUrl gives them as sent, each with its line type, carrier and reason, and litigatorDownloadUrl gives the known litigators among them in a file of their own; a Do Not Call Registry match is counted, never listed. Each number may hold only digits and phone punctuation, 40 characters at most.

POST /v1/credits/checkout with {"amount": 25} returns a Stripe link that adds that much credit to the key’s account when a person pays it. Both exist so an agent can hand its user a link to pay; neither spends anything on its own.

Keys and daily limits

An account can hold up to 10 active keys. Use one per app or machine and give each a label: if one leaks, revoking it leaves the others working.

Each key allows up to 5,000 lookups per day, resetting at midnight UTC, and the account allows up to 5,000 lookups per day across all of its keys, so more keys spread a day's lookups rather than raise the ceiling. Give a key its own lower dailyLimit when you create it or later with PATCH /v1/keys, and it stops there instead. A key with no limit of its own that is called through the MCP server stops at 500 a day, so an agent stuck in a loop cannot run up the full daily cap. Over a limit, calls return 429 rate_limited with the dailyLimit that applied and a scope of key, account or aws_new_subscription (an account billed through AWS Marketplace makes up to 500 lookups a day per subscription for its first 30 days), and GET /v1/credits reports both as dailyLimit and accountDailyLimit.

When you are not charged

Credit is debited before the carrier lookup runs and returned if the lookup produces no usable answer, so an outage costs you nothing. Only US numbers are looked up. Anything else is answered for free before any lookup runs, including a +1 number outside the US (Canada, Puerto Rico, the Caribbean), which the litigator check does not cover. A US number whose carrier data is withheld is answered free too, after the lookup, and asking again returns the same, so record it rather than retry it.

ResponseMeaningCharged
200 valid: false Not a number we can check, and reason says why: unparseable (not a phone number), not_nanp (outside the +1 numbering plan), outside_us (a +1 number outside the US) or suppressed (its carrier data is withheld, so it could not be checked; outcome is lookup_failed and asking again returns the same). A successful answer, not an error. No
401 unauthorized Missing, invalid or revoked key No
402 insufficient_credits Balance below $0.20. Top up to continue. No
429 rate_limited This key, or the account across all of its keys, reached its daily limit No
429 processing_limit The account reached its daily processing limit, which list uploads count toward too No
502 lookup_failed The carrier lookup produced no usable answer: a timeout, a dropped connection, the provider's rate limit, or an upstream error. Refunded. No
503 unavailable Lookups paused on our side No

One answer that is not a usable number is still charged: a US number the carrier lookup reports as not valid. It comes back as a 200 with outcome: "invalid" and keep: false, because the lookup ran and answered. No litigator check runs on a number that is not valid, so isLitigator is null on it, never false.

What this API does not do

POST /v1/verify does not check do-not-call registries; every answer from a lookup says so in dncEvaluated, which is always false, so an integration never has to infer coverage it has not got. A list sent with POST /v1/lists gets the same federal Do Not Call Registry check as an upload from the same account: only under the account's own verified SAN, on lists of up to 1,000 numbers. Litigator screening reduces TCPA risk; it does not eliminate it, and none of this is legal advice.

Pricing

Pay as you go. No subscriptions, no monthly minimums, no surprises.

$0.20 per verification, $10 minimum top-up

Line type + carrier + TCPA litigator check, all included -- the same $0.20 a CSV row costs in its first 2,000 rows, because it is the same product through a different door; the API has no volume bands. Credit is pre-paid and does not expire; top up between $10 and $5,000.

$25 credit

125 verifications

$50 credit

250 verifications

$100 credit

500 verifications

$500 credit

2,500 verifications

MCP Server

The same API, wired up for AI agents that speak MCP -- Claude Code, Cursor, Claude Desktop (through the mcp-remote bridge), VS Code, Windsurf and any other client that can send a header on a remote connection. With your API key in the header it is a thin, stateless proxy: the key travels straight through to the same /v1/verify, /v1/credits, /v1/credits/checkout and /v1/lists endpoints documented above, so auth, rate limits and billing all work exactly the same way.

Step-by-step setup for each client, with copy-paste config, is on the MCP server page. Claude.ai and ChatGPT's own connectors cannot send a header and speak OAuth only. The server now has an OAuth sign-in for them; that page will carry their setup steps once it has been tested end to end with each, and says what to do in the meantime.

verify_phone_number

Line type, carrier, activity score, litigator flag. $0.20/call, not charged if the number doesn't parse or is outside the US.

get_credit_balance

Remaining pre-paid balance on your account. Free to call.

buy_credits

A Stripe Checkout link that adds $10 to $5,000 of credit when a person pays it. Free to call.

scrub_list

Up to 10,000 numbers to the paid list scrub, full or litigators only, at list rates. Returns the price and a card checkout link; never paid from credit.

get_list_status

Where a list scrub stands, its counts once done, and a one-hour download link for the cleaned file.

Connect
{
  "url": "https://numberbroom.com/mcp",
  "headers": { "Authorization": "Bearer nb_live_YOUR_KEY" }
}

Per-client setup steps → Source is public: github.com/cameron-creations/numberbroom-mcp.

Quickstart

Three steps from zero to verified numbers.

1. Create an account

Sign up at numberbroom.com with email or Google. No credit card required to start.

2. Add credit and generate a key

Both live in Settings → API access. The key is shown once and never again -- we store only a hash of it.

3. Start verifying

Call POST /v1/verify with any US phone number. Watch your balance with GET /v1/credits.

Ready to verify?

Add credit and generate a key from Settings. Pre-paid, no subscription, no minimum monthly spend.

Get Started