Invoke UPS Address Validation API using C# and Visual Studio 2015


This post covers the steps needed to use the Street Address Validation Application Programming Interface (API) of United Parcel Service (UPS). We will cover the steps of registering with UPS first to get credentials/license key from UPS and then use the street address validation API in a C# console application. We will use Visual Studio 2015 as Integrated Development Environment (IDE) and build a Windows Communication Foundation (WCF) client to invoke the UPS API.


  1. You are familiar with a .net programming language (preferably C#) and Visual Studio .Net.
  2. You understand the basics of Windows Communication Foundation and how to consume a web service with the help of a WSDL file.

If you perform an internet search on the keywords ‘UPS Developer API’, you will get the link to the web page that covers all the documentation you need. The link is:

In order to access UPS API, you need a userid/password credential and an access key.

Step 1: Get Security Credentials

Get a userid and password by registering with My UPS if you don’t have one already. This is step 1 on UPS web page.


Step 2: Get Access Key

Login to the same page mentioned above by using the credentials obtained in step 1 and request access key (Step 5 on the page). The access key will be displayed on your browser window. You will also get an email with the same access key information.


Now we are ready to write code.

Step 3: Build Code

Step 3a: Download API Files

UPS exposes different APIs for different types of functionality. In this tutorial, we will use their ‘Address Validation – Street Level’ API. Please go ahead and download the API documentation.



The API will be downloaded as a zip file. Extract the zip file to a folder of your choice. Navigate to the folder that contains the WSDLs of the Address Validation Service. If you extracted the zip file to a folder called ‘C:\UPS’, you will have to navigate to ‘C:\UPS\Street Level Address Validation for SHIPPING\XAVWebServices\SCHEMAS-WSDLs’


Please note that the WSDL file and all its dependencies (XML schemas) exist in the same folder.

Step 3b: Create Console Project


Step 3c: Add Service Reference

Right click on the console project and add service reference to the UPS service.


Now provide the full path of the WSDL file. Rename the proxy namespace to XAVServiceProxy.


Also, please note how Visual Studio adds WCF client configuration to your app.config file. You don’t need to change this please note the address of the service and the types of binding and contract. The service endpoint URL is the URL of UPS test environment.


Step3d: Add code

Add the following code to the Program.cs project startup class. I have tried to document the code as much as possible so it becomes self-explanatory.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using UPSStreetAddressValidationConsoleApplication.XAVServiceProxy;
namespace UPSStreetAddressValidationConsoleApplication
class Program
static void Main(string[] args)
//this is the remote proxy object
XAVPortTypeClient Proxy = new XAVPortTypeClient();
//build the username token object
UPSSecurityUsernameToken UPSSecurityUsernameTokenObj = new UPSSecurityUsernameToken();
//use your userid when youn registered with my UPS
UPSSecurityUsernameTokenObj.Username = "your user id";
//use the password associated with your userid
UPSSecurityUsernameTokenObj.Password = "your password";
//build the security access token object
UPSSecurityServiceAccessToken UPSSecurityServiceAccessTokenObj = 
new UPSSecurityServiceAccessToken();
//your access key provided by UPS
UPSSecurityServiceAccessTokenObj.AccessLicenseNumber = "your access key";
//set the username and service access objects on the UPSSecurity input parm object
//this is the first parameter of the ProcessXAV method on UPS service
UPSSecurity UPSSecurityObj = new UPSSecurity();
UPSSecurityObj.UsernameToken = UPSSecurityUsernameTokenObj;
UPSSecurityObj.ServiceAccessToken = UPSSecurityServiceAccessTokenObj;
//build the transaction reference type
TransactionReferenceType TransactionReferenceTypeObj = new TransactionReferenceType();
//pass any value
TransactionReferenceTypeObj.CustomerContext = "Customer Data"; 
//pass any value
TransactionReferenceTypeObj.TransactionIdentifier = "12335"; 
//build the request type
RequestType RequestTypeObj = new RequestType();
//this value has to be 1
RequestTypeObj.RequestOption = new String[1] { "1"}; 
RequestTypeObj.TransactionReference = TransactionReferenceTypeObj;
//this is the class where we will pass the address data elements
//passing address of new York stock exchange for testing purpose
AddressKeyFormatType AddressKeyFormatTypeObj = new AddressKeyFormatType();
AddressKeyFormatTypeObj.AddressLine = new String[1] { "11 Wall Street" };
//political division 1 is required for get valid address validation code 
//otherwise you get an exception
AddressKeyFormatTypeObj.PoliticalDivision1 = "NY"; //state code
AddressKeyFormatTypeObj.PoliticalDivision2 = "New York"; //city
AddressKeyFormatTypeObj.CountryCode = "US"; //country must be US or PR
AddressKeyFormatTypeObj.PostcodePrimaryLow = ""; //passing a blank value
//now let’s build the second parameter
XAVRequest XAVRequestObj = new XAVRequest();
XAVRequestObj.AddressKeyFormat = AddressKeyFormatTypeObj;
XAVRequestObj.Request = RequestTypeObj;
//added to handle the intermittent error with SSL/TLS connection
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | 
SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | 
//open channel
//call the service
XAVResponse Response = Proxy.ProcessXAV(UPSSecurityObj, XAVRequestObj);
//parse the result
ItemChoiceType Result = Response.ItemElementName;
//found multiple matches
if (Result == ItemChoiceType.AmbiguousAddressIndicator) 
Console.WriteLine(String.Format("Ambiguous Address.Found {0} matching candidate addresses",
//print each candidate address that was returned as response
foreach (CandidateType candidateAddress in Response.Candidate)
Console.WriteLine(String.Format("Consignee Name: {0}", 
Console.WriteLine(String.Format("Street Line 1: {0}", 
if (candidateAddress.AddressKeyFormat.AddressLine.Length > 1)
Console.WriteLine(String.Format("Street Line 2: {0}", 
Console.WriteLine(String.Format("City: {0}", 
Console.WriteLine(String.Format("State: {0}", 
Console.WriteLine(String.Format("Zip: {0}-{1}",
//invalid address no match found
else if (Result == ItemChoiceType.NoCandidatesIndicator) 
Console.WriteLine("Invalid Address");
//valid address exactly one candidate returned
else if (Result == ItemChoiceType.ValidAddressIndicator) 
Console.WriteLine("Valid Address");
Console.WriteLine(String.Format("Consignee Name: {0}", 
Console.WriteLine(String.Format("Street Line 1: {0}", 
if (Response.Candidate[0].AddressKeyFormat.AddressLine.Length > 1)
Console.WriteLine(String.Format("Street Line 2: {0}", 
Console.WriteLine(String.Format("City: {0}", 
Console.WriteLine(String.Format("State: {0}", 
Console.WriteLine(String.Format("Zip: {0}-{1}",
//close communication channel
catch (Exception ex)
//please add code to handle SOAP exceptions
//do not close the console window unless the user presses a key


Step 4: Test the code

Run the project and test with different values of address input. I have used the address of the New York Stock Exchange as a test address in my code example.

Please note:

  1. As per their website, the UPS Test URL works only for California and New York State addresses.
  2. Make sure you pass ‘US’ or ‘PR’ as country code. If you do not pass one of two values, you will get a SOAP Exception. The current UPS API supports US and Puerto Rico country codes.
  3. Make sure you pass value of “1” as RequestOption. Please see code comments for more details.
  4. Pass the two character state code in Political Division 1. If you don’t, you will get an exception.
  5. Pass the city name in the PoliticalDivision2 field.
  6. I found UPS documentation to be dated and out of synch with their current code. But it is still a good idea to read their documentation to get some general ideas about their service.
  7. The code in this post works at the time of writing this post (December 1, 2016).
  8. No warranty is provided with the code or any documentation in this article.

This code could be refactored into multiple helper methods but I wanted to provide one block of code with no dependencies to keep things simple for this post.

I will continue to test their APIs and try RESTful invocation if their API supports it. If you have any questions, feel free to post those in the comments area. Your feedback, as always, is appreciated.

Leave a Reply

Your email address will not be published. Required fields are marked *