Carriers

Canada Post Tracking API & MCP

Query live Canada Post / Postes Canada (canadapost) domestic and international package status and scan history in a single synchronous GET request or MCP tool call. lastscanned validates 16-digit domestic PINs (gs1 Mod-10 check digit) and 13-character UPU S10 international items ending in CA (s10 Mod-11 check digit), returning a normalized TrackingResult JSON payload—without requiring a Canada Post Developer Program key or commercial customer number.

Overview & Quick Facts

PropertyValue
Carrier slug (?carrier=)canadapost
Brand & service aliasesCanada Post, Postes Canada, CPC, Xpresspost, Expedited Parcel, Regular Parcel, Priority
CategoryCanadian national postal service (Detection precedence #21 of 31)
Single-package REST endpointGET https://api.lastscanned.com/v1/track/{trackingNumber}
Batch REST endpointGET https://api.lastscanned.com/v1/track?numbers=7012...,EE12...CA (up to 25 Canada Post 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 Canada Post instead of direct requests

  • Avoid CloudFront 403 / 406 blocks & XML SOAP/REST credential setup: Direct requests to canadapost-postescanada.ca from serverless functions often fail with CloudFront 403 "Please log in" or 406 Not Acceptable errors, while Canada Post's official Developer Program API requires commercial account registration and XML/Basic Auth credentials. lastscanned returns clean JSON in one fetch().
  • Pre-validates GS1 Mod-10 & UPU S10 check digits: lastscanned validates the check digit on 16-digit PINs and …CA international numbers before making a network call, catching mistyped tracking numbers immediately.
  • Smart handling of "Photo available" & "ReadyPickup" states: Canada Post frequently inserts a "Photo available" informational event above the actual delivery scan, or marks parcels waiting at a post office as ReadyPickup. lastscanned preserves the true delivered description and maps ReadyPickup (notice card left / held for pickup) to exception so your WISMO bot can alert the recipient.

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

Canada Post is evaluated twenty-first (#21) in lastscanned's two-pass detector:

PassRule / RegexCheck DigitExamples
Pass 1 (matches) — 16-digit Domestic PIN/^\d{16}$/ (16 digits)Yes — gs1(n) (GS1 Mod-10)7012345678901230, 4007854296017911
Pass 1 (matches) — International UPU S10/^[A-Z]{2}\d{9}CA$/i (2 letters + 9 digits + CA = 13 chars)Yes — s10(n) (UPU Mod-11)EE123456785CA, LM987654323CA
Pass 2 (mayMatch)None——

GS1 Mod-10 check-digit algorithm (gs1)

Every 16-digit Canada Post domestic PIN uses the standard GS1 Mod-10 check digit (weights 3, 1 alternating from the right, excluding the final check digit):

/** GS1 mod 10 (Canada Post 16-digit PINs, SSCC, GTIN): weights 3,1 from the right, check digit excluded. */
export function gs1(n: string): boolean {
  const body = n.slice(0, -1);
  let sum = 0;
  for (let i = 0; i < body.length; i++) sum += Number(body[body.length - 1 - i]) * (i % 2 ? 1 : 3);
  return (10 - (sum % 10)) % 10 === Number(n.slice(-1));
}

When is ?carrier=canadapost required?

  • Optional (auto-detected): All 16-digit GS1 PINs and 13-character XX123456785CA S10 international numbers auto-detect in Pass 1.
  • Required (?carrier=canadapost): Legacy 12-digit or 11-digit Canada Post PINs (since 12-digit numbers route to FedEx in Pass 1), or inbound international S10 parcels originating outside Canada (e.g. LA…US, RR…GB, LY…CN) once inducted into Canada Post.

Synchronous GET Request & Normalized JSON Response

curl

curl -s "https://api.lastscanned.com/v1/track/7012345678901230" \
  -H "Authorization: Bearer $LASTSCANNED_API_KEY"

JavaScript / TypeScript (fetch)

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

MCP track_package tool call

{
  "tool": "track_package",
  "arguments": {
    "tracking_number": "7012345678901230"
  }
}

Normalized TrackingResult JSON response

{
  "carrier": "canadapost",
  "trackingNumber": "7012345678901230",
  "status": "delivered",
  "statusDescription": "Delivered to recipient's front door",
  "service": "Expedited Parcels",
  "deliveredAt": "2026-10-24T17:18:38Z",
  "deliveredAtLocal": "2026-10-24T13:18:38",
  "signedBy": null,
  "destination": {
    "city": "GUELPH",
    "state": "ON",
    "country": "CA"
  },
  "estimatedDelivery": null,
  "message": null,
  "events": [
    {
      "timestamp": "2026-10-24T17:18:38Z",
      "localTime": "2026-10-24T13:18:38",
      "status": "delivered",
      "description": "Delivered to recipient's front door",
      "location": "GUELPH, ON",
      "code": "1498"
    },
    {
      "timestamp": "2026-10-24T12:41:10Z",
      "localTime": "2026-10-24T08:41:10",
      "status": "out_for_delivery",
      "description": "Item out for delivery",
      "location": "GUELPH, ON",
      "code": "0174"
    },
    {
      "timestamp": "2026-10-24T08:12:05Z",
      "localTime": "2026-10-24T04:12:05",
      "status": "in_transit",
      "description": "Item processed",
      "location": "MISSISSAUGA, ON",
      "code": "0100"
    },
    {
      "timestamp": null,
      "localTime": "2026-10-22",
      "status": "label_created",
      "description": "Electronic information submitted by shipper",
      "location": null,
      "code": "3000"
    }
  ]
}

Raw status & event codes: events[].code preserves Canada Post's 4-digit event code ("3000"–"3002" electronic notice submitted by shipper, "0100"/"0170" item processed, "0174" out for delivery, "1400"–"1498" delivered). When a parcel is being returned under a new return PIN (returnPin), message surfaces "Being returned under <returnPin>".

Carrier-Specific Status & Integration Notes

  • Per-scan timezone offsets: Every physical Canada Post scan includes its date, time, and zoneOffset (e.g. "-04:00", "-06:00"), populating both UTC timestamp and local localTime. Electronic pre-shipment notices (3000–3002) carry a date without a clock time (localTime: "2026-10-22", timestamp: null).
  • Batch size: GET /v1/track?numbers=... and track_packages support up to 25 Canada Post numbers per batch call.

On this page