# DHL eCommerce Tracking API & MCP

URL: https://docs.lastscanned.com/carriers/dhlecommerce

Query live **DHL eCommerce** (`dhlecommerce`) package status and scan history in a single synchronous `GET` request or MCP tool call.

`dhlecommerce` covers DHL eCommerce parcels in the Americas. The same lookup also takes the USPS number of a parcel DHL hands to USPS for delivery, and returns DHL's scans followed by the USPS scans.

**Source**: Plain `POST https://api.dhlecs.com/webtrack/v4/tracking` (the JSON behind webtrack.dhlglobalmail.com), no key needed.

## Overview & Quick Facts

| Property | Value |
|---|---|
| **Carrier slug (`?carrier=`)** | `dhlecommerce` |
| **Brand aliases** | DHL eCommerce, DHL Global Mail, DHL SM Parcel, DHL Parcel Ground, DHL Parcel Expedited |
| **Category** | Regional (Americas) e-commerce parcels |
| **Single-package REST endpoint** | `GET https://api.lastscanned.com/v1/track/{trackingNumber}?carrier=dhlecommerce` |
| **Batch REST endpoint** | `GET https://api.lastscanned.com/v1/track?numbers=...,...&carrier=dhlecommerce` |
| **MCP server (`https://mcp.lastscanned.com`)** | `track_package`, `track_packages`, `list_carriers` |
| **Authentication & pricing** | `Authorization: Bearer lsk_live_...` · 1 free keyless lookup/day per IP |

## Tracking Number Formats & Auto-Detection

| Pass | Rule / Regex | Check Digit | Examples |
|---|---|---|---|
| **Pass 1 (`matches`)** | none | none | none |
| **Pass 2 (`mayMatch`)** | none | none | none |

DHL eCommerce numbers are not unmistakable: the 10-character customer reference (`123456789D`) has no check digit, and the USPS tracking numbers it also accepts (`92…`, `93…`, 22 digits, or 30 digits with a `420`+ZIP prefix) auto-detect to [USPS](/docs/carriers/usps). Pass `?carrier=dhlecommerce` for the first kind. A `420`+ZIP prefix is removed before the lookup.

## Synchronous `GET` Request & Normalized JSON Response

```bash
curl -s "https://api.lastscanned.com/v1/track/123456789D?carrier=dhlecommerce" \
  -H "Authorization: Bearer $LASTSCANNED_API_KEY"
```

```json
{
  "carrier": "dhlecommerce",
  "trackingNumber": "123456789D",
  "status": "delivered",
  "statusDescription": "Delivered: In/at mailbox",
  "service": "DHL Parcel Ground",
  "deliveredAt": "2026-08-03T14:10:00Z",
  "deliveredAtLocal": "2026-08-03T09:10:00",
  "signedBy": null,
  "destination": {
    "city": null,
    "state": null,
    "country": "US"
  },
  "message": "Handed to USPS as 9261290000000000000000",
  "events": [
    {
      "timestamp": "2026-08-03T14:10:00Z",
      "localTime": "2026-08-03T09:10:00",
      "status": "delivered",
      "description": "Delivered: In/at mailbox",
      "location": "Peoria, IL, US",
      "code": "600"
    },
    {
      "timestamp": "2026-08-03T11:10:00Z",
      "localTime": "2026-08-03T06:10:00",
      "status": "out_for_delivery",
      "description": "Out for delivery",
      "location": "Peoria, IL, US",
      "code": "598"
    },
    {
      "timestamp": "2026-08-01T15:52:17Z",
      "localTime": "2026-08-01T10:52:17",
      "status": "in_transit",
      "description": "Arrival destination DHL eCommerce facility",
      "location": "Melrose Park, IL, US",
      "code": "350"
    }
  ]
}
```

## Notes

- **USPS scans**: when the parcel rides USPS for the last mile, the answer already includes the USPS events (`Processed through USPS sort facility`, `Out for delivery`, `Delivered`), so no second lookup is needed. `message` names the USPS number (`Handed to USPS as …`) when you looked up the DHL reference rather than that number.
- **Time zone**: each scan carries a US zone (`ET`, `CT`, `MT`, `PT`) and `timestamp` is converted from it. Scans stamped `LT` (local time) have `localTime` only.

## Related Resources

- **Regex & check digits**: [Tracking number formats & auto-detection](/formats)
