Playground
Ask it yourself. Real lookups, in the browser.
Pick a carrier, type a tracking number, send. The request your code would make is on the left and the answer is on the right. 10 lookups a day without a key.
Request
POST /v1/trackcurl https://api.shipmenttrackingapi.com/v1/track \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"carrier":"ups","trackingNumbers":["YOUR_TRACKING_NUMBER"]}'The request your code sends. It needs a key; this page’s keyless trial goes through its own endpoint.
Response
200 OKExample shipment. Type a tracking number and send to see a real one.
{
"success": true,
"data": {
"carrier": "ups",
"results": [
{
"trackingNumber": "YOUR_TRACKING_NUMBER",
"status": "delivered",
"events": [
{
"timestamp": "2026-11-03T16:12:00-05:00",
"status": "pending",
"description": "Shipper created a label, UPS has not received the package yet.",
"location": "Louisville, KY, US"
},
{
"timestamp": "2026-11-04T19:41:00-05:00",
"status": "in_transit",
"description": "Departed from Facility",
"location": "Louisville, KY, US"
},
{
"timestamp": "2026-11-05T03:27:00-06:00",
"status": "in_transit",
"description": "Arrived at Facility",
"location": "Hodgkins, IL, US"
},
{
"timestamp": "2026-11-05T08:52:00-06:00",
"status": "out_for_delivery",
"description": "Out For Delivery Today",
"location": "Chicago, IL, US"
},
{
"timestamp": "2026-11-05T13:36:00-06:00",
"status": "delivered",
"description": "DELIVERED",
"location": "Chicago, IL, US"
}
]
}
]
}
}
| When | The carrier wrote | becomes | You get |
|---|---|---|---|
| Nov 3, 4:12 PM | Shipper created a label, UPS has not received the package yet. | pending | |
| Nov 4, 7:41 PM | Departed from Facility | in_transit | |
| Nov 5, 3:27 AM | Arrived at Facility | in_transit | |
| Nov 5, 8:52 AM | Out For Delivery Today | out_for_delivery | |
| Nov 5, 1:36 PM | DELIVERED | delivered |
ErrorsSame shape every time
When it says no, it says why.
Every error carries a code your program can switch on and a sentence a person can read. Only one of them, a clear “not found”, counts as a lookup.
| Code | HTTP | When |
|---|---|---|
| INVALID_CARRIER | 400 | The carrier is not one of usps, ups, fedex, dhl. |
| INVALID_TRACKING_NUMBER | 400 | A number is malformed, repeated, or not valid for that carrier. trackingNumbers is always an array. |
| TOO_MANY_TRACKING_NUMBERS | 400 | More numbers than the carrier takes in one request: 35 for USPS, 1 for the others. The keyless trial takes 1. |
| AUTH_MISSING_API_KEY | 401 | There is no Authorization header. |
| AUTH_INVALID_API_KEY | 401 | The key does not exist. |
| KEY_INACTIVE | 403 | The key was turned off. |
| DEMO_ORIGIN_NOT_ALLOWED | 403 | The keyless trial was called from somewhere other than this page. |
| NOT_FOUND | 404 | There is no such endpoint. Check the path and the method. |
| TRACKING_NOT_FOUND | 200 | The carrier has no record of that number. It comes inside results, for that number only. This is the one that counts. |
| RATE_LIMIT_EXCEEDED | 429 | More than 30 requests in a minute with a key or 6 on the keyless trial, or the trial is busy. Retry-After says when to come back. |
| MONTHLY_QUOTA_EXCEEDED | 429 | The account has used its 1,000 lookups for the month. |
| IP_QUOTA_EXCEEDED | 429 | The IP address has used its 1,000 lookups for the month, across every key. |
| DEMO_LIMIT_REACHED | 429 | The keyless trial is used up for the day: 10 lookups per IP address, or the daily total shared by all visitors. |
| INTERNAL_ERROR | 500 | Something unexpected on our side. Try again. |
| CARRIER_ERROR | 200 | The carrier did not answer for that number. It comes inside results, for that number only. Try again. |
| SERVICE_UNAVAILABLE | 503 | Something on our side. Try again. |
One exception: a body that is not valid JSON is refused before it reaches the API, with a plain 400 and no JSON.
StartAbout a minute