USPS pricing changes effective January 2024. See details

Getting Started

This guide will walk you through shipping your first package with EasyPost. In this example, we'll be shipping an EasyPost T-Shirt from EasyPost HQ to a customer.

Before You Start

  1. Sign up for an EasyPost account. Use your Test Key where the guide requires <YOUR_TEST/PRODUCTION_API_KEY>. Switch to your Production key when you're ready to buy real postage.

    Manage API Keys

  2. Enter your carrier specific credentials on the Carrier Account Dashboard.

  3. Download an EasyPost Client Library in one following languages: Python, Ruby, PHP, Java, Node.js and C#(.NET). We also have community-supported client libraries like Perl and iOS on our Integrations page. If you prefer, you can always interact directly the REST API with cURL.
  4. Read the EasyPost Objects section of the docs. You'll need to know these few details to understand some of the code samples, and how to optimize your application.

Step 1: Create To and From Addresses

To start, create the To and From Addresses for the package you'll be shipping. An Address object contains information you'd expect like name, street, city, state, country, etc. You need to create an Address object for both the To and the From Addresses.

Once you create an Address, EasyPost returns a unique ID for the Address. You can reuse this ID in the future for other packages you ship. This is helpful for when you are sending a lot of packages from a single location. For every type of object you create on EasyPost, we will pass you back a unique ID that you can use to reference in the future.

From Address
curl -X POST https://api.easypost.com/v2/addresses \
  -u "$EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
  "address": {
    "company": "EasyPost",
    "street1": "417 Montgomery Street",
    "street2": "5th Floor",
    "city": "San Francisco",
    "state": "CA",
    "zip": "94104",
    "phone": "415-528-7555"
  }
}'
From Address Response
{
  "id": "adr_...",
  "object": "Address",
  "created_at": "2014-07-10T01:05:57Z",
  "updated_at": "2014-07-10T01:05:57Z",
  "name": null,
  "company": "EasyPost",
  "street1": "417 Montgomery Street",
  "street2": "5th Floor",
  "city": "San Francisco",
  "state": "CA",
  "zip": "94104",
  "country": "US",
  "phone": "4155287555",
  "email": null,
  "mode": "test",
  "carrier_facility": null,
  "residential": null,
  "federal_tax_id": null,
  "state_tax_id": null,
  "verifications": {}
}
To Address
curl -X POST https://api.easypost.com/v2/addresses \
  -u "$EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
  "address": {
    "name": "George Costanza",
    "company": "Vandelay Industries",
    "street1": "1 E 161st St.",
    "city": "Bronx",
    "state": "NY",
    "zip": "10451"
  }
}'
To Address Response
{
  "id": "adr_...",
  "object": "Address",
  "created_at": "2014-07-10T01:06:04Z",
  "updated_at": "2014-07-10T01:06:04Z",
  "name": "George Costanza",
  "company": "Vandelay Industries",
  "street1": "1 E 161st St.",
  "street2": null,
  "city": "Bronx",
  "state": "NY",
  "zip": "10451",
  "country": "US",
  "phone": null,
  "email": null,
  "mode": "test",
  "carrier_facility": null,
  "residential": null,
  "federal_tax_id": null,
  "state_tax_id": null,
  "verifications": {}
}

Step 2: Create a Parcel

Next, you'll need to tell us about the package you're shipping. You do this by creating a Parcel object. A Parcel contains information about the weight and dimensions (length, width, and height) of a package. Weights are in ounces and dimensions are in inches. In this example, because it's a t-shirt, it's a pretty small and light package. When you create a Parcel, EasyPost will give you a unique ID that you can use to reference it after the fact.

We also have common carrier-specific packaging as predefined constants you can use. If you're using this for your packaging, you don't need to pass the dimensions, just the weight. You do this by passing the constant in the "predefined_package" parameter and we take care of the rest. Here's the full list of predefined packages we support.

