UPS Tracking API & MCP
Query live UPS (ups) package status and full scan history in a single synchronous GET request or MCP tool call. lastscanned validates UPS 1Z Mod-10 check digits upfront and returns a normalized TrackingResult JSON payload—without requiring a UPS Developer Portal OAuth application, shipper account number, or webhook receiver.
Overview & Quick Facts
| Property | Value |
|---|---|
Carrier slug (?carrier=) | ups |
| Brand & service aliases | United Parcel Service, UPS Ground, UPS Next Day Air, UPS 2nd Day Air, UPS 3 Day Select, UPS SurePost, UPS Worldwide Express / Saver / Expedited |
| Category | National & international parcel carrier (Detection precedence #1 of 31) |
| Single-package REST endpoint | GET https://api.lastscanned.com/v1/track/{trackingNumber} |
| Batch REST endpoint | GET https://api.lastscanned.com/v1/track?numbers=1Z...,1Z... (up to 35 numbers per carrier in a 100-number call) |
MCP server (https://mcp.lastscanned.com) | track_package, track_packages, list_carriers (claude mcp add --transport http lastscanned https://mcp.lastscanned.com) |
| Authentication & pricing | Authorization: Bearer lsk_live_... · 1 free keyless lookup/day per IP · Free tier (5 unique numbers/day, $0) · Pro ($4.99/mo for 1,000 unique numbers, unlimited re-polls, $0.015/extra) · HTTP 402 Stripe MPP ($0.50 for 25-number lsk_pack_ key or $0.02/number in USDC on Tempo) |
Why developers use lastscanned for UPS instead of direct requests
- Avoid Akamai Bot Manager
403blocks from serverless & edge IPs: If you try to callwebapis.ups.com/track/api/Track/GetStatusdirectly from a Cloudflare Worker, Vercel function, or AWS Lambda, Akamai rejects datacenter TLS fingerprints and IPs, and requires pairedGetCSRFToken/X-XSRF-TOKEN-STsession cookies. CallingGET https://api.lastscanned.com/v1/track/:numberfrom your Worker or Lambda returns clean JSON in onefetch(). - Skip UPS Developer Kit OAuth 2.0 & shipper account linking: Official UPS Track API credentials require registering an enterprise app, linking a 6-character UPS shipper account, and refreshing short-lived OAuth tokens.
lastscannedworks immediately with a single Bearer key (or keyless via HTTP 402). - Synchronous GET—no webhook registration: Unlike AfterShip, Ship24, or EasyPost where you must
POSTa tracker first and wait for an async webhook,GET /v1/track/:numberreturns the live UPS scan timeline inline.
Tracking Number Formats & Auto-Detection (matches vs mayMatch)
UPS is evaluated first (#1) in lastscanned's two-pass detector:
| Pass | Rule / Regex | Check Digit | Examples |
|---|---|---|---|
Pass 1 (matches) | /^1Z[0-9A-Z]{16}$/i (18 characters starting with 1Z) | Yes — ups1Z(n) (Mod-10) | 1Z999AA10123456784, 1Z5868Y60389226681 |
Pass 2 (mayMatch) | None | — | — |
ups1Z Mod-10 check-digit algorithm
Every 18-character 1Z number consists of 1Z + 6-character shipper account + 2-digit service code + 7-digit package identifier + 1 Mod-10 check digit. lastscanned validates the check digit before making any network call so typos fail fast with 400 unknown_carrier:
/** UPS 1Z: letters count as (char code - 63) mod 10, odd positions doubled, mod 10. */
export function ups1Z(n: string): boolean {
const body = n.slice(2, -1).toUpperCase();
let sum = 0;
for (let i = 0; i < body.length; i++) {
const ch = body[i];
const v = ch >= "0" && ch <= "9" ? Number(ch) : (ch.charCodeAt(0) - 63) % 10;
sum += i % 2 ? v * 2 : v;
}
return (10 - (sum % 10)) % 10 === Number(n.slice(-1));
}When is ?carrier=ups optional vs required?
- Optional (auto-detected): All standard 18-character
1Ztracking numbers with a valid Mod-10 check digit. No other carrier uses the1Zprefix. - Required (
?carrier=ups): Non-1ZUPS formats such as 9-digit or 12-digit UPS Freight / TForce PRO numbers, UPS InfoNotice numbers, or UPS Mail Innovations labels that do not use a USPS92…/93…IMpb barcode.
Synchronous GET Request & Normalized JSON Response
curl
curl -s "https://api.lastscanned.com/v1/track/1Z999AA10123456784" \
-H "Authorization: Bearer $LASTSCANNED_API_KEY"JavaScript / TypeScript (fetch)
const res = await fetch("https://api.lastscanned.com/v1/track/1Z999AA10123456784", {
headers: { Authorization: `Bearer ${process.env.LASTSCANNED_API_KEY}` },
});
const pkg = await res.json();
console.log(pkg.status, pkg.service, pkg.deliveredAt);MCP track_package tool call
{
"tool": "track_package",
"arguments": {
"tracking_number": "1Z999AA10123456784"
}
}Normalized TrackingResult JSON response
{
"carrier": "ups",
"trackingNumber": "1Z999AA10123456784",
"status": "delivered",
"statusDescription": "Delivered",
"service": "UPS Ground",
"deliveredAt": "2026-10-23T20:17:14Z",
"deliveredAtLocal": "2026-10-23T15:17:00",
"signedBy": "FRONT DOOR",
"destination": {
"city": "AUSTIN",
"state": "TX",
"country": "US"
},
"events": [
{
"timestamp": "2026-10-23T20:17:14Z",
"localTime": "2026-10-23T15:17:00",
"status": "delivered",
"description": "Delivered",
"location": "AUSTIN, TX, US",
"code": "KB"
},
{
"timestamp": "2026-10-23T13:42:08Z",
"localTime": "2026-10-23T08:42:00",
"status": "out_for_delivery",
"description": "Out For Delivery Today",
"location": "AUSTIN, TX, US",
"code": "OT"
},
{
"timestamp": "2026-10-23T09:15:30Z",
"localTime": "2026-10-23T04:15:00",
"status": "in_transit",
"description": "Arrived at Facility",
"location": "AUSTIN, TX, US",
"code": "AR"
},
{
"timestamp": "2026-10-21T22:04:11Z",
"localTime": "2026-10-21T18:04:00",
"status": "label_created",
"description": "Shipper created a label, UPS has not received the package yet.",
"location": "US",
"code": "MP"
}
]
}Raw status & scan codes: Top-level
statusDescriptionpreserves UPS's exact status wording (e.g."Delivered","On the Way"), while each entry inevents[]includes normalizedstatus, rawdescription, and UPS's 2-character activitycode(e.g."KB","OT","AR","DP","MP").
Carrier-Specific Status & Integration Notes
- Exact UTC (
timestamp) and scan-local (localTime) clocks: UPS reports bothgmtDate/gmtTime(down to the second in UTC, e.g."2026-10-23T20:17:14Z") and the scan location's wall-clock time (date/time, normalized to"2026-10-23T15:17:00"). BothtimestampandlocalTimeare populated on every scan. - UPS status type mapping: UPS package status types map deterministically to the 7 normalized statuses:
M→label_created,I→in_transit,O→out_for_delivery,D→delivered,X→exception, andRS→returned. - Service level & proof of delivery:
servicereturns the specific UPS service product (such as"UPS Ground","UPS Next Day Air", or"UPS 2nd Day Air"), andsignedBycaptures the receiver name or release location (receivedBy) when available.
Related Resources
- Live browser lookup tool: Track a UPS package live on lastscanned.com/lookup/ups
- Carrier hub: All 31 supported carriers
- Regex & check digits: Tracking number formats & auto-detection
- AI support workflows: WISMO AI agents & synchronous tracking
Carriers
Supported carriers, their ids, the number formats each one detects, developer API reference links, and carrier-specific limits.
USPS Tracking API & MCP
Track United States Postal Service (USPS Ground Advantage, Priority Mail, Priority Mail Express, Certified Mail, International S10) packages via synchronous REST GET or MCP. Normalized JSON status, scan history, and tracking number format rules—no carrier credentials required.