Home / Blogs

How to Use the UPS Express API in Django DRF in 2024

Django
·

December 26, 2023

how-to-use-the-ups-express-api-in-django-drf

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

  1. Shipper number
  2. APP_ID
  3. APP_SECRET           
  4. 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?

  1. Addresss_validation: First validate the address to which you are planning to ship the product.
  2. Ratings: Find out what are services available for shipping the product and what the price for the services is.
  3. Shipment:  Creating a shipment with the product as the metric’s
  4. 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.

Horilla Editorial Team Author

Horilla Editorial Team is a group of experienced writers and editors who are passionate about HR software. We have a deep understanding of the HR landscape and are committed to providing our readers with the most up-to-date and informative content. We have written extensively on a variety of HR software topics, including applicant tracking systems, performance management software, and payroll software etc. We are always looking for new ways to share our knowledge with the HR community. If you have a question about HR software, please don't hesitate to contact us.