Page tree
Skip to end of metadata
Go to start of metadata

 

Introduction

DOTS Address Detective ("AD") is a phone and name-assisted address validation tool. When an address does not resolve, additional clues such as having a phone number or name can help determine an address for the contact. Without these clues, or if these clues do not produce a hit, the service has the same functionality as our DOTS Address Validation – US products. A score is used to give an idea of how likely it is that this address is correct for this contact. This service utilizes the latest .Net Framework, WCF, and can be used as a RESTful service or with SOAP. 

AD can provide instant address verification and correction to websites or enhancement to contact lists.  

 

Integration

Integrating AD into your application should be easy and straightforward.  If you are using a common platform, Service Objects may already have sample code built that you can use:
https://www.serviceobjects.com/developers/sample-code/address-detective

However, if you are using a common platform that does not already have sample code, you can ask Service Objects to build you an example.  Email support@serviceobjects.com for more details.

Web Service Structure:

Web services are methods that integrate with other applications via the web, and encapsulate tricky business logic.  Web services are too large of a topic to cover in this document, but Service Objects has developed its web services to be as easy to integrate and as accessible as possible.

AD is a public XML web service that supports SOAP, POST and GET operations, using RESTful paradigms or simple HTTP transport calls.

The host path, or physical location of the web service is here:
https://trial.serviceobjects.com/ad/api.svc

A test page for the web service can be found here:
https://trial.serviceobjects.com/ad/ 

The location of the WSDL, or Web Service Definition Language document, is here (This is also accessible via the "Service Definition" link.):
https://trial.serviceobjects.com/ad/api.svc?wsdl

Important Notes!
1. This XML is the definition of the web service, meaning its inputs, outputs, operations, and the like.  Most likely, you will have another tool read this WSDL and make the operations available to you in your application.  Whenever your utilities or IDE asks for a WSDL path to AD, you can provide this one.

2. SOAP is done via POST, only with special XML markup in the post-body.

Every web service has operations that it offers to subscribers – methods that do different work and return different output.  Examining the link above, you will notice several of these operations available, which are described in detail later on.

 

Code Snippets

Address Detective C# Code Snippet
 private FixedAddressResponse FindAddress(string Address1, string Address2, string City, string State, string PostalCode, string BusinessName, string PhoneNumber, string FullName, string FirstName, string LastName, string LicenseKey)
        {
            // addressValidation is a proxy used to simplify calls to the web-service 
            AddressDetectiveClient ADClient_Primary = null;
            AddressDetectiveClient ADClient_Backup = null;
            FixedAddressResponse response = null;
            try
            {
                ADClient_Primary = new AddressDetectiveClient("DOTSAddressDetectivePrimary");
                ADClient_Primary.InnerChannel.OperationTimeout = new TimeSpan(0, 0, 0, WEB_SERVICE_REQUEST_TIMEOUT);
                response = ADClient_Primary.FindAddress(Address1, Address2, City, State, PostalCode, BusinessName, PhoneNumber, FullName, FirstName, LastName, LicenseKey);
                //NULL ERROR || FATAL ERROR RETURNED -- TRY BACKUP 
                if (response == null || (response.Error != null && response.Error.TypeCode == "3"))
                {
                    throw new Exception();
                }
                return response;
            }
            catch (Exception)
            {
                try
                {   //Use wsbackup client on backup 
                    ADClient_Backup = new AddressDetectiveClient("DOTSAddressDetectiveBackup");
                    ADClient_Backup.InnerChannel.OperationTimeout = new TimeSpan(0, 0, 0, WEB_SERVICE_REQUEST_TIMEOUT);
                    return ADClient_Backup.FindAddress(Address1, Address2, City, State, PostalCode, BusinessName, PhoneNumber, FullName, FirstName, LastName, LicenseKey);
                }
                catch (Exception e)
                {
                    throw e;
                }
                finally
                {
                    if (ADClient_Backup != null) { ADClient_Backup.Close(); }
                }
            }
            finally
            {
                if (ADClient_Primary != null) { ADClient_Primary.Close(); }
            }
        }
        private void ProcessResponse(FixedAddressResponse response)
        {
            try
            {
                if (response.Error != null)
                {
                    ProcessErrorResult(response.Error);
                }
                else
                {
                    ProcessFindAddressResult(response);
                }
            }
Address Detective Java Code Snippet
FixedAddress[] addresses = null;
ADError error= null;
								
String address1 = request.getParameter("iAddr1");
String address2 = request.getParameter("iAddr2");
String city = request.getParameter("iCity");
String state = request.getParameter("iState");
String postalCode = request.getParameter("iPostal");
String businessName = request.getParameter("iBusinessName");
String phoneNumber = request.getParameter("iPhoneNumber");
String fullName = request.getParameter("iFullName");
String firstName = request.getParameter("iFirstName");
String lastName = request.getParameter("iLastName");
String licenseKey = request.getParameter("iKey");
											
								
IAddressDetectiveProxy locator = new IAddressDetectiveProxy();
//use ssl
locator.setEndpoint("https://trial.serviceobjects.com/ad/api.svc/soap");
								
IAddressDetective ad = locator.getIAddressDetective();
DOTSAddressDetectiveStub soap = (DOTSAddressDetectiveStub)ad;
soap.setTimeout(5000);
								
try{
	 fixedAddressResponse = soap.findAddress(address1, address2, city, state, postalCode, businessName, phoneNumber, fullName, firstName, lastName, licenseKey);
									
	  addresses = fixedAddressResponse.getAddresses();
	   error = fixedAddressResponse.getError();
		 if(error !=null && error.getTypeCode() == "3")
			 {
				 throw new Exception();	
			 }
  }
catch(Exception e)
	{	//FAILOVER- USE BACKUP NOW
		try{
			//CALL SOAP USING BACKUP URL (Change the endpoint)
			fixedAddressResponse = soap.findAddress(address1, address2, city, state, postalCode, businessName, phoneNumber, fullName, firstName, lastName, licenseKey);
			addresses = fixedAddressResponse.getAddresses();
			error = fixedAddressResponse.getError();
			}
	
      //DOTS Address Detective Results     
    }
    else
    {
        //DOTS Address Detective Error  
    }
Address Detective PHP Code Snippets
<?php
	
	$Address1 = trim($Address1);
	$Address2 = trim($Address2);
	$City = trim($City);
	$State = trim($State);
	$PostalCode = trim($PostalCode);
	$BusinessName = trim($BusinessName);
	$PhoneNumber = trim($PhoneNumber);
	$FullName = trim($FullName);
	$FirstName = trim($FirstName);
	$LastName = trim($LastName);
	$LicenseKey = trim($LicenseKey);
 
$wsdlUrl = "https://trial.serviceobjects.com/ad/api.svc?wsdl";
	
try{
	$soapClient = new SoapClient($wsdlUrl, array( "trace" => 1 ));
	$result = $soapClient->FindAddress($params);
	}
	catch(Exception $e)
		{
			try
			{
			$soapClient = new SoapClient($backupWsdlUrl, array( "trace" => 1 ));
			$result = $soapClient->FindAddress($params); 
			}
			catch(Exception $ex)
			{//Both soap calls failed
				echo "<b> Primary and backup wsdls failed </b>";
				echo "$ex";
			}
		
		}
	
	if (!isset($result->FindAddressResult->Error))
	 {
		//Process AD Result
	} 
	else 
	{
		//Process AD Error
	}
}
?>
Address Detective RoR Code Snippets
 class RequestsController < ApplicationController
	def show 
		@request = Request.find(params[:id])
		#Formats inputs into a hash to pass to Soap Client
		#Hash Keys must be named as they are shown here.
		message = 	{
					"Address1" => @request.address1,
					"Address2" => @request.address2,
					"City" => @request.city,
					"State" => @request.state,
					"PostalCode" => @request.postalcode,
					"BusinessName" => @request.businessname,
					"PhoneNumber" => @request.phonenumber,
					"FullName" => @request.fullname,
					"FirstName" => @request.firstname,
					"LastName" => @request.lastname,
					"LicenseKey" => @request.licensekey,
					}
		
		#Implemented to make the code more readable when accessing the hash			
		@adresponse = :find_address_response
		@adresult = :find_address_result
		@addresses = :addresses
		@adfixed = :fixed_address
		@aderror = :error
		#Set Primary and Backup URLs here as needed
		dotsADPrimary = "https://trial.serviceobjects.com/ad/api.svc?singleWsdl"
		dotsADBackup = "https://trial.serviceobjects.com/ad/api.svc?singleWsdl"

		begin
			#initializes the soap client. The convert request keys global is necessary to receive a response from the service.
			client = Savon.client(	wsdl: dotsADPrimary,
									element_form_default: :qualified,
									convert_request_keys_to: :camelcase
								 )
			#Calls the operation with given inptus and converts response to a hash.
			response = client.call(:find_address, message: message).to_hash
			#Checks to see what results came back from the service
			processresults(response)			
			
		#If an error occurs during the call, this will use the backupurl and attempt to retrieve data.
		rescue Savon::Error => e
			begin
			backupclient = Savon.client(	wsdl: dotsADBackup,
											element_form_default: :qualified,
											convert_request_keys_to: :camelcase
									   )
			#Sets the response to the backclient call to the operation and converts response to a hash.
			response = backupclient.call(:find_address, message: message).to_hash
			processresults(response)
			#If backup url failed, this will display the error received from the server
			rescue Savon::Error =>error
				@status = error
				@displaydata = {"error" => "A Big Error Occured"}
			end
		end
	end
	private 
	def processresults(response)			
			#Processes Error Response from soap Client		
			
			#Processes Valid response from soap client	
			
	end
	
