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:
| Parameter | Type | Required | Description |
|---|---|---|---|
phone | String | ✅ | Phone number to lookup (E.164 or national format) |
countryCode | String | ✅ | 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:
- Create Twilio Client (Master account)
- Lookup Number via Twilio Lookup API v2
- Validates phone number format
- Returns carrier information
- Provides national format conversion
- 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
country | String | ✅ | 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
country | String | ✅ | 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:
| Parameter | Type | Required | Description |
|---|---|---|---|
country | String | ✅ | 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)
🔗 Related Documentation​
- Twilio Integration Overview - Main Twilio integration
- SMS Provider - SMS pricing usage
- Phone Numbers - Phone number pricing usage
External Resources: