Skip to main content

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_lookup pricing 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, a fields= 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 one data 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 flag reachable is liveStatus === "yes", and lineStatus flattens the same signal to active / inactive / unknown so fraud and win-back flows can branch on one discriminator — treat unknown as “no signal,” never as inactive.
  • network (name, type, mcc, mnc) — the current (recipient) network and its line type, reported on the response as carrier: network.name is the operator label, network.type is mobile, landline, or voip, 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.originalCarrier names the network the number was ported away from; when the upstream omits it, it is null rather than fabricated.
  • simSwap (swapped, lastSwapDate, riskLevel) — the recency verdict. swapped is true when the SIM changed inside the carrier’s monitored window, null when the operator gives no answer; the date of the most recent change lands in lastSwapDate (mapped from the upstream SIM-swap package’s last_sim_swap_date) alongside a low / medium / high / unknown risk 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. null means indeterminate — do not map it to “not roaming.”
The full Annotated schema for every field is in Number Lookup and API reference → Numbers.

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 marks cached: 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.
A cache outage degrades to a pass-through fresh dip; it never fails the lookup itself.

Cost model — per-dip charges and the daily cap

Each dip an upstream answers debits your wallet on the number_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 price and fail fast with 402 before fanning out, then charge per successful result.
  • Sandbox (testMode) dips are never billed.
  • Insufficient balance returns 402 INSUFFICIENT_BALANCE with balance_cents and cost_cents so 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):
One HTTP call, one base debit; the two packages ride the same dip a migrating Twilio integration would send with Fields=line_type_intelligence,sim_swap. A second identical call inside 10 minutes returns the same envelope with cached: true and no charge.
  • 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, and POST /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.