How to track UPS deliveries through API

Ats
2 min readMay 18, 2024

--

This is my note about how to implement the UPS tracking with the API.

Photo by Marques Thomas on Unsplash

Background

Last week, I needed to implement the tracking feature through the UPS API. I thought it should have been straightforward because the official documents looked organized.

https://developer.ups.com/api/reference

But it took more time than I thought. I felt there wasn’t enough information or blogs about it on the Internet. Then I decided to document what I did.

What I did

From the bottom line, use the right endpoint. One is for the test and the other one is for production. I didn’t notice there were two different URLs and spent a lot of hours on figuring out the reason why I couldn’t get the real data even if I sent a request with a real tracking number

# Test
url = "https://wwwcie.ups.com/security/v1/oauth/token"

# Production
url = "https://onlinetools.ups.com/security/v1/oauth/token"

After I set the right endpoint, I created the access token using the following endpoint.

https://developer.ups.com/api/reference#tag/OAuthClientCredentials_other

import requests

# url = "https://wwwcie.ups.com/security/v1/oauth/token"
url = "https://onlinetools.ups.com/security/v1/oauth/token"

username = 'your_client_id'
passowrd = 'your_secret'

payload = {
"grant_type": "client_credentials"
}

headers = {
"Content-Type": "application/x-www-form-urlencoded",
"x-merchant-id": "string"
}

response = requests.post(url, data=payload, headers=headers, auth=(username, password))

data = response.json()
access_token = data['access_token']

Please note 2 things here. Firstly, in the document, there are username and password which we need to send in basic authentication. those mean your client id and secret which were generated when you created the App on the UPS admin page. Secondly, ”grant_type”: “client_credentials” and ”Content-Type”: “application/x-www-form-urlencoded” are fixed contents. I have no idea about whether we have another option or not.

Then I sent a request to the following endpoint to track my deliveries

https://developer.ups.com/api/reference#tag/Tracking_other

import time 
import pprint
epoch_time = int(time.time())

tracking_nums ["your_tacking_number"]

for inquiry_number in tracking_nums:
url = "https://onlinetools.ups.com/api/track/v1/details/" + inquiry_number
epoch_time = int(time.time())

headers = {
"transId": str(epoch_time),
"transactionSrc": "testing",
"Authorization": f"Bearer {access_token}"
}

response = requests.get(url, headers=headers)

data = response.json()
assert inquiry_number == data['trackResponse']['shipment'][0]['package'][0]['trackingNumber']

print(inquiry_number, data['trackResponse']['shipment'][0]['package'][0]['currentStatus'])

If you use the wrong URL, you’ll see an AssertionError from the bottom line of the code snippet. I was stuck in here for a few days. If you’re seeing the address Shenzhen, China, or Changi, Singapore as the response, you would be sending the request to the test URL.

I would say the UPS documents are not kind or easy to read. Because of that, I spent much more time on it than I planned. I hope my experience would help people trying to implement the same feature.

That’s it!

--

--

Ats
Ats

Written by Ats

I like building something tangible like touch, gesture, and voice. Ruby on Rails / React Native / Yocto / Raspberry Pi / Interaction Design / CIID IDP alumni

Responses (2)