Parcel
curl -X POST https://api.easypost.com/v2/parcels \
  -u "$EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
  "parcel": {
    "length": "9",
    "width": "6",
    "height": "2",
    "weight": "10"
  }
}'
Parcel Response
{
  "id": "prcl_...",
  "object": "Parcel",
  "length": 9.0,
  "width": 6.0,
  "height": 2.0,
  "predefined_package": null,
  "weight": 10.0,
  "created_at": "2014-07-10T01:06:14Z",
  "updated_at": "2014-07-10T01:06:14Z"
}
Predefined Parcel
curl -X POST https://api.easypost.com/v2/parcels \
  -u "$EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
  "parcel": {
    "predefined_package": "FlatRateEnvelope",
    "weight": "10"
  }
}'
Predefined Parcel Response
{
  "id": "prcl_...",
  "object": "Parcel",
  "length": null,
  "width": null,
  "height": null,
  "predefined_package": "FlatRateEnvelope",
  "weight": 10.0,
  "created_at": "2014-07-10T01:06:24Z",
  "updated_at": "2014-07-10T01:06:24Z"
}

Step 3: Create a Shipment and Get Rates

Now that you have created To and From Addresses and a Parcel, you can combine them all by creating a Shipment. When you create a Shipment, the API responds with shipping rates for the all carriers you've enabled. These are the rates for shipping the Parcel between the To and From Addresses you've specified.

To create a Shipment, pass us the IDs of the To and From Addresses and Parcel that you created in the previous steps. If creation is successful, we'll return a set of rates back to you. An individual rate contains information about the carrier, the service level (eg 1 day, 2 day, Ground, etc), cost, and the estimated number of days to delivery (when available). In our example, we'll keep it simple and just use USPS as the carrier.

Create Shipment
curl -X POST https://api.easypost.com/v2/shipments \
  -u "$EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
  "shipment": {
    "to_address": {
      "id": "adr_..."
    },
    "from_address": {
      "id": "adr_..."
    },
    "parcel": {
      "id": "prcl_..."
    }
  }
}'
Printing Results
{
  "rates": [
    {
      "id": "rate_...",
      "object": "Rate",
      "created_at": "2014-07-10T01:06:46Z",
      "updated_at": "2014-07-10T01:06:46Z",
      "service": "First",
      "rate": "2.93",
      "currency": "USD",
      "est_delivery_days": 0,
      "carrier": "USPS",
      "shipment_id": "shp_..."
    },
    {
      "id": "rate_...",
      "object": "Rate",
      "created_at": "2014-07-10T01:06:46Z",
      "updated_at": "2014-07-10T01:06:46Z",
      "service": "Priority",
      "rate": "6.51",
      "currency": "USD",
      "est_delivery_days": null,
      "carrier": "USPS",
      "shipment_id": "shp_..."
    }
  ]
}

Step 4: Buy and Generate a Shipping Label

You're almost done. Now you're ready to buy the label so you can print it out and put it on your package. To do this, you need to tell us which rate you want to use. If you are using a client library, just call the buy method on the shipment and pass the ID of the rate you want to use. If using the REST API, then POST the rate ID to the shipment resource. We have examples of both below. We also have convenience functions built into the client libraries so you buy the lowest rate every time if that's easier for you.

Once you buy the label, we'll respond with a url to the image of your label that you can download and print. The url can be found on a Shipment's postage_label.label_url property (this property's name may be different if you requeset a specific label type).

By default, labels are returned in .PNG format but you can also request labels in other formats.

In the response, you'll also notice that we pass back the tracking ID for your package. You can use this to store on your side or pass to your customers. EasyPost supports sending automatic tracking updates to your app with webhooks. We'll teach you a bit more about tracking in the next tutorial.

Buy Shipment
curl -X POST https://api.easypost.com/v2/shipments/shp_.../buy \
  -u "$EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
  "rate": {
    "id": "rate_..."
  }
}'
Printing Results
{
  "postage_label": {
    "id": "pl_...",
    "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_...",
    "object": "Tracker"
  }
}

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