← Retour au blog

Shipping tracking API and webhooks explained

Shipping APIs for DevelopersSydney Larsson2545 vues

A shipping tracking API tells your application where a package is, using the tracking number you got when you bought the label. There are two ways to get that status: polling, where your code asks the API for the latest status on a schedule, and webhooks, where the carrier or platform pushes an event to your server the moment the status changes. Webhooks are almost always the better choice because they are faster and cheaper, but both have their place. This guide explains how each works, when to use which, and how to build a webhook receiver you can trust.

It is part of our hub on shipping APIs for developers. Tracking starts from a label, so if you have not created one yet, see how to create a shipping label with an API.

Polling versus webhooks

Both approaches answer the same question, "where is this package," but they get there differently.

PollingWebhooks
How it worksYour code requests the status on a timerThe platform POSTs to your endpoint when status changes
FreshnessOnly as fresh as your intervalNear real time
CostMany wasted calls; most return no changeOne call per actual event
ComplexitySimple to buildNeeds a public endpoint and verification

Use polling for one-off checks, backfills, or when you cannot expose a public endpoint. Use webhooks for anything ongoing, like keeping order statuses current or triggering delivery notifications.

How polling works

Polling is a plain GET against a tracking endpoint. The examples here are generic illustrative pseudo-REST to show the pattern, not the exact Expership contract; confirm the real endpoint and fields at /developers.

GET /tracking/TRK123456789
Authorization: Bearer YOUR_API_KEY
{
  "tracking_number": "TRK123456789",
  "status": "in_transit",
  "carrier": "CarrierA",
  "estimated_delivery": "2026-07-24",
  "events": [
    { "status": "label_created", "at": "2026-07-21T15:02:00Z", "location": "Chicago, IL" },
    { "status": "in_transit",    "at": "2026-07-22T09:41:00Z", "location": "Indianapolis, IN" }
  ]
}

The key discipline with polling is to back off. Poll active shipments more often and delivered ones not at all, and never poll every package on a tight loop, which wastes calls and can hit rate limits.

How webhooks work

With webhooks, you register an endpoint on your server once. From then on, whenever a package's status changes, the platform sends an HTTP POST to that endpoint with the event payload. Your server acknowledges with a 200 and processes the event.

POST /your-webhook-endpoint
Content-Type: application/json
X-Signature: t=1690000000,v1=abc123...

{
  "tracking_number": "TRK123456789",
  "status": "delivered",
  "carrier": "CarrierA",
  "occurred_at": "2026-07-24T17:12:00Z",
  "location": "Atlanta, GA"
}

A minimal receiver looks like this:

app.post('/webhooks/tracking', (req, res) => {
  if (!verifySignature(req)) return res.sendStatus(401);

  const evt = req.body;
  // Idempotency: ignore if we have processed this event already
  if (alreadyProcessed(evt)) return res.sendStatus(200);

  updateOrderStatus(evt.tracking_number, evt.status);
  res.sendStatus(200); // acknowledge fast
});

Building a webhook receiver you can trust

A few rules keep webhook handling reliable:

  • Verify the signature. Webhook endpoints are public, so anyone could POST to them. Providers sign each request; verify the signature before trusting the payload. Never skip this.
  • Be idempotent. Networks retry, so the same event can arrive more than once. Key on an event id or the status plus timestamp and ignore duplicates, so you do not send two "delivered" emails.
  • Acknowledge fast, process async. Return 200 quickly and do the heavy work (emails, DB writes, downstream calls) in a background job. Slow responses can cause the sender to time out and retry.
  • Handle retries. If you return a non-200, expect the platform to resend later. That is a feature: it means a brief outage on your side does not lose events.
The two mistakes that cause almost every webhook bug are skipping signature verification and assuming each event arrives exactly once. Verify, and make your handler idempotent.

What tracking statuses to expect

Status vocabularies vary by carrier, but a good tracking API normalizes them to a common set so you do not branch on every carrier's wording. Typical normalized statuses:

  • label_created - postage bought, package not yet scanned
  • in_transit - moving through the network
  • out_for_delivery - on the truck for final delivery
  • delivered - handoff complete
  • exception - a problem such as a failed delivery or address issue

Handle exception deliberately. It is your early warning for a delivery that needs intervention, and catching it early is far cheaper than a return. Many exceptions trace back to bad addresses, which an address validation API prevents before the label is ever bought.

Getting started with Expership

Expership provides a multi-carrier shipping API that includes tracking across carriers from one integration, aimed at ecommerce sellers and consolidators shipping into the U.S. Explore the reference at /developers, see the full platform, or create an account to start testing. For context, read what is a shipping API and what is shipping software.

Frequently asked questions

What is a shipping tracking API?

It is an interface that reports a package's delivery status by tracking number. You can request the status on demand (polling) or have the platform push status changes to your server as they happen (webhooks).

Should I use polling or webhooks for tracking?

Use webhooks for ongoing tracking. They deliver near-real-time updates with one call per actual event, instead of many wasted polls. Use polling only for one-off checks, backfills, or when you cannot expose a public endpoint.

How do I secure a tracking webhook?

Verify the signature on every incoming request before trusting it, since the endpoint is publicly reachable. Also make your handler idempotent so duplicate deliveries do not cause duplicate actions, and acknowledge with a 200 quickly.

Why am I getting duplicate tracking events?

Because webhook systems retry to guarantee delivery, the same event can arrive more than once. This is expected. Key on an event id or status-plus-timestamp and ignore anything you have already processed.

What does a tracking exception status mean?

It signals a problem with the delivery, such as a failed attempt, a bad address, or a hold. Treat it as an alert and act on it quickly. Many exceptions come from bad addresses, which validating the address before shipping helps prevent.

mots-clés
Rédigé par Sydney Larsson
Voir le profil →