Tracking Guide

This guide will teach you the two ways to track packages with EasyPost.

There's two methods of tracking packages with EasyPost:

  • Provide your existing tracking number and carrier.
  • Purchase the shipping label with EasyPost, which includes a free Tracker.

Our tracking service uses webhooks to give you updates about your shipments. Refer to our webhooks guide to learn how we use webhooks to send you tracking updates.

Before You Start

  1. Sign up for an EasyPost account or log in to an existing account.
  2. Setup your webhook URLs for Test Mode and Production Mode.
  3. Grab one of our official client libraries.
  4. Choose the "Step 1" that is applicable to you:

If you haven't run through our Getting Started Guide, definitely do that before moving on to this one.

Step 1: Create a Tracker using your tracking code & carrier

To track a shipment not created with EasyPost, you simply need to create a Tracker Object. You need to pass the “tracking_code" and “carrier” to the API. The “carrier” attribute is optional, though it is best to pass it if you have it available. When the “carrier” attribute is not passed, we will auto-detect the carrier for you. If we are unable to match the tracking code to a specific carrier, we will return an error.

Here is an example of how to make a tracker object:

Creating a Tracker
      
curl -X POST https://api.easypost.com/v2/trackers \
  -u <YOUR_TEST/PRODUCTION_API_KEY>: \
  -d 'tracker[tracking_code]=EZ4000000004' \
  -d 'tracker[carrier]=UPS'

      
    
JSON from Response
{
  "id": "trk_Txyy1vaM",
  "object": "Tracker",
  "mode": "test",
  "tracking_code": "EZ4000000004",
  "status": "delivered",
  "created_at": "2014-11-18T10:51:54Z",
  "updated_at": "2014-11-19T10:51:54Z",
  "signed_by": "John Tester",
  "weight": 17.6,
  "est_delivery_date": "2014-11-27T00:00:00Z",
  "shipment_id": null,
  "carrier": "UPS",
  "public_url": "https://track.easypost.com/ajE7...",
  "tracking_details": [
    {
      "object": "TrackingDetail",
      "message": "BILLING INFORMATION RECEIVED",
      "status": "pre_transit",
      "datetime": "2014-11-21T14:24:00Z",
      "tracking_location": {
        "object": "TrackingLocation",
        "city": null,
        "state": null,
        "country": null,
        "zip": null
      }
    }
  ]
}

After a Tracker is created, we will periodically check the status of your package and notify you when its status changes. Jump to Step 2 to learn how we'll give you updates via webhooks.

Step 1: Purchase a Shipping Label and Tracking Code

To start tracking a package, there is nothing extra you need to do. Whenever you purchase a shipping label with EasyPost, we’ll start automatically tracking its progress and notifying you of any updates via webhooks (more on that in step 2).

When you purchase a shipping label, we will also respond back with the tracking number for the label. You don’t need to store the tracking number to get tracking updates but it is generally good practice to store it. Here’s an example of purchasing a shipping label and getting a tracking number. To see all the steps for shipping a package, take a look at our Getting Started Guide.

Buying Shipment
      
curl -X POST https://api.easypost.com/v2/shipments/{SHIPMENT ID}/buy \
  -u <YOUR_TEST/PRODUCTION_API_KEY>: \
  -d 'rate[id]={RATE ID}'

      
    
Using Results
      
{
  "postage_label":{
    "id": "pl_UYD34S2R",
    "object":"PostageLabel",
    "created_at":"2014-07-19T01:19:31Z",
    "updated_at":"2014-07-19T01:19:31Z",
    "integrated_form":"none",
    "label_date":"2014-07-19T01:19:31Z",
    "label_resolution":300,
    "label_size":"4x6",
    "label_type":"default",
    "label_file_type": "image/png",
    "label_url": "https://amazonaws.com/.../a1b2c3.png",
    "label_pdf_url": null,
    "label_epl2_url": null,
    "label_zpl_url": null,
  },
  "tracking_code":"9499907123456123456781",
  "insurance":null,
  "selected_rate":{
    "id":"{RATE ID}",
    "object":"Rate",
    "created_at":"2014-07-19T01:19:11Z",
    "updated_at":"2014-07-19T01:19:11Z",
    "service":"First",
    "rate":"2.25",
    "currency":"USD",
    "carrier":"USPS",
    "shipment_id":"{SHIPMENT ID}"
  },
  "tracker":{
    "id": "trk_Txyy1vaM",
    "object": "Tracker",
    ...
  }
}

      
    

Step 2: Process Tracking Event Webhooks

After you purchase a shipping label or create a tracker, we will automatically start sending tracking update Events. Event Objects are sent to the webhook URLs you’ve configured. Updates will only be sent when there is a status change for the package (e.g. a package changes from "Out for Delivery" to "Delivered"). We check the status of each package more frequently once it is Out for Delivery.

The Tracker Object statuses are listed in our API Documentation.

