Number Lookup model
Lookup answers questions about a phone number — reachability, line type, the network it currently belongs to, whether the SIM changed recently, whether it was reassigned since you collected consent — without sending anything to it. This page is the model behind the endpoint: which dip answers which question, how to read the response, how the cache and the daily cap shape what you pay, and how Lookup relates to the send-time resolution surfaces it is easily confused with. The parameter-level reference lives in Number Lookup and the API reference.What a Lookup is — and is not
A Lookup is a read-only number-intelligence operation. Nothing is delivered to the subscriber: an HLR dip queries the home location register, a ported-network dip queries the portability database, and the CAMARA and reassigned-number dips query operator-held and FCC datasets — so a Lookup carries no consent requirement of its own and never touches your sender pool, routes, or sender resolution. Consequences of that framing:- Lookup never gates a send. Nothing requires you to dip a number before messaging or dialing it. Lookup is an explicit, billable operation you choose to run — typically to decide whether a send is worth attempting, or to screen for fraud before an OTP goes out.
- Lookup is billable per answered dip. Each dip an upstream actually
answers debits your wallet on the
number_lookuppricing channel (see the cost model below). A dip that falls through to local E.164 validation with no upstream call — a malformed number — is free. - Lookup is a snapshot, not a guarantee. Reachability and SIM-swap answers describe the moment the upstream answered. The caching model below bounds how stale a snapshot can get.
The data packages — which dip answers which question
The base lookup validates the number and enriches it with carrier and live-status data in one call. On top of that, afields= selector on
GET /numbers/lookup/{phone} adds opt-in packages, Twilio Lookup v2
compatible. The five dip classes:
Beyond the five dips, the catalog carries derived packages — computed
from HLR signals already returned, exposed with
derived: true and a
stated confidence level rather than presented as operator-asserted data:
phone_number_quality_score, number_reputation, sms_pumping_risk,
call_forwarding, and operator_name (the HLR home-network operator
name — a different signal from the CNAM subscriber display).
Every package entry in the response names its own status:
available (real data returned), coming_soon (the upstream provider
is not yet contracted — do not build an integration against a payload),
not_implemented (no provider wired yet), or error (that one dip
failed while the rest succeeded). Per-field status isolation means one
failed dip never voids the others.
Reading the response
The base lookup returns onedata object. The fields carry the signals:
present/liveStatus— the raw HLR presence verdict:"yes","no", or"na"when the upstream does not expose presence. The convenience flagreachableisliveStatus === "yes", andlineStatusflattens the same signal toactive/inactive/unknownso fraud and win-back flows can branch on one discriminator — treatunknownas “no signal,” never as inactive.network(name,type,mcc,mnc) — the current (recipient) network and its line type, reported on the response ascarrier:network.nameis the operator label,network.typeismobile,landline, orvoip, and the MCC/MNC pair identifies the network for pricing and routing.portability.ported— true when the number moved carriers. When the upstream supplies the donor carrier,portability.originalCarriernames the network the number was ported away from; when the upstream omits it, it isnullrather than fabricated.simSwap(swapped,lastSwapDate,riskLevel) — the recency verdict.swappedistruewhen the SIM changed inside the carrier’s monitored window,nullwhen the operator gives no answer; the date of the most recent change lands inlastSwapDate(mapped from the upstream SIM-swap package’slast_sim_swap_date) alongside alow/medium/high/unknownrisk level.roaming— serving-network MCC versus home-network MCC, derived from the HLR dip. A SIM provisioned in one country and currently serving in another is a SIM-in-unexpected-country fraud signal.nullmeans indeterminate — do not map it to “not roaming.”
Caching and freshness
A successful rich dip is written to a per-organization result cache with a 10-minute TTL. Re-dipping the same number inside the window serves the cached envelope — no upstream call and no wallet debit — and the response markscached: true.
The tradeoff is deliberate: carrier, line-type, and portability move on
a porting cadence measured in days, so a 10-minute window caps provider
spend without materially lying about those signals. Live reachability
and SIM-swap recency are the genuinely volatile signals — if your flow
screens OTPs or account-recovery sends, treat the cache window as an
upper bound on staleness and dip those specific numbers outside bulk or
scheduled scrubs.
Three properties of the cache worth knowing:
- Tenant-scoped by construction. The key binds your organization plus the normalized E.164, so two organizations dipping the same number never share an entry.
- Sandbox-isolated. Test-mode dips key separately from live dips, so a simulator result never poisons a live cache entry.
- Single-flight. Concurrent misses for the same number coalesce onto one upstream dip and one debit — a poll-happy client re-bills itself at most once per TTL window.
Cost model — per-dip charges and the daily cap
Each dip an upstream answers debits your wallet on thenumber_lookup
pricing channel. The platform fallback rate is 1 cent per query;
per-organization rate overrides apply. Every charge is recorded in your
wallet ledger and feeds the usage and analytics surfaces the same way a
message charge does.
A per-organization daily cost cap boxes runaway spend from a leaked
key or a loop in your own code. It defaults to 5,000 cents ($50) per
day, and you change it under Settings → Billing → API limits. The cap
window is a UTC calendar day and resets at midnight UTC. Crossing the
cap returns 429 with the current and cap amounts in the error details;
a cap of 0 disables Lookup for your organization outright.
To see where today stands against the cap, the lookup-history surface
reports the envelope: the configured cap (daily_cap_cents), today’s
spend (today_spend_cents), and the remainder — daily_cap_cents - today_spend_cents, floored at zero — as cap_remaining_cents. The
same envelope renders in the Number Intelligence console in the
dashboard, alongside per-day spend buckets and the recent-dip feed.
Other billing edges:
- Bulk lookups pre-check your balance for
N × unit priceand fail fast with402before fanning out, then charge per successful result. - Sandbox (
testMode) dips are never billed. - Insufficient balance returns
402 INSUFFICIENT_BALANCEwithbalance_centsandcost_centsso you can prompt a top-up.
What Lookup is not
Two surfaces are easy to confuse with Lookup. Keep them separate:- MCC/MNC resolution at send time — when you actually send, the pricing path resolves the recipient’s MCC/MNC through its own resolution cache so the send prices without a fresh network dip. That is platform-internal send-time plumbing, not a customer-initiated operation: it is never billed to you as a lookup, and it answers “how do I price this send,” not “what can I learn about this number.” The per-(organization, operator) rate override model that layers onto it is documented on the linked page.
- Number Lookup endpoint reference — the
task-level walkthrough: request parameters, the
fields=selector, bulk dips, provider configuration, and the full response schema. This page stays conceptual; that page is the reference.
Worked example — combined HLR + SIM-swap dip
Dip one number for both reachability and SIM-swap recency in a single request (URL-encode the leading+ as %2B):
Fields=line_type_intelligence,sim_swap.
A second identical call inside 10 minutes returns the same envelope with
cached: true and no charge.
Related pages
- Number Lookup — the endpoint walkthrough: selector syntax, bulk dips, provider configuration, billing edges, full schema.
- API reference → Numbers — the OpenAPI
surface for
GET /numbers/lookup/{phone},POST /numbers/lookup, andPOST /numbers/bulk-lookup. - MCC/MNC override model — the send-time network-resolution cache and the per-operator pricing overrides that layer onto it.
- Sender resolution — which sender an outbound message goes out from; the side of the pipeline Lookup never touches.
- Number lifecycle — the lifecycle of numbers your organization owns, as opposed to the third-party numbers a Lookup describes.