end
Address Detective Python Code Snippet
    mAddress1 = Address1.get()
    if mAddress1 is None or mAddress1 == "":
        mAddress1 = " "
    mAddress2 = Address2.get()
    if mAddress2 is None or mAddress2 == "":
        mAddress2 = " "
    mCity = City.get()
    if mCity is None or mCity == "":
        mCity = " "
    mState = State.get()
    if mState is None or mState == "":
        mState = " "
    mPostalCode = PostalCode.get()
    if mPostalCode is None or mPostalCode == "":
        mPostalCode = " "
    mBusinessName = BusinessName.get()
    if mBusinessName is None or mBusinessName == "":
        mBusinessName = " "
    mPhoneNumber = PhoneNumber.get()
    if mPhoneNumber is None or mPhoneNumber == "":
        mPhoneNumber = " "
    mFullName = FullName.get()
    if mFullName is None or mFullName == "":
        mFullName = " "
    mFirstName = FirstName.get()
    if mFirstName is None or mFirstName == "":
        mFirstName = " "
    mLastName = LastName.get()
    if mLastName is None or mLastName == "":
        mLastName = " "
    mLicenseKey = LicenseKey.get()
    if mLicenseKey is None or mLicenseKey == "":
        mLicenseKey = " "

    #Set the primary and backup URLs as needed
    primaryURL = 'https://trial.serviceobjects.com/ad/api.svc?wsdl'
    backupURL = 'https://trial.serviceobjects.com/ad/api.svc?wsdl'

    #This block of code calls the web service and prints the resulting values to the screen
    try:
        client = Client(primaryURL)
        result = client.service.FindAddress(Address1=mAddress1, Address2=mAddress2, City=mCity, State=mState, PostalCode=mPostalCode, BusinessName=mBusinessName, PhoneNumber=mPhoneNumber, FullName=mFullName, FirstName=mFirstName, LastName=mLastName, LicenseKey=mLicenseKey)
        #Handel response from the service
            
    #Tries the backup URL if the primary URL failed
    except:
        try:
            client = Client(primaryURL)
            result = client.service.FindAddress(Address1=mAddress1, Address2=mAddress2, City=mCity, State=mState, PostalCode=mPostalCode, BusinessName=mBusinessName, PhoneNumber=mPhoneNumber, FullName=mFullName, FirstName=mFirstName, LastName=mLastName, LicenseKey=mLicenseKey)
          #Handel response from the service


        #If the backup call failed then this will display an error to the screen
        except:
            Label(swin.window, text='Error').pack()
            print (result)

Address Detective ColdFusion Snippet
<!--Makes Request to web service --->
<cfscript>
		try
		{
			if (isDefined("form.Action") AND Action neq "")
			{
				wsresponse = CreateObject("webservice", "https://trial.serviceobjects.com/ad/api.svc?singleWsdl");							  
				outputs = wsresponse.findAddress("#Address1#", "#Address2#", "#City#", "#State#", "#PostalCode#", "#BusinessName#", "#PhoneNumber#", "#FullName#", "#FirstName#", "#LastName#", "#LicenseKey#");
				
			}
		}
	catch(any error){
		try
			{
				if (isDefined("form.Action") AND Action neq "")
				{
					wsresponse = CreateObject("webservice", "https://trial.serviceobjects.com/ad/api.svc?singleWsdl");							  
					outputs = wsresponse.findAddress("#Address1#", "#Address2#", "#City#", "#State#", "#PostalCode#", "#BusinessName#", "#PhoneNumber#", "#FullName#", "#FirstName#", "#LastName#", "#LicenseKey#");
				}
			}
			catch(any Exception)	{
		  		 writeoutput("An Error Has Occured. Please Reload and try again");		  		 
		 		}
	    }
</cfscript>
Address Detective VB Snippet
Try
    Dim ws As New AD.AddressDetectiveClient
    Dim response As AD.FixedAddressResponse
    response = ws.FindAddress(Address1.Text, Address2.Text, City.Text, State.Text, PostalCode.Text, BusinessName.Text, PhoneNumber.Text, FullName.Text, FirstName.Text, LastName.Text, LicenseKey.Text)
    If (response.Error Is Nothing) Then
        ProcessValidResponse(response.Addresses(0))
    Else
        ProcessErrorResponse(response.Error)
    End If
Catch er As Exception
    ''Set the Primary and Backup Service References as necessary
    Try
        Dim wsbackup As New AD.AddressDetectiveClient
        Dim response As AD.FixedAddressResponse
        response = wsbackup.FindAddress(Address1.Text, Address2.Text, City.Text, State.Text, PostalCode.Text, BusinessName.Text, PhoneNumber.Text, FullName.Text, FirstName.Text, LastName.Text, LicenseKey.Text)
        If (response.Error Is Nothing) Then
            ProcessValidResponse(response.Addresses(0))
        Else
            ProcessErrorResponse(response.Error)
        End If
    Catch ex As Exception
        resultsLabel.Visible = True
        resultsLabel.Text = ex.Message
    End Try
End Try
Address Detective Apex Code Snippet
wwwServiceobjectsCom.FixedAddressResponse result;
try{
wwwServiceobjectsCom.DOTSAddressDetective client = new wwwServiceobjectsCom.DOTSAddressDetective();
result = client.FindAddress([Address], [Address2], [City], [State], [PostalCode], [BusinessName], [PhoneNumber], [FullName], [FirstName], [LastName], [LicenseKey]);
}
catch(Exception ex){
 //If the first request failed try the failover endpoint
wwwServiceobjectsCom.DOTSAddressDetective backupClient = new wwwServiceobjectsCom.DOTSAddressDetective();
//The backup environment will be provided to you upon purchasing a production license key
backupClient.endpoint_x = 'https://trial.serviceobjects.com/AD/api.svc/soap';
result = backupClient.FindAddress([Address], [Address2], [City], [State], [PostalCode], [BusinessName], [PhoneNumber], [FullName], [FirstName], [LastName], [LicenseKey]);
}

Address Detective TSQL Code Snippet
SET @requestBody ='<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">'+
				   '<s:Body>'+
				   '<FindAddress xmlns="http://www.serviceobjects.com">'+
				   '<Address1>' + @address1 + '</Address1>'+
				   '<Address2>' + @address2 + '</Address2>'+
				   '<City>' + @city + '</City><State>' + @state + '</State>'+
				   '<PostalCode>' + @postalcode + '</PostalCode>'+
				   '<PhoneNumber>'+ @phonenumber + '</PhoneNumber>'+
				   '<FullName>'+ @fullname + '</FullName>'+
				   '<FirstName>'+ @firstname + '</FirstName>'+
				   '<LastName>'+ @lastname + '</LastName>'+
				   '<LicenseKey>' + @key + '</LicenseKey>'+
				   '</FindAddress>'+
				   '</s:Body>'+
				   '</s:Envelope>'
SET @requestLength = LEN(@requestBody)
	--If a production key is purchased, this will execute the failover 
IF @isLiveKey = 1
BEGIN
	EXEC sp_OACreate 'MSXML2.ServerXMLHttp', @obj OUT
	EXEC sp_OAMethod @obj, 'Open', NULL, 'POST', 'https://trial.serviceobjects.com/AD/api.svc/soap', false
	EXEC sp_OAMethod @obj, 'setRequestHeader', NULL, 'HOST', 'ws.serviceobjects.com'
	EXEC sp_OAMethod @obj, 'setRequestHeader', NULL, 'Content-Type', 'text/xml; charset=UTF-8'
	EXEC sp_OAMethod @obj, 'setRequestHeader', NULL, 'SOAPAction', '"https://www.serviceobjects.com/IAddressDetective/FindAddress"'
	EXEC sp_OAMethod @obj, 'setRequestHeader', NULL, 'Content-Length', @requestLength 
	EXEC sp_OAMethod @obj, 'send', NULL, @requestBody
	EXEC sp_OAGetProperty @obj, 'Status', @responseCode OUTPUT
	EXEC sp_OAGetProperty @obj, 'StatusText', @statusText OUTPUT
	EXEC sp_OAGetProperty @obj, 'responseText', @response OUTPUT
			
	--Checks the Response for a fatal error or if null. 
	IF @response IS NULL
	BEGIN
		EXEC sp_OACreate 'MSXML2.ServerXMLHttp', @obj OUT
		EXEC sp_OAMethod @obj, 'Open', NULL, 'POST', 'https://trial.serviceobjects.com/AD/api.svc/soap', false
		EXEC sp_OAMethod @obj, 'setRequestHeader', NULL, 'HOST', 'wsbackup.serviceobjects.com'
		EXEC sp_OAMethod @obj, 'setRequestHeader', NULL, 'Content-Type', 'text/xml; charset=UTF-8'
		EXEC sp_OAMethod @obj, 'setRequestHeader', NULL, 'SOAPAction', '"https://www.serviceobjects.com/IAddressDetective/FindAddress"'
		EXEC sp_OAMethod @obj, 'setRequestHeader', NULL, 'Content-Length', @requestLength 
		EXEC sp_OAMethod @obj, 'send', NULL, @requestBody
		EXEC sp_OAGetProperty @obj, 'Status', @responseCode OUTPUT
		EXEC sp_OAGetProperty @obj, 'StatusText', @statusText OUTPUT
		EXEC sp_OAGetProperty @obj, 'responseText', @response OUTPUT
	END
END
Address Detective NodeJS Code Snippet
var args = {Address1: 'Address1', 
			Address2: 'Address2',
			City: 'City', 
			State: 'State', 
			PostalCode: 'PostalCode', 
			BusinessName: 'BusinessName', 
			PhoneNumber: 'PhoneNumber', 
			FullName: 'FullName', 
			FirstName: 'FirstName', 
			LastName: 'LastName', 
			LicenseKey: 'Your-License-Key'};
			soap.createClient(primaryUrl, function(err, client) {
				
			  	client.FindAddress(args, function(err, result) {
			  		//This is where you will handle the service results. Your business logic will determine
			  		//how the validated information is used.
			  		//The exact output can be found in our documentation:
			  		//https://docs.serviceobjects.com/display/devguide/DOTS+Address+Detective
			  		if(err != null || result == null)
			  		{
			  			//There was an error that occurred that wasn't part of the normal service response
			  			return;
			  		}
			  		else{
			  			//Check for an error object
			  			if(result.FindAddressResult.Error != null)
			  			{
			  				//An error object was returned by the service and you will want to use 
			  				//the following failover logic.
			  				//If it was a Service Objects Fatal exception we recommend trying 
			  				//a backup server. 
			  				if(result.FindAddressResult.Error.TypeCode == "3")
			  				{
			  					//The actual backup url will be provided when you purchase a license key
			  					var backupUrl = 'https://trial.serviceobjects.com/ad/api.svc?singleWsdl';
			  					soap.createClient(backupUrl, function(failoverErr, backupClient) {
				
			  						backupClient.FindAddress(args, function(failoverErr, failoverResult) {
			  							//Handle the failoverErr or failoverResult objects.
			  							return;
			  						});
			  					});
			  				}
						}
					}
				}
Address Detective C# Code Snippet
 string mainURL = TrialURL+ address1 + "/" + address2 + "/" + city + "/" + state + "/" + postalCode + "/" + businessName + "/" + phoneNumber + "/" + fullName + "/" + firstName + "/" + lastName + "/" + licenseKey;
 ADResponse result = null;
try
{
    result = HttpGet(mainURL);
    //NULL ERROR || FATAL ERROR RETURNED -- TRY BACKUP 
    if (result == null || (result.error != null && result.error.TypeCode == "3"))
     {
     return HttpGet(backupURL);
     }
 else
 {
    return result;
 }
}
 
private ADResponse HttpGet(string requestUrl)
{
  try
  {
   //NOTE: URL encoding occurs automatically when creating the web request
   HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
   request.Timeout = WEB_SERVICE_REQUEST_TIMEOUT;//timeout for get operation
 
  using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
    {
       if (response.StatusCode != HttpStatusCode.OK)
         throw new Exception(String.Format(
         "Server error (HTTP {0}: {1}).",
          response.StatusCode,
          response.StatusDescription));

          //parse response
          DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(ADResponse));
          object objResponse = jsonSerializer.ReadObject(response.GetResponseStream());
          ADResponse jsonResponse = objResponse as ADResponse;
          return jsonResponse;
     }
   }
}

 private void ProcessResponse(ADResponse response)
        {
            try
            {
                //processing result
                if (response.error == null)
                {
                    ProcessResult(response);
                }
                //processing error
                else
                {
                    ProcessError(response.error);
                }
            }
            
        }
 
 
 
Address Detective Java Code Snippet
FoundAddressResponse ADResponse = null;
ADError error = null;
FixedAddressResponse.FixedAddress[] addresses = null;
String addr1 = request.getParameter("iAddr1");
String addr2 = request.getParameter("iAddr2");
String city = request.getParameter("iCity");
String state = request.getParameter("iState");
String postalCode = request.getParameter("iPostalCode");
String businessName = request.getParameter("iBusinessName");
String phoneNumber = request.getParameter("iPhoneNumber");
String fullName = request.getParameter("iFullName");
String firstName = request.getParameter("iFirstName");
String lastName = request.getParameter("iLastName");
String licenseKey = request.getParameter("iKey");

ADRestClient ADClient = new ADRestClient();
FixedAddressResponse result = ADClient.FindAddress(addr1,addr2, city, state, postalCode, businessName, phoneNumber, fullName, firstName, lastName, licenseKey);
if (result != null) {
error = result.error;
addresses = result.Addresses;
}
 
//Process Results
if (error == null) {
	//DOTS Address Detective Results
		
}
 
//Process Errors
else{
}
	//DOTS Address Detective Error 
	
}

Address Detective PHP Code Snippets
<?php
	$Address1 = trim($Address1);
	$Address2 = trim($Address2);
	$City = trim($City);
	$State = trim($State);
	$PostalCode = trim($PostalCode);
	$BusinessName = trim($BusinessName);
	$PhoneNumber = trim($PhoneNumber);
	$FullName = trim($FullName);
	$FirstName = trim($FirstName);
	$LastName = trim($LastName);
	$LicenseKey = trim($LicenseKey);
 
$TrialURL="https://trial.serviceobjects.com/AD/api.svc/FindAddressJson/".rawurlencode($Address1)."/".rawurlencode($Address2)."/".rawurlencode($City)."/".rawurlencode($State)."/".rawurlencode($PostalCode)."/".rawurlencode($BusinessName)."/".rawurlencode($PhoneNumber)."/".rawurlencode($FullName)."/".rawurlencode($FirstName)."/".rawurlencode($LastName)."/".rawurlencode($LicenseKey);

        // Get cURL resource
			$curl = curl_init();
			curl_setopt_array($curl, array(CURLOPT_RETURNTRANSFER => 1, CURLOPT_URL => $URL, CURLOPT_USERAGENT => 'Service Objects AddressDetective'));
			curl_setopt($curl, CURLOPT_TIMEOUT, 50); //timeout in seconds
			// Send the request & save response to $resp
			$resp = curl_exec($curl);
			
			// Close request to clear up some resources
			if($resp == false)
			{
				curl_setopt_array($curl, array(CURLOPT_RETURNTRANSFER => 1, CURLOPT_URL => $backupURL, CURLOPT_USERAGENT => 'Service Objects Address Detective'));
				curl_setopt($curl, CURLOPT_TIMEOUT, 50); //timeout in seconds
				// Send the request & save response to $resp
				$resp = curl_exec($curl);
				if($resp == false)
				{
					echo "<b> Both rest calls failed </b>";
					curl_close($curl);
					return;
				}
			}
		
		try
		{
			$jsonIterator = new RecursiveIteratorIterator(new RecursiveArrayIterator(json_decode($resp, TRUE)), RecursiveIteratorIterator::SELF_FIRST);
		}
		catch (Exception $e) 
		{  
 			echo "Invalid input.";
 			$gotValidInput = false; 
		} 
		if($gotValidInput)
		{
			//Process AD Results
		}
		else
		{
			//Process AD Error
		}
?>
Address Detective RoR Code Snippets
 class RequestsController < ApplicationController

      address1 = @request.address1
      address2 = @request.address2
      city = @request.city
      state = @request.state
      postalcode = @request.postalcode
      businessname = @request.businessname
      phonenumber = @request.phonenumber
      fullname = @request.fullname
      firstname = @request.firstname
      lastname = @request.lastname
      licensekey = @request.licensekey
      
            
      #Set Primary and Backup URLs as needed. This method encodes and standardizes the URI to pass to the REST service.
      primaryURL = URI.encode("http:s//trial.serviceobjects.com/ad/api.svc/FindAddress?"+"Address1=" + address1 + "&Address2=" + address2 + "&City=" + city + "&State=" + state + "&PostalCode=" + postalcode + "BusinessName=" + businessname + "&PhoneNumber=" + phonenumber + "&FullName=" + fullname + "&FirstName=" + firstname + "&LastName=" + lastname + "&LicenseKey=" + licensekey)
      backupURL = URI.encode("https://trial.serviceobjects.com/ad/api.svc/FindAddress?"+"Address1=" + address1 + "&Address2=" + address2 + "&City=" + city + "&State=" + state + "&PostalCode=" + postalcode + "BusinessName=" + businessname + "&PhoneNumber=" + phonenumber + "&FullName=" + fullname + "&FirstName=" + firstname + "&LastName=" + lastname + "&LicenseKey=" + licensekey)
      
      
      #These are set to access the hash that is returned
      @adresult ="FixedAddressResponse"
      @adaddresses = "Addresses"
      @adfixed = "FixedAddress"
      @aderror = "Error"
        #Begins the call the RESTful web service
      begin
        response = HTTParty.get(primaryURL, timeout: default_timeout)
        #processes the response to display to the screen
        
        #Passes the response returned from HTTParty and processes them depending on the results
        processresults(response)
        
       rescue StandardError => e
       		begin
       		#uses the backupURl in the event that the service encountered an error
       		response = HTTParty.get(backupURL, timeout: default_timeout)
          
          #processes the response returned from using the backupURL
       		processresults(response)
          #If the backup url railed this will raise an error and display the 
          #error message returned from the HTTParty gem.
       		rescue StandardError => error
       			@status = error.message
       			@displaydata = {"Error" => "An Error Occured"}
       		end
      end
      
  end
	private 
    #processes HTTParty response a
	def processresults(response)	
		
	end
	
end

 

 

 

Address Detective Python Code Snippet
    mAddress1 = Address1.get()
    if mAddress1 is None or mAddress1 == "":
        mAddress1 = " "
    mAddress2 = Address2.get()
    if mAddress2 is None or mAddress2 == "":
        mAddress2 = " "
    mCity = City.get()
    if mCity is None or mCity == "":
        mCity = " "
    mState = State.get()
    if mState is None or mState == "":
        mState = " "
    mPostalCode = PostalCode.get()
    if mPostalCode is None or mPostalCode == "":
        mPostalCode = " "
    mBusinessName = BusinessName.get()
    if mBusinessName is None or mBusinessName == "":
        mBusinessName = " "
    mPhoneNumber = PhoneNumber.get()
    if mPhoneNumber is None or mPhoneNumber == "":
        mPhoneNumber = " "
    mFullName = FullName.get()
    if mFullName is None or mFullName == "":
        mFullName = " "
    mFirstName = FirstName.get()
    if mFirstName is None or mFirstName == "":
        mFirstName = " "
    mLastName = LastName.get()
    if mLastName is None or mLastName == "":
        mLastName = " "
    mLicenseKey = LicenseKey.get()
    if mLicenseKey is None or mLicenseKey == "":
        mLicenseKey = " "
    #Set the primary and backup URLs as necessary
    primaryURL = 'https://trial.serviceobjects.com/ad/api.svc/FindAddress?'
    backupURL = 'https://trial.serviceobjects.com/ad/api.svc/FindAddress?'
    #The Requests package allows the user to format the path parameters like so instead of having to manually insert them into the URL
    inputs = {'Address1': mAddress1, 'Address2': mAddress2, 'City': mCity, 'State': mState, "PostalCode": mPostalCode, 'BusinessName': mBusinessName, 'PhoneNumber': mPhoneNumber, 'FullName': mFullName, 'FirstName':mFirstName, 'LastName':mLastName, 'LicenseKey': mLicenseKey}
    try:
        result = requests.get(primaryURL, params=inputs)

        #Parses the XML response from the service into a python dictionary type
        outputs = xmltodict.parse(result.content)

        #handle response and displays the info accordingly
  
    #This tries the backup URL if the primary URL failed
    except:
        try:
            result = requests.get(backupURL, params=inputs)
            #Parses the XML response from the service into a python dictionary type
            outputs = xmltodict.parse(result.content)

            #handle response and displays the info accordingly
           
        #Prints an error message to screen if the primary and backup url failed
        except:
            Label(swin.window, text='Error').pack()
          
            print (result)
 
Address Detective ColdFusion Snippet
<!--Makes Request to web service --->
<cfIf isDefined("form.Action") AND Action neq "" >
	<cftry>
		<cfset primaryURL =  "https://trial.serviceobjects.com/ad/api.svc/FindAddress?Address1=#Address1#&Address2=#Address2#&City=#City#&State=#State#&PostalCode=#PostalCode#&BusinessName=#BusinessName#&PhoneNumber=#PhoneNumber#&FullName=#FullName#&FirstName=#FirstName#&LastName=#LastName#&LicenseKey=#LicenseKey#">
		<cfhttp url="#primaryURL#" method="get" result="response">
		<cfset outputs = XmlParse(response.FileContent)>
		<cfcatch>
			<cftry>
				<cfset backupURL =  "https://trial.serviceobjects.com/ad/api.svc/FindAddress?Address1=#Address1#&Address2=#Address2#&City=#City#&State=#State#&PostalCode=#PostalCode#&BusinessName=#BusinessName#&PhoneNumber=#PhoneNumber#&FullName=#FullName#&FirstName=#FirstName#&LastName=#LastName#&LicenseKey=#LicenseKey#">
				<cfhttp url="#backupURL#" method="get" result="response">
				<cfset outputs = XmlParse(response.FileContent)>				
				<cfcatch >
					<cfoutput >
						The Following Error Occured: #response.StatusCode#
					</cfoutput>
				</cfcatch>
			</cftry>
		</cfcatch>
	</cftry>
</cfif>
Address Detective VB Rest Snippet
'encodes the URLs for the get Call. Set the primary and back urls as necessary
Dim primaryurl As String = "https://trial.serviceobjects.com/ad/api.svc/FindAddress?" + "Address1=" + address1 + "&Address2=" + address2 + "&City=" + city + "&State=" + state + "&PostalCode=" + postalcode + "BusinessName=" + businessname + "&PhoneNumber=" + phonenumber + "&FullName=" + fullname + "&FirstName=" + firstname + "&LastName=" + lastname + "&LicenseKey=" + licensekey
Dim backupurl As String = "https://trial.serviceobjects.com/ad/api.svc/FindAddress?" + "Address1=" + address1 + "&Address2=" + address2 + "&City=" + city + "&State=" + state + "&PostalCode=" + postalcode + "BusinessName=" + businessname + "&PhoneNumber=" + phonenumber + "&FullName=" + fullname + "&FirstName=" + firstname + "&LastName=" + lastname + "&LicenseKey=" + licensekey

Dim wsresponse As ADResponse.FixedAddressResponse = httpGet(primaryurl)


'checks if a response was returned from the service, uses the backup url if response is null or a fatal error occured.
If wsresponse Is Nothing OrElse (wsresponse.[Error] IsNot Nothing AndAlso wsresponse.[Error].TypeCode = "3") Then

    wsresponse = httpGet(backupurl)
End If

If wsresponse.[Error] IsNot Nothing Then
    ProcessErrorResponse(wsresponse.[Error])
Else
    ProcessSuccessfulResponse(wsresponse)
End If
Address Detective TSQL REST Code Snippet
BEGIN
	SET @sUrl = 'https://trial.serviceobjects.com/ad/api.svc/FindAddress?Address1=' + @address1 + '&Address2=' + @address2 + '&City=' + @city + '&State=' + @state + '&PostalCode=' + @postalcode + '&BusinessName=' + @businessname + '&PhoneNumber=' + @phonenumber + '&FullName=' + @fullname + '&FirstName=' + @firstname + '&LastName=' + @lastname + '&LicenseKey=' + @key
	EXEC sp_OACreate 'MSXML2.ServerXMLHttp', @obj OUT
	EXEC sp_OAMethod @obj, 'Open', NULL, 'Get', @sUrl, false
	EXEC sp_OAMethod @obj, 'send'
	EXEC sp_OAGetProperty @obj, 'responseText', @response OUT
			
	--Checks the Response for a fatal error or if null. 
	IF @response IS NULL
	BEGIN
		SET @sBackupUrl = 'https://trial.serviceobjects.com/ad/api.svc/FindAddress?Address1=' + @address1 + '&Address2=' + @address2 + '&City=' + @city + '&State=' + @state + '&PostalCode=' + @postalcode + '&BusinessName=' + @businessname + '&PhoneNumber=' + @phonenumber + '&FullName=' + @fullname + '&FirstName=' + @firstname + '&LastName=' + @lastname + '&LicenseKey=' + @key
		EXEC sp_OACreate 'MSXML2.ServerXMLHttp', @obj OUT
		EXEC sp_OAMethod @obj, 'Open', NULL, 'Get', @sBackupUrl, false
		EXEC sp_OAMethod @obj, 'send'
		EXEC sp_OAGetProperty @obj, 'responseText', @response OUT
	END
END
Address Detective NodeJS REST Code Snippet
//Set backup and primary URL as necessary
var primaryUrl = 'https://trial.serviceobjects.com/ad/api.svc/FindAddress?Address1='+ Address1+'&Address2='+ Address2 + '&City=' + City +'&State=' + State +'&PostalCode=' + PostalCode + '&BusinessName=' + BusinessName + '&PhoneNumber=' + PhoneNumber + '&FullName=' + FullName + '&FirstName=' + FirstName + '&LastName=' + LastName +'&LicenseKey=' + LicenseKey;
var backupUrl = 'https://trial.serviceobjects.com/ad/api.svc/FindAddress?Address1='+ Address1+'&Address2='+ Address2 + '&City=' + City +'&State=' + State +'&PostalCode=' + PostalCode + '&BusinessName=' + BusinessName + '&PhoneNumber=' + PhoneNumber + '&FullName=' + FullName + '&FirstName=' + FirstName + '&LastName=' + LastName +'&LicenseKey=' + LicenseKey;


var req = http.get(primaryUrl, function(res) {

res.setEncoding('utf8');
res.on('data', function (results) {

	var parser = require('xml2js').Parser({explicitArray: false,ignoreAttrs: true});
	parser.parseString(results, function (err, outputs) {
		if (outputs.FixedAddressResponse.Error !=  null)
		{
			//Indicates a Fatal error has occured. If this happens, the logic will then failover to the backup url
			if (outputs.FixedAddressResponse.Error.TypeCode == "3")
			{
				var backupReq = http.get(backupUrl, function(backupRes) {
					backupRes.setEncoding('utf8');
					backupRes.on('data', function (results) {

							var parser = require('xml2js').Parser({explicitArray: false,ignoreAttrs: true});
							parser.parseString(results, function (err, outputs) {

								console.log("Backup Call Was Used.");
								response.end(JSON.stringify(outputs , null, 3));
							});
						});
					});
			}
			else
			{
				//Will Display the JSON Formatted Error Response here
				response.end(JSON.stringify(outputs, null, 3));
				return;
			}
		}
		else
		{
			//Will Display the JSON Formatted Valid Response here
			response.end(JSON.stringify(outputs, null, 3));
			return;
		}
	});
});

 

 

You can find and download full sample code to our services in various languages (PHP, JAVA and C#) by clicking here. Below is a C# version.

If you are looking for a particular integration not listed in our documentation please contact us at support@serviceobjects.com.

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Net;
using System.Data;
using System.Runtime.Serialization.Json;
using System.Configuration;
namespace DOTSAD
{
    public partial class ad_rest : System.Web.UI.Page
    {
        private string TrialURL = ConfigurationManager.AppSettings["TrialURL"];
        protected void Page_Load(object sender, EventArgs e)
        {
            ErrorLabel.Visible = false;
            ResultGrid.Visible = false;
        }
        protected void btn_Validate_Click(object sender, EventArgs e)
        {
            string FullName,FirstName,LastName,Address,Address2,City,State,PostalCode,PhoneNumber,LicenseKey;
            FullName = inputFullName.Text;
            FirstName = inputFirstName.Text;
            LastName = inputLastName.Text;
            Address = inputAddress.Text;
            Address2 = inputAddress2.Text;
            City = inputCity.Text;
            State = inputState.Text;
            PostalCode = inputPostalCode.Text;
            PhoneNumber = inputPhoneNumber.Text;
            LicenseKey = inputLicenseKey.Text;
            try
            {
                //NOTE: A missing parameter is not allowed
                if (FullName == "")
                    FullName = " ";
                if (FirstName == "")
                    FirstName = " ";
                if (LastName == "")
                    LastName = " ";
                if (Address == "")
                    Address = " ";
                if (Address2 == "")
                    Address2 = " ";
                if (City == "")
                    City = " ";
                if (State == "")
                    State = " ";
                if (PostalCode == "")
                    PostalCode = " ";
                if (PhoneNumber == "")
                    PhoneNumber = " ";
                if (LicenseKey == "")
                    LicenseKey = " ";
                if (String.IsNullOrWhiteSpace(LicenseKey))
                    LicenseKey = "yourDevKey";
                FoundAddressResponse response = MakeRequest(FullName,FirstName,LastName,Address,Address2,City,State,PostalCode,PhoneNumber,LicenseKey);
                PrintResponse(response);
            }
            catch (Exception ex)
            {
                ErrorLabel.Text = ex.Message;
                ErrorLabel.Visible = true;
            }
        }
        //Creates URL and requests response from service 
        private FoundAddressResponse MakeRequest(string FullName,string FirstName,string LastName,string Address,string Address2,string City,string State,string PostalCode,string PhoneNumber,string LicenseKey)
        {
            /* 
            * Due to RFC compliance, the use of URL Paths has character limitations.  
            * Certain characters are invalid and cause HTTP Errors; these characters  
            * include #, /, ?,\ as well as some high bit characters.  
            * 
            * If you suspect that this may be an issue for you then it is recommended to change your 
            * request from the URL path parameter format to the query string parameter format.  
            * Example:  
            *     FROM {data}/{data2}/{key}?format=json  
            *     TO parameter1={data1}&parameter2={data2}&licensekey={key} 
            * Another alternative is to use HTTP Post instead of HTTP Get. 
            */
            FoundAddressResponse result = null;
            // /BestAddress/{FULLNAME}/{FIRSTNAME}/{LASTNAME}/{ADDRESS}/{ADDRESS2}/{CITY}/{STATE}/{POSTALCODE}/{PHONENUMBER}/{LICENSEKEY}?format=json
            string mainURL = TrialURL + "/BestAddress/" + FullName + "/" + FirstName + "/" + LastName + "/" + Address + "/" + Address2 + "/" + City + "/" + State + "/" + PostalCode + "/" + PhoneNumber + "/" + LicenseKey + "?format=json";
            // A trial license key is not compatible with the backup datacenter. 
            // The backup url is provided with a production license key.
            string backupURL = TrialURL + "/BestAddress/" + FullName + "/" + FirstName + "/" + LastName + "/" + Address + "/" + Address2 + "/" + City + "/" + State + "/" + PostalCode + "/" + PhoneNumber + "/" + LicenseKey + "?format=json";
            try
            {
                result = HttpGet(mainURL);
                //NULL ERROR || FATAL ERROR RETURNED -- TRY BACKUP 
                if (result == null || (result.Error != null && result.Error.TypeCode == "3"))
                {
                    return HttpGet(backupURL);
                }
                else
                {
                    return result;
                }
            }
            catch (Exception)
            {
                //ERROR IN MAIN URL - USING BACKUP
                return HttpGet(backupURL);
            }
        }
        private FoundAddressResponse HttpGet(string requestUrl)
        {
            try
            {
                //NOTE: URL encoding occurs automatically when creating the web request
                HttpWebRequest request = WebRequest.Create(requestUrl) as HttpWebRequest;
               // request.Timeout = WEB_SERVICE_REQUEST_TIMEOUT;//timeout for get operation
                using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
                {
                    if (response.StatusCode != HttpStatusCode.OK)
                        throw new Exception(String.Format(
                        "Server error (HTTP {0}: {1}).",
                        response.StatusCode,
                        response.StatusDescription));
                    //parse response
                    DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(FoundAddressResponse));
                    object objResponse = jsonSerializer.ReadObject(response.GetResponseStream());
                    FoundAddressResponse jsonResponse = objResponse as FoundAddressResponse;
                    return jsonResponse;
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        protected void PrintResponse(FoundAddressResponse response)
        {
            DataTable dtProvider = new DataTable();
            //Proccess result
            //We just output it here but this would be a good place to save data
            //to a database or send an email etc.
            dtProvider.Columns.Add(new DataColumn("Output", typeof(string)));
            dtProvider.Columns.Add(new DataColumn("Values", typeof(string)));

            if (response.Error == null)
            {
                int i = 1;
                foreach (HouseholdMember Member in response.HouseholdMembers)
                {
                    dtProvider.Rows.Add("HouseHold Member " + i, "");
                    dtProvider.Rows.Add("FirstName", Member.FirstName);
                    dtProvider.Rows.Add("LastName", Member.LastName);
                    i++;
                }
                dtProvider.Rows.Add("Best Address", "");
                dtProvider.Rows.Add("Address", response.BestAddress.Address);
                dtProvider.Rows.Add("City", response.BestAddress.City);
                dtProvider.Rows.Add("State", response.BestAddress.State);
                dtProvider.Rows.Add("Zip", response.BestAddress.Zip);
                dtProvider.Rows.Add("Address2", response.BestAddress.Address2);
                dtProvider.Rows.Add("ResidentType", response.BestAddress.ResidenceType);
                dtProvider.Rows.Add("BarcodeDigits", response.BestAddress.BarcodeDigits);
                dtProvider.Rows.Add("CarrierRoute", response.BestAddress.CarrierRoute);
                dtProvider.Rows.Add("CongressCode", response.BestAddress.CongressCode);
                dtProvider.Rows.Add("CountyName", response.BestAddress.CountyName);
                dtProvider.Rows.Add("FragmentHouse", response.BestAddress.FragmentHouse);
                dtProvider.Rows.Add("FragmentPreDir", response.BestAddress.FragmentPreDir);
                dtProvider.Rows.Add("FragmentStreet", response.BestAddress.FragmentStreet);
                dtProvider.Rows.Add("FragmentSuffix", response.BestAddress.FragmentSuffix);
                dtProvider.Rows.Add("FragmentPostDir", response.BestAddress.FragmentPostDir);
                dtProvider.Rows.Add("FragmentUnit", response.BestAddress.FragmentUnit);
                dtProvider.Rows.Add("Fragment", response.BestAddress.Fragment);
                dtProvider.Rows.Add("FragmentPMBPrefix", response.BestAddress.FragmentPMBPrefix);
                dtProvider.Rows.Add("FragmentPMBNumber", response.BestAddress.FragmentPMBNumber);
                dtProvider.Rows.Add("DPV", response.BestAddress.DPV);
                dtProvider.Rows.Add("DPVDesc", response.BestAddress.DPVDesc);
                dtProvider.Rows.Add("DPVNotes", response.BestAddress.DPVNotes);
                dtProvider.Rows.Add("DPVNotesDesc", response.BestAddress.DPVNotesDesc);
                dtProvider.Rows.Add("Corrections", response.BestAddress.Corrections);
                dtProvider.Rows.Add("CorrectionsDesc", response.BestAddress.CorrectionsDesc);
                dtProvider.Rows.Add("PhoneNumber", response.PhoneNumber);
                dtProvider.Rows.Add("ConfidenceScore", response.ConfidenceScore);
                dtProvider.Rows.Add("NotesCodes", response.NotesCodes);
                dtProvider.Rows.Add("NotesDescriptions", response.NotesDescriptions);
            }
            else
            {
                ErrorLabel.Text = "Errors Found!";
                ErrorLabel.Visible = true;
                dtProvider.Rows.Add("Type", response.Error.Type);
                dtProvider.Rows.Add("TypeCode", response.Error.TypeCode);
                dtProvider.Rows.Add("Desc", response.Error.Desc);
                dtProvider.Rows.Add("DescCode", response.Error.DescCode);
            }
            ResultGrid.DataSource = new DataView(dtProvider);
            ResultGrid.DataBind();
            ResultGrid.Visible = true;
        }
    }
}
		
             

FindAddress Example Request and Response


URL Request:
https://trial.serviceobjects.com/AD/api.svc/FindAddressJson/27%20E%20Cota%20St/STE%20500/Norwalk/CA/93101/Service%20Objects/8059631700/Mike%20Wilson/Mike/Wilson/YourKeyHere


Json Response
{"Addresses":[{"Address":"27 E Cota St Ste 500","City":"Santa Barbara","State":"CA","Zip":"93101-7602","DPV":1,"DPVDesc":"Yes, the input record is a valid mailing address","DPVNotes":"24,26,28,39","DPVNotesDesc":"SuiteLink did not find Suite or Unit data to append to the address,The input address matched the ZIP+4 record,The input address matched the DPV record,Highrise apartment\/office building address","Corrections":"2A","CorrectionsDesc":"City corrected","BarcodeDigits":"931017602254","CarrierRoute":"C006","CongressCode":"24","CountyCode":"083","CountyName":"Santa Barbara","FragmentHouse":"27","FragmentPreDir":"E","FragmentStreet":"Cota","FragmentSuffix":"St","FragmentPostDir":"","FragmentUnit":"Ste","Fragment":"500","FragmentPMBPrefix":"","FragmentPMBNumber":""}]}
XML Request: 
https://trial.serviceobjects.com/AD/api.svc/FindAddress/27%20E%20Cota%20St/STE%20500/Norwalk/CA/93101/Service%20Objects/8059631700/Mike%20Wilson/Mike/Wilson/YourKeyHere?format=xml
XML Response
<FixedAddressResponse xmlns="http://www.serviceobjects.com" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Addresses>
<FixedAddress>
<Address>27 E Cota St Ste 500</Address>
<City>Santa Barbara</City>
<State>CA</State>
<Zip>93101-7602</Zip>
<DPV>1</DPV>
<DPVDesc>Yes, the input record is a valid mailing address</DPVDesc>
<DPVNotes>24,26,28,39</DPVNotes>
<DPVNotesDesc>
SuiteLink did not find Suite or Unit data to append to the address,The input address matched the ZIP+4 record,The input address matched the DPV record,Highrise apartment/office building address
</DPVNotesDesc>
<Corrections>2A</Corrections>
<CorrectionsDesc>City corrected</CorrectionsDesc>
<BarcodeDigits>931017602254</BarcodeDigits>
<CarrierRoute>C006</CarrierRoute>
<CongressCode>24</CongressCode>
<CountyCode>083</CountyCode>
<CountyName>Santa Barbara</CountyName>
<FragmentHouse>27</FragmentHouse>
<FragmentPreDir>E</FragmentPreDir>
<FragmentStreet>Cota</FragmentStreet>
<FragmentSuffix>St</FragmentSuffix>
<FragmentPostDir/>
<FragmentUnit>Ste</FragmentUnit>
<Fragment>500</Fragment>
<FragmentPMBPrefix/>
<FragmentPMBNumber/>
</FixedAddress>
</Addresses>
</FixedAddressResponse>

List of Operations

FindAddress (Recommended Operation)  Returns a validated address that utilizes phone and name clues to increase hit rates with higher accuracy.
FindAddressLines - Behaves the same as FindAddress but the parameters can be entered in any order on the different input lines. 
FindOutlyingAddress - Can leverage additional non USPS data sources to find hard to find addresses that the USPS does not consider valid for mailing purposes.

Operation Definitions

This document defines the input, output and behavior of the web service operations in Address Detective.  Each operation has its own unique behavior and output, although some of the operations are very similar.

FindAddress (Recommended Operation)

Returns parsed and validated address elements. This operation's primary concern is to return an address to you if your input address fails. If your input address is valid, then the service is done and the validated and standardized address is returned. Additional data source results will not override the address found from your inputs.  Any found addresses should match in some way to the input address.

If your address could not be found by USPS, we will use the additional clues like Phone and Name to try to return the "correct" address to you. Since we can't be 100% certain that what we get from name or phone data will be the address you're looking for, a confidence score from 1-100 will be provided. This score goes up when, say, we see the same address turn up several times with your input clues. Or if an address we found is in the same general city/state or zip area as the one provided in the bad input address. 

URL Formats

JSON:  https://trial.serviceobjects.com/AD/api.svc/FindAddress/{ADDRESS}/{ADDRESS2}/{CITY}/{STATE}/{POSTALCODE}/{BUSINESSNAME}/{PHONENUMBER}/{FULLNAME}/{FIRSTNAME}/{LASTNAME}/{LICENSEKEY}?format=json 

XML:  https://trial.serviceobjects.com/AD/api.svc/FindAddress/{ADDRESS}/{ADDRESS2}/{CITY}/{STATE}/{POSTALCODE}/{BUSINESSNAME}/{PHONENUMBER}/{FULLNAME}/{FIRSTNAME}/{LASTNAME}/{LICENSEKEY}?format=xml

Click Here for examples and code snippets!

FindAddress Inputs

Name

Type

Description

Address1

String

Address line of the address to validate.  
For example, "123 Main Street".

Address2

String

This line is for address information that does not contribute to DPV coding an address. For example "C/O John Smith" does not help validate the address, but is still useful in delivery.

City

String

The city of the address to validate. 
For example, "New York".  The city isn't required, but if one is not provided, the Zip code is required.

State

String

The state of the address to validate.  For example, "NY".  This does not need to be contracted, full state names will work as well.  The state isn't required, but if one is not provided, the Zip code is required.

PostalCode

String

The zip code of the address to validate.  A zip code isn't required, but if one is not provided, the City and State are required.

BusinessNameStringIf this is a business address, add the business name here. It can help with the identification of a proper address.
PhoneNumberString

The phone number for the contact.

FullNameStringIf you don't have first and last names parsed separately, you can instead place the full name into this field for parsing.
FirstNameStringIf you have first and last names separated, place the first name here.
LastNameStringIf you have first and last names separated, place the last name here.

LicenseKey*

String

Your license key to use the service.  
Sign up for a free trial key at 
https://www.serviceobjects.com/products/address/address-detective

 

FindAddress Outputs

Output Parameter

Sub Parameter

Type

Description

FixedAddress

Address

String

The corrected Address line 1.

 

City

String

The corrected city name.

 

State

String

The corrected state name.

 

Zip

String

The corrected zip code + 4.

 DPV*StringNumber that correlates to a DPV(Delivery Point Validation) result. An indicator displaying whether or not the address is recognized as deliverable by the USPS.
 DPVDesc*StringA description of the DPV number.
 DPVNotes*StringNumber that correlates to DPV notes description. Service Objects may add or change Note descriptions, but will never modify existing codes.
 DPVNotesDesc*StringDetails about the DPV result. Service Objects may add or change Note descriptions, but will never modify existing codes.
 Corrections*StringNumber that correlates to a Corrections Description. Service Objects may add or change Correction descriptions, but will never modify existing codes.
 CorrectionsDesc*StringDescription of what was corrected in an address. Linked to the Corrections number. Service Objects may add or change Correction descriptions, but will never modify existing codes.
 NotesStringNot currently used.
 NotesDescStringNot currently used.
 

BarcodeDigits

String

The post office delivery barcode digits.

 

CarrierRoute

String

4 chars: 1 for the route type, 3 for the route code. Identifies a group of addresses when prepended by 5-digit Zip.

 

CongressCode

String

The congress code of the given address.

 

CountyCode

String

The county code of the given address.

 

CountyName

String

The name of the county in which the given address lies.

 

FragmentHouse

String

The parsed house number of the given address.

 

FragmentPreDir

String

The parsed pre-directional of the address's street.  "North" in "North Main St West".

 

FragmentStreet

String

The parsed name of the street in the given address.  "Main" in "North Main St West".

 

FragmentSuffix

String

The parsed suffix of the street in the given address.  "St" in "North Main St West".

 

FragmentPostDir

String

The parsed post-directional of the address's street.  "West" in "North Main St West".

 

FragmentUnit

String

The parsed unit type (e.g. "Apt" or "Ste")

 FragmentStringThe parsed "Fragment" box, apartment or unit number. Same as FragmentPMBNumber.
 

FragmentPMBPrefix

String

The parsed type of the apartment, box, unit, etc.  For example, "APT" or "BOX".

 

FragmentPMBNumber

String

The parsed apartment, box, unit, etc. number of the given address.

 

MatchRate

String

A score representing the quality of the returned address information.

Error

Type

String

The type of error. See "Error Codes" below.

 

TypeCode

String

A code that maps to the type. This code will never change, so your program should code to this.

 

Desc

String

Description of the exact error received.

 

DescCode

String

A code that maps to the error description. This code will never change, so your program should code to this.

*See section on DPV, DPV Notes and Corrections for possible values/descriptions


FindAddressLines

This operation has the same functionality as FindAddress with the exception that the parameters can be entered on any line, in any order into the input fields and an address will successfully validate. This operation can be used to validate messy or ambiguous address data and will attempt to find the correct address information before validating.

URL Formats

XML:  https://trial.serviceobjects.com/ad/api.svc/FindAddressLines?Line1={LINE1}&Line2={LINE2}&Line3={LINE3}&Line4={LINE4}&Line5={LINE5}&Line6={LINE6}&Line7={LINE7}&Line8={LINE8}&Line9={LINE9}&Line10={LINE10}&LicenseKey={LICENSEKEY}

 

FindAddressLines Inputs 

Name

Type

Description

Line1 to Line10

String

Address input field. This can be any of the inputs in that would be used for FindAddress.

LicenseKey*

String

Your license key to use the service.  
Sign up for a free trial key at 
https://www.serviceobjects.com/products/address/address-detective.

FindAddressLines Outputs

Output Parameter

Sub Parameter

Type

Description

FixedAddress

Address

String

The corrected Address line 1.

 

City

String

The corrected city name.

 

State

String

The corrected state name.

 

Zip

String

The corrected zip code + 4.

 DPV*StringNumber that correlates to a DPV(Delivery Point Validation) result. An indicator displaying whether or not the address is recognized as deliverable by the USPS.
 DPVDesc*StringA description of the DPV number.
 DPVNotes*StringNumber that correlates to DPV notes description. Service Objects may add or change Note descriptions, but will never modify existing codes.
 DPVNotesDesc*StringDetails about the DPV result. Service Objects may add or change Note descriptions, but will never modify existing codes.
 Corrections*StringNumber that correlates to a Corrections Description. Service Objects may add or change Correction descriptions, but will never modify existing codes.
 CorrectionsDesc*StringDescription of what was corrected in an address. Linked to the Corrections number. Service Objects may add or change Correction descriptions, but will never modify existing codes.
 NotesStringNot currently used.
 NotesDescStringNot currently used.
 

BarcodeDigits

String

The post office delivery barcode digits.

 

CarrierRoute

String

4 chars: 1 for the route type, 3 for the route code. Identifies a group of addresses when prepended by 5-digit Zip.

 

CongressCode

String

The congress code of the given address.

 

CountyCode

String

The county code of the given address.

 

CountyName

String

The name of the county in which the given address lies.

 

FragmentHouse

String

The parsed house number of the given address.

 

FragmentPreDir

String

The parsed pre-directional of the address's street.  "North" in "North Main St West".

 

FragmentStreet

String

The parsed name of the street in the given address.  "Main" in "North Main St West".

 

FragmentSuffix

String

The parsed suffix of the street in the given address.  "St" in "North Main St West".

 

FragmentPostDir

String

The parsed post-directional of the address's street.  "West" in "North Main St West".

 

FragmentUnit

String

The parsed unit type (e.g. "Apt" or "Ste")

 FragmentStringThe parsed "Fragment" box, apartment or unit number. Same as FragmentPMBNumber.
 

FragmentPMBPrefix

String

The parsed type of the apartment, box, unit, etc.  For example, "APT" or "BOX".

 

FragmentPMBNumber

String

The parsed apartment, box, unit, etc. number of the given address.

 

MatchRate

String

A score representing the quality of the returned address information.

Error

Type

String

The type of error. See "Error Codes" below.

 

TypeCode

String

A code that maps to the type. This code will never change, so your program should code to this.

 

Desc

String

Description of the exact error received.

 

DescCode

String

A code that maps to the error description. This code will never change, so your program should code to this.

*See section on DPV, DPV Notes and Corrections for possible values/descriptions



FindOutlyingAddress

Will leverage USPS data and additional data sources

URL Formats

XML:  https://trial.serviceobjects.com/ad/api.svc/FindOutlyingAddress?Address1={ADDRESS1}&Address2={ADDRESS2}&City={CITY}&State={STATE}&PostalCode={POSTALCODE}&LicenseKey={LICENSEKEY}&submit=Invoke

Click Here for examples and code snippets!

FindOutlyingAddress Inputs

Name

Type

Description

Address

String

Address line of the address to validate.  
For example, "123 Main Street".

Address2

String

This line is for address information that does not contribute to DPV coding an address. For example "C/O John Smith" does not help validate the address, but is still useful in delivery.

City

String

The city of the address to validate. 
For example, "New York".  The city isn't required, but if one is not provided, the Zip code is required.

State

String

The state of the address to validate.  For example, "NY".  This does not need to be contracted, full state names will work as well.  The state isn't required, but if one is not provided, the Zip code is required.

PostalCode

String

The zip code of the address to validate.  A zip code isn't required, but if one is not provided, the City and State are required.

LicenseKey*

String

Your license key to use the service.  
Sign up for a free trial key at 
https://www.serviceobjects.com/products/address/address-detective.

FindOutlyingAddress Outputs

Output Parameter

Sub Parameter

Type

Description

OutlyingAddress[]

Address1

String

The corrected Address line 1.

 Address2StringThe corrected Address line 2.
 

City

String

The corrected city name.

 

State

String

The corrected state name.

 

Zip

String

The corrected zip code + 4.

 DPVStringNumber that correlates to a DPV(Delivery Point Validation) result. An indicator displaying whether or not the address is recognized as deliverable by the USPS.
 InformationComponentsInformationComponent 
Level

-

String

The level to which the input address could be verified.

Notes-StringNotes that can give information about the validity or existance of an address
NotesDesc-StringDescriptions of the Notes given in the notes field.
Error

Type

String

The type of error. See "Error Codes" below.

 

TypeCode

String

A code that maps to the type. This code will never change, so your program should code to this.

 

Desc

String

Description of the exact error received.

 

DescCode

String

A code that maps to the error description. This code will never change, so your program should code to this.


InformationComponent

NameTypeValuesDescription
NameStringVariesThe variable name of the Name-Value pair that is to be returned. Usually contains extraneous information like parsed address fields
ValueStringVariesThe resulting value of the of the variable returned in the "Name" field.


*See section on DPV Notes and Corrections for possible values/descriptions


DPV Codes

DPV

DPV Desc

1

Yes, the input record is a valid mailing address

2

No, the input record is not in the DPV database of valid mailing addresses

3

The apartment or rural route box number is not valid, although the house number or rural route is valid

4

The input record is a valid mailing address, but is missing the apartment or rural route box number

DPV Notes

*New notes may be added over time, and some descriptions may change, but the codes will never change

DPVNotes

DPVNotesDesc:

1Perfect address
3Unique ZIP code
4Street alias - flag can be double, (i.e. &&) if extended USPS alias rules were applied
11Default ZIP+4 record used to certify the address
13Firm location but was certified as street address or high-rise
21Address exists but is vacant
22Address exists but mail is being returned
25Military APO/FPO address
26The input address matched the ZIP+4 record
27The input address did not match the ZIP+4 record
28The input address matched the DPV record
32The input address is a building name, and the primary is missing
35Missing PO box, Rural Route, or Highway Contract box number
36PO box, Rural Route, or Highway Contract primary is invalid
37The input address specified a PMB and matched a CMRA
38Street address
39Highrise apartment/office building address
40General Delivery address
41Post Office Box address
42Rural Route or Highway Contract address
43Firm or Business address

 

Corrections

*The corrections listed are preliminary corrections. More in depth and specific correction codes will be added in the future.

Corrections

CorrectionsDesc

1Address1 corrected.
2City corrected
3State corrected
4Zip corrected.

Scoring and Behavior

Address Detective's primary goal is to increase your address hit rate. That is, if an address fails, we will use the additional clues you provided (like Name and Phone) to try and get an address back to you. When we have to use these clues, there is a risk that what we find isn't going to be the right address for your contact. Because of this, we return a confidence score from 1-100 (1 means the returned address is extremely unlikely to be valid, 100 means it's extremely likely to be valid).

Here is the breakdown for recommended actions based on the output score:

Score RangeRecommendationDescription
1 - 39RejectNot enough confidence in the quality of the data to determine if this is the address you want
40 - 75ReviewGo through an internal review of this contact (e.g. follow-up with the contact)
76 - 100AcceptInternal testing determined the resulting address has a high enough quality to accept the address

Here is a breakdown of the general process the service goes through to return an address and produce a score:

1) Is the input address valid?

  • Yes: 
    • We're done! The "Best Address" is set to the results of the validated address input. Score will always be 100.
  • No:
  • Collect all address results we can find from Name, Phone, and Address by leveraging other data sources.
  • Determine the "best" address result from this set by looking for quality indicators. For example, if the same address appears multiple times, it's more likely to be a hit.
  • Run several tests against the best address, the other addresses, and the user's raw inputs. Each internal test raises or lowers the score based on results.

2) Return the Best Address, along with any Household member information, a score, and additional notes describing what we found to give a sense for why an address may have gotten a good or bad score.

 

Notes

**New and improved Notes will soon be added to DOTS Address Detective Service**

Errors

Anything that happens during a run of DOTS Address Detective that causes it to be unable to finish its normal processing is an error. If an error occurs, something similar to the following will result instead of the normal/typical output: 
Example:

 

*Error!*

  <Type>Authorization</Type>
  <TypeCode>1</TypeCode>
  <Desc>Your license key does not work on this service.</Desc>
  <DescCode>8</DescCode>

 

There are four error types described below.

Error Types

Type

TypeCode

Billable

Standard Across All Gen2 Web Services

Authorization

1

No

Yes

User Input

2

Yes

No

Service Objects Fatal

3

No

Yes

Domain Specific

4

Yes

No

Error type 1: Authorization

Theses are standard to all Generation 2 DOTS Web Services.

DescCode

Desc

0

Unknown authorization error.

1

Please provide a valid license key for this web service.

2

The daily allowable number of transactions for this license key has been exceeded.

3

The monthly allowable number of transactions for this license key has been exceeded.

4

The total allowable number of transactions for this license key has been exceeded.

5

There are not enough transactions available. Check your daily/monthly transaction limits.

6

This license key has not yet been activated.

7

This license key has expired.

8

Your license key does not work on this service

Error type 2: User Input

User Input errors are caused when a user inputs an invalid value or fails to provide a certain input field altogether. If a developer creates a request and mistypes a parameter name, it will probably cause a User Input Error.

DescCode

Desc

1Address and Address2 fields were too long.  Together, they must be 100 characters or less.
2Address field was too long, must be 100 characters or less.
3Please input a street address.
4Please input either zip code or both city and state.

 

Error type 3: Service Objects Fatal

The Desc will always be the same and the DescCode has no meaning. This is standard to all Generation 2 DOTS Web Services. This is a rare error that signals either a bug in the DOTS Address Detective service, or a Network/Connectivity issue.

DescCode

Desc

1

Unhandled error. Please contact Service Objects.

Error type 4: Domain Specific

Domain specific errors represent the common errors seen in Service Objects services. Domain Specific errors indicate that the service completed successfully but the result is not good.

DescCode

Desc

1Address not found
2Firm/Highrise name conflict
3Multiple addresses match
4Insufficient address data
5Please enter a valid address number.
6PR Urb not found in city street list
7Street not found
8Street number or box number out of range
9Address could not be found, search timed out.
10City has no streets (Unable to load street list)
11Error initializing service
12Internal error.
13Server busy. Please try your request again.
14City not found
15State not found
16DPV Lockout. Contact Service Objects immediately.
17Address not found but the region has General Delivery service

 

Frequently Asked Questions

I have an Address3 field.  What should I do with it?

We currently don't support any handling of the Address3 field.  Passing it in as part of either the Address1 or Address2 fields is not recommended, as it may inhibit validation. If this information must be included, then your best option is to append all your address lines together separated by spaces, and sent through our ValidateAddressSingleLine operation along with city, state, and zip code appended.

The Sample Code is Giving Strange Errors or is Crashing!

Most likely, the sample code cannot connect to Service Objects.  Many environments will not allow you to connect out on port 80, or will clip out XML data from these requests/responses.

The easiest way to check for this is to open a browser on the machine running the sample code.  In your browser, navigate to:
https://trial.serviceobjects.com/ad

Then try to run one of the operations with your trial key. If you get a browser error, or get no data back, then the sample code isn't able to connect either.  Contact your systems administrator to resolve why you are not able to connect to Service Objects.

Address Detective says it can't find my street!

DOTS Address Detective doesn't know about every address, especially empty lots or new streets. Often, it won't be able to validate these locations.  We are as good as the USPS at identifying addresses, and although AD uses additional non-USPS sources of address data, not every data set is complete. If the USPS has an address we don't, we will have it within 30 days after our monthly update is run.

Does Address Detective do delivery point validation?  I need to know if the USPS can deliver to this address.

Yes. Look at the "DPV" code returned in the "BestAddress" object. This is a 1-4 code describing the level of deliverability of this address. (See above for DPV codes and their meaning).

Is Address Detective CASS-certified?  Can I use it to get postal discounts?

Yes and No. Address Detective uses our DOTS Address Validation 3 service whose core address validation engine is CASS certified.  It meets and exceeds all requirements for address correction except bulk mail discounts. However, AV3 does not have a mechanism to "presort" address lists and because of this we are not formally CASS certified.  You cannot use AD or AV3 for bulk-rate postal discounts.

What are the possible errors that AD will return if an address is invalid?

Please refer to "Error Codes", above.

What does "Multiple Addresses Match" mean?  How do I get a single result?

"Multiple Addresses Match" means that AV found the address, but couldn't resolve it from other addresses that were very similar, typically because of directional elements.

For example, if you validate "123 Main street, Anytown, CA", but in Anytown, CA, there is both a "West Main street" and an "East Main street", then this will result in a "Multiple Addresses Match".  You will need to specify either West Main or East Main as the street name to get a corrected, single address.

There are other cases in which "multiple addresses match" will occur, but are rare and often have to do with a difference in zip+4, or suite numbers.

We do not currently have the GetPossibleMatches operation from Address Validation 2, but we will in the future. 

I need to know exactly how long each of the output fields could be.  What is your standard field length?

Please email us at support@serviceobjects.com, and we'll send you the exact field length specifications.  As a general rule, you won't get a field longer than 80 characters.

Does AD validate suite or apartment numbers?

Yes. Just take a look at the DPV output code to determine if the given suite number is incorrect, or if you're missing a suite number entirely. 

Does AD validate PO Boxes/box numbers?

Yes.  PO boxes are correctable and are indeed validated.  Out of range PO Box numbers will yield the appropriate error

Where do you get your address information?

We get our data primarily from the USPS, but Address Detective leverages various other proprietary sources to try and obtain an address through other clues.

How often do you update your address data?

We'll update our information monthly, but in some special situations, we may update it more frequently.

I am not a programmer.  How do I use DOTS Address Detective?

Service Objects runs batches for you!  A free batch trial is available at https://www.serviceobjects.com/batch/upload.

Conclusion

Service Objects is proud to offer you a free trial of DOTS Address Detective

Sign up today for a free trial at:
https://www.serviceobjects.com/products/address/address-detective

Other technical questions or concerns can be directed to support@serviceobjects.com.

If you are interested in purchasing any other DOTS Address Validation products, please contact sales@serviceobjects.com 

 

 
We want to hear from you! We're always looking to improve our developer guides.
Please email your suggestions to 
devguidefeedback@serviceobjects.com. 

  • No labels