Carriers

Cirro E-Commerce Tracking API & MCP

Query live Cirro E-Commerce (cirro) package status and scan history in a single synchronous GET request or MCP tool call. lastscanned auto-detects 14-character CR… and 17-character CIFR… tracking numbers and returns a normalized TrackingResult JSON payload—without requiring Cirro shipper credentials, HMAC-SHA256 request signing, or webhook infrastructure.

Overview & Quick Facts

PropertyValue
Carrier slug (?carrier=)cirro
Brand & service aliasesCIRRO E-Commerce, CIRRO Parcel, GOFO Express (acquired CIRRO E-Commerce in 2026)
CategoryCross-border & US e-commerce parcel carrier (Detection precedence #14 of 31)
Single-package REST endpointGET https://api.lastscanned.com/v1/track/{trackingNumber}
Batch REST endpointGET https://api.lastscanned.com/v1/track?numbers=CR...,CIFR... (up to 35 numbers per carrier in a 100-number call)
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 Cirro E-Commerce

  • Skip Nebula HMAC-SHA256 signing & rate-limit CAPTCHAs: Direct calls to Cirro's tracking endpoint require computing an HMAC-SHA256 Nebula token: signature over Timestamp + NumberList and trigger CAPTCHA error codes (1003 / 1004) when polled repeatedly from a single backend IP. Calling GET https://api.lastscanned.com/v1/track/:number works cleanly in one fetch().
  • Unified Cirro + GOFO network coverage: Following GOFO Express's 2026 acquisition of Cirro E-Commerce, CR… and CIFR… parcels move seamlessly through GOFO's US last-mile hubs while preserving full origin-to-doorstep scan visibility.

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

Cirro is evaluated fourteenth (#14) in lastscanned's two-pass detector:

PassRule / RegexCheck DigitExamples
Pass 1 (matches) — CR prefix/^CR\d{12}$/i (CR + 12 digits = 14 chars)—CR010740141269, CR010928374650
Pass 1 (matches) — CIFR prefix/^CIFR\d{13}$/i (CIFR + 13 digits = 17 chars)—CIFR5358366457896
Pass 2 (mayMatch)None——

Disambiguating Cirro vs GOFO (?carrier=cirro)

  • Auto-detected (CR + 12 digits and CIFR + 13 digits): No ?carrier= parameter is needed.
  • When ?carrier=cirro is required: Shipper order numbers starting with SKP… (SKP919023354) or GFUS… numbers that you specifically want to inspect via Cirro's endpoint instead of gofo.

Synchronous GET Request & Normalized JSON Response

curl

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

JavaScript / TypeScript (fetch)

const res = await fetch("https://api.lastscanned.com/v1/track/CR010740141269", {
  headers: { Authorization: `Bearer ${process.env.LASTSCANNED_API_KEY}` },
});
const pkg = await res.json();
console.log(pkg.status, pkg.statusDescription, pkg.deliveredAt);

MCP track_package tool call

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

Normalized TrackingResult JSON response

{
  "carrier": "cirro",
  "trackingNumber": "CR010740141269",
  "status": "delivered",
  "statusDescription": "Your package has been delivered, Left at Front Door",
  "service": null,
  "deliveredAt": "2026-10-25T19:08:44Z",
  "deliveredAtLocal": "2026-10-25T15:08:44",
  "signedBy": "J. DOE",
  "destination": {
    "city": "PHILADELPHIA",
    "state": "PA",
    "country": "US"
  },
  "estimatedDelivery": null,
  "events": [
    {
      "timestamp": "2026-10-25T19:08:44Z",
      "localTime": "2026-10-25T15:08:44",
      "status": "delivered",
      "description": "Your package has been delivered, Left at Front Door",
      "location": "PHILADELPHIA, PA",
      "code": "Delivered"
    },
    {
      "timestamp": null,
      "localTime": "2026-10-25T08:19:10",
      "status": "out_for_delivery",
      "description": "Your package is out for delivery",
      "location": "PHILADELPHIA, PA",
      "code": "Transit"
    },
    {
      "timestamp": null,
      "localTime": "2026-10-24T22:41:05",
      "status": "in_transit",
      "description": "Arrived at Sorting Center",
      "location": "CARLSTADT, NJ",
      "code": "Transit"
    },
    {
      "timestamp": null,
      "localTime": "2026-10-22T10:15:00",
      "status": "label_created",
      "description": "Shipment information received",
      "location": null,
      "code": "Processing"
    }
  ]
}

Raw status & scan codes: events[].code preserves Cirro's StatusCode ("Processing", "Transit", "Delivered", "Alert", "FailedAttempt", "Exception", "Return", "Returned"), while lastscanned also inspects the event description to promote "out for delivery" scans inside the "Transit" category to out_for_delivery.

Carrier-Specific Status & Integration Notes

  • Latest scan UTC (timestamp) vs historical localTime: Cirro provides an explicit GMT±HH:MM timezone (GmtProcessTimezone) only on the latest scan (LastTrackEvent), while historical rows in DetailList report local wall-clock time (ProcessTime) without a per-row offset. Therefore, events[0].timestamp (and deliveredAt) is populated in UTC, while earlier scans populate localTime with timestamp: null.
  • Up to 20 numbers per upstream batch: lastscanned automatically chunks larger Cirro batches so you can pass up to 35 Cirro numbers in a single GET /v1/track?numbers=... request.

On this page