> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Number Lookup model — which data package answers which question

> The read-only number-intelligence operation: the five dip classes (HLR, ported network, SIM swap, reassigned number, CNAM) and the derived risk packages, what each field in the response means, how the 10-minute result cache trades freshness against cost, and how per-dip charges and the daily cap envelope carry into your wallet.

# 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](/numbers/lookup) and the
[API reference](/api-reference/numbers).

## 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](#cost-model-per-dip-charges-and-the-daily-cap)
  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:

| Package                        | Question it answers                                                                                                                                                                                   | Source                                                                                                               |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `line_type_intelligence` (HLR) | Is this line reachable and present on-network right now, and what is its line type?                                                                                                                   | Devotel HLR home-location-register dip — the primary source; Telnyx is the fallback when HLR is unconfigured         |
| Portability (`portability`)    | Which network does this number currently belong to, and has it been ported away from its original carrier? The donor network often prices differently, so a ported verdict re-prices the destination. | Devotel HLR                                                                                                          |
| `sim_swap`                     | When did the SIM most recently change? A swap inside the last few days is the classic account-takeover pre-OTP screen.                                                                                | GSMA Open Gateway / CAMARA SIM Swap (carrier-asserted last-SIM-change timestamp), with a best-effort Telnyx fallback |
| `reassigned_number`            | Has this US number been permanently disconnected — and possibly given to a new subscriber — since the date you collected consent? Establishes the TCPA reassigned-number safe harbor.                 | FCC Reassigned Numbers Database. US-only; requires a `consent_date` request parameter                                |
| `cnam` / `caller_name`         | What display name do carriers present for this line?                                                                                                                                                  | Telnyx caller-name dip; the pair flips to `coming_soon` when Telnyx is unconfigured                                  |

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](/numbers/lookup) and
[API reference → Numbers](/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](/concepts/mccmnc-override-model)** —
  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](/numbers/lookup)** — 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`):

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/numbers/lookup/%2B14155550100?fields=line_type_intelligence,sim_swap" \
  -H "X-API-Key: dv_live_sk_..."
```

```json theme={null}
{
  "data": {
    "phoneNumber": "+14155550100",
    "valid": true,
    "carrier": { "name": "Verizon", "type": "mobile", "mcc": "310", "mnc": "004" },
    "portability": { "ported": false, "originalCarrier": null },
    "simSwap": { "swapped": false, "lastSwapDate": "2026-04-02", "riskLevel": "low" },
    "liveStatus": "yes",
    "reachable": true,
    "lineStatus": "active",
    "cached": false
  },
  "dataPackages": {
    "line_type_intelligence": {
      "status": "available",
      "reason": "hlr_live",
      "provider": "devotel-hlr",
      "data": { "type": "mobile", "carrier_name": "Verizon", "mobile_country_code": "310", "mobile_network_code": "004" }
    },
    "sim_swap": {
      "status": "available",
      "reason": "camara_sim_swap",
      "provider": "camara",
      "data": { "swapped": false, "last_sim_swap_date": "2026-04-02", "last_sim_swap_date_monitored_period": 240 }
    }
  }
}
```

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.

## Related pages

* [Number Lookup](/numbers/lookup) — the endpoint walkthrough: selector
  syntax, bulk dips, provider configuration, billing edges, full schema.
* [API reference → Numbers](/api-reference/numbers) — the OpenAPI
  surface for `GET /numbers/lookup/{phone}`, `POST /numbers/lookup`, and
  `POST /numbers/bulk-lookup`.
* [MCC/MNC override model](/concepts/mccmnc-override-model) — the
  send-time network-resolution cache and the per-operator pricing
  overrides that layer onto it.
* [Sender resolution](/concepts/sender-resolution) — which sender an
  outbound message goes out from; the side of the pipeline Lookup never
  touches.
* [Number lifecycle](/concepts/number-lifecycle) — the lifecycle of
  numbers your organization owns, as opposed to the third-party numbers
  a Lookup describes.
