How to Use the UPS Express API in Django DRF in 2024
What is the UPS Express API?
The UPS Express API is like a set of digital tools provided by UPS (United Parcel Service) that allows computer programs (like the ones running websites or apps) to talk to UPS’s systems. It’s a way for businesses and developers to integrate UPS services directly into their websites or applications.
What Does the UPS Express API Do?
Imagine you have an online store, and you want to offer your customers real-time shipping rates, generate shipping labels, and track packages without leaving your website. The UPS Express API lets you do just that. It’s like having a direct line to UPS’s powerful shipping and tracking capabilities.
To read more about the key features & best practices of Django Rest Framework, refer to our blog What are the Key Features & Best Practices of Django Rest Framework
Key Features of UPS Express API:
Real-Time Shipping Rates: Your website can talk to UPS through the API to get the latest shipping rates based on factors like package weight, destination, and shipping speed.
Label Generation: You can use the API to generate shipping labels for packages. This is handy because customers can purchase and print shipping labels right from your website.
Package Tracking: Your customers can track their packages directly on your website. The API provides the latest information about where the package is and when it’s expected to be delivered.
Address Validation: The API helps ensure that the shipping address your customer provides is accurate and complete, reducing the chances of delivery issues.
How to integrate the UPS Shipping method in Django DRF
There are some requirements to work with UPS.
Requirements
- Shipper number
- APP_ID
- APP_SECRET
- AccessToken
We can find the shipper number on the UPS invoice. To get APP_ID, and APP_SECRET you can create an app in the developer account of UPS.
How to get AccessToken for UPS :
To get an api_token we Need to implement Oauth of the UPS request
import requests import base64 import time # Your UPS API credentials client_id = 'your_client_id' client_secret = 'your_client_secret' domain = 'https://wwwcie.ups.com' url = f"{domain}/security/v1/oauth/token" def get_ups_api_key(): # Generate the Authorization header headers = { "Content-Type": "application/x-www-form-urlencoded", 'Authorization': f'Basic {base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()}', } # Payload for token request payload = {"grant_type": "client_credentials"} # Make the API request response = requests.post(url, data=payload, headers=headers) if response.status_code == 200: data = response.json() expires_in = data['expires_in'] access_token= data[‘access_token’] return {'status': 'error', ‘access_token’: access_token, 'error': response.json()} # Example usage: result = get_ups_api_key() print(result)
After receiving the access_token we can store it on the database. It will expire on an hour basis you can also write the logic for it based on the interval you can request a new access_token
What is the UPS Workflow?
- Addresss_validation: First validate the address to which you are planning to ship the product.
- Ratings: Find out what are services available for shipping the product and what the price for the services is.
- Shipment: Creating a shipment with the product as the metric’s
- Pickup: Arranging pickup for the shipment we created.
Address Validation
First, verify the address you want to ship to and find out if shipping to that specific address is available or not to validate the address in UPS use the following Python code.
Django URLs:
from django.urls import path
from . import views
urlpatterns = [
path('ups-address-validator',views.UpsAddressValidatorView.as_view()),
]
Django Views:
class UpsAddressValidatorView(APIView):
def post(self,request):
data = ups_api_key()
country_code = request.data.get('country_code','')
city_code = request.data.get('city_code','')
try:
if data['status'] == 'success':
api_key = data['api_key']
domain = data['domain']
url = f"{domain}/api/addressvalidation/v1/1"
data = {
"XAVRequest": {
"AddressKeyFormat": {
"PoliticalDivision1": city_code,
"CountryCode": country_code
}
}
}
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}"
}
response = requests.post(url=url, headers=headers, json=data)
return Response(response.json())
except Exception as E:
return Response(str(E))
Ratings:
By using rating API we can fetch what shipping services are available and also their service rates. We can use the service code received in the response in shipment to choose a service we like to ship our product.
Django URL:
from django.urls import path
from . import views
urlpatterns = [
path('ups-rates',views.UpsRates.as_view()),
]
Django views.py
class UpsRates(APIView):
def post(self, request):
url = "https://wwwcie.ups.com/api/rating/v1/shop"
payload = request.data.get(‘payload’,None)
headers = {
"Content-Type": "application/json",
"transId": "string",
"transactionSrc": "testing",
"Authorization": "Bearer <YOUR_TOKEN_HERE>"
}
response = requests.post(url, json=payload, headers=headers)
data = response.json()
return Response(data)
The requested JSON samples are given below you can add your details based on your needs:
{"payload":{
"RateRequest": {
"Request": {
"TransactionReference": {
"CustomerContext": "CustomerContext"
}
},
"Shipment": {
"Shipper": {
"Name": "ShipperName",
"ShipperNumber": "ShipperNumber",
"Address": {
"AddressLine": [
"ShipperAddressLine",
"ShipperAddressLine",
"ShipperAddressLine"
],
"City": "TIMONIUM",
"StateProvinceCode": "MD",
"PostalCode": "21093",
"CountryCode": "US"
}
},
"ShipTo": {
"Name": "ShipToName",
"Address": {
"AddressLine": [
"ShipToAddressLine",
"ShipToAddressLine",
"ShipToAddressLine"
],
"City": "Alpharetta",
"StateProvinceCode": "GA",
"PostalCode": "30005",
"CountryCode": "US"
}
},
"ShipFrom": {
"Name": "ShipFromName",
"Address": {
"AddressLine": [
"ShipFromAddressLine",
"ShipFromAddressLine",
"ShipFromAddressLine"
],
"City": "TIMONIUM",
"StateProvinceCode": "MD",
"PostalCode": "21093",
"CountryCode": "US"
}
},
"PaymentDetails": {
"ShipmentCharge": {
"Type": "01",
"BillShipper": {
"AccountNumber": "ShipperNumber"
}
}
},
"Service": {
"Code": "03",
"Description": "Ground"
},
"NumOfPieces": "1",
"Package": {
"SimpleRate": {
"Description": "SimpleRateDescription",
"Code": "XS"
},
"PackagingType": {
"Code": "02",
"Description": "Packaging"
},
"Dimensions": {
"UnitOfMeasurement": {
"Code": "IN",
"Description": "Inches"
},
"Length": "5",
"Width": "5",
"Height": "5"
},
"PackageWeight": {
"UnitOfMeasurement": {
"Code": "LBS",
"Description": "Pounds"
},
"Weight": "1"
}
}
}
}
}
}
Shipment Creation
You can create shipment and pickup on the same view and choose the service for the shipment from the data given in the rates API response to create shipment and pickup for the shipment using the following code.
Django URL:
from django.urls import path, include
from . import views
urlpatterns = [
path('ups-shipment',views.UpsShippingCreateView.as_view()),
]
Django views
class UpsShippingCreateView(APIView):
def post(self, request):
payload_ship = request.data.get('payload_shipping')
payload_pickup = request.data.get('payload_pickup')
api_key = "API_KEY"
domain = "https://wwwcie.ups.com"
url = f"{domain}/api/shipments/v1/ship"
ship_headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}",
}
response_ship = requests.post(
url=url, json=payload_ship, headers=ship_headers)
ship = response_ship.json()
data = []
data.append(ship)
if response_ship.status_code == 200:
pickup_headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}",
}
url = f"{domain}/api/pickupcreation/v1/pickup"
response_pickup = requests.post(
url, json=payload_pickup, headers=pickup_headers)
pickup = response_pickup.json()
data.append(pickup)
return Response(data)
In the response of shipment you will receive a label in binary code you can convert it to an image print out the image and attach it to your package. Based on the pickup date you choose, the UPS services will pick up the package at the given address.
You can use the following JSON to request a shipment for testing purposes update the shipper number to your number to use this
{
"payload_shipping": {
"ShipmentRequest": {
"Request": {
"SubVersion": "1801",
"RequestOption": "nonvalidate",
"TransactionReference": {
"CustomerContext": ""
}
},
"Shipment": {
"Description": "Ship WS test",
"Shipper": {
"Name": "Demo Shipper",
"ShipperNumber": "YOUR_SHIPPER_NUMBER",
"AttentionName": "RECV NAME",
"Phone": {
"Number": "+40727000009"
},
"Address": {
"AddressLine": [
"Sos odai 93 101 sector 1"
],
"City": "Bucharest",
"StateProvinceCode": "B",
"PostalCode": "013601",
"CountryCode": "RO"
}
},
"ShipTo": {
"Name": "Demo Receiver",
"AttentionName": "RECV NAME",
"Phone": {
"Number": "+40 727000009"
},
"Address": {
"AddressLine": [
"228 Rue de Rivoli"
],
"City": "Paris",
"StateProvinceCode": "",
"PostalCode": "75001",
"CountryCode": "FR"
}
},
"ShipFrom": {
"Name": "Demo ShipFrom",
"Address": {
"AddressLine": [
"Sos odai 93 101 sector 1"
],
"City": "BUCHAREST",
"StateProvinceCode": "B",
"PostalCode": "013601",
"CountryCode": "RO"
}
},
"PaymentInformation": {
"ShipmentCharge": {
"Type": "01",
"BillShipper": {
"AccountNumber": "YOUR_SHIPPER_NUMBER"
}
}
},
"Service": {
"Code": "11",
"Description": "Express"
},
"Package": {
"Description": " ",
"Packaging": {
"Code": "02",
"Description": "Nails"
},
"Dimensions": {
"UnitOfMeasurement": {
"Code": "CM",
"Description": ""
},
"Length": "10",
"Width": "30",
"Height": "45"
},
"PackageWeight": {
"UnitOfMeasurement": {
"Code": "KGS",
"Description": "Pounds"
},
"Weight": "20"
}
}
},
"LabelSpecification": {
"LabelImageFormat": {
"Code": "GIF",
"Description": "GIF"
},
"HTTPUserAgent": "Mozilla/4.5"
}
}
},
"payload_pickup": {
"PickupCreationRequest": {
"RatePickupIndicator": "Y",
"Shipper": {
"Account": {
"AccountNumber": "YOUR_SHIPPER_NUMBER",
"AccountCountryCode": "RO"
}
},
"PickupDateInfo": {
"CloseTime": "1400",
"ReadyTime": "0500",
"PickupDate": "20231201"
},
"PickupAddress": {
"CompanyName": "Pickup Proxy",
"ContactName": "Pickup Manager",
"AddressLine": "Sos odai 93 101 sector 1",
"Room": "R01", //not required
"Floor": "2", //not required
"City": "Bucharest",
"StateProvince": "B", //not required
"Urbanization": "", //not required
"PostalCode": "013601", //not required
"CountryCode": "RO",
"ResidentialIndicator": "Y",
"PickupPoint": "Lobby", //not required
"Phone": {
"Number": "5555555555",
"Extension": "911"
}
},
"AlternateAddressIndicator": "Y",
"PickupPiece": [
{
"ServiceCode": "001",
"Quantity": "27",
"DestinationCountryCode": "RO",
"ContainerCode": "01"
},
{
"ServiceCode": "012",
"Quantity": "4",
"DestinationCountryCode": "FR",
"ContainerCode": "01"
}
],
"TotalWeight": { //not required
"Weight": "5.5",
"UnitOfMeasurement": "LBS"
},
"OverweightIndicator": "N",
"PaymentMethod": "01",
"SpecialInstruction": "Test ",
"ReferenceNumber": "CreatePickupRef"
}
}
}
To read more about setting up token authentication in Django Rest Framework, refer to our blog How to Set Up Token Authentication in Django Rest Framework
Conclusion
In this blog, we have described the basic workflow for implementing UPS shipping services in Django DRF and you can also get more information in UPS documentation there. You can find tracking the shipment and individual pickup creation and a lot more features.