# Package Tracking API: AfterShip Shipment Export (`nabeelbaghoor/package-tracking-api`) Actor

Export package and parcel tracking data from your AfterShip account across 1,100+ carriers: shipment status, checkpoints, delivery dates and ETAs, filtered by status, courier, country and date. Also courier lists, courier detection and AI delivery date estimates. Bring your own key.

- **URL**: https://apify.com/nabeelbaghoor/package-tracking-api.md
- **Developed by:** [Nabeel Hassan](https://apify.com/nabeelbaghoor) (community)
- **Categories:** E-commerce, Developer tools, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $8.00 / 1,000 tracking record returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Package Tracking API: AfterShip Shipment Export

Export the package and parcel tracking data in your own AfterShip account, across 1,100+ carriers, as one clean dataset row per shipment, courier or delivery estimate.

AfterShip is a shipment tracking platform that follows parcels across UPS, FedEx, USPS, DHL, Royal Mail, China Post and more than 1,100 other carriers and normalises every scan into one status model. This actor is a workflow and export tool on top of the documented AfterShip Tracking API (version 2026-07 on api.aftership.com): it pulls the trackings you already have, filtered by status, courier, country and date, flattens the latest checkpoint and delivery estimate into columns, and hands the rows to CSV, Excel, Google Sheets, BI dashboards, CRMs, webhooks or AI agents. Bring your own API key.

BYOK, not live tested: every route, parameter and field comes from AfterShip's own published SDKs for API version 2026-07, and the routes were probed on 2026-10-25 with an invalid key. The actor has not been run against a live AfterShip key.

### What it does

- **Get trackings (export)**: every shipment in your account with tracking number, courier, status and substatus, the full checkpoint history, origin and destination, order ID and number, pickup and delivery dates, on time status, returned to sender flag and the carrier, AfterShip AI and latest estimated delivery dates. Filter by status, courier, origin and destination country, created or updated date range, keyword, tracking numbers, order IDs, shipment tags, transit time and return to sender. Pages are followed automatically, 200 trackings per request.
- **Get tracking by ID**: one row per AfterShip tracking ID, with optional translation of checkpoint messages into 41 languages.
- **Get couriers**: the 1,100+ carriers AfterShip supports, or only the ones active on your account, with slug, name, website, phone, required tracking fields, languages and service countries.
- **Detect courier**: the likely carrier (slug and full courier record) for each tracking number, before you track it.
- **Estimated delivery date**: AfterShip's AI predicted delivery date, with earliest and latest date and a confidence code, for a carrier and route, one prediction per destination postal code.
- **Create trackings (opt-in)**: adds new tracking numbers to your AfterShip account so AfterShip starts following them. It runs only when you tick the confirm box, and every new tracking counts against your own AfterShip shipment quota.
- **Pay only for results**: refused, unknown and empty lookups are recorded as a free row that says why, never charged.

### How to use it

1. In the AfterShip admin open Settings, API keys (organization.automizely.com/api-keys) and create an API key.
2. Paste the key into the API key field (or set the DATA_API_KEY secret). It is sent only to AfterShip in the as-api-key header and is removed from everything the actor logs.
3. Pick a mode, set filters, and start the run. Download the rows as JSON, CSV or Excel, schedule the run for a daily sync with the Updated after filter, or call the actor from your own code.

A missing or rejected key, a plan that does not cover the chosen feature or an empty input ends the run cleanly with a status message that says what to change.

### Input

| Field | Modes | Description |
| --- | --- | --- |
| `mode` | all | `listTrackings` (default), `getTracking`, `listCouriers`, `detectCourier`, `predictDeliveryDate` or `createTrackings` |
| `trackingNumbers` | Get trackings, Detect courier, Create trackings | Tracking numbers, one per line |
| `trackingIds` | Get tracking by ID | AfterShip tracking IDs |
| `tags` | Get trackings | Status: Pending, InfoReceived, InTransit, OutForDelivery, AttemptFail, Delivered, AvailableForPickup, Exception, Expired |
| `slugs` | Get trackings, Get couriers, Detect courier | Courier codes such as ups, fedex, usps, dhl |
| `keyword` | Get trackings | Searches tracking number, title, order ID, customer and custom fields |
| `origins`, `destinations`, `courierDestinations` | Get trackings | ISO 3166-1 alpha-3 country codes such as USA or CHN |
| `createdAtMin`, `createdAtMax`, `updatedAtMin`, `updatedAtMax` | Get trackings | Dates such as 2026-10-01 or date and times |
| `shipmentTags`, `orderIds`, `returnToSender`, `transitTime` | Get trackings | Further documented filters |
| `lang` | Get tracking by ID | Translate checkpoint messages |
| `activeOnly` | Get couriers | Only the couriers active on your account |
| `courierSlug` | Estimated delivery date, Create trackings | One courier code |
| `confirmCreate` | Create trackings | Must be on for that mode to run |
| `originCountry`, `originState`, `originPostalCode`, `destinationCountry`, `destinationState`, `destinationPostalCodes`, `pickupTime`, `serviceTypeName` | Estimated delivery date | The route to predict |
| `maxResults` | all | Most rows to return and charge for |
| `requestsPerMinute` | all | Pacing for calls to AfterShip |
| `apiKey` | all | Your AfterShip API key (secret) |

### Output

Every row keeps every field AfterShip returns (including the `checkpoints` array), plus flat columns that are easy to filter: `trackingId`, `trackingNumber`, `courierSlug`, `courierName`, `status`, `subStatus`, `statusMessage`, `originCountry`, `destinationCountry`, `orderId`, `expectedDelivery`, `shipmentDeliveryDate`, `lastCheckpointTime`, `lastCheckpointMessage`, `lastCheckpointLocation` and `checkpointCount`. Detection rows add `matchedCount` and `matchedSlugs`; estimate rows add `estimatedDeliveryDate`, `estimatedDeliveryDateMin`, `estimatedDeliveryDateMax` and `confidenceCode`. A refused lookup has `found` set to false and a `note` with AfterShip's own words.

Example Get trackings row (shape from the AfterShip 2026-07 tracking model, values illustrative):

```json
{
    "mode": "listTrackings",
    "modeLabel": "Get trackings",
    "recordType": "tracking",
    "query": "1Z999AA10123456784",
    "found": true,
    "trackingId": "7f3a1c6c2e2b4c1e9a0d5b8f6e4c3a21",
    "trackingNumber": "1Z999AA10123456784",
    "courierSlug": "ups",
    "status": "InTransit",
    "subStatus": "InTransit_001",
    "statusMessage": "In Transit",
    "originCountry": "CHN",
    "destinationCountry": "USA",
    "orderId": "6845a095a27a4caeb27487806f058add",
    "expectedDelivery": "2026-10-28",
    "shipmentDeliveryDate": null,
    "lastCheckpointTime": "2026-10-24T09:12:00-07:00",
    "lastCheckpointMessage": "Arrived at Facility",
    "lastCheckpointLocation": "Louisville, KY, United States",
    "checkpointCount": 6,
    "active": true,
    "transit_time": 4,
    "return_to_sender": false,
    "courier_tracking_link": "https://www.ups.com/track?tracknum=1Z999AA10123456784",
    "latest_estimated_delivery": { "type": "specific", "source": "Carrier EDD", "datetime": "2026-10-28", "datetime_min": null, "datetime_max": null },
    "checkpoints": [
        { "checkpoint_time": "2026-10-24T09:12:00-07:00", "city": "Louisville", "state": "KY", "country_region": "USA", "message": "Arrived at Facility", "tag": "InTransit", "subtag": "InTransit_001", "slug": "ups" }
    ],
    "created_at": "2026-10-20T03:15:22+00:00",
    "updated_at": "2026-10-24T16:20:41+00:00",
    "retrievedAt": "2026-10-25T12:00:00.000Z",
    "note": null
}
```

### Pricing

| Event | Price | Charged for |
| --- | --- | --- |
| `tracking-record` | 0.008 USD | Each tracking read (Get trackings, Get tracking by ID) |
| `courier-record` | 0.005 USD | Each courier listed |
| `courier-detection` | 0.005 USD | Each tracking number matched to a courier |
| `delivery-estimate` | 0.01 USD | Each AI estimated delivery date |
| `tracking-created` | 0.01 USD | Each tracking added in the opt-in Create mode |

Refused, unknown, duplicate and empty lookups are never charged. Your AfterShip plan and shipment quota are billed separately by AfterShip.

### FAQ

#### What is the AfterShip Tracking API?

The AfterShip Tracking API is the REST API of AfterShip (Automizely Pte. Ltd.) for shipment tracking. It lets a merchant add tracking numbers, read normalised statuses and checkpoints across 1,100+ carriers, list and detect couriers and get AI estimated delivery dates, at api.aftership.com/tracking/2026-07 with an as-api-key header.

#### Do I need my own AfterShip API key?

Yes. This is a bring your own key actor: it calls AfterShip with your key, under your plan, its quotas and its terms. Create the key in the AfterShip admin under Settings, API keys.

#### Can this actor track any package number for me?

It reads the trackings already in your AfterShip account. To start following a new number, use the opt-in Create trackings mode (or add it in AfterShip); AfterShip then fetches carrier updates and the next Get trackings run exports them. Each new tracking uses your own AfterShip shipment quota.

#### How do I export all delivered or delayed shipments to CSV or Google Sheets?

Run Get trackings with Status set to Delivered, or to Exception and AttemptFail for problem shipments, add a created date range, then download the dataset as CSV or Excel or connect it to Google Sheets through an Apify integration.

#### How do I find which courier a tracking number belongs to?

Use Detect courier. AfterShip matches the number format against its couriers (optionally only the slugs you list) and the row carries `matchedSlugs` plus the full courier records, including any extra fields the carrier needs such as a postal code or ship date.

#### How far back can I export trackings?

AfterShip keeps trackings for 120 days, so created and updated date filters work inside that window. Schedule the actor daily with Updated after set to yesterday to keep a longer history in your own storage.

#### What does the estimated delivery date mode need?

A courier slug, origin and destination countries (ISO alpha-3), an origin state or postal code, a destination state or postal codes, and the local pickup time. The AI estimated delivery date is an AfterShip feature that must be active on your account; otherwise AfterShip refuses the request and the run ends with that message, uncharged.

#### What do I pay?

Pay per result: 0.008 USD per tracking, 0.005 USD per courier or courier detection, and 0.01 USD per delivery estimate or created tracking. Refused and empty lookups are free.

### Keyword map

package tracking API, parcel tracking API, shipment tracking API, AfterShip API, AfterShip tracking export, AfterShip to CSV, AfterShip to Google Sheets, multi carrier tracking, UPS FedEx USPS DHL tracking, tracking number lookup, courier detection API, carrier list API, delivery status export, estimated delivery date API, EDD prediction, order tracking data, ecommerce shipment analytics, delivery exception report.

### Routes probed and sources

Routes and fields were taken from AfterShip's own SDKs for API version 2026-07 (tracking-sdk-nodejs 17.0.0 and tracking-sdk-python), because aftership.com/docs blocks scripted readers. On 2026-10-25 every route was called with an invalid key: all answered AfterShip's 401 envelope "The API key is invalid", and so did invented paths, because AfterShip checks the key before the route. The API version is confirmed live: an invented version such as /tracking/2099-01 answers 404 before the key is read, while /tracking/2026-07 answers 401.

### Licensing and data use

This actor works only with your own AfterShip account and API key, and AfterShip's terms of service and developer terms apply to everything it returns. It is an export and workflow tool for your own shipment data: it does not resell AfterShip data or offer a replacement for the AfterShip API. Customer details in your trackings (names, emails, phone numbers) are your own customers' personal data; handle the exported rows accordingly. This actor is not affiliated with or endorsed by AfterShip.

# Actor input Schema

## `mode` (type: `string`):

Get trackings exports the shipments already in your AfterShip account, filtered by status, courier, country, date and more, with every checkpoint. Get tracking by ID reads single trackings. Get couriers lists the carriers AfterShip supports or the ones active on your account. Detect courier finds the carrier of a tracking number. Estimated delivery date asks the AfterShip AI for a delivery date on a route. Create trackings is opt-in: it adds new tracking numbers to your account and uses your AfterShip shipment quota.

## `trackingNumbers` (type: `array`):

Get trackings (optional filter, up to 50 per request, 1,000 per run), Detect courier and Create trackings. One tracking number per line, 4 to 100 characters.

## `trackingIds` (type: `array`):

Get tracking by ID only. One AfterShip tracking ID per line (the id field of a tracking row, not the tracking number).

## `tags` (type: `array`):

Get trackings only. Keep only shipments whose current status is one of these. Empty means every status.

## `slugs` (type: `array`):

Get trackings, Get couriers and Detect courier. AfterShip courier codes such as dhl, ups, usps or fedex, one per line. Filters the trackings and couriers returned; for Detect courier, limits detection to these couriers.

## `keyword` (type: `string`):

Get trackings only. Searches tracking_number, title, order_id, customer name, email and phone, and custom fields.

## `origins` (type: `array`):

Get trackings only. Origin country or region codes in ISO 3166-1 alpha-3, such as CHN, USA or GBR.

## `destinations` (type: `array`):

Get trackings only. Destination country or region codes in ISO 3166-1 alpha-3, such as USA, DEU or AUS.

## `courierDestinations` (type: `array`):

Get trackings only. Destination country codes (ISO 3166-1 alpha-3) as the carrier reports them.

## `createdAtMin` (type: `string`):

Get trackings only. A date such as 2026-10-01, or a date and time such as 2026-10-01T08:00:00Z. AfterShip keeps trackings for 120 days.

## `createdAtMax` (type: `string`):

Get trackings only. A date (end of that day, UTC) or a date and time.

## `updatedAtMin` (type: `string`):

Get trackings only. Useful for daily syncs: export only shipments that changed since a date or a date and time.

## `updatedAtMax` (type: `string`):

Get trackings only. A date (end of that day, UTC) or a date and time.

## `shipmentTags` (type: `array`):

Get trackings only. Your own shipment tags, one per line.

## `orderIds` (type: `array`):

Get trackings only. Order IDs from your store, one per line.

## `returnToSender` (type: `string`):

Get trackings only. Keep only shipments that are (or are not) being returned to the sender.

## `transitTime` (type: `integer`):

Get trackings only. Keep only shipments with exactly this many days in transit.

## `lang` (type: `string`):

Get tracking by ID only, optional. Translates checkpoint messages from the carrier language. Empty keeps the original language.

## `activeOnly` (type: `boolean`):

Get couriers only. On: the couriers you activated in AfterShip. Off: every courier AfterShip supports.

## `courierSlug` (type: `string`):

Estimated delivery date (required) and Create trackings (optional, empty means AfterShip auto detects). One AfterShip courier code such as ups or fedex.

## `confirmCreate` (type: `boolean`):

Create trackings only. Must be on for that mode to run. Each new tracking number is added to your AfterShip account and counts against your AfterShip shipment quota.

## `originCountry` (type: `string`):

Estimated delivery date only. ISO 3166-1 alpha-3 code of the place the carrier picks up from, such as USA.

## `originState` (type: `string`):

Estimated delivery date only. State or province of the origin, such as CA. Give this or the origin postal code.

## `originPostalCode` (type: `string`):

Estimated delivery date only. Postal code of the origin. Give this or the origin state.

## `destinationCountry` (type: `string`):

Estimated delivery date only. ISO 3166-1 alpha-3 code of the destination, such as USA.

## `destinationState` (type: `string`):

Estimated delivery date only. State or province of the destination. Give this or destination postal codes.

## `destinationPostalCodes` (type: `array`):

Estimated delivery date only. One prediction per postal code (up to 100 per run).

## `pickupTime` (type: `string`):

Estimated delivery date only. Local pickup date and time at the origin, such as 2026-11-02 15:00:00.

## `serviceTypeName` (type: `string`):

Estimated delivery date only, optional. The AfterShip service type code of the carrier service, as listed in the AfterShip docs.

## `maxResults` (type: `integer`):

The most rows this run returns and charges for.

## `requestsPerMinute` (type: `integer`):

Pacing for calls to AfterShip. The default AfterShip limit is 10 requests per second; throttled calls are retried after the reset time AfterShip sends.

## `apiKey` (type: `string`):

Your own AfterShip API key, from the AfterShip admin under Settings, API keys (organization.automizely.com/api-keys). Stored as a secret and sent only to AfterShip in the as-api-key header; it is never logged. You can instead set the DATA_API_KEY environment secret.

## Actor input object example

```json
{
  "mode": "listTrackings",
  "returnToSender": "any",
  "activeOnly": false,
  "confirmCreate": false,
  "maxResults": 100,
  "requestsPerMinute": 300
}
```

# Actor output Schema

## `records` (type: `string`):

One row per record the chosen mode returns.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("nabeelbaghoor/package-tracking-api").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("nabeelbaghoor/package-tracking-api").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call nabeelbaghoor/package-tracking-api --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nabeelbaghoor/package-tracking-api"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/8pcC9Kps5rufHI6rz/builds/wp3yP3eYlOsgz0lrf/openapi.json
