Number Intelligence dashboard: console, metering, and spend caps
Orbit’s Number Intelligence product answers one question about a phone number — what is it, is it live, and how risky is it — through one console and one set of endpoints:- HLR lookups — carrier, line type, portability, reachability.
- Live activity — current on-network reachability, roaming, and serving network.
- Risk signals — SIM-swap recency, identity match, number reputation, SMS-pumping risk, and the fused trust-package verdict.
The lookup console
The console lives under Numbers → Lookup in the dashboard and has three parts:- Single lookup — one number, one verdict. Handy when the compose flow flags a recipient, or you want to eyeball a single suspicious destination before a send.
- Bulk lookup — up to 100 numbers per request, with a per-row result table. This is the pre-flight scrub you run against a campaign audience before launch; drop dead, invalid, or high-risk numbers and only then send.
- Recent lookups + history — the outcome feed and analytics the console renders from your lookup history: every billed lookup with when it ran, the masked number, what it resolved (line type), and what it cost, plus daily totals and the cap remaining for today.
POST /numbers/lookup, GET /numbers/lookup/{phone}, POST /numbers/bulk-lookup, and GET /numbers/lookup-history — so anything you can do in the console, you can automate. The samples below exercise each one.
Run lookups from the API
Authenticate every request withX-API-Key: dv_live_sk_... against https://api.orbit.devotel.io/api/v1. The samples below assume jq for readability; none of the response shapes depend on it.
Single lookup. One number, one request body — { "phone": "<E.164>" } with a fields selector for the fused payload:
dataPackages entry answers with the same discriminated status — available when the provider returned data in data, coming_soon when the upstream is not configured for your deployment, error on a per-field upstream miss. Branch on status, never on the presence of data. The full field catalog is on the Lookup reference.
Bulk lookup. Send up to 100 numbers per request; each row resolves to one result entry:
results are keyed per number — the console bulk table renders this exact array. A row with a non-zero error_code and no resolved payload is a genuine per-number error and is not billed; rows that resolved line-type/carrier data are billed even when the upstream stamps a non-zero error_code on them.
When the wallet cannot cover the batch, the endpoint fails all-or-nothing: the balance pre-flight checks N × unit price before any upstream work and returns 402 INSUFFICIENT_BALANCE — no row resolves and nothing is billed:
details.balance_cents and details.cost_cents to render a top-up prompt. Exceeding the shared daily cap instead returns 429 — retry tomorrow or raise the cap under Settings → Billing → API limits. Retrying the same bulk body collapses onto the same ledger rows (see Metering and spend), so a replay after a 5xx does not double-charge.
Idempotent re-read. GET /numbers/lookup/{phone} returns the same verdict for a re-query — a hit on the short-lived per-org result cache is served without a second upstream dip and without a second charge ("cached": true):
+ as %2B. The response carries the richer shape — carrier, portability, simSwap, roaming, liveStatus, reachable — plus dataPackages when you pass a fields query selector.
Lookup history. The console analytics are one read — the same payload backs the summary card, the daily chart, and the recent-lookups feed:
days bounds the window (max 90) and limit bounds the recent feed. Numbers in the feed arrive already masked; line_type is the outcome the lookup resolved, or null when the upstream carried none.
Node SDK — pre-flight scrub against a campaign audience. The console bulk flow maps directly onto numbers.bulkLookup: send the list, keep the rows that resolved, drop the rest — this is the same filter the console’s bulk table applies before you hit send:
present: "no" (unreachable on-network) is the row class the console flags before a send — keep those out of the campaign. When the pre-flight balance check would reject the batch, wrap the call in a top-up prompt: 402 INSUFFICIENT_BALANCE carries details.balance_cents / details.cost_cents.
Metering and spend
Every upstream-answered lookup is billed to your wallet on thenumber_lookup channel — fallback 1¢/query, per-org overrides apply. The rules that matter operationally:
- Charged on answer. A single lookup is charged after the upstream returns; if the query falls back to local E.164 validation (no upstream call), it is free. Bulk lookups charge per successful row.
- Pre-flight balance check. Bulk lookup checks
N × unit priceagainst your balance before it fans out, and short-circuits with402 INSUFFICIENT_BALANCE— not a partial answer. - Shared daily cap. A per-organization daily cap (default $50/day, configurable from Settings → Billing → API limits) applies across all lookup paths — single, bulk, and any flow that taps the same HLR signal (the compose-time recipient chip counts toward the same bucket). Exceeding the cap returns
429; the console shows cap remaining for today. - Sandbox.
testModerequests are never billed and never count toward the cap. - Bulk idempotency. A retried bulk request collapses onto the same ledger rows — you are not charged twice for the same number in the same request.
Sandbox credits and test-mode lookups are not billed, but they still run the
same upstream dip — use them for end-to-end tests, not for free volume.
Reading the history analytics
GET /numbers/lookup-history returns up to 90 days of lookup activity — the same analytics payload the console renders:
- Summary — total lookups, total spend, today’s spend vs the daily cap, and the dominant wallet currency.
- Daily buckets — a per-day count and spend series for the chart.
- Recent feed — the rows for the log: when each lookup ran, the masked number, the resolved line type when the upstream carried one, and the cost.
Before you send
The console is the diagnostics half of the product. The pre-send half lives in the same surface:- List hygiene — bulk-lookup a campaign audience and drop invalid and unreachable numbers before launch, not after.
- Fraud / ATO gating — dip
sms_pumping_riskandnumber_reputationbefore granting an OTP send; a VOIP/virtual line with recent SIM-swap activity is the classic SMS-pumping / SIM-hijack fingerprint. - Reachability pre-flight —
live_activityfuses current on-network presence, roaming, and the serving network into one verdict, so a parked or dead line doesn’t eat a costly send.
Related guides
- Number Lookup (reference) — endpoint shapes, Fields selector, and the data-package catalog.
- Numbers — the full endpoint reference for every channel.
- Batch DNC pre-flight scrubbing — the compliance half of the pre-send gate (opt-out status, not line intelligence).
- Number health diagnostics — read per-DID health signals and decide swap vs wait vs reroute.
- Rate limits — the shared per-tenant rate-limit taxonomy lookup routes live under.