When you purchase a label in either Test or Production mode, you will immediately get a tracking event after purchase. Test and Production mode behave slightly differently:

  • In Test Mode, you will get only one tracking event in one of the supported statuses (e.g. "in_transit", "delivered", etc.). After this update, you receive no more events in Test mode.
  • In Production Mode, you will get your first of multiple tracking events for your package. The first tracking event is status "unknown". The package stays in "unknown" until it is scanned by the carrier.

You’ll know it is a tracking update event because the object "type" is "Event" and the "description" is "tracker.updated". The "result" value of Event will also contain a Tracker object that has the information about the current progress of the package. When building application logic, the “status” of Tracker object is most useful and reliable to use.

The Tracker object also contains additional information from the carrier in “tracking_details” attribute. For example, along with “in_transit” updates you may receive information that it reached a particular location (eg “Processed through Sort Facility June 01 2013 4:53 pm BELL GARDENS CA 9020”). The “tracking_details” will be an array containing both details about the current status and all previous statuses. The oldest status is the first element of the array and we append newer statuses as they come in. Order is not perfectly reliable as carrier data is occasionally incorrect. We recommend using the “status” on the Tracker object for any key business logic.

Here’s an example of a tracking event webhook:

{
  "id": "evt_qatAiJDM",
  "object": "Event",
  "created_at": "2014-11-19T10:51:54Z",
  "updated_at": "2014-11-19T10:51:54Z",
  "description": "tracker.updated",
  "mode": "test",
  "previous_attributes": {
    "status": "unknown"
  },
  "pending_urls": [],
  "completed_urls": [],
  "result": {
    "id": "trk_Txyy1vaM",
    "object": "Tracker",
    "mode": "test",
    "tracking_code": "EZ4000000004",
    "status": "delivered",
    "created_at": "2014-11-18T10:51:54Z",
    "updated_at": "2014-11-19T10:51:54Z",
    "signed_by": "John Tester",
    "weight": 17.6,
    "est_delivery_date": "2014-11-27T00:00:00Z",
    "shipment_id": null,
    "carrier": "UPS",
    "public_url": "https://track.easypost.com/djE7...",
    "tracking_details": [
      {
        "object": "TrackingDetail",
        "message": "BILLING INFORMATION RECEIVED",
        "status": "pre_transit",
        "datetime": "2014-11-21T14:24:00Z",
        "tracking_location": {
          "object": "TrackingLocation",
          "city": null,
          "state": null,
          "country": null,
          "zip": null
        }
      },
      {
        "object": "TrackingDetail",
        "message": "ORIGIN SCAN",
        "status": "in_transit",
        "datetime": "2014-11-21T14:48:00Z",
        "tracking_location": {
          "object": "TrackingLocation",
          "city": "SOUTH SAN FRANCISCO",
          "state": "CA",
          "country": "US",
          "zip": null
        }
      },
      {
        "object": "TrackingDetail",
        "message": "DEPARTURE SCAN",
        "status": "in_transit",
        "datetime": "2014-11-22T08:51:00Z",
        "tracking_location": {
          "object": "TrackingLocation",
          "city": "SOUTH SAN FRANCISCO",
          "state": "CA",
          "country": "US",
          "zip": null
        }
      },
      {
        "object": "TrackingDetail",
        "message": "ARRIVAL SCAN",
        "status": "in_transit",
        "datetime": "2014-11-23T09:31:00Z",
        "tracking_location": {
          "object": "TrackingLocation",
          "city": "SAN FRANCISCO",
          "state": "CA",
          "country": "US",
          "zip": null
        }
      },
      {
        "object": "TrackingDetail",
        "message": "OUT FOR DELIVERY",
        "status": "out_for_delivery",
        "datetime": "2014-11-24T08:10:00Z",
        "tracking_location": {
          "object": "TrackingLocation",
          "city": "SAN FRANCISCO",
          "state": "CA",
          "country": "US",
          "zip": null
        }
      },
      {
        "object": "TrackingDetail",
        "message": "DELIVERED",
        "status": "delivered",
        "datetime": "2014-11-19T10:51:54Z",
        "tracking_location": {
          "object": "TrackingLocation",
          "city": "SAN FRANCISCO",
          "state": "CA",
          "country": "US",
          "zip": null
        }
      }
    ]
  }
}

Step 3: Engage With Your Customers

Once you're receiving webhooks, there's a lot of ways for you to re-engage with your customers. Here's a few ideas that some of our customers use:

EasyPost Tracking Page
  • Provide a link to our public tracking page where your customers can check on their delivery progress at their leisure. Just send them the track.easypost.com URL found on the public_url field of a Tracker Object.
  • Send emails when key tracking events take place (Out for Delivery, Delivered). Our Email Tracking Notifications Tutorial will help you get started by taking you through a SendGrid integration.
  • Send SMS when key tracking events take place. The SMS Tracking Notifications Tutorial will give you an example that leverages Twilio.

Congratulations! You’ve just tracked your first package with EasyPost! Check out our Full Reference API Documentation.