Skip to content

Documentation

Tracking

Scan history for a parcel, in one status vocabulary that means the same thing for every carrier.

GET /v1/tracking/:tracking

Pass the tracking_number from a shipment. The history is refreshed from the carrier when you ask for it, and events are always returned in chronological order regardless of what order the carrier sent them in.

Request
curl https://api.shipstack.example/v1/tracking/15012345678901 \
  -H "Authorization: Bearer $SHIPSTACK_API_KEY"
200 OK
{
  "tracking_number": "15012345678901",
  "courier": "dpd",
  "status": "out_for_delivery",
  "events": [
    {
      "status": "pre_transit",
      "description": "Label created",
      "occurred_at": "2026-09-01T10:24:11Z"
    },
    {
      "status": "in_transit",
      "description": "Parcel collected",
      "location": "Leeds",
      "occurred_at": "2026-09-01T18:02:00Z",
      "carrier_code": "PU"
    },
    {
      "status": "out_for_delivery",
      "description": "Out for delivery",
      "location": "Bristol",
      "occurred_at": "2026-09-02T07:41:00Z",
      "carrier_code": "WC"
    }
  ]
}

Status vocabulary

Every carrier's own status strings map onto exactly one of these, so you never write carrier-specific branching.

StatusMeaning
pre_transitThe label exists; the carrier does not have the parcel yet.
in_transitMoving through the carrier's network.
out_for_deliveryWith the driver, out for delivery today.
deliveredDelivered. Terminal.
exceptionSomething went wrong: a failed attempt, a customs hold, damage.
returnedReturned to sender. Terminal.
unknownThe carrier sent something we do not recognise.

Polling

delivered and returned are terminal: once a parcel reaches either, stop polling it. Each event also carries the carrier's own raw status in carrier_code, which is useful for support conversations but should not be branched on.