
UPS Shipping API Integration: Developer Guide
A comprehensive developer guide to integrating with the UPS Shipping API — authentication, rate shopping, label generation, tracking, address validation, and production deployment best practices.

UPS Shipping API Integration: Developer Guide
Integrating with the UPS API allows your application to programmatically create shipments, generate labels, track packages, validate addresses, and access the full range of UPS services. This developer guide walks through every aspect of the UPS API integration process, from authentication to production deployment, with practical code examples and best practices.
UPS API Overview
UPS offers a comprehensive suite of RESTful APIs through the UPS Developer Kit. In 2024, UPS completed a major migration from their legacy XML-based APIs to modern OAuth 2.0 REST APIs. All new integrations should use the REST APIs.
Available APIs
| API | Purpose | Key Endpoints |
|---|---|---|
| Rating API | Get shipping rates and transit times | /api/rating/v2403/rate |
| Shipping API | Create shipments and generate labels | /api/shipments/v2409/ship |
| Tracking API | Track packages and get delivery status | /api/track/v1/details |
| Address Validation API | Validate and correct addresses | /api/addressvalidation/v2/validate |
| Time in Transit API | Get estimated delivery dates | /api/deliverytimeintransit/v1/estimateddelivery |
| Locator API | Find UPS locations and Access Points | /api/locations/v2/search/availabilities |
| Pickup API | Schedule package pickups | /api/pickupcreation/v1/pickup |
| Void API | Cancel shipments and void labels | /api/shipments/v2409/void/cancel |
API Environments
| Environment | Base URL | Purpose |
|---|---|---|
| Sandbox (CIE) | https://wwwcie.ups.com | Testing and development |
| Production | https://onlinetools.ups.com | Live production traffic |
Authentication: OAuth 2.0
All UPS REST APIs use OAuth 2.0 client credentials flow for authentication.
Step 1: Create a UPS Developer Account
Step 2: Obtain an Access Token
Request an access token from the OAuth endpoint:
POST https://onlinetools.ups.com/security/v1/oauth/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic {base64(clientId:clientSecret)}grant_type=client_credentials
Response:
{
"token_type": "Bearer",
"issued_at": "1706803200000",
"client_id": "your_client_id",
"access_token": "eyJhbGciOi...",
"expires_in": "14399",
"status": "approved"
}
Step 3: Use the Token in API Calls
Include the access token in the Authorization header of all subsequent API calls:
Authorization: Bearer eyJhbGciOi...
Token Management Best Practices
| Practice | Implementation |
|---|---|
| Cache tokens | Store token and expiry; reuse until 5 minutes before expiration |
| Handle expiry | Implement automatic token refresh logic |
| Secure storage | Never log or expose tokens; use environment variables |
| Rate limiting | UPS allows ~250 token requests per day; caching is essential |
Rating API: Getting Shipping Rates
The Rating API is typically the first API you integrate because it allows you to display shipping costs to customers.
Basic Rate Request
POST /api/rating/v2403/rate
Authorization: Bearer {token}
Content-Type: application/json
transId: {unique-transaction-id}{
"RateRequest": {
"Request": {
"SubVersion": "2403",
"TransactionReference": {
"CustomerContext": "order-12345"
}
},
"Shipment": {
"Shipper": {
"Name": "Your Business Name",
"ShipperNumber": "YOUR_ACCOUNT",
"Address": {
"AddressLine": ["123 Main St"],
"City": "New York",
"StateProvinceCode": "NY",
"PostalCode": "10001",
"CountryCode": "US"
}
},
"ShipTo": {
"Name": "Customer Name",
"Address": {
"AddressLine": ["456 Oak Ave"],
"City": "Los Angeles",
"StateProvinceCode": "CA",
"PostalCode": "90001",
"CountryCode": "US"
}
},
"ShipFrom": {
"Name": "Your Warehouse",
"Address": {
"AddressLine": ["123 Main St"],
"City": "New York",
"StateProvinceCode": "NY",
"PostalCode": "10001",
"CountryCode": "US"
}
},
"Package": [
{
"PackagingType": {
"Code": "02",
"Description": "Customer Supplied Package"
},
"Dimensions": {
"UnitOfMeasurement": { "Code": "IN" },
"Length": "12",
"Width": "10",
"Height": "8"
},
"PackageWeight": {
"UnitOfMeasurement": { "Code": "LBS" },
"Weight": "5"
}
}
]
}
}
}
Rate Response Key Fields
| Field | Location in Response | Description |
|---|---|---|
| Service code | RatedShipment.Service.Code | UPS service identifier |
| Total charges | RatedShipment.TotalCharges.MonetaryValue | Total shipping cost |
| Billable weight | RatedShipment.BillingWeight.Weight | Actual or DIM weight used for pricing |
| Transit days | RatedShipment.GuaranteedDelivery.BusinessDaysInTransit | Expected delivery days |
| Surcharges | RatedShipment.ItemizedCharges[] | Fuel, residential, etc. |
UPS Service Codes Reference
| Code | Service Name | Typical Transit |
|---|---|---|
| 01 | UPS Next Day Air | 1 business day |
| 02 | UPS 2nd Day Air | 2 business days |
| 03 | UPS Ground | 1–5 business days |
| 12 | UPS 3 Day Select | 3 business days |
| 13 | UPS Next Day Air Saver | 1 business day (end of day) |
| 14 | UPS Next Day Air Early AM | 1 business day (8:00/8:30 AM) |
| 59 | UPS 2nd Day Air AM | 2 business days (AM delivery) |
Shop Rates (Compare All Services)
To get rates for all available services in one call, use the "Shop" request option:
{
"RateRequest": {
"Request": {
"RequestOption": "Shop"
},
"Shipment": { ... }
}
}
This returns an array of RatedShipment objects, one for each available service, sorted by cost.
Shipping API: Creating Labels
Once a customer selects a service and confirms their order, use the Shipping API to create the shipment and generate a label.
Create Shipment Request
POST /api/shipments/v2409/ship
Authorization: Bearer {token}
Content-Type: application/json{
"ShipmentRequest": {
"Request": {
"SubVersion": "2409",
"TransactionReference": {
"CustomerContext": "order-12345"
}
},
"Shipment": {
"Shipper": {
"Name": "Your Business",
"AttentionName": "Shipping Dept",
"ShipperNumber": "YOUR_ACCOUNT",
"Phone": { "Number": "2125551234" },
"Address": {
"AddressLine": ["123 Main St"],
"City": "New York",
"StateProvinceCode": "NY",
"PostalCode": "10001",
"CountryCode": "US"
}
},
"ShipTo": {
"Name": "John Customer",
"Phone": { "Number": "3105559876" },
"Address": {
"AddressLine": ["456 Oak Ave"],
"City": "Los Angeles",
"StateProvinceCode": "CA",
"PostalCode": "90001",
"CountryCode": "US"
}
},
"PaymentInformation": {
"ShipmentCharge": [{
"Type": "01",
"BillShipper": {
"AccountNumber": "YOUR_ACCOUNT"
}
}]
},
"Service": {
"Code": "03",
"Description": "UPS Ground"
},
"Package": [{
"Packaging": {
"Code": "02"
},
"Dimensions": {
"UnitOfMeasurement": { "Code": "IN" },
"Length": "12",
"Width": "10",
"Height": "8"
},
"PackageWeight": {
"UnitOfMeasurement": { "Code": "LBS" },
"Weight": "5"
}
}]
},
"LabelSpecification": {
"LabelImageFormat": {
"Code": "ZPL"
},
"LabelStockSize": {
"Height": "6",
"Width": "4"
}
}
}
}
Label Format Options
| Format Code | Format | Use Case |
|---|---|---|
| GIF | GIF image | Web display, email labels |
| PNG | PNG image | High-quality printing |
| ZPL | Zebra Printer Language | Thermal label printers |
| EPL | Eltron Printer Language | Older thermal printers |
| PDF document | Standard laser/inkjet printing |
Response: Tracking Number and Label
The response contains:
| Field | Description |
|---|---|
| ShipmentIdentificationNumber | Master tracking number for the shipment |
| PackageResults[].TrackingNumber | Individual package tracking numbers |
| PackageResults[].ShippingLabel.GraphicImage | Base64-encoded label image |
| ShipmentCharges.TotalCharges | Actual shipping cost charged |
Tracking API: Package Status
Single Package Tracking
GET /api/track/v1/details/{trackingNumber}
Authorization: Bearer {token}
transId: {unique-id}
transactionSrc: your-app-name
Tracking Response Key Fields
| Field | Description |
|---|---|
| currentStatus.type | Current status (In Transit, Delivered, etc.) |
| currentStatus.code | Status code (021 = In Transit, 011 = Delivered) |
| deliveryDate[].date | Actual or estimated delivery date |
| activity[] | Array of scan events with timestamps and locations |
| weight | Package weight as recorded by UPS |
Common Status Codes
| Code | Type | Description |
|---|---|---|
| 003 | Order Processed | Label created, not yet in UPS system |
| 005 | Shipped | Package picked up and in transit |
| 021 | In Transit | Package moving through UPS network |
| 011 | Delivered | Package delivered |
| 007 | Exception | Delivery exception (weather, address issue, etc.) |
Address Validation API
Validating addresses before creating shipments prevents failed deliveries and costly address corrections.
Validation Request
POST /api/addressvalidation/v2/validate
Authorization: Bearer {token}
Content-Type: application/json{
"XAVRequest": {
"AddressKeyFormat": {
"AddressLine": ["456 Oak Avenue"],
"PoliticalDivision2": "Los Angeles",
"PoliticalDivision1": "CA",
"PostcodePrimaryLow": "90001",
"CountryCode": "US"
}
}
}
Response Classification
| Indicator | Meaning | Action |
|---|---|---|
| Valid | Address is valid and deliverable | Proceed with shipment |
| Ambiguous | Multiple matching addresses found | Present candidates to user |
| Invalid | Address not found or not deliverable | Request correction from customer |
Residential Indicator
The Address Validation API also returns whether the address is residential or commercial:
| Value | Type | Impact |
|---|---|---|
| 1 | Residential | Residential surcharge applies |
| 2 | Commercial | No residential surcharge |
Error Handling
UPS APIs return structured error responses that you should handle gracefully:
Common Error Codes
| Error Code | Description | Resolution |
|---|---|---|
| 111100 | Invalid access token | Refresh your OAuth token |
| 111210 | Rate limit exceeded | Implement exponential backoff |
| 120100 | Invalid address | Validate address before shipping |
| 120500 | Service not available | Check service availability for route |
| 150000 | Package exceeds limits | Check weight and dimension limits |
| 250000 | Shipper account invalid | Verify account number and credentials |
Error Handling Best Practices
| Practice | Implementation |
|---|---|
| Retry logic | Retry transient errors (5xx, timeouts) with exponential backoff |
| Circuit breaker | Stop calling API after repeated failures; fall back to cached rates |
| Logging | Log all API requests and responses for debugging |
| Monitoring | Alert on error rate increases |
| Graceful degradation | Show cached rates or estimated delivery times when API is unavailable |
Rate Limiting and Performance
UPS API Rate Limits
| Endpoint | Limit | Period |
|---|---|---|
| OAuth token | ~250 requests | Per day |
| Rating API | 1,000 requests | Per minute |
| Shipping API | 500 requests | Per minute |
| Tracking API | 500 requests | Per minute |
| Address Validation | 1,000 requests | Per minute |
Performance Optimization
| Strategy | Implementation | Impact |
|---|---|---|
| Token caching | Cache OAuth token; refresh 5 min before expiry | Eliminates 99%+ of token calls |
| Rate caching | Cache rate responses for same origin/dest/weight for 15–60 min | Reduces rating calls by 70%+ |
| Batch tracking | Track up to 35 packages in a single request | Reduces tracking calls by 97% |
| Connection pooling | Reuse HTTP connections | 30–50% latency reduction |
| Async processing | Queue label creation for non-real-time orders | Smooths API call volume |
Webhook Integration for Real-Time Tracking
Instead of polling the Tracking API, UPS offers webhook notifications (Quantum View) that push tracking events to your server:
Setting Up Webhooks
Webhook Event Types
| Event | Description |
|---|---|
| Manifest | Package label created |
| Origin Scan | Package picked up by UPS |
| In Transit | Package scanned at hub |
| Out for Delivery | Package on delivery vehicle |
| Delivered | Package delivered |
| Exception | Delivery exception occurred |
Webhook Receiver Implementation
Your webhook endpoint should:
Testing in Sandbox
Sandbox Test Credentials
UPS provides a sandbox (Customer Integration Environment, CIE) for testing:
| Setting | Value |
|---|---|
| Base URL | https://wwwcie.ups.com |
| Test account numbers | Provided in developer portal |
| Test addresses | Any valid US address |
Testing Checklist
| Test Case | What to Verify |
|---|---|
| Rate request | Rates returned for all service levels |
| Multi-package rate | Correct pricing for multi-piece shipments |
| Label creation | Label image generated and valid |
| Label void | Successful cancellation of created label |
| Address validation | Valid, ambiguous, and invalid addresses handled |
| Tracking | Status returned for test tracking numbers |
| Error handling | Application handles API errors gracefully |
| Token refresh | Token auto-refreshes before expiry |
| Rate limits | Application behaves correctly when throttled |
Test Tracking Numbers
UPS provides test tracking numbers in the sandbox:
| Tracking Number | Status |
|---|---|
| 1Z12345E0291980793 | Delivered |
| 1Z12345E0205271688 | In Transit |
| 1Z12345E6605272234 | Exception |
Production Deployment Checklist
Before going live with your UPS API integration:
| Item | Status |
|---|---|
| OAuth token caching implemented | Required |
| Error handling and retry logic | Required |
| Rate limiting and throttling | Required |
| Logging and monitoring | Required |
| Address validation before shipping | Recommended |
| Label storage and retrieval | Required |
| Webhook receiver (Quantum View) | Recommended |
| DIM weight calculation verified | Required |
| Surcharge handling (residential, fuel, etc.) | Required |
| Multi-package shipment support | If applicable |
| International shipment support (customs docs) | If applicable |
| Return label generation | If applicable |
| Void/cancel shipment flow | Required |
| Production credentials rotated from sandbox | Required |
Conclusion
Integrating with the UPS API opens up powerful shipping capabilities for your application. The modern OAuth 2.0 REST APIs are well-documented, reliable, and performant. Start with the Rating and Address Validation APIs for customer-facing features, add the Shipping API for label generation, and implement webhook-based tracking for real-time visibility. Follow the best practices outlined in this guide — especially around token management, error handling, rate caching, and thorough testing — to build a robust, production-ready integration that scales with your business.
Ready to save on shipping?
Get started with Atoship for free and access discounted USPS, UPS, and FedEx rates. No monthly fees, no contracts.
Create Free Account



