Skip to main content
RapidDev - Software Development Agency
v0-integrationsNext.js API Route

How to Integrate UPS API with V0

To integrate the UPS API with V0 by Vercel, create a Next.js API route that authenticates via UPS OAuth2 and calls UPS Rating, Tracking, or Address Validation APIs. V0 generates the shipping calculator or tracking UI; you store your UPS client credentials in Vercel environment variables. The result is a real-time shipping rate calculator or order tracking feature powered directly by UPS's carrier network.

What you'll learn

  • How to generate a shipping rate calculator or tracking UI with V0
  • How to implement UPS OAuth2 client credentials flow in a Next.js API route
  • How to call the UPS Rating API to get shipping rates for different service levels
  • How to call the UPS Tracking API to fetch real-time package status
  • How to store UPS client credentials securely in Vercel environment variables
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate13 min read25 minutesOtherApril 2026RapidDev Engineering Team
TL;DR

To integrate the UPS API with V0 by Vercel, create a Next.js API route that authenticates via UPS OAuth2 and calls UPS Rating, Tracking, or Address Validation APIs. V0 generates the shipping calculator or tracking UI; you store your UPS client credentials in Vercel environment variables. The result is a real-time shipping rate calculator or order tracking feature powered directly by UPS's carrier network.

Add UPS Shipping Rates and Tracking to Your V0 E-Commerce App

UPS operates the world's largest carrier network with APIs that reflect decades of shipping industry complexity. The UPS Developer API suite includes Rating (shipping cost quotes), Tracking (real-time package status), Address Validation (verify delivery addresses), Time in Transit (delivery date estimates), Shipping (label creation), and Pickup (schedule pickups). For V0 e-commerce apps, the Rating and Tracking APIs are the most commonly needed.

The Rating API returns rates for multiple UPS services in a single call — UPS Ground, UPS 3 Day Select, UPS 2nd Day Air, UPS Next Day Air, and international options. You pass the origin ZIP, destination ZIP, package dimensions and weight, and UPS returns the applicable service options with negotiated rates if you have a UPS account discount.

Tracking requires either a UPS tracking number (1Z...) or your shipment reference number. The API returns the full checkpoint history including scan timestamps, location names, and event descriptions, plus the estimated delivery date. All of this lives server-side in your Next.js API route — the browser only sees the transformed response.

Integration method

Next.js API Route

UPS APIs connect to V0-generated Next.js apps through server-side API routes that first obtain an OAuth2 bearer token from UPS, then call UPS Rating, Tracking, or Address Validation APIs. The UPS client ID and client secret live in Vercel environment variables. OAuth tokens are cached short-term to avoid re-authenticating on every request.

Prerequisites

  • A V0 account at v0.dev with a Next.js project created
  • A UPS developer account at developer.ups.com
  • A UPS app created in the UPS Developer Portal with client ID and client secret
  • For rate discounts: a UPS shipper account number linked to your developer app
  • A Vercel account connected to your V0 project for deployment

Step-by-step guide

1

Create a UPS Developer Account and Get Credentials

Go to developer.ups.com and sign in with your UPS.com account (or create one). Navigate to Apps → Create App. Fill in the app name, description, and contact details. Select the API products you need: Rating, Tracking, and Address Validation are the most commonly needed for e-commerce apps. After creating the app, you receive a Client ID and Client Secret. Copy these immediately — the client secret is only shown once and you will need to regenerate it if lost. These credentials authenticate your app with UPS's OAuth2 token endpoint. UPS offers two environments: a test environment (CIE — Customer Integration Environment) and production. For development, use the CIE environment credentials. Production credentials are granted after UPS approves your app for live use. The CIE test environment uses test tracking numbers and does not generate real shipping labels or charges. If you want to use your company's negotiated UPS shipping rates in the Rating API, you also need to add your UPS Account Number to the developer app. Without an account number, the Rating API returns standard list rates. With your account number, it returns your negotiated discounted rates.

