Phone-number intelligence. Line type, carrier, ported-from, fraud signals.
MNP-aware carrier lookup over the same wires that carry Bird's SMS and Voice traffic. One endpoint, same auth, same error envelope as every other Bird channel — because the same engineering team built them all.
import { BirdClient } from "@bird/sdk";
const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });
const { data, error } = await bird.lookup.get({
phone: "+14155550172",
}).safe();
if (error) throw error;
console.log(data);
// → {
// phone: "+14155550172",
// line_type: "mobile",
// carrier: "T-Mobile USA",
// country: "US",
// ported_from: "AT&T Mobility",
// fraud_score: 0.07,
// valid: true,
// }5 minutes from npm install to first lookup
Look up a number from the language you already use.
SDKs in every major runtime. Lookup answers in under 300ms at the median — fast enough to gate an SMS send on it.
import { BirdClient } from "@bird/sdk";
const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });
const { data, error } = await bird.lookup.get({
phone: "+14155550172",
}).safe();Ten fields you'd be assembling from three vendors otherwise.
Concrete data points, named and audit-able. Each one comes from a real source, not a model guessing.
- 01
Line-type detection
Mobile, landline, VoIP, toll-free, premium, pager. Decide whether SMS is even possible before you send.
- 02
Carrier identification
Current carrier name and country code per E.164 input. Updated against MNP registries continuously.
- 03
Ported-from history
The previous carrier the number was ported away from. Useful for routing-cost forecasting and fraud heuristics.
- 04
Country and region format
Returns E.164, national, and international formatting; the country and region codes a router needs.
- 05
Fraud signals
A fraud_score 0-1 per number, blending velocity, line-type heuristics, recent-port flags, and known-bad lists.
- 06
Validity and reachability
A boolean valid and a reachable window — some numbers parse fine but the carrier no longer assigns them.
- 07
Batch lookup
POST a list of up to 1,000 numbers in one call. The same per-number pricing applies; you save the round trips.
- 08
Cache-aware pricing
A 24h cache on identical inputs is free. You only pay when the answer would actually differ.
- 09
Webhooks for batch jobs
For large batches, subscribe lookup.completed and read the result file instead of holding an HTTP connection.
- 10
Same auth, same error envelope
One API key for Lookup, SMS, Email, WhatsApp, Voice. One error type registry across all of them.
Why we build Lookup
Because you shouldn't learn a number is a landline by watching the SMS fail.
We were already running MNP lookups inside Bird SMS routing — we had to, to pick the cheapest carrier route in real time. Lookup is that same query, surfaced as a first-class endpoint, so you can gate signups, score risk, and forecast routing cost without sending a single SMS. Same auth, same error envelope, same webhooks as the rest of the platform.
import { BirdClient } from "@bird/sdk";
const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });
const { data, error } = await bird.lookup.get({
phone: "+14155550172",
}).safe();
if (error) throw error;
console.log(data);
// → {
// phone: "+14155550172",
// line_type: "mobile",
// carrier: "T-Mobile USA",
// country: "US",
// ported_from: "AT&T Mobility",
// fraud_score: 0.07,
// valid: true,
// }Every state change is a webhook.
HMAC-signed payloads, replay-protected, idempotent. Single-number lookups are synchronous; batch lookups fan out as webhooks.
{
"type": "lookup.completed",
"id": "evt_2qB72y...",
"created_at": "2026-05-19T15:42:01.221Z",
"data": {
"lookup_id": "lkp_4hQ8m2nT",
"phone": "+14155550172",
"line_type": "mobile",
"carrier": "T-Mobile USA",
"country": "US",
"ported_from": "AT&T Mobility",
"fraud_score": 0.07,
"valid": true
}
}Retry schedule: 5s, 30s, 5m, 30m, 2h, 6h, 12h. Dead-letter after the final attempt; every dead-lettered event is replayable from the dashboard or API.
lookup.completedA lookup (single or batch) finished. Payload includes the full response.lookup.failedLookup could not be performed; payload includes the error envelope.
Look up the number, then send to it.
Same auth, same idempotency contract, same error envelope. Lookup is shaped like every other endpoint — the difference is that it returns data instead of dispatching a message.
Lookup.
await bird.lookup.get({
phone: "+14155550172",
});Carrier, line type, ported-from, fraud signals — returned synchronously in under 300ms.
SMS.
await bird.sms.send({
from: "Bird",
to: "+14155550172",
text: `Your code is ${code}.`,
});Same auth, same error envelope. Gate the send on the lookup result — drop the landlines before they cost you.