Skip to main content

Twilio Pricing Provider

🎯 Overview​

The Pricing Provider (Providers/pricing.js) provides phone number lookup, validation, and pricing information for SMS, voice calls, and phone numbers across different countries.

Source: external/Integrations/Twilio/Providers/pricing.js

Key Capabilities:

  • Phone number lookup and validation
  • SMS pricing by country
  • Voice call pricing by country
  • Phone number pricing by country
  • Carrier information
  • Number format validation

🔌 Provider Functions​

lookupNumber()​

Validate and retrieve information about a phone number.

Signature:

exports.lookupNumber = async(phone, countryCode);

Parameters:

ParameterTypeRequiredDescription
phoneString✅Phone number to lookup (E.164 or national format)
countryCodeString✅ISO 3166-1 alpha-2 country code (US, GB, CA, etc.)

Returns:

Promise<{
callingCountryCode: string; // Country calling code (+1, +44, etc.)
countryCode: string; // ISO country code
phoneNumber: string; // E.164 formatted number
nationalFormat: string; // National format (e.g., "(212) 555-1234")
valid: boolean; // Whether number is valid
validationErrors: string[]; // Validation error messages
callerName: {
// Caller ID info (if available)
callerName: string;
callerType: string;
errorCode: string;
};
carrier: {
// Carrier information
mobileCountryCode: string;
mobileNetworkCode: string;
name: string; // Carrier name
type: string; // "mobile", "landline", "voip"
errorCode: string;
};
url: string;
}>;

Business Logic:

  1. Create Twilio Client (Master account)
  2. Lookup Number via Twilio Lookup API v2
    • Validates phone number format
    • Returns carrier information
    • Provides national format conversion
  3. Return Lookup Data

Example Usage:

const pricingProvider = require('./Providers/pricing');

// Lookup US phone number
const lookup = await pricingProvider.lookupNumber('+12125551234', 'US');

console.log('Valid:', lookup.valid); // true
console.log('National Format:', lookup.nationalFormat); // (212) 555-1234
console.log('Carrier:', lookup.carrier.name); // Verizon Wireless
console.log('Type:', lookup.carrier.type); // mobile

if (!lookup.valid) {
console.error('Validation errors:', lookup.validationErrors);
}

Lookup International Number:

// Lookup UK number
const ukLookup = await pricingProvider.lookupNumber('+442071234567', 'GB');

console.log('Country:', ukLookup.countryCode); // GB
console.log('Calling Code:', ukLookup.callingCountryCode); // +44
console.log('National Format:', ukLookup.nationalFormat); // 020 7123 4567

Validate Number Format:

// Validate potentially invalid number
const invalid = await pricingProvider.lookupNumber('123456', 'US');

console.log('Valid:', invalid.valid); // false
console.log('Errors:', invalid.validationErrors);
// Output: ["Phone number is invalid"]

Data Flow:

sequenceDiagram
participant API as DashClicks API
participant Provider as Pricing Provider
participant Twilio as Twilio Lookup API v2

API->>Provider: lookupNumber(phone, countryCode)
Provider->>Twilio: lookups.v2.phoneNumbers(phone).fetch()
Note over Twilio: Validate format<br/>Lookup carrier<br/>Get national format
Twilio-->>Provider: Lookup data
Provider-->>API: Return validation + carrier info

style Provider fill:#e3f2fd
style Twilio fill:#fff4e6

getSMSPricing()​

Get SMS pricing information for a specific country.

Signature:

exports.getSMSPricing = async(country);

Parameters:

ParameterTypeRequiredDescription
countryString✅ISO 3166-1 alpha-2 country code

Returns:

Promise<{
country: string; // Country name
isoCountry: string; // Country code
priceUnit: string; // Currency (USD, GBP, etc.)
inboundSmsPrices: Array<{
type: string; // "local", "mobile", "national"
basePrice: string;
currentPrice: string;
}>;
outboundSmsPrices: Array<{
mcc: string; // Mobile Country Code
mnc: string; // Mobile Network Code
carrier: string;
prices: Array<{
type: string; // "sms"
basePrice: string;
currentPrice: string;
}>;
}>;
url: string;
}>;

Example Usage:

// Get US SMS pricing
const smsPricing = await pricingProvider.getSMSPricing('US');

console.log('Country:', smsPricing.country); // United States
console.log('Currency:', smsPricing.priceUnit); // USD

// Outbound SMS price
const outbound = smsPricing.outboundSmsPrices[0];
console.log('Carrier:', outbound.carrier); // AT&T
console.log('Price per SMS:', outbound.prices[0].currentPrice); // 0.0075

// Inbound SMS price
const inbound = smsPricing.inboundSmsPrices.find(p => p.type === 'local');
console.log('Inbound price:', inbound.currentPrice); // 0.0075

Calculate Campaign Cost:

async function calculateSMSCampaignCost(country, messageCount) {
const pricing = await pricingProvider.getSMSPricing(country);

const outboundPrice = parseFloat(pricing.outboundSmsPrices[0].prices[0].currentPrice);

const totalCost = Math.abs(outboundPrice * messageCount);

return {
country: pricing.country,
messageCount,
pricePerSms: outboundPrice,
totalCost: totalCost.toFixed(4),
currency: pricing.priceUnit,
};
}

// Usage
const cost = await calculateSMSCampaignCost('US', 5000);
console.log(`Cost to send 5000 SMS: $${cost.totalCost}`);
// Output: Cost to send 5000 SMS: $37.5000

getCallPricing()​

Get voice call pricing for a specific country.

Signature:

exports.getCallPricing = async(country);

Parameters:

ParameterTypeRequiredDescription
countryString✅ISO 3166-1 alpha-2 country code

Returns:

Promise<{
country: string;
isoCountry: string;
priceUnit: string; // Currency
inboundCallPrices: Array<{
type: string; // "local", "mobile", "national", "toll free"
basePrice: string;
currentPrice: string;
}>;
outboundCallPrices: Array<{
originationPrefixes: string[];
destinationPrefixes: string[];
basePrice: string;
currentPrice: string;
}>;
url: string;
}>;

Example Usage:

// Get US voice call pricing
const callPricing = await pricingProvider.getCallPricing('US');

console.log('Country:', callPricing.country); // United States
console.log('Currency:', callPricing.priceUnit); // USD

// Inbound call pricing
const inbound = callPricing.inboundCallPrices.find(p => p.type === 'local');
console.log('Inbound (local):', inbound.currentPrice); // 0.0085 per minute

const tollFree = callPricing.inboundCallPrices.find(p => p.type === 'toll free');
console.log('Inbound (toll-free):', tollFree.currentPrice); // 0.0220 per minute

// Outbound call pricing
const outbound = callPricing.outboundCallPrices[0];
console.log('Outbound price:', outbound.currentPrice); // 0.0140 per minute

Calculate Call Cost:

async function estimateCallCost(country, durationMinutes) {
const pricing = await pricingProvider.getCallPricing(country);

const outboundPrice = parseFloat(pricing.outboundCallPrices[0].currentPrice);

const totalCost = outboundPrice * durationMinutes;

return {
country: pricing.country,
durationMinutes,
pricePerMinute: outboundPrice,
totalCost: totalCost.toFixed(4),
currency: pricing.priceUnit,
};
}

// Usage
const cost = await estimateCallCost('US', 30);
console.log(`30-minute call cost: $${cost.totalCost}`);
// Output: 30-minute call cost: $0.4200

getPhonePricing()​

Get phone number pricing for a specific country.

Signature:

exports.getPhonePricing = async(country);

Parameters:

ParameterTypeRequiredDescription
countryString✅ISO 3166-1 alpha-2 country code

Returns:

Promise<{
country: string;
isoCountry: string;
phoneNumberPrices: Array<{
type: string; // "local", "mobile", "toll free"
basePrice: string;
currentPrice: string;
}>;
priceUnit: string; // Currency
url: string;
}>;

Example Usage:

// Get US phone number pricing
const phonePricing = await pricingProvider.getPhonePricing('US');

console.log('Country:', phonePricing.country); // United States
console.log('Currency:', phonePricing.priceUnit); // USD

// Local number monthly price
const local = phonePricing.phoneNumberPrices.find(p => p.type === 'local');
console.log('Local number:', local.currentPrice); // 1.00 per month

// Toll-free monthly price
const tollFree = phonePricing.phoneNumberPrices.find(p => p.type === 'toll free');
console.log('Toll-free:', tollFree.currentPrice); // 2.00 per month

// Mobile number monthly price
const mobile = phonePricing.phoneNumberPrices.find(p => p.type === 'mobile');
console.log('Mobile:', mobile?.currentPrice || 'Not available');

Calculate Monthly Phone Number Costs:

async function calculatePhoneNumberCosts(country, counts) {
const pricing = await pricingProvider.getPhonePricing(country);

const localPrice = parseFloat(
pricing.phoneNumberPrices.find(p => p.type === 'local')?.currentPrice || 0,
);

const tollFreePrice = parseFloat(
pricing.phoneNumberPrices.find(p => p.type === 'toll free')?.currentPrice || 0,
);

const localCost = localPrice * (counts.local || 0);
const tollFreeCost = tollFreePrice * (counts.tollFree || 0);

return {
country: pricing.country,
currency: pricing.priceUnit,
local: {
count: counts.local || 0,
priceEach: localPrice,
total: localCost.toFixed(2),
},
tollFree: {
count: counts.tollFree || 0,
priceEach: tollFreePrice,
total: tollFreeCost.toFixed(2),
},
totalMonthlyCost: (localCost + tollFreeCost).toFixed(2),
};
}