V0 Prompt

Create a UPS shipping credentials test page that calls /api/ups/auth-test (returns whether UPS authentication succeeds) and shows a green 'UPS API Connected' or red 'UPS credentials error' status badge. Include the token expiry time if connected.

Paste this in V0 chat

Pro tip: UPS CIE test tracking numbers for testing the Tracking API: 1Z999AA10123456784 (delivered), 1Z999AA13657672709 (in transit). These always return the same test data in the CIE environment.

Expected result: You have a UPS developer app with Client ID and Client Secret. The app has the Rating, Tracking, and Address Validation API products enabled.

2

Create the UPS OAuth2 Token Route

UPS API calls require a valid OAuth2 bearer token obtained from the UPS token endpoint. Create a utility function that handles the token exchange and caches the result to avoid re-authenticating on every request. The UPS OAuth2 client credentials flow works as follows: POST to https://onlinetools.ups.com/security/v1/oauth/token (production) or https://wwwcie.ups.com/security/v1/oauth/token (test) with grant_type=client_credentials in the body. The request uses HTTP Basic Authentication with your client ID as the username and client secret as the password. UPS returns a JSON response with access_token and token_type fields. Create the token caching logic at the module level so it persists across warm serverless function invocations. Cache the token along with its expiry time — UPS tokens expire after a set period (typically 14,400 seconds / 4 hours). Before each API call, check if the cached token is still valid. If it has expired, fetch a new one. Separating the token management into a utility function keeps your main API routes clean and ensures consistent token handling across all UPS API endpoints in your app.

lib/ups-auth.ts
1// lib/ups-auth.ts
2interface UPSToken {
3 accessToken: string;
4 expiresAt: number;
5}
6
7let cachedToken: UPSToken | null = null;
8
9export async function getUPSAccessToken(): Promise<string> {
10 // Return cached token if still valid (with 60 second buffer)
11 if (cachedToken && cachedToken.expiresAt > Date.now() + 60000) {
12 return cachedToken.accessToken;
13 }
14
15 const clientId = process.env.UPS_CLIENT_ID;
16 const clientSecret = process.env.UPS_CLIENT_SECRET;
17 const baseUrl = process.env.UPS_ENVIRONMENT === 'production'
18 ? 'https://onlinetools.ups.com'
19 : 'https://wwwcie.ups.com';
20
21 if (!clientId || !clientSecret) {
22 throw new Error('UPS_CLIENT_ID and UPS_CLIENT_SECRET must be set');
23 }
24
25 const credentials = Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
26
27 const response = await fetch(`${baseUrl}/security/v1/oauth/token`, {
28 method: 'POST',
29 headers: {
30 Authorization: `Basic ${credentials}`,
31 'Content-Type': 'application/x-www-form-urlencoded',
32 },
33 body: 'grant_type=client_credentials',
34 });
35
36 if (!response.ok) {
37 const error = await response.text();
38 throw new Error(`UPS auth failed: ${error}`);
39 }
40
41 const data = await response.json();
42 cachedToken = {
43 accessToken: data.access_token,
44 expiresAt: Date.now() + (data.expires_in * 1000),
45 };
46
47 return cachedToken.accessToken;
48}

Pro tip: Set UPS_ENVIRONMENT=production in your Vercel production environment and leave it unset (defaulting to CIE test) in preview environments. This ensures test credentials are used during development.

Expected result: The token utility function successfully obtains and caches a UPS OAuth2 access token. The token is reused across multiple API calls within its expiry window.

3

Create the UPS Rating API Route

