# Migrating from 17TRACK API to lastscanned

URL: https://docs.lastscanned.com/migrate-from-17track

If your engineering team is migrating off **17TRACK Tracking API v2.2 / v2.4** due to the **January 7, 2026 free-tier termination**, the **April 1, 2026 USPS Mailer ID (`mid`) enforcement**, or the **10× quota multiplier on `getRealTimeTrackInfo`**, you can switch to `lastscanned` in under 15 minutes.

## Why Developers Are Leaving 17TRACK in 2026

1. **Free Tier Terminated (Jan 7, 2026)**: 17TRACK ended its recurring 100/month free API quota, replacing it with a one-time 200-number trial that never renews. `lastscanned` provides a permanent free tier (**10 unique tracking numbers/month**, resetting monthly) plus **$10/mo Pro (1,500 numbers + unlimited free re-polls)** and **$5 non-expiring credit packs**.
2. **Async `register` Queue & `-18019902` ("Tracking number is not registered yet")**: Calling 17TRACK's `gettrackinfo` on an unregistered barcode fails with `-18019902`. You must first `POST /register` and wait for an async webhook crawl. `lastscanned` returns live carrier events **synchronously on the very first `GET /v1/track/{number}` call**.
3. **10× Quota Penalty & Blocked Carriers on `getRealTimeTrackInfo`**: 17TRACK's synchronous `getRealTimeTrackInfo` endpoint deducts **10 tracking quotas per call** and explicitly **blocks USPS (`21051`), DHL eCommerce US (`7047`), Royal Mail (`11031`), and Australia Post (`1151`)**. On `lastscanned`, every synchronous call—including USPS, DHL, Royal Mail, and Australia Post—costs **1 quota per unique tracking number per billing period** (and re-polling the same number on Pro is **free**).
4. **April 1, 2026 USPS Mailer ID (`mid`) Gate & `-18010020` Extra Parameter Errors**: Across 150 carriers, 17TRACK rejects lookups with `-18010020` (*"Submitted additional parameters are incorrect"*) unless you pass `destination_country`, `postal_code`, `phone`, or—since April 1, 2026 for USPS (`21051`)—the shipper's **6-digit USPS Mailer ID (`mid`)**. `lastscanned` requires **only the tracking number**.

## Side-by-Side API Migration

### Before: 17TRACK (2-Step Async or 10-Quota Real-Time + Extra Parameters)

```bash
# Step 1: Register and pay 1 quota (or pay 10 quotas on /getRealTimeTrackInfo, which blocks USPS 21051)
curl -X POST https://api.17track.net/track/v2.2/register \
  -H "17token: YOUR_17TRACK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[{"number": "9400111899223456789012", "carrier": 21051, "param": "123456"}]'

# Step 2: Poll /gettrackinfo later (returns -18019902 until async crawl finishes)
```

### After: `lastscanned` (1 Synchronous `GET`, 1 Quota, Zero Extra Params)

```bash
curl "https://api.lastscanned.com/v1/track/9400111899223456789012" \
  -H "Authorization: Bearer lsk_live_YOUR_API_KEY"
```

## Status Enum Mapping (`17TRACK latest_status.status` → `lastscanned status`)

| 17TRACK `latest_status.status` | `lastscanned` `status` | Notes |
| --- | --- | --- |
| `InfoReceived` | `pre_shipment` | Label created; carrier awaiting physical parcel |
| `InTransit` | `in_transit` | Active transit, sort facility scan, or customs clearance |
| `OutForDelivery` | `out_for_delivery` | On vehicle for delivery today |
| `Delivered` | `delivered` | Terminal delivery scan |
| `AvailableForPickup` / `DeliveryFailure` / `Exception` | `exception` | Action required, held for pickup, customs hold, or delay |
| `Expired` | `expired` | Carrier aged out tracking history |
| `NotFound` | `unknown` | No tracking data returned by carrier |

## Replacing 17TRACK's `externalcall.js` (`window.YQV5`) Frontend Widget

If your storefront or help center embeds 17TRACK's legacy `//www.17track.net/externalcall.js` (`window.YQV5.trackSingle`), swap the script URL to `https://lastscanned.com/embed.js`. Our built-in `window.YQV5` compatibility shim renders an ad-free `lastscanned` lookup widget inside your existing `#YQContainer` element automatically. Configure yours in the [Tracking Widget Generator](https://lastscanned.com/tools/tracking-widget-generator).
