UPS Tracking Service API


This post covers the steps needed to use the Tracking Service 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 ‘Tracking’ 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\Tracking’, you will have to do the following:

Navigate to:


Copy all the schema files (.xsd) files from this folder to:


The ‘SCHEMAS-WSDLs’ folder will look like this:

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

Step 3b: Create Console Project with the name ‘UPSTrackingConsoleApplication’

Step 3c: Add Service Reference

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

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

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.Text;
using System.Threading.Tasks;
using UPSTrackingConsoleApplication.UPSTrackingProxy;</code>
namespace UPSTracking
class Program
static void Main(string[] args)
//create the client proxy
TrackPortTypeClient track = new TrackPortTypeClient();
//create username token
UPSSecurityUsernameToken upssUsrNameToken = new UPSSecurityUsernameToken();
//this is your my UPS userid
upssUsrNameToken.Username = "your userid";
//this is your my UPS password
upssUsrNameToken.Password = "your password";
UPSSecurityServiceAccessToken upssSvcAccessToken = 
new UPSSecurityServiceAccessToken();
//this is your my UPS access key
upssSvcAccessToken.AccessLicenseNumber = "your access token";
//create UPS security object
UPSSecurity upss = new UPSSecurity();
//set the user name token
upss.UsernameToken = upssUsrNameToken;
//set the service access token
upss.ServiceAccessToken = upssSvcAccessToken;
//create the request object
RequestType request = new RequestType();
//must be hard coded to 15
String[] requestOption = { "15" };
//set the request option
request.RequestOption = requestOption;
TrackRequest tr = new TrackRequest();
tr.Request = request;
//this is your UPS tracking id like 1Z123455....
tr.InquiryNumber = "1Zxxxxxxxxxx";
//added to handle the intermittent error with SSL/TLS connection
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | 
SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | 
//open channel
//invoke the service
TrackResponse trackResponse = track.ProcessTrack(upss, tr);
//close channel
Console.WriteLine("The transaction was a " + 
Console.WriteLine("Shipment Service " + 
//print tracking process result
foreach (ShipmentType shipment in trackResponse.Shipment)
foreach (PackageType package in shipment.Package)
foreach (ActivityType Act in package.Activity)
Console.WriteLine("City {0} {1}, Date {2}, Time {3}, Status {4}", 
Act.ActivityLocation.Address.StateProvinceCode, Act.Date, Act.Time, 
catch (Exception ex)
Console.WriteLine(String.Format("Error in processing tracking request: {0}", 

Step 4: Test the code

Run the project and test with different values of address input. The output of the program will look similar to this.

The transaction was a Success
Shipment Service UPS GROUND
City XYZ CA, Date 20161129, Time 115600, Status Delivered
City XYZ CA, Date 20161129, Time 044000, Status Out For Delivery
City XYZ CA, Date 20161129, Time 042400, Status Out For Delivery
City XYZ CA, Date 20161129, Time 032500, Status Arrival Scan
City MNP CA, Date 20161129, Time 014600, Status Departure Scan
City MNP CA, Date 20161128, Time 082400, Status Arrival Scan
City EFG FL, Date 20161123, Time 103800, Status Departure Scan
City EFG FL, Date 20161123, Time 020400, Status Arrival Scan
City ABC FL, Date 20161122, Time 224300, Status Departure Scan
City ABC FL, Date 20161122, Time 173900, Status Origin Scan
City , Date 20161121, Time 193111, Status Order Processed: Ready for UPS

Please note:

  1. Make sure you pass value of “15” as RequestOption. Please see code comments for more details.
  2. 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.
  3. The code in this post works at the time of writing this post (December 1, 2016).
  4. 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.