Create app/api/ups/rates/route.ts to fetch shipping rates. The UPS Rating API accepts origin and destination ZIP codes, package weight and dimensions, and optional services to quote. It returns available UPS services with rates. The UPS Rating API endpoint for fetching multiple service rates is at /api/rating/v2205/Rate (or the current version path — check the UPS API catalog). The request body is a JSON structure with Shipment details including Shipper address, Ship To address, and Package details. The Rating Code 'Shop' returns rates for all available services in a single call — this is more efficient than calling the Rate endpoint once per service. UPS rate responses include service names, service codes, and monetary amounts in both base rate and total with surcharges. Map UPS service codes to human-readable names in your UI: 03 = UPS Ground, 12 = UPS 3 Day Select, 02 = UPS 2nd Day Air, 01 = UPS Next Day Air Saver, 01 = UPS Next Day Air. The Guaranteed flag indicates services with guaranteed delivery dates.

app/api/ups/rates/route.ts
1import { NextRequest, NextResponse } from 'next/server';
2import { getUPSAccessToken } from '@/lib/ups-auth';
3
4const UPS_SERVICE_NAMES: Record<string, string> = {
5 '03': 'UPS Ground',
6 '12': 'UPS 3 Day Select',
7 '02': 'UPS 2nd Day Air',
8 '59': 'UPS 2nd Day Air A.M.',
9 '13': 'UPS Next Day Air Saver',
10 '01': 'UPS Next Day Air',
11};
12
13export async function GET(request: NextRequest) {
14 const { searchParams } = new URL(request.url);
15 const originZip = searchParams.get('originZip') || process.env.UPS_ORIGIN_ZIP;
16 const destZip = searchParams.get('destZip');
17 const weight = searchParams.get('weight') || '1';
18
19 if (!destZip) {
20 return NextResponse.json({ error: 'destZip is required' }, { status: 400 });
21 }
22
23 const baseUrl = process.env.UPS_ENVIRONMENT === 'production'
24 ? 'https://onlinetools.ups.com'
25 : 'https://wwwcie.ups.com';
26
27 try {
28 const accessToken = await getUPSAccessToken();
29
30 const response = await fetch(`${baseUrl}/api/rating/v2205/Shop`, {
31 method: 'POST',
32 headers: {
33 Authorization: `Bearer ${accessToken}`,
34 'Content-Type': 'application/json',
35 transId: `rate-${Date.now()}`,
36 transactionSrc: 'MyApp',
37 },
38 body: JSON.stringify({
39 RateRequest: {
40 Shipment: {
41 Shipper: {
42 Address: { PostalCode: originZip, CountryCode: 'US' },
43 },
44 ShipTo: {
45 Address: { PostalCode: destZip, CountryCode: 'US' },
46 },
47 Package: {
48 PackagingType: { Code: '02' },
49 PackageWeight: { UnitOfMeasurement: { Code: 'LBS' }, Weight: weight },
50 },
51 },
52 },
53 }),
54 });
55
56 if (!response.ok) {
57 const error = await response.json();
58 return NextResponse.json(
59 { error: error.response?.errors?.[0]?.message || 'UPS rating failed' },
60 { status: response.status }
61 );
62 }
63
64 const data = await response.json();
65 const rates = data.RateResponse?.RatedShipment?.map((s: any) => ({
66 service: UPS_SERVICE_NAMES[s.Service?.Code] || `UPS Service ${s.Service?.Code}`,
67 serviceCode: s.Service?.Code,
68 totalCharge: s.TotalCharges?.MonetaryValue,
69 currency: s.TotalCharges?.CurrencyCode,
70 estimatedDays: s.GuaranteedDelivery?.BusinessDaysInTransit,
71 })) || [];
72
73 return NextResponse.json({ rates });
74 } catch (error) {
75 console.error('UPS Rating error:', error);
76 return NextResponse.json({ error: 'Failed to fetch shipping rates' }, { status: 500 });
77 }
78}

Pro tip: Add UPS_ORIGIN_ZIP as a Vercel environment variable with your business's shipping ZIP code so you do not need to pass it from the frontend on every rate request.

Expected result: Calling /api/ups/rates?destZip=10001&weight=2 returns an array of UPS service options with prices. The shipping calculator UI displays the available services and prices.

4

Add Credentials to Vercel and Test End-to-End

