Prerequisites
- Node.js 18+ (native
fetchis available without any packages) - A free VeriRouteIntel API key — get yours here (a free API sandbox included, no credit card)
Step 1: Get Your API Key
Sign up at verirouteintel.com/signup. After confirming your email, your API key appears on the dashboard under API Keys. Copy it — you'll pass it as a Bearer token in every request.
Store it as an environment variable rather than hardcoding it:
export VRI_API_KEY="your_key_here"
Or add it to a .env file if you're using dotenv.
Step 2: Make Your First Lookup (JavaScript)
No npm packages needed for the request itself. Node.js 18+ ships fetch natively.
// carrier-lookup.js
const API_KEY = process.env.VRI_API_KEY;
const BASE_URL = 'https://verirouteintel.com/api/v1';
async function lookupCarrier(phoneNumber) {
const response = await fetch(`${BASE_URL}/lrn`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
phone_number: phoneNumber,
include_enhanced_lrn: true,
messaging_lookup: true,
}),
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Lookup failed [${response.status}]: ${error.error || response.statusText}`);
}
return response.json();
}
// Usage
(async () => {
const result = await lookupCarrier('14155550100');
console.log(result);
})();
Run it:
VRI_API_KEY=your_key_here node carrier-lookup.js
Step 3: TypeScript Version
The same function with full type coverage:
// carrier-lookup.ts
interface EnhancedLRN {
carrier: string;
carrier_type: 'mobile' | 'landline' | 'voip' | 'unknown';
city: string;
zip_code: string;
}
interface MessagingInfo {
provider: string | null;
enabled: boolean;
country: string;
country_code: string;
reference_id: string;
}
interface CarrierLookupResult {
phone_number: string;
lrn: string;
lrn_activated_at: string | null;
enhanced_lrn: EnhancedLRN;
messaging: MessagingInfo;
}
const API_KEY = process.env.VRI_API_KEY!;
const BASE_URL = 'https://verirouteintel.com/api/v1';
async function lookupCarrier(phoneNumber: string): Promise<CarrierLookupResult> {
const response = await fetch(`${BASE_URL}/lrn`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
phone_number: phoneNumber,
include_enhanced_lrn: true,
messaging_lookup: true,
}),
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Lookup failed [${response.status}]: ${error.error || response.statusText}`);
}
return response.json() as Promise<CarrierLookupResult>;
}
export { lookupCarrier, CarrierLookupResult, MessagingInfo, EnhancedLRN };
Step 4: Parse the Response
A successful lookup returns:
{
"phone_number": "14155550100",
"lrn": "14153000000",
"lrn_activated_at": "2018-03-15T00:00:00Z",
"enhanced_lrn": {
"carrier": "T-Mobile USA",
"carrier_type": "mobile",
"city": "San Francisco",
"zip_code": "94102"
},
"messaging": {
"provider": "Twilio",
"enabled": true,
"country": "United States",
"country_code": "US",
"reference_id": "MSG-ref-abc123"
}
}
| Field | What it tells you |
|---|---|
lrn |
Line Routing Number — reflects number porting |
lrn_activated_at |
When this LRN was last activated; a recent date signals a recent port |
enhanced_lrn.carrier |
The voice network: AT&T, Verizon, T-Mobile, or regional MVNO |
enhanced_lrn.carrier_type |
mobile, landline, or voip — essential for TCPA scoping |
messaging.provider |
The SMS aggregator: Twilio, Bandwidth, Sinch, Telnyx, Vonage, etc. |
messaging.enabled |
Whether the number can receive SMS at all |
Step 5: Error Handling
The API uses standard HTTP status codes. Here's a production-ready error handler:
async function lookupCarrierSafe(phoneNumber) {
try {
const response = await fetch(`${BASE_URL}/lrn`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
phone_number: phoneNumber,
include_enhanced_lrn: true,
messaging_lookup: true,
}),
});
const data = await response.json();
switch (response.status) {
case 200:
return { success: true, data };
case 400:
return { success: false, error: 'Invalid phone number format', code: 'INVALID_NUMBER' };
case 401:
return { success: false, error: 'Invalid or missing API key', code: 'AUTH_ERROR' };
case 402:
return { success: false, error: 'Insufficient account balance', code: 'INSUFFICIENT_BALANCE' };
case 429:
return { success: false, error: 'Rate limit exceeded — retry after delay', code: 'RATE_LIMITED' };
default:
return { success: false, error: data.error || 'Unknown error', code: 'API_ERROR' };
}
} catch (err) {
return { success: false, error: 'Network error', code: 'NETWORK_ERROR' };
}
}
Retry strategy: retry on 429 with exponential backoff. Do not retry on 400 (bad input) or 402 (account balance) — those require action before retrying.
Bulk Lookups for High-Volume Use Cases
For campaign pre-flight, lead list validation, or contact center hygiene, use the /api/v1/lrn/bulk endpoint. It accepts up to 1,000 numbers per request, deduplicates automatically, and bills only for unique numbers.
const response = await fetch(`${BASE_URL}/lrn/bulk`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
phone_numbers: ['14155550100', '12125550199', '13105550177'],
include_messaging: true,
}),
});
const { results, summary, billing } = await response.json();
// summary.duplicates_removed shows how many numbers were deduplicated
// billing.actual_cost shows the final charge
Copy the code — free API key. VeriRouteIntel includes a free API sandbox. No credit card required.
Get your free API keyFrequently Asked Questions
What's the difference between a carrier and a messaging provider?
The carrier is the voice network — AT&T, Verizon, T-Mobile, or a regional MVNO. The messaging provider is the SMS aggregator sitting between the carrier and the sender: Twilio, Bandwidth, Sinch, Telnyx, Vonage, and others. A Verizon subscriber can have their SMS traffic routed through Bandwidth. Most carrier lookup APIs return only the voice carrier; VeriRouteIntel returns both in a single call.
Does this work for ported numbers?
Yes. The API uses LRN (Line Routing Number) data, which reflects the current routing state of a number including porting events. The lrn_activated_at field shows when the current LRN was activated — a recent date indicates a recent port.
What phone number formats does the API accept?
The API accepts NANP (North American Numbering Plan) numbers in any common format: 10-digit (4155550100), E.164 (+14155550100), or punctuated (415-555-0100). The API normalizes the number before lookup.
What's the rate limit on the free sandbox?
Every account includes a free API sandbox, and standard API rate limits apply. For high-volume throughput requirements, see the pricing page for plan options.