Call-center screening checks phone numbers before or during a call, so agents and diallers spend time on real contacts. The carrier lookup reports line type, carrier and country; the HLR lookup says whether a mobile number is live. Where enabled, spam reputation reports whether a number appears in nuisance-call reports, with reasons. Spam reputation is in limited access.
What problems does screening solve?
Contact centers lose time and money in both directions:
- Inbound. Robocalls and nuisance calls tie up agents and IVR minutes. Scam callers pretend to be customers. A reputation signal lets you send high-risk calls to an IVR or a verification step instead of a live agent.
- Outbound. Dialling lists contain fixed lines where you expected mobiles, numbers that are no longer assigned, numbers that were recently offered as unassigned, and numbers with fraud reports. Checking them first protects agent time and your caller reputation.
- Lead intake. Web leads with a spoofed or recently unassigned number are a common sign of fake leads. See lead verification.
Spam reputation works from report classes described in general terms: telecom regulator actions, government nuisance-call complaint data, community reports and a signal for recently unassigned numbers. There's also a VoIP hint, which is not a risk by itself. Every level comes with the reasons behind it. Report texts and reporter details are never returned. The HLR lookup answers a different question: whether the mobile network considers the number assigned and reachable at the moment you ask.
How does the workflow look?
Inbound calls:
- Your telephony platform receives the caller ID.
- Call
POST /v1/lookupwithchecks: ["spam", "carrier"]and a shortwait, for example 3 seconds. - Route the call using the table below and log the level, not the raw response.
- If the answer isn't back in time, route the call normally. Never hold a caller on a pending check.
Outbound lists:
- Call
POST /v1/jobs/estimate(free) with the list andchecks: ["carrier", "hlr"]. For US and Canadian lists, addnetwork.carrier_us, and addspamif it's enabled for your account. - Create the job with
POST /v1/jobs, passing the estimate asmax_cost. - Download the CSV. Each check has its own columns, such as
number.spam.risk_levelandnetwork.carrier.line_type. - Remove or reorder rows before they reach the dialler.
Which checks answer which question?
| Check | What it answers | When to run it | Link |
|---|---|---|---|
carrier | Mobile, fixed line or VoIP? Which carrier and country? | Inbound calls; outbound list preparation | Carrier lookup |
network.carrier_us (bulk) | Current carrier for US and Canadian numbers | US/CA outbound lists | US/CA carrier lookup |
hlr | Is the mobile number assigned and reachable now? | Outbound lists before a campaign | HLR lookup |
spam (limited access) | Is the number in spam or nuisance-call reports, and why? | Inbound calls; outbound lists; lead intake | Spam reputation |
What should you do with each result?
| Result | Suggested action |
|---|---|
risk_level: high (score ≥ 80 and a regulator action or two or more signal classes) | Inbound: IVR or verification step. Outbound: remove from the list |
risk_level: medium | Inbound: ask for extra verification. Outbound: review |
risk_level: low | Handle normally and watch for patterns |
risk_level: no_reports | No negative signal. Not proof of safety |
reason_unassigned: true | Treat as a possible spoofed caller ID or fake lead |
HLR status: invalid | Outbound: remove; the number isn't assigned |
HLR status: unreachable | Outbound: move to a later retry slot |
line_type: fixed_line on a mobile campaign | Move to the voice-only queue |
unknown / unsupported_country | Handle normally; not charged |
What does a request look like?
curl https://api.mobilevalidate.com/v1/lookup \
-H "Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" \
-H "Content-Type: application/json" \
-d '{"numbers":["+447700900001"],"checks":["spam","carrier"],"wait":3}'// npm install mobilevalidate · Node.js 20+ · save as check.mjs and run: node check.mjs
import { MobileValidate } from "mobilevalidate";
// Omit apiKey to read MOBILEVALIDATE_API_KEY from the environment.
const mv = new MobileValidate({ apiKey: "mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym" });
const { data, error } = await mv.lookup({
numbers: ["+447700900001"],
checks: ["spam", "carrier"],
wait: 3,
});
if (error) console.error(error.code, error.message);
else console.dir(data.results, { depth: null });// Node.js 18+, Deno, Bun or the browser console (ES module: save as .mjs or use "type": "module").
const res = await fetch("https://api.mobilevalidate.com/v1/lookup", {
method: "POST",
headers: {
Authorization: "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym",
"Content-Type": "application/json",
},
body: JSON.stringify({
numbers: ["+447700900001"],
checks: ["spam", "carrier"],
wait: 3,
}),
});
console.log(res.status, res.headers.get("x-request-id"));
console.dir(await res.json(), { depth: null });# pip install mobilevalidate-sdk
from mobilevalidate import MobileValidate
# Omit api_key to read MOBILEVALIDATE_API_KEY from the environment.
mv = MobileValidate(api_key="mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym")
result = mv.lookup(numbers=["+447700900001"], checks=["spam", "carrier"], wait=3)
print(result)<?php
$ch = curl_init('https://api.mobilevalidate.com/v1/lookup');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'numbers' => ['+447700900001'],
'checks' => ['spam', 'carrier'],
'wait' => 3,
]),
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), PHP_EOL, $response, PHP_EOL;package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
body := strings.NewReader(`{"numbers":["+447700900001"],"checks":["spam","carrier"],"wait":3}`)
req, err := http.NewRequest("POST", "https://api.mobilevalidate.com/v1/lookup", body)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym")
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
out, _ := io.ReadAll(res.Body)
fmt.Println(res.Status, string(out))
}require "net/http"
require "json"
uri = URI("https://api.mobilevalidate.com/v1/lookup")
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer mv_test_publicSandboxn9ZgneuhR1B9CRfKG3fulym"
req["Content-Type"] = "application/json"
req.body = JSON.generate({
"numbers" => ["+447700900001"],
"checks" => ["spam", "carrier"],
"wait" => 3
})
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(req) }
puts res.code, res.bodyRuns as pasted with the public sandbox key, which answers the test values only. In the SDKs, omit the key to use MOBILEVALIDATE_API_KEY.
In test mode the whole +44 7700 900xxx test range is allowed for spam reputation, so the documented numbers work. Response (excerpt, test mode: checks of the first item):
{
"number.spam": {
"service": "number.spam", "status": "completed", "registered": true,
"attributes": {
"risk_level": "high", "risk_score": 95, "reason_regulator": true, "reason_government": false,
"reason_community": true, "reason_unassigned": false, "voip_range": false, "top_category": "robocall",
"first_seen": "2025-11", "last_seen": "2026-08", "sources": 2
},
"confidence": "high", "confidence_score": 0.99, "checked_at": "2026-09-25T14:28:24.778Z",
"cached": false, "age_seconds": 0, "billed": false, "reason": null, "poll_after_ms": null
},
"network.carrier": {
"service": "network.carrier", "status": "completed", "registered": true,
"attributes": {"line_type": "mobile", "carrier": "Test Carrier", "country": "GB"},
"confidence": "high", "confidence_score": 0.99, "checked_at": "2026-09-25T14:28:24.778Z",
"cached": false, "age_seconds": 0, "billed": false, "reason": null, "poll_after_ms": null
}
}For attributes services, registered: true means "data found". The answer is in attributes. This test caller is high risk with a regulator action, so an inbound call would go to the IVR or a verification step.
How much does it cost?
You're not charged for inconclusive results (unknown, unsupported country, timeout, invalid, duplicate). For spam reputation, every level, including no_reports, is a conclusive answer and is billed. Numbers from sanctioned countries and regions return unsupported_country for free. The carrier lookup is billed when it returns a carrier. When no carrier data exists for a number, the answer is unknown and free. For the HLR lookup, reachable, unreachable and invalid are all billed. See pricing for current rates.
Spam answers come from our own reference data, which is refreshed daily. That keeps real-time answers fast, and repeat checks within 24 hours are served from your account's cache for free. That matters for repeat callers.
What limits and rules apply?
A lookup takes up to 100 numbers and a job up to 50,000. Requests that look like sequential number ranges or generated e-mail lists are rejected, and each account has a daily cap on numbers. Spam scores can change as new reports arrive and old ones age out, so read checked_at.
What about consent and compliance?
A reputation level is a signal about a number, not a judgment about a person. Numbers get spoofed and reassigned. Always give legitimate callers a way through, for example a verification step. Don't use the results for credit, employment, housing or insurance decisions.
For outbound work, screening doesn't replace consent or do-not-call rules. In the US, the TCPA and the telemarketing rules in 47 CFR 64.1200 govern calls to mobiles and marketing calls, and the FCC's call authentication framework (STIR/SHAKEN) governs caller ID. Other countries have their own rules. This is not legal advice.
People who find their number in our data can object or ask for access through the opt-out form and the data-subject notice.
What are the common mistakes?
- Blocking on
no_reportsgaps. No reports is not safe, and it isn't suspicious either. It is the absence of a signal. - Blocking every VoIP caller. The
voip_rangehint adds no risk points on purpose. Many businesses call from VoIP ranges. - Holding callers on a pending check. Use a short
waitand route normally if the answer is late. - Dialling
invalidnumbers again next week. Remove them from the list and fix the source record. - Keeping full responses. Log the level and reasons you acted on, with
checked_at.
More on inbound routing: screening inbound calls with spam reputation.
Frequently asked questions
Is the spam reputation check available to every customer?
Not yet. Spam reputation is in limited access, for approved customers only, until its review is finished. The carrier lookup and the HLR lookup are available to all customers.
Which countries does spam reputation cover?
All countries except sanctioned ones, which return unsupported_country and are not charged. Report data is densest for North American and European numbers and growing elsewhere, so give no_reports less weight for other countries.
Does no_reports mean a caller is safe?
No. It means we hold no reports for the number. New, rarely used or spoofed numbers can still be abusive. Treat it as no negative signal and combine it with other checks.
Is a no_reports answer charged?
Yes. Every risk level, including no_reports, is a conclusive answer and is billed. Unknown and unsupported-country results are free.
Can the carrier lookup tell me who is calling?
No. It returns line type, carrier and country for the number. It never returns names or any other details about the person behind the number.
How does the HLR lookup help outbound dialling?
It asks the home network whether a mobile number is assigned and reachable. Numbers reported as invalid (not assigned) can come off the list before an agent dials them; unreachable ones can be retried later.
Does screening replace STIR/SHAKEN?
No. STIR/SHAKEN authenticates caller ID on the call itself in the US and Canada. Spam reputation and line type are separate signals about the number, and they work alongside it.
Related
- ServicePhone number reputation lookup: spam score and reasons
- ServicePhone carrier lookup by number: carrier and line type API
- ServiceHLR lookup API: live mobile network status
- ServiceUS and Canada carrier lookup in bulk (ported numbers)
- Use caseContactability checks for collections and accounts receivable
- Use caseLead and form verification
Guides on this topic
All articlesResearch
Robocall Mitigation Database: a 2026 census of 11,467 filings
We counted all 11,467 published FCC Robocall Mitigation Database filings: 42% certify full STIR/SHAKEN, 36% rely on mitigation only. Data and method.
8 min read
Fraud prevention
Phone number reputation lookup: free ways to check a number, and when you need an API
Free ways to run a phone number reputation lookup (regulator complaint data, phone labels, report sites), their limits, and when an API score is worth it.
10 min read
Fraud prevention
STIR/SHAKEN attestation levels A, B and C, explained
What STIR/SHAKEN attestation levels A, B and C mean, what they don't prove, how they relate to spam labels, and the rules in the US, Canada and France.
8 min read