Add your UPS credentials to Vercel Dashboard → Settings → Environment Variables. You need: UPS_CLIENT_ID, UPS_CLIENT_SECRET, UPS_ENVIRONMENT (set to 'test' for CIE or 'production' for live), and optionally UPS_ORIGIN_ZIP for your business shipping origin. For Preview and Development environments, use your CIE test credentials and set UPS_ENVIRONMENT=test. For Production, use your production UPS credentials after your app has been approved for live use. Keeping test credentials in non-production environments prevents accidentally generating real UPS labels or incurring charges during development. After adding variables and redeploying, test the shipping rate calculator by entering a destination ZIP code. For CIE testing, use ZIP code 10001 (New York) as a destination. For package tracking, use UPS test tracking number 1Z999AA10123456784 which always returns a test tracking response in the CIE environment. If you need to add the UPS Tracking API route alongside the Rating route, it follows the same OAuth2 pattern — call getUPSAccessToken(), then POST to the UPS Tracking endpoint at /api/track/v1/details/{trackingNumber}. The tracking response includes activity array with date, time, location, description, and status for each checkpoint.

V0 Prompt

Finalize the shipping checkout flow: after the user selects a UPS service from the rates list, show a summary card with the selected service name, estimated delivery date, and final price. Add a 'Continue to Payment' button that includes the selected shipping service and cost in the order data. Handle the loading state while rates are fetching with shimmer placeholder cards.

Paste this in V0 chat

Pro tip: UPS API rate versions update periodically. If you see errors about deprecated endpoints, check developer.ups.com for the current API version path and update the endpoint URLs in your route handlers.

Expected result: The complete shipping rate flow works end-to-end. Customers enter their ZIP code, see live UPS rates, select a service, and proceed to payment with the shipping cost included in the order total.

Common use cases

Checkout Shipping Rate Calculator

Display real-time UPS shipping rates at checkout so customers can choose their preferred service level and see exact costs. The rates update when the customer enters their ZIP code, using the UPS Rating API with your account's negotiated rates.

V0 Prompt

Create a shipping options selector component for a checkout page. After the customer enters their ZIP code, call /api/ups/rates with the destination ZIP, package weight (2 lbs), and dimensions. Display each service as a radio button card showing service name (UPS Ground, 2nd Day Air, Next Day Air), estimated delivery date, and price. Highlight the recommended option. Show a loading skeleton while rates are fetching.

Copy this prompt to try it in V0

Order Tracking Page

Build a customer-facing order tracking page where customers enter their UPS tracking number and see a real-time shipment timeline with delivery status, current location, and estimated delivery date.

V0 Prompt

Create an order tracking page with a tracking number input field and a 'Track Package' button. On submit, call /api/ups/track?trackingNumber=1Z999AA10123456784. Display the delivery status banner at the top (In Transit / Delivered / Exception), the estimated delivery date, origin and destination cities, and a vertical timeline of tracking events with timestamp, location, and event description. Use a checkmark for the final 'Delivered' milestone.

Copy this prompt to try it in V0

Address Validation Before Shipping

Validate customer shipping addresses in real-time as they are typed to prevent failed deliveries due to incorrect addresses. The UPS Address Validation API checks if an address is a valid UPS deliverable location and suggests corrections.

V0 Prompt

Add address validation to the checkout shipping form. When the customer fills in their address and moves to the next field, call POST /api/ups/validate-address with the address data. If UPS returns a corrected address, show a banner 'Did you mean: [corrected address]?' with 'Use this address' and 'Keep my address' buttons. Show a green checkmark badge on validated addresses.

Copy this prompt to try it in V0

Troubleshooting

401 Unauthorized when calling the UPS token endpoint

Cause: UPS_CLIENT_ID or UPS_CLIENT_SECRET is incorrect, or the credentials are from the wrong environment (CIE vs production). The Basic auth header must use the exact credentials from the UPS developer portal.

