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 Though some codes may be longer, you only need to pass us the first six digits of the code. Also, remove any “.” in the harmonization code before sending to us. In our case, the harmonization code for a cotton T-shirt is “6109.10.00”, so we’ll just pass “610910” as the “hs_tariff_number”.

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

customs_item1 = EasyPost::CustomsItem.create(
  description: 'T-shirt',
  quantity: 1,
  value: 11,
  weight: 6,
  hs_tariff_number: '610910',
  origin_country: 'US',

CustomsItems JSON Response
  "id": "cstitem_KutRe43q",
  "object": "CustomsItem",
  "description": "T-shirt",
  "quantity": 1,
  "value": 11,
  "weight": 6,
  "hs_tariff_number": "610910",
  "origin_country": "US",
  "created_at": "2014-07-22T01:53:42Z",
  "updated_at": "2014-07-22T01:53:42Z"

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 we 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

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 you specify ‘other’ in the “restriction_type attribute”, 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.

    • If the value of the goods is less than $2,500, then you pass the following EEL code: "NOEEI 30.37(a)"
    • If the value of the goods is greater than $2,500, you need to get an Automated Export System (AES) Internal Transaction Number (ITN) for your shipment. ITN will look like “AES X20120502123456”. To get an ITN, go to the AESDirect website.
    • An ITN is required for any international shipment valued over $2,500 and/or requires an export license unless exemptions apply.

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)
customs_info = EasyPost::CustomsInfo.create(
  eel_pfc: 'NOEEI 30.37(a)',
  customs_certify: true,
  customs_signer: 'Jarrett Streebin',
  contents_type: 'gift',
  customs_items: [customs_item1, customs_item2]

CustomsInfo JSON Response
  "id": "cstinfo_uNYte45w",
  "object": "CustomsInfo",
  "contents_explanation": null,
  "contents_type": "gift",
  "customs_certify": true,
  "customs_signer": "Jarrett Streebin",
  "eel_pfc": "NOEEI 30.37(a)",
  "non_delivery_option": null,
  "restriction_comments": null,
  "restriction_type": null,
  "customs_items": [{
    "id": "cstitem_KutRe43q",
    "object": "CustomsItem",
    "description": "T-shirt",
    "quantity": 1,
    "value": 11,
    "weight": 6,
    "hs_tariff_number": "610910",
    "origin_country": "US",
    "created_at": "2014-07-22T01:53:42Z",
    "updated_at": "2014-07-22T01:53:42Z"
  }, {
    "id": "cstitem_PoIheWE2",
    "object": "CustomsItem",
    "description": "Hat",
    "hs_tariff_number": "650400",
    "origin_country": "US",
    "quantity": 1,
    "value": 20,
    "weight": 14,
    "created_at": "2014-07-22T01:53:51Z",
    "updated_at": "2014-07-22T01:53:51Z"
  "created_at": "2014-07-22T01:56:54Z",
  "updated_at": "2014-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
shipment = EasyPost::Shipment.create(
  to_address: {
    name: 'Tim Canterbury',
    company: 'Wernham Hogg',
    street1: '118 Clippenham Lane',
    city: 'Slough',
    zip: 'SL15BE',
    country: 'GB',
  from_address: {
    name: 'EasyPost',
    street1: '417 Montgomery Street',
    street2: '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: customs_info

Buying an International Label
  rate: shipment.lowest_rate(carriers = ['USPS'], services = ['First'])

##OR {id: '{RATE_ID}'})

## Print PNG link
puts shipment.postage_label.label_url

## Print Tracking Code
puts shipment.postage_label.tracking_code


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