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
| Property | Value |
|---|---|
Carrier slug (?carrier=) | canadapost |
| Brand & service aliases | Canada Post, Postes Canada, CPC, Xpresspost, Expedited Parcel, Regular Parcel, Priority |
| Category | Canadian national postal service (Detection precedence #21 of 31) |
| Single-package REST endpoint | GET https://api.lastscanned.com/v1/track/{trackingNumber} |
| Batch REST endpoint | GET 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 & pricing | Authorization: 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/406blocks & XML SOAP/REST credential setup: Direct requests tocanadapost-postescanada.cafrom serverless functions often fail with CloudFront403 "Please log in"or406 Not Acceptableerrors, while Canada Post's official Developer Program API requires commercial account registration and XML/Basic Auth credentials.lastscannedreturns clean JSON in onefetch(). - Pre-validates GS1 Mod-10 & UPU S10 check digits:
lastscannedvalidates the check digit on 16-digit PINs and…CAinternational 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 asReadyPickup.lastscannedpreserves the truedelivereddescription and mapsReadyPickup(notice card left / held for pickup) toexceptionso 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:
| Pass | Rule / Regex | Check Digit | Examples |
|---|---|---|---|
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
XX123456785CAS10 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[].codepreserves 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),messagesurfaces"Being returned under <returnPin>".
Carrier-Specific Status & Integration Notes
- Per-scan timezone offsets: Every physical Canada Post scan includes its
date,time, andzoneOffset(e.g."-04:00","-06:00"), populating both UTCtimestampand locallocalTime. 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=...andtrack_packagessupport up to 25 Canada Post numbers per batch call.
Related Resources
- Live browser lookup tool: Track a Canada Post package live on lastscanned.com/lookup/canadapost
- Carrier hub: All 31 supported carriers
- Regex & check digits: Tracking number formats & auto-detection
- AI support workflows: WISMO AI agents & synchronous tracking
Intelcom (Dragonfly) Tracking API & MCP
Track Intelcom / Dragonfly (INTLCM 16-character Canadian and Australian last-mile packages) via synchronous REST GET or MCP. Normalized JSON status, scan history, dropoff notes, and tracking number format rules—no carrier credentials required.
Purolator Tracking API & MCP
Track Purolator Courier (3-letter + 9-digit PINs and 12-digit Canadian courier PINs) via synchronous REST GET or MCP. Normalized JSON status, scan history, provincial timezone normalization, and tracking number format rules—no carrier credentials required.