Solution: Go to developer.ups.com → Apps → your app → API Keys. Verify the Client ID matches UPS_CLIENT_ID in Vercel. If the secret is unknown, generate a new client secret — this invalidates the old one. Update Vercel and redeploy.

UPS Rating returns empty rates or 'No rates found' for valid ZIP codes

Cause: The UPS account number is not configured (returning no negotiated rates), or the package weight/dimensions combination triggers exclusions, or you are using the CIE test environment with production-only service codes.

Solution: Try without specifying a UPS account number to get standard list rates. Verify the destination ZIP code is a valid US ZIP. In the CIE test environment, not all service levels are available — test with UPS Ground (code 03) to confirm basic connectivity before testing premium services.

'transId' header error — 'Transaction ID is required'

Cause: The UPS API requires a transId header on every request for request tracing and debugging. Missing this header returns a 400 error on some UPS API endpoints.

Solution: Add a transId header with a unique string (transaction ID) to every UPS API request. A combination of a timestamp and random string works: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`. Also include transactionSrc with your app name.

typescript
1headers: {
2 Authorization: `Bearer ${accessToken}`,
3 'Content-Type': 'application/json',
4 transId: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
5 transactionSrc: 'MyApp',
6}

Best practices

  • Cache the UPS OAuth2 bearer token and reuse it across requests until near expiry — fetching a new token for every API call adds 300-500ms latency and increases the chance of rate limiting.
  • Use separate UPS CIE test credentials for Preview/Development environments and production credentials for Production — this prevents test requests from showing up in your UPS account dashboard.
  • Always include the transId header on UPS API requests — it is required by some endpoints and helps UPS support troubleshoot issues if you contact them.
  • Store your origin ZIP code as an environment variable (UPS_ORIGIN_ZIP) rather than hardcoding it — this makes it easy to update if your fulfillment location changes.
  • Add the UPS account number to your developer app for negotiated rate access — standard list rates can be significantly higher than your actual shipping costs, giving customers inaccurate price expectations.
  • Handle UPS service code mapping to human-readable names in your API route, not the frontend — UPS can add or change service codes and centralizing this mapping makes updates easier.
  • Test address validation before allowing order completion for high-value shipments — undeliverable addresses cause costly failed delivery attempts and returns.

Alternatives

Frequently asked questions

Do I need a UPS account to use the UPS API?

You need a UPS developer account (free at developer.ups.com) to get API credentials. For shipping rate quotes using standard list rates, a UPS shipper account is not required. To get your negotiated discounted rates through the API, you need to link your UPS shipper account number to your developer app. Label creation requires a UPS shipper account.

What is the difference between UPS CIE and production environments?

The UPS Customer Integration Environment (CIE) is a test environment with sandbox credentials and test tracking numbers. Requests in CIE do not create real shipments, incur charges, or affect your UPS account. Production credentials are required for live shipping operations. Always develop and test with CIE credentials to avoid creating unintended shipments.

How do UPS API rate limits work?

UPS applies rate limits per API key and endpoint. The exact limits are not publicly published but are enforced to prevent abuse. For typical e-commerce checkout flows (rates requested when a customer enters their address), the limits are generous. If you are building a batch rate-comparison tool, contact UPS developer support about higher limits.

Can the UPS API create shipping labels?

Yes, the UPS Shipping API supports label creation and can return label data as a Base64-encoded PDF or ZPL format. Label creation requires a linked UPS shipper account with billing configured. The Shipping API is more complex than Rating and Tracking — it requires shipper address, recipient address, package details, and service selection. A UPS account manager approval may be needed for production label access.

What UPS tracking numbers can I use for testing?

In the CIE test environment, UPS provides standard test tracking numbers that always return the same test data: 1Z999AA10123456784 (delivered status), 1Z999AA13657672709 (in transit status), and others listed in the UPS developer documentation. These numbers do not correspond to real shipments — they return scripted test responses from the UPS CIE API.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.