- C#
- Python
- NodeJS
Address Insight C# Rest Code Snippet
using System.Web;
namespace address_insight_us_dot_net.REST
{
/// <summary>
/// Provides functionality to call the ServiceObjects AddressInsight (AIN) REST API's GetAddressInsight endpoint,
/// retrieving address validation, geocoding, and demographic information for a given US address
/// with fallback to a backup endpoint for reliability in live mode.
/// </summary>
public class GetAddressInsightClient
{
// Base URL constants: production, backup, and trial
private const string LiveBaseUrl = "https://sws.serviceobjects.com/ain/api.svc/json/";
private const string BackupBaseUrl = "https://swsbackup.serviceobjects.com/ain/api.svc/json/";
private const string TrialBaseUrl = "https://trial.serviceobjects.com/ain/api.svc/json/";
/// <summary>
/// Synchronously calls the GetAddressInsight REST endpoint to retrieve address insight information,
/// attempting the primary endpoint first and falling back to the backup if the response is invalid
/// (Error.TypeCode == "3") in live mode.
/// </summary>
/// <param name="input">The input parameters including business name, address, city, state, zip, test type, and license key.</param>
/// <returns>Deserialized <see cref="AINResponse"/> containing address insight data or an error.</returns>
public static AINResponse Invoke(GetAddressInsightInput input)
{
// Use query string parameters so missing/optional fields don't break the URL
string url = BuildUrl(input, input.IsLive ? LiveBaseUrl : TrialBaseUrl);
AINResponse response = Helper.HttpGet<AINResponse>(url, input.TimeoutSeconds);
// Fallback on error in live mode
if (input.IsLive && !IsValid(response))
{
string fallbackUrl = BuildUrl(input, BackupBaseUrl);
AINResponse fallbackResponse = Helper.HttpGet<AINResponse>(fallbackUrl, input.TimeoutSeconds);
return fallbackResponse;
}
return response;
}
/// <summary>
/// Asynchronously calls the GetAddressInsight REST endpoint to retrieve address insight information,
/// attempting the primary endpoint first and falling back to the backup if the response is invalid
/// (Error.TypeCode == "3") in live mode.
/// </summary>
/// <param name="input">The input parameters including business name, address, city, state, zip, test type, and license key.</param>
/// <returns>Deserialized <see cref="AINResponse"/> containing address insight data or an error.</returns>
public static async Task<AINResponse> InvokeAsync(GetAddressInsightInput input)
{
// Use query string parameters so missing/optional fields don't break the URL
string url = BuildUrl(input, input.IsLive ? LiveBaseUrl : TrialBaseUrl);
AINResponse response = await Helper.HttpGetAsync<AINResponse>(url, input.TimeoutSeconds).ConfigureAwait(false);
// Fallback on error in live mode
if (input.IsLive && !IsValid(response))
{
string fallbackUrl = BuildUrl(input, BackupBaseUrl);
AINResponse fallbackResponse = await Helper.HttpGetAsync<AINResponse>(fallbackUrl, input.TimeoutSeconds).ConfigureAwait(false);
return fallbackResponse;
}
return response;
}
// Build the full request URL, including URL-encoded query string
private static string BuildUrl(GetAddressInsightInput input, string baseUrl)
{
// Construct query string with URL-encoded parameters
string qs = $"GetAddressInsight?" +
$"BusinessName={Helper.UrlEncode(input.BusinessName)}" +
$"&Address1={Helper.UrlEncode(input.Address1)}" +
$"&Address2={Helper.UrlEncode(input.Address2)}" +
$"&City={Helper.UrlEncode(input.City)}" +
$"&State={Helper.UrlEncode(input.State)}" +
$"&Zip={Helper.UrlEncode(input.Zip)}" +
$"&TestType={Helper.UrlEncode(input.TestType)}" +
$"&LicenseKey={Helper.UrlEncode(input.LicenseKey)}";
return baseUrl + qs;
}
private static bool IsValid(AINResponse response) => response?.Error == null || response.Error.TypeCode != "3";
/// <summary>
/// Input parameters for the GetAddressInsight API call. Represents a US address to retrieve address insights
/// with cascading logic for partial matches.
/// </summary>
/// <param name="BusinessName">A company name for a business, can provide additional insight or append a SuiteLink value. Optional.</param>
/// <param name="Address1">Address line 1 of the contact or business address (e.g., "123 Main Street").</param>
/// <param name="Address2">Address line 2 of the contact or business address (e.g., "Apt 4B"). Optional.</param>
/// <param name="City">The city of the address (e.g., "New York"). Optional if zip is provided.</param>
/// <param name="State">The state of the address (e.g., "NY"). Optional if zip is provided.</param>
/// <param name="Zip">The ZIP code of the address. Optional if city and state are provided.</param>
/// <param name="TestType">The test type, either empty or "census_loose" for best possible match based on census data. Optional.</param>
/// <param name="LicenseKey">The license key to authenticate the API request.</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 GetAddressInsightInput(
string BusinessName = "",
string Address1 = "",
string Address2 = "",
string City = "",
string State = "",
string Zip = "",
string TestType = "",
string LicenseKey = "",
bool IsLive = true,
int TimeoutSeconds = 15
);
}
}
/// <summary>
/// This is the return from the AIN endpoint
/// </summary>
///
public class AINResponse
{
public string Status { get; set; }
public string StatusScore { get; set; }
public string AddressStatus { get; set; }
public string DPV { get; set; }
public string DPVDesc { get; set; }
public string Address { get; set; }
public string AddressExtra { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public string BarcodeDigits { get; set; }
public string CarrierRoute { get; set; }
public string CongressCode { get; set; }
public string CountyCode { get; set; }
public string CountyName { get; set; }
public string FragmentHouse { get; set; }
public string FragmentPreDir { get; set; }
public string FragmentStreet { get; set; }
public string FragmentSuffix { get; set; }
public string FragmentPostDir { get; set; }
public string FragmentUnit { get; set; }
public string FragmentUnitNumber { get; set; }
public string Fragment { get; set; }
public string FragmentPMBPrefix { get; set; }
public string FragmentPMBNumber { get; set; }
public string Corrections { get; set; }
public string CorrectionsDesc { get; set; }
public string AddressNotes { get; set; }
public string AddressNotesCodes { get; set; }
public string GeocodeStatus { get; set; }
public string LocationLatitude { get; set; }
public string LocationLongitude { get; set; }
public string CensusTract { get; set; }
public string CensusBlock { get; set; }
public string PlaceName { get; set; }
public string ClassFP { get; set; }
public string SLDUST { get; set; }
public string SLDLST { get; set; }
public string CountyFIPS { get; set; }
public string StateFIPS { get; set; }
public string GeocodeNotes { get; set; }
public string GeocodeNotesCodes { get; set; }
public string ZipStatus { get; set; }
public string ZipLatitude { get; set; }
public string ZipLongitude { get; set; }
public string CityType { get; set; }
public string CityAliasName { get; set; }
public string AreaCode { get; set; }
public string TimeZone { get; set; }
public string DaylightSaving { get; set; }
public string MSA { get; set; }
public string CBSA { get; set; }
public string CBSA_Div { get; set; }
public string PMSA { get; set; }
public string DMA { get; set; }
public string ZipHouseholdValue { get; set; }
public string ZipPersonsPerHousehold { get; set; }
public string ZipHouseholdIncome { get; set; }
public string CountyHouseholdIncome { get; set; }
public string StateHouseholdIncome { get; set; }
public string ZipNotes { get; set; }
public string ZipNotesCodes { get; set; }
public string Debug { get; set; }
public Error Error { get; set; }
public override string ToString()
{
return $"\n{{\n\tStatus: {Status}\n\t" +
$"StatusScore: {StatusScore}\n\t" +
$"AddressStatus: {AddressStatus}\n\t" +
$"DPV: {DPV}\n\t" +
$"DPVDesc: {DPVDesc}\n\t" +
$"Address: {Address}\n\t" +
$"AddressExtra: {AddressExtra}\n\t" +
$"City: {City}\n\t" +
$"State: {State}\n\t" +
$"Zip: {Zip}\n\t" +
$"BarcodeDigits: {BarcodeDigits}\n\t" +
$"CarrierRoute: {CarrierRoute}\n\t" +
$"CongressCode: {CongressCode}\n\t" +
$"CountyCode: {CountyCode}\n\t" +
$"CountyName: {CountyName}\n\t" +
$"FragmentHouse: {FragmentHouse}\n\t" +
$"FragmentPreDir: {FragmentPreDir}\n\t" +
$"FragmentStreet: {FragmentStreet}\n\t" +
$"FragmentSuffix: {FragmentSuffix}\n\t" +
$"FragmentPostDir: {FragmentPostDir}\n\t" +
$"FragmentUnit: {FragmentUnit}\n\t" +
$"FragmentUnitNumber: {FragmentUnitNumber}\n\t" +
$"FragmentPMBPrefix: {FragmentPMBPrefix}\n\t" +
$"FragmentPMBNumber: {FragmentPMBNumber}\n\t" +
$"Corrections: {Corrections}\n\t" +
$"CorrectionsDesc: {CorrectionsDesc}\n\t" +
$"AddressNotes: {AddressNotes}\n\t" +
$"AddressNotesCodes: {AddressNotesCodes}\n\t" +
$"GeocodeStatus: {GeocodeStatus}\n\t" +
$"LocationLatitude: {LocationLatitude}\n\t" +
$"LocationLongitude: {LocationLongitude}\n\t" +
$"CensusTract: {CensusTract}\n\t" +
$"CensusBlock: {CensusBlock}\n\t" +
$"PlaceName: {PlaceName}\n\t" +
$"ClassFP: {ClassFP}\n\t" +
$"SLDUST: {SLDUST}\n\t" +
$"SLDLST: {SLDLST}\n\t" +
$"CountyFIPS: {CountyFIPS}\n\t" +
$"StateFIPS: {StateFIPS}\n\t" +
$"GeocodeNotes: {GeocodeNotes}\n\t" +
$"GeocodeNotesCodes: {GeocodeNotesCodes}\n\t" +
$"ZipStatus: {ZipStatus}\n\t" +
$"ZipLatitude: {ZipLatitude}\n\t" +
$"ZipLongitude: {ZipLongitude}\n\t" +
$"CityType: {CityType}\n\t" +
$"CityAliasName: {CityAliasName}\n\t" +
$"AreaCode: {AreaCode}\n\t" +
$"TimeZone: {TimeZone}\n\t" +
$"DaylightSaving: {DaylightSaving}\n\t" +
$"MSA: {MSA}\n\t" +
$"CBSA: {CBSA}\n\t" +
$"CBSA_Div: {CBSA_Div}\n\t" +
$"PMSA: {PMSA}\n\t" +
$"DMA: {DMA}\n\t" +
$"ZipHouseholdValue: {ZipHouseholdValue}\n\t" +
$"ZipPersonsPerHousehold: {ZipPersonsPerHousehold}\n\t" +
$"ZipHouseholdIncome: {ZipHouseholdIncome}\n\t" +
$"CountyHouseholdIncome: {CountyHouseholdIncome}\n\t" +
$"StateHouseholdIncome: {StateHouseholdIncome}\n\t" +
$"ZipNotes: {ZipNotes}\n\t" +
$"ZipNotesCodes: {ZipNotesCodes}\n\t" +
$"Error: {{{Error}}}\n}}";
}
}
public class Error
{
public string Type { get; set; }
public string TypeCode { get; set; }
public string Desc { get; set; }
public string DescCode { get; set; }
public override string ToString()
{
return $"Type: {Type} " +
$"TypeCode: {TypeCode} " +
$"Desc: {Desc} " +
$"DescCode: {DescCode} ";
}
}
using System.Text.Json;
using System.Web;
namespace address_insight_us_dot_net.REST
{
public class Helper
{
public static T HttpGet<T>(string url, int timeoutSeconds)
{
using var httpClient = new HttpClient
{
Timeout = TimeSpan.FromSeconds(timeoutSeconds)
};
using var request = new HttpRequestMessage(HttpMethod.Get, url);
using HttpResponseMessage response = httpClient
.SendAsync(request)
.GetAwaiter()
.GetResult();
response.EnsureSuccessStatusCode();
using Stream responseStream = response.Content
.ReadAsStreamAsync()
.GetAwaiter()
.GetResult();
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
object? obj = JsonSerializer.Deserialize(responseStream, typeof(T), options);
T result = (T)obj!;
return result;
}
// Asynchronous HTTP GET and JSON deserialize
public static async Task<T> HttpGetAsync<T>(string url, int timeoutSeconds)
{
HttpClient HttpClient = new HttpClient();
HttpClient.Timeout = TimeSpan.FromSeconds(timeoutSeconds);
using var httpResponse = await HttpClient.GetAsync(url).ConfigureAwait(false);
httpResponse.EnsureSuccessStatusCode();
var stream = await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
return JsonSerializer.Deserialize<T>(stream)!;
}
public static string UrlEncode(string value) => HttpUtility.UrlEncode(value ?? string.Empty);
}
}
Address Insight Python Rest Code Snippet
from ain_response import AINResponse, Error
import requests
# Endpoint URLs for ServiceObjects AddressInsight (AIN) API
primary_url = "https://sws.serviceobjects.com/ain/api.svc/json/GetAddressInsight?"
backup_url = "https://swsbackup.serviceobjects.com/ain/api.svc/json/GetAddressInsight?"
trial_url = "https://trial.serviceobjects.com/ain/api.svc/json/GetAddressInsight?"
def get_address_insight(
business_name: str,
address1: str,
address2: str,
city: str,
state: str,
zip_code: str,
test_type: str,
license_key: str,
is_live: bool = True
) -> AINResponse:
"""
Call ServiceObjects AddressInsight (AIN) API's GetAddressInsight endpoint
to retrieve address validation, geocoding, and demographic information for a given US address.
Parameters:
business_name: A company name for a business, can provide additional insight or append a SuiteLink value. Optional.
address1: Address line 1 of the contact or business address (e.g., "123 Main Street").
address2: Address line 2 of the contact or business address (e.g., "Apt 4B"). Optional.
city: The city of the address (e.g., "New York"). Optional if zip is provided.
state: The state of the address (e.g., "NY"). Optional if zip is provided.
zip_code: The ZIP code of the address. Optional if city and state are provided.
test_type: The test type, either empty or "census_loose" for best possible match based on census data. Optional.
license_key: Your ServiceObjects license key.
is_live: Use live or trial servers.
Returns:
AINResponse: Parsed JSON response with address insight results or error details.
Raises:
RuntimeError: If the API returns an error payload.
requests.RequestException: On network/HTTP failures (trial mode).
"""
params = {
"BusinessName": business_name,
"Address1": address1,
"Address2": address2,
"City": city,
"State": state,
"Zip": zip_code,
"TestType": test_type,
"LicenseKey": license_key,
}
# Select the base URL: production vs trial
url = primary_url if is_live else trial_url
try:
# Attempt primary (or trial) endpoint
response = requests.get(url, params=params, timeout=10)
response.raise_for_status()
data = response.json()
# If API returned an error in JSON payload, trigger fallback
error = data.get('Error')
if not (error is None or error.get('TypeCode') != "3"):
if is_live:
# Try backup URL
response = requests.get(backup_url, params=params, timeout=10)
response.raise_for_status()
data = response.json()
# If still error, propagate exception
if 'Error' in data:
raise RuntimeError(f"AddressInsight service error: {data['Error']}")
else:
# Trial mode error is terminal
raise RuntimeError(f"AddressInsight trial error: {data['Error']}")
# Convert JSON response to AINResponse for structured access
error = Error(**data.get("Error", {})) if data.get("Error") else None
return AINResponse(
Status=data.get("Status"),
StatusScore=data.get("StatusScore"),
AddressStatus=data.get("AddressStatus"),
DPV=data.get("DPV"),
DPVDesc=data.get("DPVDesc"),
Address=data.get("Address"),
AddressExtra=data.get("AddressExtra"),
City=data.get("City"),
State=data.get("State"),
Zip=data.get("Zip"),
BarcodeDigits=data.get("BarcodeDigits"),
CarrierRoute=data.get("CarrierRoute"),
CongressCode=data.get("CongressCode"),
CountyCode=data.get("CountyCode"),
CountyName=data.get("CountyName"),
FragmentHouse=data.get("FragmentHouse"),
FragmentPreDir=data.get("FragmentPreDir"),
FragmentStreet=data.get("FragmentStreet"),
FragmentSuffix=data.get("FragmentSuffix"),
FragmentPostDir=data.get("FragmentPostDir"),
FragmentUnit=data.get("FragmentUnit"),
FragmentUnitNumber=data.get("FragmentUnitNumber"),
Fragment=data.get("Fragment"),
FragmentPMBPrefix=data.get("FragmentPMBPrefix"),
FragmentPMBNumber=data.get("FragmentPMBNumber"),
Corrections=data.get("Corrections"),
CorrectionsDesc=data.get("CorrectionsDesc"),
AddressNotes=data.get("AddressNotes"),
AddressNotesCodes=data.get("AddressNotesCodes"),
GeocodeStatus=data.get("GeocodeStatus"),
LocationLatitude=data.get("LocationLatitude"),
LocationLongitude=data.get("LocationLongitude"),
CensusTract=data.get("CensusTract"),
CensusBlock=data.get("CensusBlock"),
PlaceName=data.get("PlaceName"),
ClassFP=data.get("ClassFP"),
SLDUST=data.get("SLDUST"),
SLDLST=data.get("SLDLST"),
CountyFIPS=data.get("CountyFIPS"),
StateFIPS=data.get("StateFIPS"),
GeocodeNotes=data.get("GeocodeNotes"),
GeocodeNotesCodes=data.get("GeocodeNotesCodes"),
ZipStatus=data.get("ZipStatus"),
ZipLatitude=data.get("ZipLatitude"),
ZipLongitude=data.get("ZipLongitude"),
CityType=data.get("CityType"),
CityAliasName=data.get("CityAliasName"),
AreaCode=data.get("AreaCode"),
TimeZone=data.get("TimeZone"),
DaylightSaving=data.get("DaylightSaving"),
MSA=data.get("MSA"),
CBSA=data.get("CBSA"),
CBSA_Div=data.get("CBSA_Div"),
PMSA=data.get("PMSA"),
DMA=data.get("DMA"),
ZipHouseholdValue=data.get("ZipHouseholdValue"),
ZipPersonsPerHousehold=data.get("ZipPersonsPerHousehold"),
ZipHouseholdIncome=data.get("ZipHouseholdIncome"),
CountyHouseholdIncome=data.get("CountyHouseholdIncome"),
StateHouseholdIncome=data.get("StateHouseholdIncome"),
ZipNotes=data.get("ZipNotes"),
ZipNotesCodes=data.get("ZipNotesCodes"),
Debug=data.get("Debug", []),
Error=error
)
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=10)
response.raise_for_status()
data = response.json()
if "Error" in data:
raise RuntimeError(f"AddressInsight backup error: {data['Error']}") from req_exc
error = Error(**data.get("Error", {})) if data.get("Error") else None
return AINResponse(
Status=data.get("Status"),
StatusScore=data.get("StatusScore"),
AddressStatus=data.get("AddressStatus"),
DPV=data.get("DPV"),
DPVDesc=data.get("DPVDesc"),
Address=data.get("Address"),
AddressExtra=data.get("AddressExtra"),
City=data.get("City"),
State=data.get("State"),
Zip=data.get("Zip"),
BarcodeDigits=data.get("BarcodeDigits"),
CarrierRoute=data.get("CarrierRoute"),
CongressCode=data.get("CongressCode"),
CountyCode=data.get("CountyCode"),
CountyName=data.get("CountyName"),
FragmentHouse=data.get("FragmentHouse"),
FragmentPreDir=data.get("FragmentPreDir"),
FragmentStreet=data.get("FragmentStreet"),
FragmentSuffix=data.get("FragmentSuffix"),
FragmentPostDir=data.get("FragmentPostDir"),
FragmentUnit=data.get("FragmentUnit"),
FragmentUnitNumber=data.get("FragmentUnitNumber"),
Fragment=data.get("Fragment"),
FragmentPMBPrefix=data.get("FragmentPMBPrefix"),
FragmentPMBNumber=data.get("FragmentPMBNumber"),
Corrections=data.get("Corrections"),
CorrectionsDesc=data.get("CorrectionsDesc"),
AddressNotes=data.get("AddressNotes"),
AddressNotesCodes=data.get("AddressNotesCodes"),
GeocodeStatus=data.get("GeocodeStatus"),
LocationLatitude=data.get("LocationLatitude"),
LocationLongitude=data.get("LocationLongitude"),
CensusTract=data.get("CensusTract"),
CensusBlock=data.get("CensusBlock"),
PlaceName=data.get("PlaceName"),
ClassFP=data.get("ClassFP"),
SLDUST=data.get("SLDUST"),
SLDLST=data.get("SLDLST"),
CountyFIPS=data.get("CountyFIPS"),
StateFIPS=data.get("StateFIPS"),
GeocodeNotes=data.get("GeocodeNotes"),
GeocodeNotesCodes=data.get("GeocodeNotesCodes"),
ZipStatus=data.get("ZipStatus"),
ZipLatitude=data.get("ZipLatitude"),
ZipLongitude=data.get("ZipLongitude"),
CityType=data.get("CityType"),
CityAliasName=data.get("CityAliasName"),
AreaCode=data.get("AreaCode"),
TimeZone=data.get("TimeZone"),
DaylightSaving=data.get("DaylightSaving"),
MSA=data.get("MSA"),
CBSA=data.get("CBSA"),
CBSA_Div=data.get("CBSA_Div"),
PMSA=data.get("PMSA"),
DMA=data.get("DMA"),
ZipHouseholdValue=data.get("ZipHouseholdValue"),
ZipPersonsPerHousehold=data.get("ZipPersonsPerHousehold"),
ZipHouseholdIncome=data.get("ZipHouseholdIncome"),
CountyHouseholdIncome=data.get("CountyHouseholdIncome"),
StateHouseholdIncome=data.get("StateHouseholdIncome"),
ZipNotes=data.get("ZipNotes"),
ZipNotesCodes=data.get("ZipNotesCodes"),
Debug=data.get("Debug", []),
Error=error
)
except Exception as backup_exc:
raise RuntimeError("AddressInsight service unreachable on both endpoints") from backup_exc
else:
raise RuntimeError(f"AddressInsight trial error: {str(req_exc)}") from req_exc
from dataclasses import dataclass
from typing import Optional, List
@dataclass
class Error:
Type: Optional[str] = None
TypeCode: Optional[str] = None
Desc: Optional[str] = None
DescCode: Optional[str] = None
def __str__(self) -> str:
return f"Error: Type={self.Type}, TypeCode={self.TypeCode}, Desc={self.Desc}, DescCode={self.DescCode}"
@dataclass
class AINResponse:
Status: Optional[str] = None
StatusScore: Optional[str] = None
AddressStatus: Optional[str] = None
DPV: Optional[str] = None
DPVDesc: Optional[str] = None
Address: Optional[str] = None
AddressExtra: Optional[str] = None
City: Optional[str] = None
State: Optional[str] = None
Zip: Optional[str] = None
BarcodeDigits: Optional[str] = None
CarrierRoute: Optional[str] = None
CongressCode: Optional[str] = None
CountyCode: Optional[str] = None
CountyName: Optional[str] = None
FragmentHouse: Optional[str] = None
FragmentPreDir: Optional[str] = None
FragmentStreet: Optional[str] = None
FragmentSuffix: Optional[str] = None
FragmentPostDir: Optional[str] = None
FragmentUnit: Optional[str] = None
FragmentUnitNumber: Optional[str] = None
Fragment: Optional[str] = None
FragmentPMBPrefix: Optional[str] = None
FragmentPMBNumber: Optional[str] = None
Corrections: Optional[str] = None
CorrectionsDesc: Optional[str] = None
AddressNotes: Optional[str] = None
AddressNotesCodes: Optional[str] = None
GeocodeStatus: Optional[str] = None
LocationLatitude: Optional[str] = None
LocationLongitude: Optional[str] = None
CensusTract: Optional[str] = None
CensusBlock: Optional[str] = None
PlaceName: Optional[str] = None
ClassFP: Optional[str] = None
SLDUST: Optional[str] = None
SLDLST: Optional[str] = None
CountyFIPS: Optional[str] = None
StateFIPS: Optional[str] = None
GeocodeNotes: Optional[str] = None
GeocodeNotesCodes: Optional[str] = None
ZipStatus: Optional[str] = None
ZipLatitude: Optional[str] = None
ZipLongitude: Optional[str] = None
CityType: Optional[str] = None
CityAliasName: Optional[str] = None
AreaCode: Optional[str] = None
TimeZone: Optional[str] = None
DaylightSaving: Optional[str] = None
MSA: Optional[str] = None
CBSA: Optional[str] = None
CBSA_Div: Optional[str] = None
PMSA: Optional[str] = None
DMA: Optional[str] = None
ZipHouseholdValue: Optional[str] = None
ZipPersonsPerHousehold: Optional[str] = None
ZipHouseholdIncome: Optional[str] = None
CountyHouseholdIncome: Optional[str] = None
StateHouseholdIncome: Optional[str] = None
ZipNotes: Optional[str] = None
ZipNotesCodes: Optional[str] = None
Debug: Optional[List[str]] = None
Error: Optional['Error'] = None
def __post_init__(self):
if self.Debug is None:
self.Debug = []
def __str__(self) -> str:
debug_string = ', '.join(self.Debug) if self.Debug else 'None'
error = str(self.Error) if self.Error else 'None'
return (f"AINResponse: Status={self.Status}, StatusScore={self.StatusScore}, AddressStatus={self.AddressStatus}, "
f"DPV={self.DPV}, DPVDesc={self.DPVDesc}, Address={self.Address}, AddressExtra={self.AddressExtra}, "
f"City={self.City}, State={self.State}, Zip={self.Zip}, BarcodeDigits={self.BarcodeDigits}, "
f"CarrierRoute={self.CarrierRoute}, CongressCode={self.CongressCode}, CountyCode={self.CountyCode}, "
f"CountyName={self.CountyName}, FragmentHouse={self.FragmentHouse}, FragmentPreDir={self.FragmentPreDir}, "
f"FragmentStreet={self.FragmentStreet}, FragmentSuffix={self.FragmentSuffix}, FragmentPostDir={self.FragmentPostDir}, "
f"FragmentUnit={self.FragmentUnit}, FragmentUnitNumber={self.FragmentUnitNumber}, Fragment={self.Fragment}, "
f"FragmentPMBPrefix={self.FragmentPMBPrefix}, FragmentPMBNumber={self.FragmentPMBNumber}, "
f"Corrections={self.Corrections}, CorrectionsDesc={self.CorrectionsDesc}, AddressNotes={self.AddressNotes}, "
f"AddressNotesCodes={self.AddressNotesCodes}, GeocodeStatus={self.GeocodeStatus}, LocationLatitude={self.LocationLatitude}, "
f"LocationLongitude={self.LocationLongitude}, CensusTract={self.CensusTract}, CensusBlock={self.CensusBlock}, "
f"PlaceName={self.PlaceName}, ClassFP={self.ClassFP}, SLDUST={self.SLDUST}, SLDLST={self.SLDLST}, "
f"CountyFIPS={self.CountyFIPS}, StateFIPS={self.StateFIPS}, GeocodeNotes={self.GeocodeNotes}, "
f"GeocodeNotesCodes={self.GeocodeNotesCodes}, ZipStatus={self.ZipStatus}, ZipLatitude={self.ZipLatitude}, "
f"ZipLongitude={self.ZipLongitude}, CityType={self.CityType}, CityAliasName={self.CityAliasName}, "
f"AreaCode={self.AreaCode}, TimeZone={self.TimeZone}, DaylightSaving={self.DaylightSaving}, "
f"MSA={self.MSA}, CBSA={self.CBSA}, CBSA_Div={self.CBSA_Div}, PMSA={self.PMSA}, DMA={self.DMA}, "
f"ZipHouseholdValue={self.ZipHouseholdValue}, ZipPersonsPerHousehold={self.ZipPersonsPerHousehold}, "
f"ZipHouseholdIncome={self.ZipHouseholdIncome}, CountyHouseholdIncome={self.CountyHouseholdIncome}, "
f"StateHouseholdIncome={self.StateHouseholdIncome}, ZipNotes={self.ZipNotes}, ZipNotesCodes={self.ZipNotesCodes}, "
f"Debug=[{debug_string}], Error={error}")
Address Insight NodeJS Rest Code Snippet
import axios from 'axios';
import querystring from 'querystring';
import { AINResponse } from './ain_response.js';
/**
* @constant
* @type {string}
* @description The base URL for the live ServiceObjects AddressInsight (AIN) API service.
*/
const LiveBaseUrl = 'https://sws.serviceobjects.com/ain/api.svc/json/';
/**
* @constant
* @type {string}
* @description The base URL for the backup ServiceObjects AddressInsight (AIN) API service.
*/
const BackupBaseUrl = 'https://swsbackup.serviceobjects.com/ain/api.svc/json/';
/**
* @constant
* @type {string}
* @description The base URL for the trial ServiceObjects AddressInsight (AIN) API service.
*/
const TrialBaseUrl = 'https://trial.serviceobjects.com/ain/api.svc/json/';
/**
* <summary>
* Checks if a response from the API is valid by verifying that it either has no Error object
* or the Error.TypeCode is not equal to '3'.
* </summary>
* <param name="response" type="Object">The API response object to validate.</param>
* <returns type="boolean">True if the response is valid, false otherwise.</returns>
*/
const isValid = (response) => !response?.Error || response.Error.TypeCode !== '3';
/**
* <summary>
* Constructs a full URL for the GetAddressInsight API endpoint by combining the base URL
* with query parameters derived from the input parameters.
* </summary>
* <param name="params" type="Object">An object containing all the input parameters.</param>
* <param name="baseUrl" type="string">The base URL for the API service (live, backup, or trial).</param>
* <returns type="string">The constructed URL with query parameters.</returns>
*/
const buildUrl = (params, baseUrl) =>
`${baseUrl}GetAddressInsight?${querystring.stringify(params)}`;
/**
* <summary>
* Performs an HTTP GET request to the specified URL with a given timeout.
* </summary>
* <param name="url" type="string">The URL to send the GET request to.</param>
* <param name="timeoutSeconds" type="number">The timeout duration in seconds for the request.</param>
* <returns type="Promise<AINResponse>">A promise that resolves to a AINResponse object containing the API response data.</returns>
* <exception cref="Error">Thrown if the HTTP request fails, with a message detailing the error.</exception>
*/
const httpGet = async (url, timeoutSeconds) => {
try {
const response = await axios.get(url, { timeout: timeoutSeconds * 1000 });
return new AINResponse(response.data);
} catch (error) {
throw new Error(`HTTP request failed: ${error.message}`);
}
};
/**
* <summary>
* Provides functionality to call the ServiceObjects AddressInsight (AIN) API's GetAddressInsight endpoint,
* retrieving address validation, geocoding, and demographic information for a given US address
* with fallback to a backup endpoint for reliability in live mode.
* </summary>
*/
const GetAddressInsightClient = {
/**
* <summary>
* Asynchronously invokes the GetAddressInsight API endpoint, attempting the primary endpoint
* first and falling back to the backup if the response is invalid (Error.TypeCode == '3') in live mode.
* </summary>
* @param {string} BusinessName - A company name for a business, can provide additional insight or append a SuiteLink value. Optional.
* @param {string} Address1 - Address line 1 of the contact or business address (e.g., "123 Main Street").
* @param {string} Address2 - Address line 2 of the contact or business address (e.g., "Apt 4B"). Optional.
* @param {string} City - The city of the address (e.g., "New York"). Optional if zip is provided.
* @param {string} State - The state of the address (e.g., "NY"). Optional if zip is provided.
* @param {string} Zip - The ZIP code of the address. Optional if city and state are provided.
* @param {string} TestType - The test type, either empty or "census_loose" for best possible match based on census data. Optional.
* @param {string} LicenseKey - Your license key to use the service.
* @param {boolean} isLive - Value to determine whether to use the live or trial servers.
* @param {number} timeoutSeconds - Timeout, in seconds, for the call to the service.
* @returns {Promise<AINResponse>} - A promise that resolves to a AINResponse object.
*/
async invokeAsync(BusinessName, Address1, Address2, City, State, Zip, TestType, LicenseKey, isLive = true, timeoutSeconds = 15) {
const params = {
BusinessName,
Address1,
Address2,
City,
State,
Zip,
TestType,
LicenseKey
};
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;
},
/**
* <summary>
* Synchronously invokes the GetAddressInsight API endpoint by wrapping the async call
* and awaiting its result immediately.
* </summary>
* @param {string} BusinessName - A company name for a business, can provide additional insight or append a SuiteLink value. Optional.
* @param {string} Address1 - Address line 1 of the contact or business address (e.g., "123 Main Street").
* @param {string} Address2 - Address line 2 of the contact or business address (e.g., "Apt 4B"). Optional.
* @param {string} City - The city of the address (e.g., "New York"). Optional if zip is provided.
* @param {string} State - The state of the address (e.g., "NY"). Optional if zip is provided.
* @param {string} Zip - The ZIP code of the address. Optional if city and state are provided.
* @param {string} TestType - The test type, either empty or "census_loose" for best possible match based on census data. Optional.
* @param {string} LicenseKey - Your license key to use the service.
* @param {boolean} isLive - Value to determine whether to use the live or trial servers.
* @param {number} timeoutSeconds - Timeout, in seconds, for the call to the service.
* @returns {AINResponse} - A AINResponse object with address insight details or an error.
*/
invoke(BusinessName, Address1, Address2, City, State, Zip, TestType, LicenseKey, isLive = true, timeoutSeconds = 15) {
return (async () => await this.invokeAsync(
BusinessName, Address1, Address2, City, State, Zip, TestType, LicenseKey, isLive, timeoutSeconds
))();
}
};
export { GetAddressInsightClient, AINResponse };
/**
* Error object for API responses.
*/
export class Error {
constructor(data = {}) {
this.Type = data.Type;
this.TypeCode = data.TypeCode;
this.Desc = data.Desc;
this.DescCode = data.DescCode;
}
toString() {
return `Error: Type = ${this.Type}, TypeCode = ${this.TypeCode}, Desc = ${this.Desc}, DescCode = ${this.DescCode}`;
}
}
/**
* Response from GetAddressInsight API, containing address validation, geocoding, and demographic information.
*/
export class AINResponse {
constructor(data = {}) {
this.Status = data.Status;
this.StatusScore = data.StatusScore;
this.AddressStatus = data.AddressStatus;
this.DPV = data.DPV;
this.DPVDesc = data.DPVDesc;
this.Address = data.Address;
this.AddressExtra = data.AddressExtra;
this.City = data.City;
this.State = data.State;
this.Zip = data.Zip;
this.BarcodeDigits = data.BarcodeDigits;
this.CarrierRoute = data.CarrierRoute;
this.CongressCode = data.CongressCode;
this.CountyCode = data.CountyCode;
this.CountyName = data.CountyName;
this.FragmentHouse = data.FragmentHouse;
this.FragmentPreDir = data.FragmentPreDir;
this.FragmentStreet = data.FragmentStreet;
this.FragmentSuffix = data.FragmentSuffix;
this.FragmentPostDir = data.FragmentPostDir;
this.FragmentUnit = data.FragmentUnit;
this.FragmentUnitNumber = data.FragmentUnitNumber;
this.Fragment = data.Fragment;
this.FragmentPMBPrefix = data.FragmentPMBPrefix;
this.FragmentPMBNumber = data.FragmentPMBNumber;
this.Corrections = data.Corrections;
this.CorrectionsDesc = data.CorrectionsDesc;
this.AddressNotes = data.AddressNotes;
this.AddressNotesCodes = data.AddressNotesCodes;
this.GeocodeStatus = data.GeocodeStatus;
this.LocationLatitude = data.LocationLatitude;
this.LocationLongitude = data.LocationLongitude;
this.CensusTract = data.CensusTract;
this.CensusBlock = data.CensusBlock;
this.PlaceName = data.PlaceName;
this.ClassFP = data.ClassFP;
this.SLDUST = data.SLDUST;
this.SLDLST = data.SLDLST;
this.CountyFIPS = data.CountyFIPS;
this.StateFIPS = data.StateFIPS;
this.GeocodeNotes = data.GeocodeNotes;
this.GeocodeNotesCodes = data.GeocodeNotesCodes;
this.ZipStatus = data.ZipStatus;
this.ZipLatitude = data.ZipLatitude;
this.ZipLongitude = data.ZipLongitude;
this.CityType = data.CityType;
this.CityAliasName = data.CityAliasName;
this.AreaCode = data.AreaCode;
this.TimeZone = data.TimeZone;
this.DaylightSaving = data.DaylightSaving;
this.MSA = data.MSA;
this.CBSA = data.CBSA;
this.CBSA_Div = data.CBSA_Div;
this.PMSA = data.PMSA;
this.DMA = data.DMA;
this.ZipHouseholdValue = data.ZipHouseholdValue;
this.ZipPersonsPerHousehold = data.ZipPersonsPerHousehold;
this.ZipHouseholdIncome = data.ZipHouseholdIncome;
this.CountyHouseholdIncome = data.CountyHouseholdIncome;
this.StateHouseholdIncome = data.StateHouseholdIncome;
this.ZipNotes = data.ZipNotes;
this.ZipNotesCodes = data.ZipNotesCodes;
this.Debug = data.Debug || [];
this.Error = data.Error ? new Error(data.Error) : null;
}
toString() {
const debugString = this.Debug.length ? this.Debug.join(', ') : 'null';
return `AINResponse: Status = ${this.Status}, StatusScore = ${this.StatusScore}, AddressStatus = ${this.AddressStatus}, ` +
`DPV = ${this.DPV}, DPVDesc = ${this.DPVDesc}, Address = ${this.Address}, AddressExtra = ${this.AddressExtra}, ` +
`City = ${this.City}, State = ${this.State}, Zip = ${this.Zip}, BarcodeDigits = ${this.BarcodeDigits}, ` +
`CarrierRoute = ${this.CarrierRoute}, CongressCode = ${this.CongressCode}, CountyCode = ${this.CountyCode}, ` +
`CountyName = ${this.CountyName}, FragmentHouse = ${this.FragmentHouse}, FragmentPreDir = ${this.FragmentPreDir}, ` +
`FragmentStreet = ${this.FragmentStreet}, FragmentSuffix = ${this.FragmentSuffix}, FragmentPostDir = ${this.FragmentPostDir}, ` +
`FragmentUnit = ${this.FragmentUnit}, FragmentUnitNumber = ${this.FragmentUnitNumber}, Fragment = ${this.Fragment}, ` +
`FragmentPMBPrefix = ${this.FragmentPMBPrefix}, FragmentPMBNumber = ${this.FragmentPMBNumber}, ` +
`Corrections = ${this.Corrections}, CorrectionsDesc = ${this.CorrectionsDesc}, AddressNotes = ${this.AddressNotes}, ` +
`AddressNotesCodes = ${this.AddressNotesCodes}, GeocodeStatus = ${this.GeocodeStatus}, LocationLatitude = ${this.LocationLatitude}, ` +
`LocationLongitude = ${this.LocationLongitude}, CensusTract = ${this.CensusTract}, CensusBlock = ${this.CensusBlock}, ` +
`PlaceName = ${this.PlaceName}, ClassFP = ${this.ClassFP}, SLDUST = ${this.SLDUST}, SLDLST = ${this.SLDLST}, ` +
`CountyFIPS = ${this.CountyFIPS}, StateFIPS = ${this.StateFIPS}, GeocodeNotes = ${this.GeocodeNotes}, ` +
`GeocodeNotesCodes = ${this.GeocodeNotesCodes}, ZipStatus = ${this.ZipStatus}, ZipLatitude = ${this.ZipLatitude}, ` +
`ZipLongitude = ${this.ZipLongitude}, CityType = ${this.CityType}, CityAliasName = ${this.CityAliasName}, ` +
`AreaCode = ${this.AreaCode}, TimeZone = ${this.TimeZone}, DaylightSaving = ${this.DaylightSaving}, ` +
`MSA = ${this.MSA}, CBSA = ${this.CBSA}, CBSA_Div = ${this.CBSA_Div}, PMSA = ${this.PMSA}, DMA = ${this.DMA}, ` +
`ZipHouseholdValue = ${this.ZipHouseholdValue}, ZipPersonsPerHousehold = ${this.ZipPersonsPerHousehold}, ` +
`ZipHouseholdIncome = ${this.ZipHouseholdIncome}, CountyHouseholdIncome = ${this.CountyHouseholdIncome}, ` +
`StateHouseholdIncome = ${this.StateHouseholdIncome}, ZipNotes = ${this.ZipNotes}, ZipNotesCodes = ${this.ZipNotesCodes}, ` +
`Debug = [${debugString}], Error = ${this.Error ? this.Error.toString() : 'null'}`;
}
}
export default AINResponse;