- C#
- Python
- NodeJS
Phone Validation International C# Rest Code Snippet
using System.Text.Json;
using System.Web;
namespace phone_validation_international_dot_net.REST
{
/// <summary>
/// Provides functionality to call the ServiceObjects Phone Validation International (PVI) REST API's GetPhoneDetails endpoint,
/// retrieving comprehensive carrier and exchange information for a given phone number with fallback to a backup endpoint for reliability in live mode.
/// </summary>
public class GetPhoneDetailsClient
{
// Base URL constants: production, backup, and trial
private const string LiveBaseUrl = "https://sws.serviceobjects.com/PVI/";
private const string BackupBaseUrl = "https://swsbackup.serviceobjects.com/PVI/";
private const string TrialBaseUrl = "https://trial.serviceobjects.com/PVI/";
/// <summary>
/// Synchronously calls the GetPhoneDetails REST endpoint to retrieve phone details,
/// attempting the primary endpoint first and falling back to the backup if the response is invalid
/// (Error.Status == "500") in live mode.
/// </summary>
/// <param name="input">The input parameters including phone number, country, options, and authentication ID.</param>
/// <returns>Deserialized <see cref="PVIResponse"/> containing phone details or an error.</returns>
public static PVIResponseWrapper Invoke(GetPhoneDetailsInput input)
{
// Use query string parameters so missing/optional fields don't break the URL
string url = BuildUrl(input, input.IsLive ? LiveBaseUrl : TrialBaseUrl);
string jsonResponse = Helper.HttpGet(url, input.TimeoutSeconds);
bool IsValid = true;
PVIResponseWrapper response = new();
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
if (jsonResponse.Replace(" ", "").Contains("\"status\":4"))
{
response.ProblemDetails = JsonSerializer.Deserialize<ProblemDetails>(jsonResponse, options);
}
else if (jsonResponse.Replace(" ", "").Contains("\"status\":5"))
{
IsValid = false;
}
else
{
response.PhoneDetails = JsonSerializer.Deserialize<PhoneDetails>(jsonResponse, options);
}
// Fallback on error in live mode
if (input.IsLive && !IsValid)
{
string fallbackUrl = BuildUrl(input, BackupBaseUrl);
string fallbackJsonResponse = Helper.HttpGet(fallbackUrl, input.TimeoutSeconds);
response = new();
if (fallbackJsonResponse.Replace(" ", "").Contains("\"status\":4") || fallbackJsonResponse.Replace(" ", "").Contains("\"status\":5"))
{
response.ProblemDetails = JsonSerializer.Deserialize<ProblemDetails>(jsonResponse, options);
}
else
{
response.PhoneDetails = JsonSerializer.Deserialize<PhoneDetails>(jsonResponse, options);
}
return response;
}
return response;
}
/// <summary>
/// Asynchronously calls the GetPhoneDetails REST endpoint to retrieve phone details,
/// attempting the primary endpoint first and falling back to the backup if the response is invalid
/// (Error.Status == "500") in live mode.
/// </summary>
/// <param name="input">The input parameters including phone number, country, options, and authentication ID.</param>
/// <returns>Deserialized <see cref="PVIResponse"/> containing phone details or an error.</returns>
public static async Task<PVIResponseWrapper> InvokeAsync(GetPhoneDetailsInput input)
{
// Use query string parameters so missing/optional fields don't break the URL
string url = BuildUrl(input, input.IsLive ? LiveBaseUrl : TrialBaseUrl);
string jsonResponse = await Helper.HttpGetAsync(url, input.TimeoutSeconds).ConfigureAwait(false);
bool IsValid = true;
PVIResponseWrapper response = new();
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
if (jsonResponse.Replace(" ", "").Contains("\"status\":4"))
{
response.ProblemDetails = JsonSerializer.Deserialize<ProblemDetails>(jsonResponse, options);
}
else if (jsonResponse.Replace(" ", "").Contains("\"status\":5"))
{
IsValid = false;
}
else
{
response.PhoneDetails = JsonSerializer.Deserialize<PhoneDetails>(jsonResponse, options);
}
if (input.IsLive && !IsValid)
{
string fallbackUrl = BuildUrl(input, BackupBaseUrl);
string fallbackJsonResponse = await Helper.HttpGetAsync(fallbackUrl, input.TimeoutSeconds).ConfigureAwait(false);
response = new();
if (fallbackJsonResponse.Replace(" ", "").Contains("\"status\":4") || fallbackJsonResponse.Replace(" ", "").Contains("\"status\":5"))
{
response.ProblemDetails = JsonSerializer.Deserialize<ProblemDetails>(jsonResponse, options);
}
else
{
response.PhoneDetails = JsonSerializer.Deserialize<PhoneDetails>(jsonResponse, options);
}
return response;
}
return response;
}
// Build the full request URL, including URL-encoded query string
public static string BuildUrl(GetPhoneDetailsInput input, string baseUrl)
{
// Construct query string with URL-encoded parameters
string qs = $"GetPhoneDetails?" +
$"Phone={Helper.UrlEncode(input.Phone)}" +
$"&Country={Helper.UrlEncode(input.Country)}" +
$"&Options={Helper.UrlEncode(input.Options)}" +
$"&AuthID={Helper.UrlEncode(input.AuthID)}";
return baseUrl + qs;
}
/// <summary>
/// Input parameters for the GetPhoneDetails API call. Represents a phone number to retrieve details for.
/// </summary>
/// <param name="Phone">The phone number to validate (variable digit length).</param>
/// <param name="Country">The location of the phone number (1-3 digit Country Calling Code, ISO2, ISO3, or Country Name).</param>
/// <param name="Options">Comma-separated list of optional parameters. Optional.</param>
/// <param name="AuthID">The authentication ID provided by Service Objects.</param>
/// <param name="IsLive">Indicates whether to use the live service (true) or trial service (false).</param>
/// <param name="TimeoutSeconds">Timeout duration for the API call, in seconds.</param>
public record GetPhoneDetailsInput(
string Phone = "",
string Country = "",
string Options = "",
string AuthID = "",
bool IsLive = true,
int TimeoutSeconds = 15
);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace phone_validation_international_dot_net.REST
{
public class PVIResponseWrapper
{
public PhoneDetails? PhoneDetails;
public ProblemDetails? ProblemDetails;
public PVIResponseWrapper() { }
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Web;
namespace phone_validation_international_dot_net.REST
{
public static class Helper
{
private static readonly HttpClient _client = new HttpClient();
public static async Task<string> HttpGetAsync(string url, int timeoutSeconds)
{
_client.Timeout = TimeSpan.FromSeconds(timeoutSeconds);
HttpResponseMessage response = await _client.GetAsync(url).ConfigureAwait(false);
string jsonResponse = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return jsonResponse;
}
public static string HttpGet(string url, int timeoutSeconds)
{
_client.Timeout = TimeSpan.FromSeconds(timeoutSeconds);
HttpResponseMessage response = _client.GetAsync(url).GetAwaiter().GetResult();
string jsonResponse = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
return jsonResponse;
}
public static string UrlEncode(string value) => HttpUtility.UrlEncode(value ?? string.Empty);
}
}
Phone Validation International Python Rest Code Snippet
from pvi_response import PVIResponse, TimeZone, ProblemDetails, ServiceProvider
import requests
import json
# Endpoint URLs for ServiceObjects Phone Validation International (PVI) API
primary_url = "https://sws.serviceobjects.com/PVI/GetPhoneDetails?"
backup_url = "https://swsbackup.serviceobjects.com/PVI/GetPhoneDetails?"
trial_url = "https://trial.serviceobjects.com/PVI/GetPhoneDetails?"
def get_phone_details(
phone: str,
country: str = "",
options: str = "",
auth_id: str = "",
is_live: bool = True,
timeout_seconds: int = 15
) -> PVIResponse:
"""
Calls the ServiceObjects Phone Validation International (PVI) API's GetPhoneDetails endpoint
to retrieve phone details (e.g., carrier, line type, time zones) for a given phone number.
Validates input parameters and returns a ProblemDetails response if invalid. Uses a backup endpoint for reliability in live mode.
Args:
phone (str): The phone number to validate (e.g., "+12025550123").
country (str, optional): The country code or name (e.g., "US"). Optional.
options (str, optional): Optional. Reserved for future use.
auth_id (str): Required. Authentication ID provided by Service Objects.
is_live (bool, optional): Option to use live service (true) or trial service (false). Defaults to True.
timeout_seconds (int, optional): Timeout in seconds for the HTTP request. Defaults to 15.
Returns:
PVIResponse: Parsed JSON response with phone details or a ProblemDetails if validation fails or the API call fails.
Raises:
RuntimeError: If the API returns an error payload with status "500".
requests.RequestException: On network/HTTP failures (trial mode).
"""
params = {
"Phone": phone,
"Country": country,
"Options": options,
"AuthID": auth_id
}
url = primary_url if is_live else trial_url
try:
# Attempt primary (or trial) endpoint
response = requests.get(url, params=params, timeout=timeout_seconds)
response.raise_for_status()
data = response.json()
# If API returned an error in JSON payload, trigger fallback
problem_details = data.get('ProblemDetails')
if problem_details:
if is_live:
# Try backup URL
response = requests.get(backup_url, params=params, timeout=timeout_seconds)
response.raise_for_status()
data = response.json()
problem_details = data.get('ProblemDetails')
if problem_details:
return PVIResponse(ProblemDetails=ProblemDetails(**problem_details))
else:
# Trial mode error is terminal
return PVIResponse(ProblemDetails=ProblemDetails(**problem_details))
# Convert JSON response to PVIResponse for structured access
#problem_details = ProblemDetails(**data.get("ProblemDetails", {})) if data.get("ProblemDetails") else None
return PVIResponse(
Score=data.get("score"),
PhoneIn=data.get("phoneIn"),
CountryCode=data.get("countryCode"),
FormatNational=data.get("formatNational"),
FormatInternational=data.get("formatInternational"),
FormatE164=data.get("formatE164"),
Extension=data.get("extension"),
Locality=data.get("locality"),
AdminArea=data.get("adminArea"),
AdminAreaAbbr=data.get("adminAreaAbbr"),
Country=data.get("country"),
CountryISO2=data.get("countryISO2"),
CountryISO3=data.get("countryISO3"),
Latitude=data.get("latitude"),
Longitude=data.get("longitude"),
LatLongMatchLevel=data.get("latLongMatchLevel"),
TimeZones=[
TimeZone(
ZoneName=zone.get("zoneName"),
ZoneAbbr=zone.get("zoneAbbr"),
CountryISO3=zone.get("countryISO3"),
UtcOffset=zone.get("utcOffset")
)
for zone in data.get("timeZones", [])
] if "timeZones" in data else [],
LineType=data.get("lineType"),
SmsAddress=data.get("smsAddress"),
ValidPhone=data.get("validPhone"),
ValidPhoneLength=data.get("validPhoneLength"),
Notes=data.get("notes", []),
Warnings=data.get("warnings", []),
CurrentProvider=ServiceProvider(
ProviderID=data.get("currentProvider", {}).get("providerID"),
ProviderName=data.get("currentProvider", {}).get("providerName"),
CountryISO3=data.get("currentProvider", {}).get("countryISO3")
) if data.get("currentProvider") else None,
PreviousProvider=ServiceProvider(
ProviderID=data.get("previousProvider", {}).get("providerID"),
ProviderName=data.get("previousProvider", {}).get("providerName"),
CountryISO3=data.get("previousProvider", {}).get("countryISO3")
) if data.get("previousProvider") else None,
OriginalProvider=ServiceProvider(
ProviderID=data.get("originalProvider", {}).get("providerID"),
ProviderName=data.get("originalProvider", {}).get("providerName"),
CountryISO3=data.get("originalProvider", {}).get("countryISO3")
) if data.get("originalProvider") else None,
LastPortedDate=data.get("lastPortedDate")
)
except requests.RequestException as req_exc:
# Network or HTTP-level error occurred
if is_live:
try:
# Fallback to backup URL
response = requests.get(backup_url, params=params, timeout=timeout_seconds)
response.raise_for_status()
data = response.json()
problem_details = data.get('ProblemDetails')
if problem_details:
return PVIResponse(ProblemDetails=ProblemDetails(**problem_details))
#problem_details = ProblemDetails(**data.get("ProblemDetails", {})) if data.get("ProblemDetails") else None
return PVIResponse(
Score=data.get("score"),
PhoneIn=data.get("phoneIn"),
CountryCode=data.get("countryCode"),
FormatNational=data.get("formatNational"),
FormatInternational=data.get("formatInternational"),
FormatE164=data.get("formatE164"),
Extension=data.get("extension"),
Locality=data.get("locality"),
AdminArea=data.get("adminArea"),
AdminAreaAbbr=data.get("adminAreaAbbr"),
Country=data.get("country"),
CountryISO2=data.get("countryISO2"),
CountryISO3=data.get("countryISO3"),
Latitude=data.get("latitude"),
Longitude=data.get("longitude"),
LatLongMatchLevel=data.get("latLongMatchLevel"),
TimeZones=[
TimeZone(
ZoneName=zone.get("zoneName"),
ZoneAbbr=zone.get("zoneAbbr"),
CountryISO3=zone.get("countryISO3"),
UtcOffset=zone.get("utcOffset")
)
for zone in data.get("timeZones", [])
] if "timeZones" in data else [],
LineType=data.get("lineType"),
SmsAddress=data.get("smsAddress"),
ValidPhone=data.get("validPhone"),
ValidPhoneLength=data.get("validPhoneLength"),
Notes=data.get("notes", []),
Warnings=data.get("warnings", []),
CurrentProvider=ServiceProvider(
ProviderID=data.get("currentProvider", {}).get("providerID"),
ProviderName=data.get("currentProvider", {}).get("providerName"),
CountryISO3=data.get("currentProvider", {}).get("countryISO3")
) if data.get("currentProvider") else None,
PreviousProvider=ServiceProvider(
ProviderID=data.get("previousProvider", {}).get("providerID"),
ProviderName=data.get("previousProvider", {}).get("providerName"),
CountryISO3=data.get("previousProvider", {}).get("countryISO3")
) if data.get("previousProvider") else None,
OriginalProvider=ServiceProvider(
ProviderID=data.get("originalProvider", {}).get("providerID"),
ProviderName=data.get("originalProvider", {}).get("providerName"),
CountryISO3=data.get("originalProvider", {}).get("countryISO3")
) if data.get("originalProvider") else None,
LastPortedDate=data.get("lastPortedDate")
)
except Exception as backup_exc:
data = json.loads(backup_exc.response.content)
problem_details = ProblemDetails(
Type=data["type"],
Title=data["title"],
Status=data["status"]
)
return PVIResponse(
ProblemDetails=problem_details
)
else:
data = json.loads(req_exc.response.content)
problem_details = ProblemDetails(
Type=data["type"],
Title=data["title"],
Status=data["status"]
)
return PVIResponse(
ProblemDetails=problem_details
)
"""
Response classes for Phone Validation International (PVI) API.
"""
from dataclasses import dataclass
from typing import Optional, List
@dataclass
class TimeZone:
ZoneName: Optional[str] = None
ZoneAbbr: Optional[str] = None
CountryISO3: Optional[str] = None
UtcOffset: Optional[str] = None
def __str__(self) -> str:
return (f"TimeZone: ZoneName={self.ZoneName}, ZoneAbbr={self.ZoneAbbr}, "
f"CountryISO3={self.CountryISO3}, UtcOffset={self.UtcOffset}")
@dataclass
class ServiceProvider:
ProviderID: Optional[str] = None
ProviderName: Optional[str] = None
CountryISO3: Optional[str] = None
def __str__(self) -> str:
return (f"ServiceProvider: ProviderID={self.ProviderID}, ProviderName={self.ProviderName}, "
f"CountryISO3={self.CountryISO3}")
@dataclass
class ProblemDetails:
Type: Optional[str] = None
Title: Optional[str] = None
Status: Optional[str] = None
Detail: Optional[str] = None
def __str__(self) -> str:
return (f"ProblemDetails: Type={self.Type}, Title={self.Title}, "
f"Status={self.Status}, Detail={self.Detail}")
@dataclass
class PVIResponse:
Score: Optional[str] = None
PhoneIn: Optional[str] = None
CountryCode: Optional[str] = None
FormatNational: Optional[str] = None
FormatInternational: Optional[str] = None
FormatE164: Optional[str] = None
Extension: Optional[str] = None
Locality: Optional[str] = None
AdminArea: Optional[str] = None
AdminAreaAbbr: Optional[str] = None
Country: Optional[str] = None
CountryISO2: Optional[str] = None
CountryISO3: Optional[str] = None
Latitude: Optional[float] = None
Longitude: Optional[float] = None
LatLongMatchLevel: Optional[str] = None
TimeZones: Optional[List['TimeZone']] = None
LineType: Optional[str] = None
SmsAddress: Optional[str] = None
ValidPhone: Optional[bool] = None
ValidPhoneLength: Optional[bool] = None
Notes: Optional[List[str]] = None
Warnings: Optional[List[str]] = None
CurrentProvider: Optional['ServiceProvider'] = None
PreviousProvider: Optional['ServiceProvider'] = None
OriginalProvider: Optional['ServiceProvider'] = None
LastPortedDate: Optional[str] = None
ProblemDetails: Optional['ProblemDetails'] = None
def __post_init__(self):
if self.TimeZones is None:
self.TimeZones = []
if self.Notes is None:
self.Notes = []
if self.Warnings is None:
self.Warnings = []
def __str__(self) -> str:
"""
Convert the phone details response to a string representation.
"""
time_zones_string = ', '.join(str(zone) for zone in self.TimeZones) if self.TimeZones else 'None'
notes_string = f"[{', '.join(self.Notes)}]" if self.Notes else 'None'
warnings_string = f"[{', '.join(self.Warnings)}]" if self.Warnings else 'None'
current_provider = str(self.CurrentProvider) if self.CurrentProvider else 'None'
previous_provider = str(self.PreviousProvider) if self.PreviousProvider else 'None'
original_provider = str(self.OriginalProvider) if self.OriginalProvider else 'None'
problem_details = str(self.ProblemDetails) if self.ProblemDetails else 'None'
return (f"PVIResponse: Score={self.Score}, PhoneIn={self.PhoneIn}, CountryCode={self.CountryCode}, "
f"FormatNational={self.FormatNational}, FormatInternational={self.FormatInternational}, "
f"FormatE164={self.FormatE164}, Extension={self.Extension}, Locality={self.Locality}, "
f"AdminArea={self.AdminArea}, AdminAreaAbbr={self.AdminAreaAbbr}, Country={self.Country}, "
f"CountryISO2={self.CountryISO2}, CountryISO3={self.CountryISO3}, Latitude={self.Latitude}, "
f"Longitude={self.Longitude}, LatLongMatchLevel={self.LatLongMatchLevel}, "
f"LineType={self.LineType}, SmsAddress={self.SmsAddress}, ValidPhone={self.ValidPhone}, "
f"ValidPhoneLength={self.ValidPhoneLength}, LastPortedDate={self.LastPortedDate}, "
f"TimeZones=[{time_zones_string}], Notes={notes_string}, Warnings={warnings_string}, "
f"CurrentProvider={current_provider}, PreviousProvider={previous_provider}, "
f"OriginalProvider={original_provider}, ProblemDetails={problem_details}")
Phone Validation International NodeJS Rest Code Snippet
import axios from 'axios';
import querystring from 'querystring';
import { PVIResponse } from './pvi_response.js';
/**
* @constant
* @type {string}
* @description The base URL for the live ServiceObjects Phone Validation International (PVI) API service.
*/
const LiveBaseUrl = 'https://sws.serviceobjects.com/PVI/';
/**
* @constant
* @type {string}
* @description The base URL for the backup ServiceObjects Phone Validation International (PVI) API service.
*/
const BackupBaseUrl = 'https://swsbackup.serviceobjects.com/PVI/';
/**
* @constant
* @type {string}
* @description The base URL for the trial ServiceObjects Phone Validation International (PVI) API service.
*/
const TrialBaseUrl = 'https://trial.serviceobjects.com/PVI/';
/**
* Checks if a response from the API is valid by verifying that it either has no ProblemDetails object
* or the ProblemDetails.Status is not equal to 500.
* @param {PVIResponse} response - The API response object to validate.
* @returns {boolean} True if the response is valid, false otherwise.
*/
const isValid = (response) => !response?.ProblemDetails || response.ProblemDetails.Status !== 500;
/**
* Constructs a full URL for the GetPhoneDetails API endpoint by combining the base URL
* with URL-encoded query parameters derived from the input parameters.
* @param {Object} params - An object containing all the input parameters.
* @param {string} baseUrl - The base URL for the API service (live, backup, or trial).
* @returns {string} The constructed URL with query parameters.
*/
const buildUrl = (params, baseUrl) =>
`${baseUrl}GetPhoneDetails?${querystring.stringify(params)}`;
/**
* Performs an HTTP GET request to the specified URL with a given timeout.
* @param {string} url - The URL to send the GET request to.
* @param {number} timeoutSeconds - The timeout duration in seconds for the request.
* @returns {Promise<PVIResponse>} A promise that resolves to a PVIResponse object containing the API response data.
* @throws {Error} If the HTTP request fails, with a message detailing the error.
*/
export const httpGet = async (url, timeoutSeconds) => {
let result = new PVIResponse();
try {
const response = await axios.get(url, { timeout: timeoutSeconds * 1000 });
if (response.status === 200) {
result.Score = response.data.score ?? null;
result.PhoneIn = response.data.phoneIn ?? null;
result.CountryCode = response.data.countryCode ?? null;
result.FormatNational = response.data.formatNational ?? null;
result.FormatInternational = response.data.formatInternational ?? null;
result.FormatE164 = response.data.formatE164 ?? null;
result.Extension = response.data.extension ?? null;
result.Locality = response.data.locality ?? null;
result.AdminArea = response.data.adminArea ?? null;
result.AdminAreaAbbr = response.data.adminAreaAbbr ?? null;
result.Country = response.data.country ?? null;
result.CountryISO2 = response.data.countryISO2 ?? null;
result.CountryISO3 = response.data.countryISO3 ?? null;
result.Latitude = response.data.latitude ?? null;
result.Longitude = response.data.longitude ?? null;
result.LatLongMatchLevel = response.data.latLongMatchLevel ?? null;
result.TimeZones = response.data.timeZones ?? [];
result.LineType = response.data.lineType ?? null;
result.SmsAddress = response.data.smsAddress ?? null;
result.ValidPhone = response.data.validPhone ?? null;
result.ValidPhoneLength = response.data.validPhoneLength ?? null;
result.Notes = response.data.notes ?? null;
result.Warnings = response.data.warnings ?? null;
result.CurrentProvider = response.data.currentProvider ?? null;
result.PreviousProvider = response.data.previousProvider ?? null;
result.OriginalProvider = response.data.originalProvider ?? null;
result.LastPortedDate = response.data.lastPortedDate ?? null;
result.ProblemDetails = null;
} else {
result.ProblemDetails = {
Title: "Service Objects Error",
Status: response.status,
Detail: response.statusText
};
result.Score = null;
result.PhoneIn = null;
result.CountryCode = null;
result.FormatNational = null;
result.FormatInternational = null;
result.FormatE164 = null;
result.Extension = null;
result.Locality = null;
result.AdminArea = null;
result.AdminAreaAbbr = null;
result.Country = null;
result.CountryISO2 = null;
result.CountryISO3 = null;
result.Latitude = null;
result.Longitude = null;
result.LatLongMatchLevel = null;
result.TimeZones = [];
result.LineType = null;
result.SmsAddress = null;
result.ValidPhone = null;
result.ValidPhoneLength = null;
result.Notes = null;
result.Warnings = null;
result.CurrentProvider = null;
result.PreviousProvider = null;
result.OriginalProvider = null;
result.LastPortedDate = null;
}
} catch (error) {
result.ProblemDetails = {
type: error.response.data.type,
title: error.response.data.title,
status: error.response.data.status,
detail: error.response.data.detail
};
result.Score = null;
result.PhoneIn = null;
result.CountryCode = null;
result.FormatNational = null;
result.FormatInternational = null;
result.FormatE164 = null;
result.Extension = null;
result.Locality = null;
result.AdminArea = null;
result.AdminAreaAbbr = null;
result.Country = null;
result.CountryISO2 = null;
result.CountryISO3 = null;
result.Latitude = null;
result.Longitude = null;
result.LatLongMatchLevel = null;
result.TimeZones = [];
result.LineType = null;
result.SmsAddress = null;
result.ValidPhone = null;
result.ValidPhoneLength = null;
result.Notes = null;
result.Warnings = null;
result.CurrentProvider = null;
result.PreviousProvider = null;
result.OriginalProvider = null;
result.LastPortedDate = null;
}
return result;
};
/**
* Provides functionality to call the ServiceObjects Phone Validation International (PVI) API's GetPhoneDetails endpoint,
* retrieving phone details (e.g., carrier, line type, time zones) for a given phone number
* with fallback to a backup endpoint for reliability in live mode.
*/
const GetPhoneDetailsClient = {
/**
* Asynchronously invokes the GetPhoneDetails API endpoint, attempting the primary endpoint
* first and falling back to the backup if the response is invalid (ProblemDetails.Status == 500) in live mode.
* @param {string} Phone - The phone number to validate (e.g., "+12025550123").
* @param {string} [Country] - The country code or name (e.g., "US"). Optional.
* @param {string} [Options] - Optional. Reserved for future use.
* @param {string} AuthID - Your license key to use the service.
* @param {boolean} [isLive=true] - Value to determine whether to use the live or trial servers.
* @param {number} [timeoutSeconds=15] - Timeout, in seconds, for the call to the service.
* @returns {Promise<PVIResponse>} A promise that resolves to a PVIResponse object.
*/
async invokeAsync(Phone, Country, Options, AuthID, isLive = true, timeoutSeconds = 15) {
const params = {
Phone,
Country,
Options,
AuthID
};
const url = buildUrl(params, isLive ? LiveBaseUrl : TrialBaseUrl);
let response = await httpGet(url, timeoutSeconds);
if (isLive && !isValid(response)) {
const fallbackUrl = buildUrl(params, BackupBaseUrl);
const fallbackResponse = await httpGet(fallbackUrl, timeoutSeconds);
return fallbackResponse;
}
return response;
},
/**
* Synchronously invokes the GetPhoneDetails API endpoint by wrapping the async call
* and awaiting its result immediately. Note: This method should be used cautiously
* in Node.js as it blocks the event loop.
* @param {string} Phone - The phone number to validate (e.g., "+12025550123").
* @param {string} [Country] - The country code or name (e.g., "US"). Optional.
* @param {string} [Options] - Optional. Reserved for future use.
* @param {string} AuthID - Your license key to use the service.
* @param {boolean} [isLive=true] - Value to determine whether to use the live or trial servers.
* @param {number} [timeoutSeconds=15] - Timeout, in seconds, for the call to the service.
* @returns {PVIResponse} A PVIResponse object with phone details or an error.
*/
invoke(Phone, Country, Options, AuthID, isLive = true, timeoutSeconds = 15) {
return (async () => await this.invokeAsync(
Phone, Country, Options, AuthID, isLive, timeoutSeconds
))();
}
};
export { GetPhoneDetailsClient, PVIResponse };
/**
* Phone details response component for PVI API.
*/
export class PVIResponse {
constructor(data = {}) {
this.Score = data.score;
this.PhoneIn = data.phoneIn;
this.CountryCode = data.countryCode;
this.FormatNational = data.formatNational;
this.FormatInternational = data.formatInternational;
this.FormatE164 = data.formatE164;
this.Extension = data.extension;
this.Locality = data.locality;
this.AdminArea = data.adminArea;
this.AdminAreaAbbr = data.adminAreaAbbr;
this.Country = data.country;
this.CountryISO2 = data.countryISO2;
this.CountryISO3 = data.countryISO3;
this.Latitude = data.latitude;
this.Longitude = data.longitude;
this.LatLongMatchLevel = data.latLongMatchLevel;
this.TimeZones = (data.timeZones || []).map(zone => new TimeZone(zone));
this.LineType = data.lineType;
this.SmsAddress = data.smsAddress;
this.ValidPhone = data.validPhone;
this.ValidPhoneLength = data.validPhoneLength;
this.Notes = data.notes;
this.Warnings = data.warnings;
this.CurrentProvider = data.currentProvider;
this.PreviousProvider = data.previousProvider;
this.OriginalProvider = data.originalProvider;
this.LastPortedDate = data.lastPortedDate;
}
toString() {
const timeZonesString = this.TimeZones.length
? this.TimeZones.map(zone => zone.toString()).join(", ")
: "null";
const notesString = this.Notes ? `[${this.Notes.join(", ")}]` : "null";
const warningsString = this.Warnings ? `[${this.Warnings.join(", ")}]` : "null";
return `Score: ${this.Score}, PhoneIn: ${this.PhoneIn}, CountryCode: ${this.CountryCode}, FormatNational: ${this.FormatNational}, ` +
`FormatInternational: ${this.FormatInternational}, FormatE164: ${this.FormatE164}, Extension: ${this.Extension}, ` +
`Locality: ${this.Locality}, AdminArea: ${this.AdminArea}, AdminAreaAbbr: ${this.AdminAreaAbbr}, ` +
`Country: ${this.Country}, CountryISO2: ${this.CountryISO2}, CountryISO3: ${this.CountryISO3}, ` +
`Latitude: ${this.Latitude}, Longitude: ${this.Longitude}, LatLongMatchLevel: ${this.LatLongMatchLevel}, ` +
`LineType: ${this.LineType}, SmsAddress: ${this.SmsAddress}, ValidPhone: ${this.ValidPhone}, ` +
`ValidPhoneLength: ${this.ValidPhoneLength}, LastPortedDate: ${this.LastPortedDate}, ` +
`TimeZones: [${timeZonesString}], Notes: ${notesString}, Warnings: ${warningsString}, ` +
`CurrentProvider: ${this.CurrentProvider ? this.CurrentProvider.toString() : "null"}, ` +
`PreviousProvider: ${this.PreviousProvider ? this.PreviousProvider.toString() : "null"}, ` +
`OriginalProvider: ${this.OriginalProvider ? this.OriginalProvider.toString() : "null"}`;
}
}
/**
* Problem details component for PVI API errors.
*/
export class ProblemDetails {
constructor({ type = null, title = null, status = null, detail = null } = {}) {
this.type = type;
this.title = title;
this.status = status;
this.detail = detail;
}
toString() {
return `Type: ${this.type}, Title: ${this.title}, Status: ${this.status}, Detail: ${this.detail}`;
}
}
/**
* Time zone information for a phone number.
*/
export class TimeZone {
constructor(data = {}) {
this.ZoneName = data.zoneName;
this.ZoneAbbr = data.zoneAbbr;
this.CountryISO3 = data.countryISO3;
this.UtcOffset = data.utcOffset;
}
toString() {
return `ZoneName: ${this.ZoneName}, ZoneAbbr: ${this.ZoneAbbr}, CountryISO3: ${this.CountryISO3}, UtcOffset: ${this.UtcOffset}`;
}
}