VeriRoute IntelGet started
Developer documentationPricing & inclusions

VeriRoute Intel Node.js SDK

Official Node.js/TypeScript SDK for VeriRoute Intel phone number intelligence API.

Features

Endpoint Coverage

SDK method Endpoint
cnam() / cnamBulk() POST /api/v1/cnam / POST /api/v1/cnam/bulk
lrn() / lrnBulk() POST /api/v1/lrn / POST /api/v1/lrn/bulk
messaging() POST /api/v1/messaging
trust() / trustV2() POST /api/v1/trust / POST /api/v2/trust
spam() / spamBatch() POST /api/v1/spam / POST /api/v1/spam/batch
spamEnhanced() POST /api/v1/spam/lookup/enhanced
spamReport() POST /api/v1/spam/report
submitJob() / jobStatus() / jobResults() / listJobs() POST /api/v1/jobs / GET /api/v1/jobs/<id> / GET /api/v1/jobs/<id>/results / GET /api/v1/jobs
analytics() GET /api/v1/analytics
usage() / usageAll() GET /api/v1/reports/usage / GET /api/v1/reports/usage/all
exportHistory() GET /api/v1/reports/export
pricing() GET /api/v1/pricing/all
status() GET /api/v1/status
validateKey() POST /api/v1/auth/validate-key

The single-number lrn() call with includeEnhanced / includeCnam / includeTrust / messagingLookup is the combined-products lookup - one call, one number, every product you select.

Unrecognized response fields are preserved: every typed result carries the untransformed response item on its raw property, so fields added to the API after this SDK release are never silently dropped.

Installation

npm install verirouteintel
yarn add verirouteintel
pnpm add verirouteintel

Quick Start

import { VeriRoute } from 'verirouteintel';

const vri = new VeriRoute('your_api_key');

// CNAM - Get caller name
const caller = await vri.cnam('+15551234567');
console.log(caller.cnam); // "JOHN DOE"

// LRN - Get carrier and line type
const info = await vri.lrn('+15551234567');
console.log(info.carrier);  // "Verizon Wireless"
console.log(info.lineType); // "mobile"

// Trust - Check spam reputation
const trust = await vri.trust('+15551234567');
console.log(trust.isSpam);     // false
console.log(trust.isRobocall); // false

API Reference

Initialization

import { VeriRoute } from 'verirouteintel';

// Simple initialization
const vri = new VeriRoute('your_api_key');

// With options
const vri = new VeriRoute({
  apiKey: 'your_api_key',
  baseUrl: 'https://api-service.verirouteintel.io', // optional
  timeout: 30000, // optional, in milliseconds
  retries: 3,     // optional, retry attempts
});

CNAM Lookup

// Basic CNAM
const result = await vri.cnam('+15551234567');
console.log(result.cnam);     // "JOHN DOE"
console.log(result.number);   // "+15551234567"

// CNAM with spam check
const result = await vri.cnam('+15551234567', { includeSpam: true });
console.log(result.spamType); // "NONE" | "SPAM" | "SCAM" | "ROBOCALL"

// Bulk CNAM (up to 1,000 numbers)
const bulk = await vri.cnamBulk(['+15551234567', '+15559876543']);
console.log(bulk.results);    // Array of CNAM results
console.log(bulk.successful); // 2
console.log(bulk.failed);     // 0

LRN Lookup (Carrier & Line Type)

// Basic LRN
const info = await vri.lrn('+15551234567');
console.log(info.carrier);  // "Verizon Wireless"
console.log(info.lineType); // "mobile" | "landline" | "voip" | "unknown"
console.log(info.lrn);      // "5551230000"

// With enhanced location data
const info = await vri.lrn('+15551234567', { includeEnhanced: true });
console.log(info.enhanced.city);       // "New York"
console.log(info.enhanced.state);      // "NY"
console.log(info.enhanced.zipCode);    // "10001"
console.log(info.enhanced.county);     // "New York County"
console.log(info.enhanced.timezone);   // "America/New_York"
console.log(info.enhanced.rateCenter); // "NWYORK"
console.log(info.enhanced.lata);       // "227"
console.log(info.enhanced.ocn);        // "1001"

// With messaging provider
const info = await vri.lrn('+15551234567', { messagingLookup: true });
console.log(info.messaging.provider);    // "Verizon Wireless"
console.log(info.messaging.enabled);     // true
console.log(info.messaging.country);     // "United States"
console.log(info.messaging.countryCode); // "US"

// With CNAM (caller name)
const info = await vri.lrn('+15551234567', { includeCnam: true });
console.log(info.cnam?.callerName); // "ACME CORP"

// With trust/reputation data
const info = await vri.lrn('+15551234567', { includeTrust: true });
console.log(info.trust?.reputationScore); // 85 (0-100, higher = more trustworthy)
console.log(info.trust?.trustLevel);      // "high" | "medium" | "low"
console.log(info.trust?.isSpam);          // false
console.log(info.trust?.lastUpdated);     // ISO 8601 timestamp

// Full lookup with everything - single API call
const info = await vri.lrn('+15551234567', {
  includeEnhanced: true,
  messagingLookup: true,
  includeCnam: true,
  includeTrust: true,
});

// Bulk LRN with all options
const bulk = await vri.lrnBulk(['+15551234567', '+15559876543'], {
  includeEnhanced: true,
  includeCnam: true,
  includeTrust: true,
});

Trust / Spam Detection

// Full reputation check (v1)
const trust = await vri.trust('+15551234567');
console.log(trust.isSpam);         // false
console.log(trust.isRobocall);     // false
console.log(trust.isScam);         // false
console.log(trust.spamType);       // "NONE"
console.log(trust.complaintCount); // 0
console.log(trust.subjects);       // []
console.log(trust.firstReported);  // null
console.log(trust.lastReported);   // null

// Trust v2 - with reputation scoring
const trust = await vri.trustV2('+15551234567');
console.log(trust.reputationScore); // 0-100, higher = more trustworthy
console.log(trust.trustLevel);      // "high" (>=70), "medium" (40-69), "low" (<40)
console.log(trust.lastUpdated);     // ISO 8601 timestamp
console.log(trust.isSpam);          // false
console.log(trust.complaintCount);  // 0

// Quick spam check
const spam = await vri.spam('+15551234567');
console.log(spam.isSpam);    // false
console.log(spam.spamType);  // "NONE"

// Batch spam check
const batch = await vri.spamBatch(['+15551234567', '+15559876543']);

// Enhanced multi-source spam lookup with composite scoring
const enhanced = await vri.spamEnhanced('+15551234567');
console.log(enhanced.spamScore);       // 0.0-1.0 composite spam score
console.log(enhanced.robocallScore);   // 0.0-1.0
console.log(enhanced.confidence);      // 0.0-1.0 confidence in the verdict
console.log(enhanced.sources);         // Sources with a finding
console.log(enhanced.totalComplaints); // Complaints found across sources

// Report spam
const report = await vri.spamReport('+15551234567', {
  reportType: 'robocall', // 'spam' | 'robocall' | 'scam' | 'telemarketing' | 'fraud' | 'phishing'
  details: 'Automated warranty scam call',
  messageContent: 'Your car warranty is expiring...', // optional
});
console.log(report.success);        // true
console.log(report.phoneNumber);    // "+15551234567" (E.164)
console.log(report.complaintCount); // Total complaints now on record

Messaging Provider

const msg = await vri.messaging('+15551234567');
console.log(msg.messagingProvider);    // "Verizon Wireless"
console.log(msg.messagingEnabled);     // true
console.log(msg.messagingCountry);     // "United States"
console.log(msg.messagingCountryCode); // "US"

Analytics & Usage

// Get analytics
const analytics = await vri.analytics({ preset: '30d' });
console.log(analytics.totalLookups);
console.log(analytics.carrierTypeBreakdown);
console.log(analytics.spamBreakdown);
console.log(analytics.geographicBreakdown);

// Custom date range
const customAnalytics = await vri.analytics({
  startDate: '2025-01-01',
  endDate: '2025-01-31',
});

// Get usage report - with period parameter
const usage = await vri.usage({ period: 'week' }); // 'day', 'week', or 'month'
console.log(usage.totalLookups);
console.log(usage.totalSpent);
console.log(usage.byProduct);    // { cnam: 100, lrn: 200, spam: 50, ... }
console.log(usage.byInterface);  // { api: 300, web: 50, batch: 0 }
console.log(usage.spamBreakdown); // { spam: 10, scam: 5, robocall: 3 }

// Custom date range (overrides period)
const customUsage = await vri.usage({
  startDate: '2024-12-01',
  endDate: '2024-12-31',
  groupBy: 'week', // Time series grouping
});
for (const entry of customUsage.timeSeries) {
  console.log(`${entry.date}: ${entry.count} lookups, $${entry.spent.toFixed(2)}`);
}

// Aggregated usage across ALL of your API keys (same parameters)
const allUsage = await vri.usageAll({ period: 'month' });
console.log(allUsage.totalLookups);

// Export lookup history for this key as CSV
const csv = await vri.exportHistory({ startDate: '2026-08-01', limit: 5000 });
await fs.promises.writeFile('history.csv', csv);

// Validate API key
const isValid = await vri.validateKey();

Pricing & Platform Status

// Current price per lookup for each product - estimate costs programmatically
const rates = await vri.pricing();
console.log(rates); // { lrn: 0.0005, cnam: 0.006, spam: 0.007, ... }
const estimated = rates.lrn * numbers.length;

// Cheap connectivity check - no API key required, never billed
const s = await vri.status();
console.log(s.status); // "operational" | "degraded" | "outage"
for (const component of s.components) {
  console.log(component.name, component.status, component.detail);
}

Async Jobs (up to 100,000 numbers)

For lists beyond the 1,000-number synchronous cap, submit an async job. The job runs in the background at the same per-lookup pricing; the estimated cost is reserved from your balance at submission and settled to actual usage on completion. Duplicates are removed (charged once) and invalid numbers are skipped, reported, and never charged.

// Submit a job
const job = await vri.submitJob(numbers, {
  includeEnhanced: true,
  includeCnam: true,
});
console.log(job.jobId);                 // UUID
console.log(job.status);                // "SUBMITTED"
console.log(job.summary.unique);        // Unique valid numbers to process
console.log(job.summary.invalid);       // Invalid inputs skipped (with examples)
console.log(job.billing.estimatedCost); // Amount reserved from your balance

// Poll for completion
let current = job;
while (current.status !== 'COMPLETED' && current.status !== 'FAILED') {
  await new Promise((r) => setTimeout(r, 5000));
  current = await vri.jobStatus(job.jobId);
}

// Download the result CSV
if (current.status === 'COMPLETED') {
  const csv = await vri.jobResults(job.jobId);
  await fs.promises.writeFile('results.csv', csv);
  console.log(current.billing.actualCost); // Settled cost
}

// List your 50 most recent jobs
const recent = await vri.listJobs();
for (const j of recent.jobs) {
  console.log(j.jobId, j.status);
}

Completion Webhooks

Instead of polling, supply a webhookUrl and VeriRoute Intel POSTs a job.completed event when the job finishes. With a webhookSecret, the request carries an HMAC-SHA256 signature in the X-Webhook-Signature header (sha256=<hex>), computed over the raw request body:

const job = await vri.submitJob(numbers, {
  webhookUrl: 'https://example.com/hooks/vri',
  webhookSecret: 'your-shared-secret',
});

Verify the signature in your handler with verifyWebhookSignature - always against the raw body, never re-serialized JSON:

import { verifyWebhookSignature } from 'verirouteintel';

// Express: use a raw body parser for this route, NOT express.json()
app.post('/hooks/vri', express.raw({ type: 'application/json' }), async (req, res) => {
  const signature = req.header('X-Webhook-Signature') ?? '';
  const valid = await verifyWebhookSignature(req.body, signature, 'your-shared-secret');
  if (!valid) return res.status(401).end();

  const event = JSON.parse(req.body.toString('utf8'));
  console.log(event.job.id, event.job.status);
  res.status(204).end();
});

Webhook URLs must be publicly reachable HTTPS/HTTP addresses; delivery is retried on failure and your endpoint should answer 2xx within 10 seconds.

Error Handling

import {
  VeriRoute,
  VeriRouteError,
  AuthenticationError,
  RateLimitError,
  InsufficientBalanceError,
  InvalidPhoneError,
  InternationalNotSupportedError,
} from 'verirouteintel';

try {
  const result = await vri.lrn('+15551234567');
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key');
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter} seconds`);
  } else if (error instanceof InsufficientBalanceError) {
    console.error('Add credits to your account');
  } else if (error instanceof InvalidPhoneError) {
    console.error(`Invalid phone: ${error.phoneNumber}`);
  } else if (error instanceof InternationalNotSupportedError) {
    console.error('Only US/Canada numbers supported');
  } else if (error instanceof VeriRouteError) {
    console.error(`API error: ${error.code} - ${error.message}`);
  }
}

TypeScript Support

Full TypeScript support with complete type definitions:

import type {
  CnamResult,
  LrnResult,
  EnhancedLrnData,
  MessagingData,
  CnamData,
  TrustData,
  TrustResult,
  TrustResultV2,
  SpamResult,
} from 'verirouteintel';

// Types are inferred automatically
const info = await vri.lrn('+15551234567', {
  includeEnhanced: true,
  includeCnam: true,
  includeTrust: true,
});
// info.enhanced is typed as EnhancedLrnData | undefined
// info.cnam is typed as CnamData | undefined
// info.trust is typed as TrustData | undefined

Shorthand Import

// Full name
import { VeriRoute } from 'verirouteintel';

// Shorthand
import { VRI } from 'verirouteintel';

const vri = new VRI('your_api_key');

Requirements

Links

Changelog

1.3.0

License

MIT

Product prices · public rates

Each selected product adds its per-number cost. Estimates do not submit lookups or charge your wallet.

lrn
$0.000500 per number
enhanced_lrn
$0.000000 per number
messaging_provider
$0.000900 per number
cnam
$0.006000 per number
spam
$0.007000 per number
Pricing & inclusions

Enter opens the first result · Escape closes search