Carriers

Purolator Tracking API & MCP

Query live Purolator (purolator) package status and scan history across Canada and the US in a single synchronous GET request or MCP tool call. lastscanned auto-detects 12-character alphanumeric Purolator PINs (3 letters + 9 digits) in Pass 2 (mayMatch) and tracks 12-digit numeric PINs with ?carrier=purolator, returning a normalized TrackingResult JSON payload—without requiring a Purolator E-Ship Web Services production key.

Overview & Quick Facts

PropertyValue
Carrier slug (?carrier=)purolator
Brand & service aliasesPurolator, Purolator Courier, Purolator Express, Purolator Ground
CategoryCanadian national courier & freight network (Detection precedence #22 of 31)
Single-package REST endpointGET https://api.lastscanned.com/v1/track/{trackingNumber}
Batch REST endpointGET https://api.lastscanned.com/v1/track?numbers=PQR...,EWN... (up to 25 Purolator numbers per batch; up to 100 total numbers)
MCP server (https://mcp.lastscanned.com)track_package, track_packages, list_carriers (claude mcp add --transport http lastscanned https://mcp.lastscanned.com)
Authentication & pricingAuthorization: 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 Purolator instead of direct requests

  • Skip Purolator E-Ship SOAP/REST certification & WAF rejections: Purolator's official E-Ship developer portal requires registering a billing account, requesting development keys, and completing formal certification for production credentials, while unconfigured requests to public-tracking.purolator.com are rejected by Purolator's WAF. lastscanned returns normalized JSON in a single fetch().
  • Automatic Canadian provincial timezone conversion: Purolator prints scan times ("2026-10-24 18:45:19") in the local clock of the scanning terminal without a UTC offset. lastscanned maps all 13 Canadian provinces and territories (BC → America/Vancouver, AB → America/Edmonton, SK → America/Regina, MB → America/Winnipeg, ON/QC → America/Toronto, NB → America/Moncton, NS/PE → America/Halifax, NL → America/St_Johns, YT/NT/NU) to compute accurate UTC timestamp values alongside localTime.
  • Full event history per parcel: Multi-number searches on Purolator's portal only return summary statuses; lastscanned fetches the full scan-by-scan history for up to 25 PINs in parallel.

Tracking Number Formats & Auto-Detection (matches vs mayMatch)

Purolator is evaluated twenty-second (#22) in lastscanned's two-pass detector:

PassRule / RegexCheck DigitExamples
Pass 1 (matches)None (false)——
Pass 2 (mayMatch) — Alphanumeric PIN/^[A-Z]{3}\d{9}$/i (3 letters + 9 digits = 12 chars)—PQR482019376, EWN001815469
Explicit (?carrier=purolator) — 12-digit PIN/^\d{12}$/ (12 digits — collides with FedEx in Pass 1)—520769802262, 334918273645

Why 12-digit Purolator PINs require ?carrier=purolator

  • Alphanumeric PINs (PQR482019376) auto-detect in Pass 2: 3-letter + 9-digit Purolator PINs do not collide with any Pass 1 carrier (note that Sendle's QSS + 9 digits matches in Pass 1 before Pass 2 runs) and are routed to purolator automatically.
  • 12-digit numeric PINs (520769802262) require ?carrier=purolator: Because 12-digit numeric tracking numbers have no check digit and are also the primary format for FedEx Express / Ground, bare 12-digit numbers route to fedex by default. Always append ?carrier=purolator (or pass "carrier": "purolator" in MCP) when tracking a 12-digit numeric Purolator PIN.

Synchronous GET Request & Normalized JSON Response

curl

# 3-letter + 9-digit PIN (auto-detected)
curl -s "https://api.lastscanned.com/v1/track/PQR482019376" \
  -H "Authorization: Bearer $LASTSCANNED_API_KEY"

# 12-digit numeric PIN (pass ?carrier=purolator)
curl -s "https://api.lastscanned.com/v1/track/520769802262?carrier=purolator" \
  -H "Authorization: Bearer $LASTSCANNED_API_KEY"

JavaScript / TypeScript (fetch)

const res = await fetch("https://api.lastscanned.com/v1/track/PQR482019376", {
  headers: { Authorization: `Bearer ${process.env.LASTSCANNED_API_KEY}` },
});
const pkg = await res.json();
console.log(pkg.status, pkg.destination, pkg.events[0]);

MCP track_package tool call

{
  "tool": "track_package",
  "arguments": {
    "tracking_number": "520769802262",
    "carrier": "purolator"
  }
}

Normalized TrackingResult JSON response

{
  "carrier": "purolator",
  "trackingNumber": "PQR482019376",
  "status": "delivered",
  "statusDescription": "Shipment delivered",
  "service": null,
  "deliveredAt": "2026-10-24T22:45:19Z",
  "deliveredAtLocal": "2026-10-24T18:45:19",
  "signedBy": null,
  "destination": {
    "city": "Etobicoke",
    "state": "ON",
    "country": "CA"
  },
  "estimatedDelivery": null,
  "events": [
    {
      "timestamp": "2026-10-24T22:45:19Z",
      "localTime": "2026-10-24T18:45:19",
      "status": "delivered",
      "description": "Shipment delivered",
      "location": "Etobicoke, ON",
      "code": "9500"
    },
    {
      "timestamp": "2026-10-24T12:18:04Z",
      "localTime": "2026-10-24T08:18:04",
      "status": "out_for_delivery",
      "description": "On vehicle for delivery",
      "location": "Etobicoke, ON",
      "code": "4200"
    },
    {
      "timestamp": "2026-10-24T07:52:30Z",
      "localTime": "2026-10-24T03:52:30",
      "status": "in_transit",
      "description": "Arrived at sort facility",
      "location": "Mississauga, ON",
      "code": "0300"
    },
    {
      "timestamp": "2026-10-23T20:10:00Z",
      "localTime": "2026-10-23T16:10:00",
      "status": "label_created",
      "description": "Shipping label created with reference(s)",
      "location": "Toronto, ON",
      "code": "3000"
    }
  ]
}

Raw status & scan codes: events[].code preserves Purolator's 4-digit scan code ("3000"/"3010" label created, "2380" picked up, "0300"/"1310"/"4060"/"7220" arrived at sort facility, "1300"/"7525" departed sort facility, "4200" on vehicle for delivery, "9260" attempted delivery, "6500"/"9230" address correction required, "9550" held for pickup, "9500"/"9000" delivered), while package-level states (SDR, POP, IND, INT, OFD, ATT, DEL) normalize to the 7 standard statuses.

On this page