// Usage
const cost = await calculatePhoneNumberCosts('US', { local: 10, tollFree: 2 });
console.log('Monthly cost:', cost);
// Output:
// {
// country: 'United States',
// currency: 'USD',
// local: { count: 10, priceEach: 1.00, total: '10.00' },
// tollFree: { count: 2, priceEach: 2.00, total: '4.00' },
// totalMonthlyCost: '14.00'
// }

💡 Integration Examples​

Phone Number Validation Before Purchase​

async function validateAndPurchaseNumber(phoneNumber, countryCode) {
// 1. Validate number format
const lookup = await pricingProvider.lookupNumber(phoneNumber, countryCode);

if (!lookup.valid) {
throw new Error(`Invalid phone number: ${lookup.validationErrors.join(', ')}`);
}

// 2. Check if it's a mobile number (for SMS campaigns)
if (lookup.carrier.type !== 'mobile') {
console.warn(`Number is ${lookup.carrier.type}, not mobile`);
}

// 3. Purchase number
const numberProvider = require('./number-api');
const number = await numberProvider.addProvisionNumber(accountSID, authToken, {
phoneNumber: lookup.phoneNumber, // Use E.164 format from lookup
friendlyName: `${lookup.carrier.name} - ${lookup.nationalFormat}`,
smsUrl: process.env.TWILIO_SMS_URL,
});

return {
number,
carrier: lookup.carrier,
nationalFormat: lookup.nationalFormat,
};
}

Pricing Dashboard​

async function getTwilioPricingDashboard(country = 'US') {
// Get all pricing info
const [smsPricing, callPricing, phonePricing] = await Promise.all([
pricingProvider.getSMSPricing(country),
pricingProvider.getCallPricing(country),
pricingProvider.getPhonePricing(country),
]);

return {
country: smsPricing.country,
currency: smsPricing.priceUnit,
sms: {
outbound: parseFloat(smsPricing.outboundSmsPrices[0].prices[0].currentPrice),
inbound: parseFloat(smsPricing.inboundSmsPrices[0].currentPrice),
},
calls: {
outbound: parseFloat(callPricing.outboundCallPrices[0].currentPrice),
inbound: {
local: parseFloat(callPricing.inboundCallPrices.find(p => p.type === 'local').currentPrice),
tollFree: parseFloat(
callPricing.inboundCallPrices.find(p => p.type === 'toll free')?.currentPrice || 0,
),
},
},
phoneNumbers: {
local: parseFloat(
phonePricing.phoneNumberPrices.find(p => p.type === 'local')?.currentPrice || 0,
),
tollFree: parseFloat(
phonePricing.phoneNumberPrices.find(p => p.type === 'toll free')?.currentPrice || 0,
),
},
};
}

// Usage
const pricing = await getTwilioPricingDashboard('US');
console.log('Pricing Dashboard:', pricing);
// Output:
// {
// country: 'United States',
// currency: 'USD',
// sms: { outbound: 0.0075, inbound: 0.0075 },
// calls: { outbound: 0.014, inbound: { local: 0.0085, tollFree: 0.022 } },
// phoneNumbers: { local: 1.00, tollFree: 2.00 }
// }

Bulk Number Validation​

async function validatePhoneNumbers(phoneNumbers, countryCode) {
const results = {
valid: [],
invalid: [],
byCarrier: {},
};

for (const phone of phoneNumbers) {
try {
const lookup = await pricingProvider.lookupNumber(phone, countryCode);

if (lookup.valid) {
results.valid.push({
phone: lookup.phoneNumber,
nationalFormat: lookup.nationalFormat,
carrier: lookup.carrier.name,
type: lookup.carrier.type,
});

// Count by carrier
const carrier = lookup.carrier.name;
results.byCarrier[carrier] = (results.byCarrier[carrier] || 0) + 1;
} else {
results.invalid.push({
phone,
errors: lookup.validationErrors,
});
}
} catch (error) {
results.invalid.push({
phone,
errors: [error.message],
});
}
}

return results;
}

🚨 Error Handling​

Common Errors​

1. Invalid Phone Number​

Error: 20404 - The requested resource was not found
  • Cause: Phone number format is invalid
  • Solution: Ensure number is in E.164 format or valid national format

2. Country Not Supported​

Error: 20404 - The requested resource was not found
  • Cause: Country code not supported by Twilio
  • Solution: Check supported countries at Twilio Pricing

3. Lookup Rate Limit​

Error: 20429 - Too Many Requests
  • Cause: Exceeded Twilio Lookup API rate limits
  • Solution: Implement rate limiting and caching

⚡ Performance Considerations​

  • Caching: Pricing data changes infrequently, cache for 24 hours
  • Rate Limits: Lookup API has rate limits, implement throttling
  • Batch Validation: For large lists, implement queuing and delays
  • Cost: Lookup API has per-request fees ($0.005-0.01 per lookup)

External Resources:

💬

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:31 AM