{"id":4203,"date":"2022-11-12T14:08:25","date_gmt":"2022-11-12T14:08:25","guid":{"rendered":"https:\/\/serviceobjects.wpaladdin.com\/?page_id=4203"},"modified":"2025-09-27T00:27:33","modified_gmt":"2025-09-27T07:27:33","slug":"gppl2-rest","status":"publish","type":"page","link":"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/","title":{"rendered":"GPPL2 &#8211; REST"},"content":{"rendered":"\n<div style=\"height:34px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<div class=\"wp-block-create-block-tabs\"><ul class=\"tab-labels\" role=\"tablist\" aria-label=\"tabbed content\"><li class=\"tab-label active\" role=\"tab\" aria-selected=\"true\" aria-controls=\"C#\" tabindex=\"0\">C#<\/li><li class=\"tab-label\" role=\"tab\" aria-selected=\"false\" aria-controls=\"Python\" tabindex=\"0\">Python<\/li><li class=\"tab-label\" role=\"tab\" aria-selected=\"false\" aria-controls=\"NodeJS\" tabindex=\"0\">NodeJS<\/li><\/ul><div class=\"tab-content\">\n<div class=\"wp-block-create-block-tab tab-panel\" role=\"tabpanel\" tabindex=\"0\">\n<p><strong>Phone Exchange C# Rest Code Snippet<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\ufeffusing System.Web;\n\nnamespace geophone_plus_2_dot_net.REST\n{\n    \/\/\/ &lt;summary>\n    \/\/\/ Provides functionality to call the ServiceObjects GeoPhone Plus 2 REST API's GetPhoneInfo endpoint,\n    \/\/\/ retrieving reverse phone lookup information (e.g., provider, contacts, SMS\/MMS addresses) with fallback to a backup endpoint\n    \/\/\/ for reliability in live mode.\n    \/\/\/ &lt;\/summary>\n    public class GetPhoneInfoClient\n    {\n        private const string LiveBaseUrl = \"https:\/\/sws.serviceobjects.com\/gppl2\/api.svc\/\";\n        private const string BackupBaseUrl = \"https:\/\/swsbackup.serviceobjects.com\/gppl2\/api.svc\/\";\n        private const string TrialBaseUrl = \"https:\/\/trial.serviceobjects.com\/gppl2\/api.svc\/\";\n\n        \/\/\/ &lt;summary>\n        \/\/\/ Synchronously calls the GetPhoneInfo REST endpoint to retrieve reverse phone lookup information,\n        \/\/\/ attempting the primary endpoint first and falling back to the backup if the response is invalid\n        \/\/\/ (Error.TypeCode == \"3\") in live mode.\n        \/\/\/ &lt;\/summary>\n        \/\/\/ &lt;param name=\"input\">The input parameters including phone number, test type, and license key.&lt;\/param>\n        \/\/\/ &lt;returns>Deserialized &lt;see cref=\"GPPL2Response\"\/>.&lt;\/returns>\n        public static GPPL2Response Invoke(GetPhoneInfoInput input)\n        {\n            \/\/Use query string parameters so missing\/options fields don't break\n            \/\/the URL as path parameters would.\n            string url = BuildUrl(input, input.IsLive ? LiveBaseUrl : TrialBaseUrl);\n            GPPL2Response response = Helper.HttpGet&lt;GPPL2Response>(url, input.TimeoutSeconds);\n\n            \/\/ Fallback on error in live mode\n            if (input.IsLive &amp;&amp; !IsValid(response))\n            {\n                string fallbackUrl = BuildUrl(input, BackupBaseUrl);\n                GPPL2Response fallbackResponse = Helper.HttpGet&lt;GPPL2Response>(fallbackUrl, input.TimeoutSeconds);\n                return fallbackResponse;\n            }\n\n            return response;\n        }\n\n        \/\/\/ &lt;summary>\n        \/\/\/ Asynchronously calls the GetPhoneInfo REST endpoint to retrieve reverse phone lookup information,\n        \/\/\/ attempting the primary endpoint first and falling back to the backup if the response is invalid\n        \/\/\/ (Error.TypeCode == \"3\") in live mode.\n        \/\/\/ &lt;\/summary>\n        \/\/\/ &lt;param name=\"input\">The input parameters including phone number, test type, and license key.&lt;\/param>\n        \/\/\/ &lt;returns>Deserialized &lt;see cref=\"GPPL2Response\"\/>.&lt;\/returns>\n        public static async Task&lt;GPPL2Response> InvokeAsync(GetPhoneInfoInput input)\n        {\n            \/\/ Use query string parameters so missing\/optional fields don't break\n            \/\/ the URL as path parameters would.\n            string url = BuildUrl(input, input.IsLive ? LiveBaseUrl : TrialBaseUrl);\n            GPPL2Response response = await Helper.HttpGetAsync&lt;GPPL2Response>(url, input.TimeoutSeconds).ConfigureAwait(false);\n            if (input.IsLive &amp;&amp; !IsValid(response))\n            {\n                string fallbackUrl = BuildUrl(input, BackupBaseUrl);\n                GPPL2Response fallbackResponse = await Helper.HttpGetAsync&lt;GPPL2Response>(fallbackUrl, input.TimeoutSeconds).ConfigureAwait(false);\n                return fallbackResponse;\n            }\n\n            return response;\n        }\n\n        \/\/ Build the full request URL, including URL-encoded query string\n        public static string BuildUrl(GetPhoneInfoInput input, string baseUrl)\n        {\n            string qs = $\"GetPhoneInfoJson?\" +\n                     $\"PhoneNumber={HttpUtility.UrlEncode(input.PhoneNumber)}\" +\n                     $\"&amp;TestType={HttpUtility.UrlEncode(input.TestType)}\" +\n                     $\"&amp;LicenseKey={HttpUtility.UrlEncode(input.LicenseKey)}\";\n            return baseUrl + qs;\n        }\n\n        private static bool IsValid(GPPL2Response response) => \n            response?.Error == null || response.Error.TypeCode != \"3\";\n\n        \/\/\/ &lt;summary>\n        \/\/\/ This is the basic operation for finding the reverse-lookup information.Given a phone number and test type, it will consult national directory-assistance databases to find the owner and address registered.The addresses returned are validated via third party address-validation technique. They are returned to you exactly as the phone carrier releases them.If you need these addresses to be validated, using Service Objects\u2019 AddressValidation web services is highly recommended.Both the contact\u2019s information and the phone company\u2019s information are returned with this operation. Two valuable bits of information are also retrieved \u2013 whether the phone line is for business or residential purposes, and whether the phone line is landline or wireless.By examining the WSDL, you may see that multiple groups of contact\/exchange information are possible. Although they are possible in the XML, you will only see one exchange per output, always.It is common, however, to see multiple contacts per phone number (as people change numbers, or there may be multiple businesses at the same phone number.) It is highly recommended that you handle each of these contacts, rather than just the first contact returned.\n        \/\/\/ &lt;\/summary>\n        \/\/\/ &lt;param name=\"PhoneNumber\">10 digit phone number&lt;\/param>\n        \/\/\/ &lt;param name=\"TestType\">\u201cFULL\u201d, \u201cBASIC\u201d or \u201cNORMAL\u201d&lt;\/param>\n        \/\/\/ &lt;param name=\"LicenseKey\">Your license key to use the service&lt;\/param>\n        \/\/\/ &lt;param name=\"IsLive\">Option to use live service or trial service&lt;\/param>\n        \/\/\/ &lt;param name=\"TimeoutSeconds\">Timeout, in seconds, for the call to the service.  &lt;\/param>\n        public record GetPhoneInfoInput(\n            string PhoneNumber = \"\",\n            string TestType = \"\",\n            string LicenseKey = \"\",\n            bool IsLive = true,\n            int TimeoutSeconds = 15\n        );\n    }\n}\n\n\n\ufeffusing System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace geophone_plus_2_dot_net.REST\n{\n    public class GPPL2Response\n    {\n        public string PhoneNumber { get; set; }\n        public string TestType { get; set; }\n        public string LicenseKey { get; set; }\n        public PhoneInfo PhoneInfo { get; set; }\n        public Error Error { get; set; }\n    }\n    public class PhoneInfo\n    {\n        public Provider Provider { get; set; }\n        public Contacts[] Contacts { get; set; }\n        public string SMSAddress { get; set; }\n        public string MMSAddress { get; set; }\n        public string DateFirstSeen { get; set; }\n        public string DateOfPorting { get; set; }\n        public string NoteCodes { get; set; }\n        public string NoteDescriptions { get; set; }\n        public string TokensUsed { get; set; }\n\n        public override string ToString()\n        {\n            string contactsString = Contacts != null ? string.Join(\", \", Contacts.Select(contact => contact.ToString())) : \"null\";\n\n            return $\"PhoneInfo - Providers: {Provider}, Contacts: [{contactsString}], SMSAddress: {SMSAddress}, MMSAddress: {MMSAddress}, DateFirstSeen: {DateFirstSeen}, DateOfPorting: {DateOfPorting}, NoteCodes: {NoteCodes}, NoteDescriptions: {NoteDescriptions}, TokensUsed: {TokensUsed}\";\n        }\n    }\n    public class Provider\n    {\n        public string Name { get; set; }\n        public string City { get; set; }\n        public string State { get; set; }\n        public string LineType { get; set; }\n        public string Latitude { get; set; }\n        public string Longitude { get; set; }\n\n        public override string ToString()\n        {\n            return $\"Provider - Name: {Name}, City: {City}, State: {State}, LineType: {LineType}, Latitude: {Latitude}, Longitude: {Longitude}\";\n        }\n    }\n    public class Contacts\n    {\n        public string Name { get; set; }\n        public string Address { get; set; }\n        public string City { get; set; }\n        public string State { get; set; }\n        public string PostalCode { get; set; }\n        public string PhoneType { get; set; }\n        public string Latitude { get; set; }\n        public string Longitude { get; set; }\n        public string SICCode { get; set; }\n        public string SICDesc { get; set; }\n        public string QualityScore { get; set; }\n\n        public override string ToString()\n        {\n            return $\"Contacts - Name: {Name}, Address: {Address}, City: {City}, State: {State}, PostalCode: {PostalCode}, PhoneType: {PhoneType}, Latitude: {Latitude}, Longitude: {Longitude}, SICCode: {SICCode}, SICDesc: {SICDesc}, QualityScore: {QualityScore}\";\n        }\n    }\n    public class Error\n    {\n        public string Type { get; set; }\n        public string TypeCode { get; set; }\n        public string Desc { get; set; }\n        public string DescCode { get; set; }\n        public override string ToString()\n        {\n            return $\"Type: {Type} \" +\n                $\"TypeCode: {TypeCode} \" +\n                $\"Desc: {Desc} \" +\n                $\"DescCode: {DescCode} \";\n        }\n    }\n\n}\n\n\n\ufeffusing System.Text.Json;\nusing System.Web;\n\nnamespace geophone_plus_2_dot_net.REST\n{\n    public class Helper\n    {\n        public static T HttpGet&lt;T>(string url, int timeoutSeconds)\n        {\n            using var httpClient = new HttpClient\n            {\n                Timeout = TimeSpan.FromSeconds(timeoutSeconds)\n            };\n            using var request = new HttpRequestMessage(HttpMethod.Get, url);\n            using HttpResponseMessage response = httpClient\n                .SendAsync(request)\n                .GetAwaiter()\n                .GetResult();\n            response.EnsureSuccessStatusCode();\n            using Stream responseStream = response.Content\n                .ReadAsStreamAsync()\n                .GetAwaiter()\n                .GetResult();\n            var options = new JsonSerializerOptions\n            {\n                PropertyNameCaseInsensitive = true\n            };\n            object? obj = JsonSerializer.Deserialize(responseStream, typeof(T), options);\n            T result = (T)obj!;\n            return result;\n        }\n\n        \/\/ Asynchronous HTTP GET and JSON deserialize\n        public static async Task&lt;T> HttpGetAsync&lt;T>(string url, int timeoutSeconds)\n        {\n            HttpClient HttpClient = new HttpClient();\n            HttpClient.Timeout = TimeSpan.FromSeconds(timeoutSeconds);\n            using var httpResponse = await HttpClient.GetAsync(url).ConfigureAwait(false);\n            httpResponse.EnsureSuccessStatusCode();\n            var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);\n            return JsonSerializer.Deserialize&lt;T>(stream)!;\n        }\n\n        public static string UrlEncode(string value) => HttpUtility.UrlEncode(value ?? string.Empty);\n    }\n}<\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-create-block-tab tab-panel\" role=\"tabpanel\" tabindex=\"0\">\n<p><strong>Phone Exchange Python Rest Code Snippet<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">import requests\nfrom gppl2_response import GPPL2Response, Provider, Contacts, PhoneInfo, Error\n\n# Endpoint URLs for GeoPhone Plus 2 GetPhoneInfo REST API\nprimary_url = 'https:\/\/sws.serviceobjects.com\/gppl2\/api.svc\/GetPhoneInfoJson?'\nbackup_url = 'https:\/\/swsbackup.serviceobjects.com\/gppl2\/api.svc\/GetPhoneInfoJson?'\ntrial_url = 'https:\/\/trial.serviceobjects.com\/gppl2\/api.svc\/GetPhoneInfoJson?'\n\ndef get_phone_info(\n    phone_number: str,\n    test_type: str,\n    license_key: str,\n    is_live: bool = True,\n    timeout_seconds: int = 15\n) -> GPPL2Response:\n    \"\"\"\n    Call GeoPhone Plus 2 GetPhoneInfo API to retrieve reverse phone lookup information.\n\n    Parameters:\n        phone_number: The 10 digit phone number.\n        test_type: The type of validation to perform ('FULL', 'BASIC', or 'NORMAL').\n        license_key: Your license key to use the service\n        is_live: Value to determine whether to use the live or trial servers (default: True).\n        timeout_seconds: Timeout, in seconds, for the call to the service (default: 15).\n\n    Returns:\n        GPPL2Response: Parsed JSON response with phone information or error details.\n    \"\"\"\n    params = {\n        'PhoneNumber': phone_number,\n        'TestType': test_type,\n        'LicenseKey': license_key\n    }\n\n    # Select the base URL: production vs trial\n    url = primary_url if is_live else trial_url\n\n    # Attempt primary (or trial) endpoint first\n    try:\n        response = requests.get(url, params=params, timeout=timeout_seconds)\n        response.raise_for_status()\n        data = response.json()\n\n        # If API returned an error in JSON payload, trigger fallback\n        error = getattr(response, 'Error', None)\n        if not (error is None or getattr(error, 'TypeCode', None) != \"3\"):\n            if is_live:\n            # Try backup URL\n              response = requests.get(backup_url, params=params, timeout=timeout_seconds)\n              response.raise_for_status()\n              data = response.json()\n\n            # If still error, propagate exception\n            if 'Error' in data:\n                raise RuntimeError(f\"GPPL2 service error: {data['Error']}\")\n\n            else:\n              # Trial mode error is terminal\n              raise RuntimeError(f\"GPPL2 trial error: {data['Error']}\")\n\n        # Convert JSON response to GPPL2Response for structured access\n        error = Error(**data.get('Error', {})) if data.get('Error') else None\n        phone_info = None\n        if data.get('PhoneInfo'):\n            provider = Provider(**data['PhoneInfo'].get('Provider', {})) if data['PhoneInfo'].get('Provider') else None\n            contacts = [Contacts(**contact) for contact in data['PhoneInfo'].get('Contacts', [])] if data['PhoneInfo'].get('Contacts') else None\n            phone_info = PhoneInfo(\n                Provider=provider,\n                Contacts=contacts,\n                SMSAddress=data['PhoneInfo'].get('SMSAddress'),\n                MMSAddress=data['PhoneInfo'].get('MMSAddress'),\n                DateFirstSeen=data['PhoneInfo'].get('DateFirstSeen'),\n                DateOfPorting=data['PhoneInfo'].get('DateOfPorting'),\n                NoteCodes=data['PhoneInfo'].get('NoteCodes'),\n                NoteDescriptions=data['PhoneInfo'].get('NoteDescriptions'),\n                TokensUsed=data['PhoneInfo'].get('TokensUsed')\n            )\n\n        return GPPL2Response(\n            PhoneNumber=data.get('PhoneNumber'),\n            TestType=data.get('TestType'),\n            LicenseKey=data.get('LicenseKey'),\n            PhoneInfo=phone_info,\n            Error=error\n        )\n\n    except requests.RequestException as req_exc:\n        # Network or HTTP-level error occurred\n        if is_live:\n            try:\n                # Fallback to backup URL on network failure\n                response = requests.get(backup_url, params=params, timeout=timeout_seconds)\n                response.raise_for_status()\n                data = response.json()\n                if 'Error' in data:\n                    raise RuntimeError(f\"GPPL2 backup error: {data['Error']}\") from req_exc\n\n                # Convert JSON response to GPPL2Response for structured access\n                error = Error(**data.get('Error', {})) if data.get('Error') else None\n                phone_info = None\n                if data.get('PhoneInfo'):\n                    provider = Provider(**data['PhoneInfo'].get('Provider', {})) if data['PhoneInfo'].get('Provider') else None\n                    contacts = [Contacts(**contact) for contact in data['PhoneInfo'].get('Contacts', [])] if data['PhoneInfo'].get('Contacts') else None\n                    phone_info = PhoneInfo(\n                        Provider=provider,\n                        Contacts=contacts,\n                        SMSAddress=data['PhoneInfo'].get('SMSAddress'),\n                        MMSAddress=data['PhoneInfo'].get('MMSAddress'),\n                        DateFirstSeen=data['PhoneInfo'].get('DateFirstSeen'),\n                        DateOfPorting=data['PhoneInfo'].get('DateOfPorting'),\n                        NoteCodes=data['PhoneInfo'].get('NoteCodes'),\n                        NoteDescriptions=data['PhoneInfo'].get('NoteDescriptions'),\n                        TokensUsed=data['PhoneInfo'].get('TokensUsed')\n                    )\n\n                return GPPL2Response(\n                    PhoneNumber=data.get('PhoneNumber'),\n                    TestType=data.get('TestType'),\n                    LicenseKey=data.get('LicenseKey'),\n                    PhoneInfo=phone_info,\n                    Error=error\n                )\n            except Exception as backup_exc:\n                raise RuntimeError(\"GPPL2 service unreachable on both endpoints\") from backup_exc\n        else:\n            raise RuntimeError(f\"GPPL2 trial error: {str(req_exc)}\") from req_exc\n\n\n\nfrom dataclasses import dataclass\nfrom typing import Optional, List\n\n@dataclass\nclass Provider:\n    Name: Optional[str] = None\n    City: Optional[str] = None\n    State: Optional[str] = None\n    LineType: Optional[str] = None\n    Latitude: Optional[str] = None\n    Longitude: Optional[str] = None\n\n    def __str__(self) -> str:\n        return (f\"Provider: Name={self.Name}, City={self.City}, State={self.State}, \"\n                f\"LineType={self.LineType}, Latitude={self.Latitude}, Longitude={self.Longitude}\")\n\n@dataclass\nclass Contacts:\n    Name: Optional[str] = None\n    Address: Optional[str] = None\n    City: Optional[str] = None\n    State: Optional[str] = None\n    PostalCode: Optional[str] = None\n    PhoneType: Optional[str] = None\n    Latitude: Optional[str] = None\n    Longitude: Optional[str] = None\n    SICCode: Optional[str] = None\n    SICDesc: Optional[str] = None\n    QualityScore: Optional[str] = None\n\n    def __str__(self) -> str:\n        return (f\"Contacts: Name={self.Name}, Address={self.Address}, City={self.City}, \"\n                f\"State={self.State}, PostalCode={self.PostalCode}, PhoneType={self.PhoneType}, \"\n                f\"Latitude={self.Latitude}, Longitude={self.Longitude}, SICCode={self.SICCode}, \"\n                f\"SICDesc={self.SICDesc}, QualityScore={self.QualityScore}\")\n\n@dataclass\nclass PhoneInfo:\n    Provider: Optional[Provider] = None\n    Contacts: Optional[List[Contacts]] = None\n    SMSAddress: Optional[str] = None\n    MMSAddress: Optional[str] = None\n    DateFirstSeen: Optional[str] = None\n    DateOfPorting: Optional[str] = None\n    NoteCodes: Optional[str] = None\n    NoteDescriptions: Optional[str] = None\n    TokensUsed: Optional[str] = None\n\n    def __str__(self) -> str:\n        contacts = \", \".join(str(c) for c in self.Contacts) if self.Contacts else \"None\"\n        provider = str(self.Provider) if self.Provider else \"None\"\n        return (f\"PhoneInfo: Provider={provider}, Contacts=[{contacts}], SMSAddress={self.SMSAddress}, \"\n                f\"MMSAddress={self.MMSAddress}, DateFirstSeen={self.DateFirstSeen}, \"\n                f\"DateOfPorting={self.DateOfPorting}, NoteCodes={self.NoteCodes}, \"\n                f\"NoteDescriptions={self.NoteDescriptions}, TokensUsed={self.TokensUsed}\")\n\n@dataclass\nclass Error:\n    Type: Optional[str] = None\n    TypeCode: Optional[str] = None\n    Desc: Optional[str] = None\n    DescCode: Optional[str] = None\n\n    def __str__(self) -> str:\n        return (f\"Error: Type={self.Type}, TypeCode={self.TypeCode}, Desc={self.Desc}, \"\n                f\"DescCode={self.DescCode}\")\n\n@dataclass\nclass GPPL2Response:\n    PhoneNumber: Optional[str] = None\n    TestType: Optional[str] = None\n    LicenseKey: Optional[str] = None\n    PhoneInfo: Optional[PhoneInfo] = None\n    Error: Optional[Error] = None\n\n    def __str__(self) -> str:\n        phone_info = str(self.PhoneInfo) if self.PhoneInfo else \"None\"\n        error = str(self.Error) if self.Error else \"None\"\n        return (f\"GPPL2Response: PhoneNumber={self.PhoneNumber}, TestType={self.TestType}, \"\n                f\"LicenseKey={self.LicenseKey}, PhoneInfo={phone_info}\")<\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-create-block-tab tab-panel\" role=\"tabpanel\" tabindex=\"0\">\n<p><strong>Phone Exchange NodeJS<\/strong> <strong>Rest Code Snippet<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"js\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\nimport axios from 'axios';\nimport querystring from 'querystring';\nimport { GPPL2Response } from '.\/gppl2_response.js';\n\n\/**\n * @constant\n * @type {string}\n * @description The base URL for the live ServiceObjects GeoPhone Plus 2 API service.\n *\/\nconst liveBaseUrl = 'https:\/\/sws.serviceobjects.com\/gppl2\/api.svc\/';\n\n\/**\n * @constant\n * @type {string}\n * @description The base URL for the backup ServiceObjects GeoPhone Plus 2 API service.\n *\/\nconst backupBaseUrl = 'https:\/\/swsbackup.serviceobjects.com\/gppl2\/api.svc\/';\n\n\/**\n * @constant\n * @type {string}\n * @description The base URL for the trial ServiceObjects GeoPhone Plus 2 API service.\n *\/\nconst trialBaseUrl = 'https:\/\/trial.serviceobjects.com\/gppl2\/api.svc\/';\n\n\/**\n * &lt;summary>\n * Checks if a response from the API is valid by verifying that it either has no Error object\n * or the Error.TypeCode is not equal to '1'.\n * &lt;\/summary>\n * &lt;param name=\"response\" type=\"Object\">The API response object to validate.&lt;\/param>\n * &lt;returns type=\"boolean\">True if the response is valid, false otherwise.&lt;\/returns>\n *\/\nconst isValid = (response) => !response?.Error || response.Error.TypeCode !== '3';\n\n\/**\n * &lt;summary>\n * Constructs a full URL for the GetPhoneInfo API endpoint by combining the base URL\n * with query parameters derived from the input parameters.\n * &lt;\/summary>\n * &lt;param name=\"params\" type=\"Object\">An object containing all the input parameters.&lt;\/param>\n * &lt;param name=\"baseUrl\" type=\"string\">The base URL for the API service (live, backup, or trial).&lt;\/param>\n * &lt;returns type=\"string\">The constructed URL with query parameters.&lt;\/returns>\n *\/\nconst buildUrl = (params, baseUrl) =>\n    `${baseUrl}GetPhoneInfoJson?${querystring.stringify(params)}`;\n\n\/**\n * &lt;summary>\n * Performs an HTTP GET request to the specified URL with a given timeout.\n * &lt;\/summary>\n * &lt;param name=\"url\" type=\"string\">The URL to send the GET request to.&lt;\/param>\n * &lt;param name=\"timeoutSeconds\" type=\"number\">The timeout duration in seconds for the request.&lt;\/param>\n * &lt;returns type=\"Promise&lt;GPPL2Response>\">A promise that resolves to a GPPL2Response object containing the API response data.&lt;\/returns>\n * &lt;exception cref=\"Error\">Thrown if the HTTP request fails, with a message detailing the error.&lt;\/exception>\n *\/\nconst httpGet = async (url, timeoutSeconds) => {\n    try {\n        const response = await axios.get(url, { timeout: timeoutSeconds * 1000 });\n        return new GPPL2Response(response.data);\n    } catch (error) {\n        throw new Error(`HTTP request failed: ${error.message}`);\n    }\n};\n\n\/**\n * &lt;summary>\n * Provides functionality to call the ServiceObjects GeoPhone Plus 2 API's GetPhoneInfo endpoint,\n * retrieving reverse phone lookup information with fallback to a backup endpoint for reliability in live mode.\n * &lt;\/summary>\n *\/\nconst GetPhoneInfoClient = {\n    \/**\n     * &lt;summary>\n     * Asynchronously invokes the GetPhoneInfo API endpoint, attempting the primary endpoint\n     * first and falling back to the backup if the response is invalid (Error.TypeCode == '3') in live mode.\n     * &lt;\/summary>\n     * @param {string} phoneNumber - 10 digit phone number.\n     * @param {string} testType - The type of validation to perform ('FULL', 'BASIC', or 'NORMAL').\n     * @param {string} licenseKey - Your license key to use the service\n     * @param {boolean} isLive - Value to determine whether to use the live or trial servers.\n     * @param {number} timeoutSeconds - Timeout, in seconds, for the call to the service.\n     * @returns {Promise&lt;GPPL2Response>} - A promise that resolves to a GPPL2Response object.\n     *\/\n    async invokeAsync(phoneNumber, testType, licenseKey, isLive = true, timeoutSeconds = 15) {\n        const params = {\n            phoneNumber,\n            testType,\n            licenseKey\n        };\n\n        const url = buildUrl(params, isLive ? liveBaseUrl : trialBaseUrl);\n        let response = await httpGet(url, timeoutSeconds);\n\n        if (isLive &amp;&amp; !isValid(response)) {\n            const fallbackUrl = buildUrl(params, BackupBaseUrl);\n            const fallbackResponse = await httpGet(fallbackUrl, timeoutSeconds);\n            return isValid(fallbackResponse) ? fallbackResponse : response;\n        }\n\n        return response;\n    },\n\n    \/**\n     * &lt;summary>\n     * Synchronously invokes the GetPhoneInfo API endpoint by wrapping the async call\n     * and awaiting its result immediately.\n     * &lt;\/summary>\n     * @returns {GPPL2Response} - A GPPL2Response object with reverse phone lookup details or an error.\n     *\/\n    invoke(phoneNumber, testType, licenseKey, isLive = true, timeoutSeconds = 15) {\n        return (async () => await this.invokeAsync(\n            phoneNumber, testType, licenseKey, isLive, timeoutSeconds\n        ))();\n    }\n};\n\nexport { GetPhoneInfoClient, GPPL2Response };\n\n\n\nexport class Provider {\n    constructor(data = {}) {\n        this.Name = data.Name;\n        this.City = data.City;\n        this.State = data.State;\n        this.LineType = data.LineType;\n        this.Latitude = data.Latitude;\n        this.Longitude = data.Longitude;\n    }\n\n    toString() {\n        return `Provider: Name = ${this.Name}, City = ${this.City}, State = ${this.State}, LineType = ${this.LineType}, Latitude = ${this.Latitude}, Longitude = ${this.Longitude}`;\n    }\n}\n\nexport class Contacts {\n    constructor(data = {}) {\n        this.Name = data.Name;\n        this.Address = data.Address;\n        this.City = data.City;\n        this.State = data.State;\n        this.PostalCode = data.PostalCode;\n        this.PhoneType = data.PhoneType;\n        this.Latitude = data.Latitude;\n        this.Longitude = data.Longitude;\n        this.SICCode = data.SICCode;\n        this.SICDesc = data.SICDesc;\n        this.QualityScore = data.QualityScore;\n    }\n\n    toString() {\n        return `Contacts: Name = ${this.Name}, Address = ${this.Address}, City = ${this.City}, State = ${this.State}, PostalCode = ${this.PostalCode}, PhoneType = ${this.PhoneType}, Latitude = ${this.Latitude}, Longitude = ${this.Longitude}, SICCode = ${this.SICCode}, SICDesc = ${this.SICDesc}, QualityScore = ${this.QualityScore}`;\n    }\n}\n\nexport class PhoneInfo {\n    constructor(data = {}) {\n        this.Provider = data.Provider ? new Provider(data.Provider) : null;\n        this.Contacts = (data.Contacts || []).map(contact => new Contacts(contact));\n        this.SMSAddress = data.SMSAddress;\n        this.MMSAddress = data.MMSAddress;\n        this.DateFirstSeen = data.DateFirstSeen;\n        this.DateOfPorting = data.DateOfPorting;\n        this.NoteCodes = data.NoteCodes;\n        this.NoteDescriptions = data.NoteDescriptions;\n        this.TokensUsed = data.TokensUsed;\n    }\n\n    toString() {\n        const contactsString = this.Contacts.length\n            ? this.Contacts.map(contact => contact.toString()).join(', ')\n            : 'null';\n        return `PhoneInfo: Provider = ${this.Provider ? this.Provider.toString() : 'null'}, Contacts = [${contactsString}], SMSAddress = ${this.SMSAddress}, MMSAddress = ${this.MMSAddress}, DateFirstSeen = ${this.DateFirstSeen}, DateOfPorting = ${this.DateOfPorting}, NoteCodes = ${this.NoteCodes}, NoteDescriptions = ${this.NoteDescriptions}, TokensUsed = ${this.TokensUsed}`;\n    }\n}\n\nexport class Error {\n    constructor(data = {}) {\n        this.Type = data.Type;\n        this.TypeCode = data.TypeCode;\n        this.Desc = data.Desc;\n        this.DescCode = data.DescCode;\n    }\n\n    toString() {\n        return `Error: Type = ${this.Type}, TypeCode = ${this.TypeCode}, Desc = ${this.Desc}, DescCode = ${this.DescCode}`;\n    }\n}\n\nexport class GPPL2Response {\n    constructor(data = {}) {\n        this.PhoneNumber = data.PhoneNumber;\n        this.TestType = data.TestType;\n        this.LicenseKey = data.LicenseKey;\n        this.PhoneInfo = data.PhoneInfo ? new PhoneInfo(data.PhoneInfo) : null;\n        this.Error = data.Error ? new Error(data.Error) : null;\n    }\n\n    toString() {\n        return `GPPL2Response: PhoneNumber = ${this.PhoneNumber}, TestType = ${this.TestType}, LicenseKey = ${this.LicenseKey}, PhoneInfo = ${this.PhoneInfo ? this.PhoneInfo.toString() : 'null'}, Error = ${this.Error ? this.Error.toString() : 'null'}`;\n    }\n}\n\nexport default GPPL2Response;<\/pre>\n<\/div>\n<\/div><\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":2,"featured_media":0,"parent":4116,"menu_order":1,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-4203","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>GPPL2 - REST<\/title>\n<meta name=\"description\" content=\"C#PythonNodeJS Phone Exchange C# Rest Code Snippet \ufeffusing System.Web; namespace geophone_plus_2_dot_net.REST { \/\/\/ &lt;summary&gt; \/\/\/ Provides functionality\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"GPPL2 - REST\" \/>\n<meta property=\"og:description\" content=\"C#PythonNodeJS Phone Exchange C# Rest Code Snippet \ufeffusing System.Web; namespace geophone_plus_2_dot_net.REST { \/\/\/ &lt;summary&gt; \/\/\/ Provides functionality\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/\" \/>\n<meta property=\"og:site_name\" content=\"Service Objects | Contact, Phone, Email Verification | Data Quality Services\" \/>\n<meta property=\"article:modified_time\" content=\"2025-09-27T07:27:33+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/\",\"url\":\"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/\",\"name\":\"GPPL2 - REST\",\"isPartOf\":{\"@id\":\"https:\/\/www.serviceobjects.com\/docs\/#website\"},\"datePublished\":\"2022-11-12T14:08:25+00:00\",\"dateModified\":\"2025-09-27T07:27:33+00:00\",\"description\":\"C#PythonNodeJS Phone Exchange C# Rest Code Snippet \ufeffusing System.Web; namespace geophone_plus_2_dot_net.REST { \/\/\/ &lt;summary> \/\/\/ Provides functionality\",\"breadcrumb\":{\"@id\":\"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.serviceobjects.com\/docs\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"DOTS GeoPhone Plus 2\",\"item\":\"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"GPPL2 &#8211; Code Snippets and Sample Code\",\"item\":\"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"GPPL2 &#8211; REST\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.serviceobjects.com\/docs\/#website\",\"url\":\"https:\/\/www.serviceobjects.com\/docs\/\",\"name\":\"Service Objects | Contact, Phone, Email Verification | Data Quality Services\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/www.serviceobjects.com\/docs\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.serviceobjects.com\/docs\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.serviceobjects.com\/docs\/#organization\",\"name\":\"Service Objects | Contact, Phone, Email Verification | Data Quality Services\",\"url\":\"https:\/\/www.serviceobjects.com\/docs\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.serviceobjects.com\/docs\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.serviceobjects.com\/docs\/wp-content\/uploads\/2022\/08\/SO-logo-2560px-transparent.png\",\"contentUrl\":\"https:\/\/www.serviceobjects.com\/docs\/wp-content\/uploads\/2022\/08\/SO-logo-2560px-transparent.png\",\"width\":2560,\"height\":1440,\"caption\":\"Service Objects | Contact, Phone, Email Verification | Data Quality Services\"},\"image\":{\"@id\":\"https:\/\/www.serviceobjects.com\/docs\/#\/schema\/logo\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"GPPL2 - REST","description":"C#PythonNodeJS Phone Exchange C# Rest Code Snippet \ufeffusing System.Web; namespace geophone_plus_2_dot_net.REST { \/\/\/ &lt;summary> \/\/\/ Provides functionality","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/","og_locale":"en_US","og_type":"article","og_title":"GPPL2 - REST","og_description":"C#PythonNodeJS Phone Exchange C# Rest Code Snippet \ufeffusing System.Web; namespace geophone_plus_2_dot_net.REST { \/\/\/ &lt;summary> \/\/\/ Provides functionality","og_url":"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/","og_site_name":"Service Objects | Contact, Phone, Email Verification | Data Quality Services","article_modified_time":"2025-09-27T07:27:33+00:00","twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/","url":"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/","name":"GPPL2 - REST","isPartOf":{"@id":"https:\/\/www.serviceobjects.com\/docs\/#website"},"datePublished":"2022-11-12T14:08:25+00:00","dateModified":"2025-09-27T07:27:33+00:00","description":"C#PythonNodeJS Phone Exchange C# Rest Code Snippet \ufeffusing System.Web; namespace geophone_plus_2_dot_net.REST { \/\/\/ &lt;summary> \/\/\/ Provides functionality","breadcrumb":{"@id":"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/gppl2-rest\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.serviceobjects.com\/docs\/"},{"@type":"ListItem","position":2,"name":"DOTS GeoPhone Plus 2","item":"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/"},{"@type":"ListItem","position":3,"name":"GPPL2 &#8211; Code Snippets and Sample Code","item":"https:\/\/www.serviceobjects.com\/docs\/dots-geophone-plus-2\/gppl2-code-snippets-and-sample-code\/"},{"@type":"ListItem","position":4,"name":"GPPL2 &#8211; REST"}]},{"@type":"WebSite","@id":"https:\/\/www.serviceobjects.com\/docs\/#website","url":"https:\/\/www.serviceobjects.com\/docs\/","name":"Service Objects | Contact, Phone, Email Verification | Data Quality Services","description":"","publisher":{"@id":"https:\/\/www.serviceobjects.com\/docs\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.serviceobjects.com\/docs\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.serviceobjects.com\/docs\/#organization","name":"Service Objects | Contact, Phone, Email Verification | Data Quality Services","url":"https:\/\/www.serviceobjects.com\/docs\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.serviceobjects.com\/docs\/#\/schema\/logo\/image\/","url":"https:\/\/www.serviceobjects.com\/docs\/wp-content\/uploads\/2022\/08\/SO-logo-2560px-transparent.png","contentUrl":"https:\/\/www.serviceobjects.com\/docs\/wp-content\/uploads\/2022\/08\/SO-logo-2560px-transparent.png","width":2560,"height":1440,"caption":"Service Objects | Contact, Phone, Email Verification | Data Quality Services"},"image":{"@id":"https:\/\/www.serviceobjects.com\/docs\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/www.serviceobjects.com\/docs\/wp-json\/wp\/v2\/pages\/4203","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.serviceobjects.com\/docs\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.serviceobjects.com\/docs\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.serviceobjects.com\/docs\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.serviceobjects.com\/docs\/wp-json\/wp\/v2\/comments?post=4203"}],"version-history":[{"count":17,"href":"https:\/\/www.serviceobjects.com\/docs\/wp-json\/wp\/v2\/pages\/4203\/revisions"}],"predecessor-version":[{"id":12356,"href":"https:\/\/www.serviceobjects.com\/docs\/wp-json\/wp\/v2\/pages\/4203\/revisions\/12356"}],"up":[{"embeddable":true,"href":"https:\/\/www.serviceobjects.com\/docs\/wp-json\/wp\/v2\/pages\/4116"}],"wp:attachment":[{"href":"https:\/\/www.serviceobjects.com\/docs\/wp-json\/wp\/v2\/media?parent=4203"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}