Customs Guide

This guide will teach you how to pass the necessary customs information for shipping internationally. In this example, we will be sending a customer in the UK an EasyPost T-Shirt and hat from our office in the US.

When shipping internationally, you go through the same steps as shipping domestically, except that you need to add customs information to your shipment. EasyPost uses this information to automatically generate the necessary customs forms for your shipment. You need to pass customs information whenever you are shipping between two countries.

Before You Start

  1. Sign up for an EasyPost account.
  2. Grab one of our official client libraries.

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

Step 1: Creating Custom Items

When shipping internationally, carriers require that you add information about the contents of your package. This information is used by the customs process for the country to which you are shipping.

To add information about your package's contents, you need to create a CustomsItem object for each type of item you are shipping. If you have multiples of the same item in the package, you don't need to create a new CustomsItem for each. You just specify the number of items when creating the CustomsItem object.

When creating a CustomsItem you pass the following:

  • description = A brief description of the item
  • quantity = Number of that item contained in the package
  • weight = Total weight in ounces of all the items of that type in the package
  • value = Total value in US dollars of all the items of that type in the package
  • hs_tariff_number = The six digit code for your item as specified by harmonized system for tariffs. We talk a bit more about this below.
  • origin_country = Where the item was manufactured or assembled.

To get the "hs_tariff_number", you'll need to look up the harmonization code associated with whatever product you are shipping. You can search for them on hts.usitc.gov.

Here is an example where we create a CustomsItem object for the T-shirt we're shipping:

CustomsItems
curl -X POST https://api.easypost.com/v2/customs_items \
  -u "$EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
  "customs_item": {
    "description": "T-shirt",
    "quantity": "1",
    "weight": "5",
    "value": "10",
    "hs_tariff_number": "123456",
    "origin_country": "US"
  }
}'
CustomsItems JSON Response
{
  "id": "cstitem_...",
  "object": "CustomsItem",
  "description": "T-shirt",
  "quantity": 1,
  "value": 10,
  "weight": 5,
  "code": null,
  "hs_tariff_number": "123456",
  "origin_country": "US",
  "created_at": "2022-04-22T06:56:43Z",
  "updated_at": "2022-04-22T06:56:43Z"
}

Step 2: Create a Customs Info Form

Once you've created the CustomsItem objects for the items you are shipping, you next need to associate them with the customs form that you will be adding to your shipment. We call this form the CustomsInfo object. You will need only one CustomsInfo object per shipment.

The Customsinfo object contains a bunch of attributes that are very specific to shipping goods across borders. Below we'll do our best to explain each though it can be a bit confusing. If you ever have any specific questions, don't hesitate to email us at support@easypost.com.

When creating a CustomsInfo object you need to pass:

  • customs_items = An array of CustomsItem objects. This array should contain any items you are shipping in your package.
  • contents_type = The type of item you are sending. You pass one of the following: 'merchandise', 'returned_goods', 'documents', 'gift', 'sample', 'other'.
  • contents_explanation = If you specify 'other' in the 'contents_type' attribute, you must supply a brief description in this attribute.
  • restriction_type = Describes if your shipment requires any special treatment / quarantine when entering the country. You pass one of the following: 'none', 'other', 'quarantine', 'sanitary_phytosanitary_inspection'.
  • restriction_comments = If the "restriction_type" attribute is not "none", you must supply a brief description of what is required.
  • customs_certify = This is a boolean value (true, false) that takes the place of the signature on the physical customs form. This is how you indicate that the information you have provided is accurate.
  • customs_signer = This is the name of the person who is certifying that the information provided on the customs form is accurate. Use a name of the person in your organization who is responsible for this.
  • non_delivery_option = In case the shipment cannot be delivered, this option tells the carrier what you want to happen to the package. You can pass either: 'abandon', 'return'. The value defaults to 'return'. If you pass 'abandon', you will not receive the package back if it cannot be delivered.
  • eel_pfc = When shipping outside the US, you need to provide either an Exemption and Exclusion Legend (EEL) code or a Proof of Filing Citation (PFC). Which you need is based on the value of the goods being shipped.

The trickiest part of creating the CustomsInfo object is figuring out the values for the attributes. Once you've done that, it's simply a matter of passing those values to us. Here's an example of creating the CustomsInfo object for our shipment of T-shirt and Hat to the UK:

CustomsInfo (Customs Form)
curl -X POST https://api.easypost.com/v2/customs_infos \
  -u "$EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
  "customs_info": {
    "customs_certify": "true",
    "customs_signer": "Steve Brule",
    "contents_type": "merchandise",
    "contents_explanation": "",
    "restriction_type": "none",
    "eel_pfc": "NOEEI 30.37(a)",
    "customs_items": [
      {
        "description": "T-shirt",
        "quantity": "1",
        "weight": "5",
        "value": "10",
        "hs_tariff_number": "123456",
        "origin_country": "US"
      }
    ]
  }
}'
CustomsInfo JSON Response
{
  "id": "cstinfo_...",
  "object": "CustomsInfo",
  "contents_explanation": null,
  "contents_type": "gift",
  "customs_certify": true,
  "customs_signer": "Steve Brule",
  "eel_pfc": "NOEEI 30.37(a)",
  "non_delivery_option": null,
  "restriction_comments": null,
  "restriction_type": null,
  "customs_items": [
    {
      "id": "cstitem_...",
      "object": "CustomsItem",
      "description": "T-shirt",
      "quantity": 1,
      "value": 10,
      "weight": 5,
      "hs_tariff_number": "123456",
      "origin_country": "US",
      "created_at": "2022-07-22T01:53:42Z",
      "updated_at": "2022-07-22T01:53:42Z"
    }
  ],
  "created_at": "2022-07-22T01:56:54Z",
  "updated_at": "2022-07-22T01:56:54Z"
}

Step 3: Create Shipment and Attach Customs Info

Now that you've created the required customs information, you can now create your international shipment. The only difference from a domestic shipment is that you need to also pass the CustomsInfo object when creating a shipment.

When you buy a shipping label for your shipment, we automatically create additional customs forms that you need. Most often, the customs form is integrated into the label and you can put it directly on your package. If you ever have any questions about a specific carrier, don't hesitate to email us.

Example Customs Label

Here's an example where we are creating an international shipment:

Create International Shipment
curl -X POST https://api.easypost.com/v2/shipments \
  -u "$EASYPOST_API_KEY": \
  -H 'Content-Type: application/json' \
  -d '{
  "shipment": {
    "to_address": {
      "name": "Tim Canterbury",
      "company": "Wernham Hogg",
      "street1": "118 Clippenham Lane",
      "city": "Slough",
      "zip": "SL15BE",
      "country": "GB"
    },
    "from_address": {
      "company": "EasyPost",
      "street1": "5th Floor",
      "city": "San Francisco",
      "state": "CA",
      "zip": "94104",
      "country": "US",
      "phone": "415-528-7555"
    },
    "parcel": {
      "length": "9",
      "width": "6",
      "height": "3",
      "weight": "20"
    },
    "customs_info": {
      "id": "cstinfo_..."
    }
  }
}'
Buying an International Label
{
  "id": "shp_...",
  "object": "Shipment",
  "mode": "test",
  "to_address": {
    "id": "adr_...",
    "object": "Address",
    "name": "Tim Canterbury",
    "company": "Wernham Hogg",
    "street1": "1118 Clippenham Lane",
    "street2": "",
    "city": "Slough",
    "state": "",
    "zip": "SL15BE",
    "country": "GB",
    "phone": null,
    "email": null,
    "created_at": "2022-07-22T01:54:53Z",
    "updated_at": "2022-07-22T01:54:53Z"
  },
  "from_address": {
    "id": "adr_...",
    "object": "Address",
    "name": "",
    "company": "EasyPost",
    "street1": "417 Montgomery Street",
    "street2": "5th Floor",
    "city": "San Francisco",
    "state": "CA",
    "zip": "94104",
    "country": "US",
    "phone": "4155287555",
    "email": null,
    "created_at": "2022-07-22T01:54:53Z",
    "updated_at": "2022-07-22T01:54:53Z"
  },
  "parcel": {
    "id": "prcl_...",
    "object": "Parcel",
    "length": 9,
    "width": 6,
    "height": 3,
    "predefined_package": null,
    "weight": 20,
    "created_at": "2022-07-22T01:54:53Z",
    "updated_at": "2022-07-22T01:54:53Z"
  },
  "customs_info": {
    "id": "cstinfo_...",
    "object": "CustomsInfo",
    "contents_explanation": null,
    "contents_type": "gift",
    "customs_certify": true,
    "customs_signer": "Tim Canterbury",
    "eel_pfc": "NOEEI 30.37(a)",
    "non_delivery_option": null,
    "restriction_comments": null,
    "restriction_type": null,
    "created_at": "2014-07-22T01:56:54Z",
    "updated_at": "2014-07-22T01:56:54Z",
    "customs_items": [
      {
        "id": "cstitem_...",
        "object": "CustomsItem",
        "description": "T-shirt",
        "quantity": 1,
        "value": 11,
        "weight": 6,
        "hs_tariff_number": "610910",
        "origin_country": "US",
        "created_at": "2022-07-22T01:53:42Z",
        "updated_at": "2022-07-22T01:53:42Z"
      },
      {
        "id": "cstitem_...",
        "object": "CustomsItem",
        "description": "Hat",
        "hs_tariff_number": "650400",
        "origin_country": "US",
        "quantity": 1,
        "value": 20,
        "weight": 14,
        "created_at": "2022-07-22T01:53:51Z",
        "updated_at": "2022-07-22T01:53:51Z"
      }
    ]
  },
  "rates": [],
  "scan_form": null,
  "selected_rate": null,
  "postage_label": null,
  "tracking_code": null,
  "refund_status": null,
  "insurance": null,
  "created_at": "2022-07-22T01:54:53Z",
  "updated_at": "2022-07-22T01:54:53Z"
}

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