Setup
- Client Libraries
- First Shipment
- Authentication
- Test Mode
- Carrier Accounts
- Address Validation
- International Shipments
- Returns
- Track Shipments
Advanced
- Single Call Label Creation
- Multi-Piece Shipment
- Batch Label Creation
- Refunds
- Insurance
- Webhooks
- Manifests
- Shipping on Stripe
Platforms
References
Support
Create Your First Shipment
Get shipping rates and generate your first shipping label.
The Setup
Before you begin, you’ll need to:
- Grab your Test or Live Token from the API page of your Shippo dashboard. Learn more about Authentication.
- Install one of our client libraries, available in most major programming languages. If you prefer, you can also use cURL to interact directly with our REST API.
- By default, you have access to Shippo's discounted accounts for any U.S. outbound shipments with carriers such as USPS and DHL Express. After this tutorial, you can visit the carrier account tutorial if you'd like to add additional carriers.
High-Level Structure
To create a shipping label, you'll need to follow two simple steps:
- Create the Shipment Object, consisting of a sender address, a recipient address, and a parcel (blue objects below). The Shipment response will contain the list of available Rates.
- Create Transaction Object, i.e. the actual label, for any of the Rates from the Shipment response (green object below).

1. Create the Shipment Object
The purpose of the Shipment object is to retrieve rates. It represents a request to ship a given package between the sender and recipient addresses. You could create the Address and Parcel objects in separate API calls but we suggest creating the Address and Parcel objects inline as it will save you time and extra network calls.
For both Address objects make sure to send the following values: name, street1, city, state (only for US & CA), zip, country and email. All US and Australian addresses are automatically validated. For more information see our Address Validation Tutorial.
The Shipment object has additional properties (such as signature confirmation, 3rd party billing, COD, etc.) that you can find in our API reference.
curl https://api.goshippo.com/shipments/ \
-H "Authorization: ShippoToken <API_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
"object_purpose":"PURCHASE",
"address_from":{
"object_purpose":"PURCHASE",
"name":"Mr. Hippo",
"street1":"215 Clayton St.",
"city":"San Francisco",
"state":"CA",
"zip":"94117",
"country":"US",
"phone":"+1 555 341 9393",
"email":"[email protected]"
},
"address_to":{
"object_purpose":"PURCHASE",
"name":"Mrs. Hippo",
"street1":"965 Mission St.",
"city":"San Francisco",
"state":"CA",
"zip":"94105",
"country":"US",
"phone":"+1 555 341 9393",
"email":"[email protected]"
},
"parcel":{
"length":"5",
"width":"5",
"height":"5",
"distance_unit":"in",
"weight":"2",
"mass_unit":"lb"
},
"async": false
}'
require 'shippo'
Shippo::api_token = '<API_TOKEN>'
address_from = {
:object_purpose => 'PURCHASE',
:name => 'Shawn Ippotle',
:street1 => '965 Mission St.',
:city => 'San Francisco',
:state => 'CA',
:zip => '94117',
:country => 'US',
:phone => '+1 555 341 9393',
:email => '[email protected]'
}
address_to = {
:object_purpose => 'PURCHASE',
:name => 'Mr Hippo',
:street1 => 'Broadway 1',
:city => 'New York',
:state => 'NY',
:zip => '10007',
:country => 'US',
:phone => '+1 555 341 9393',
:email => '[email protected]'
}
parcel = {
:length => 5,
:width => 1,
:height => 5.555,
:distance_unit => :in,
:weight => 2,
:mass_unit => :lb
}
shipment = Shippo::Shipment.create(
:object_purpose => 'PURCHASE',
:address_from => address_from,
:address_to => address_to,
:parcel => parcel,
:async => false
)
import shippo
shippo.api_key = "<API_TOKEN>"
address_from = {
"object_purpose": "PURCHASE",
"name": "Shawn Ippotle",
"street1": "215 Clayton St.",
"city": "San Francisco",
"state": "CA",
"zip": "94117",
"country": "US",
"phone": "+1 555 341 9393",
"email": "[email protected]"
}
address_to = {
"object_purpose": "PURCHASE",
"name": "Mr Hippo",
"street1": "Broadway 1",
"city": "New York",
"state": "NY",
"zip": "10007",
"country": "US",
"phone": "+1 555 341 9393",
"email": "[email protected]"
}
parcel = {
"length": "5",
"width": "5",
"height": "5",
"distance_unit": "in",
"weight": "2",
"mass_unit": "lb"
}
shipment = shippo.Shipment.create(
object_purpose = 'PURCHASE',
address_from = address_from,
address_to = address_to,
parcel = parcel,
async = False
)
require_once('lib/Shippo.php');
Shippo::setApiKey("<API_TOKEN>");
$fromAddress = array(
'object_purpose' => 'PURCHASE',
'name' => 'Shawn Ippotle',
'street1' => '215 Clayton St.',
'city' => 'San Francisco',
'state' => 'CA',
'zip' => '94117',
'country' => 'US',
'phone' => '+1 555 341 9393',
'email' => '[email protected]'
);
$toAddress = array(
'object_purpose' => 'PURCHASE',
'name' => 'Mr Hippo"',
'street1' => 'Broadway 1',
'city' => 'New York',
'state' => 'NY',
'zip' => '10007',
'country' => 'US',
'phone' => '+1 555 341 9393',
'email' => '[email protected]'
);
$parcel = array(
'length'=> '5',
'width'=> '5',
'height'=> '5',
'distance_unit'=> 'in',
'weight'=> '2',
'mass_unit'=> 'lb',
);
$shipment = Shippo_Shipment::create( array(
'object_purpose'=> 'PURCHASE',
'address_from'=> $fromAddress,
'address_to'=> $toAddress,
'parcel'=> $parcel,
'async'=> false
)
);
var shippo = require('shippo')('<API_TOKEN>');
var addressFrom = {
"object_purpose": "PURCHASE",
"name": "Shawn Ippotle",
"street1": "215 Clayton St.",
"city": "San Francisco",
"state": "CA",
"zip": "94117",
"country": "US",
"phone": "+1 555 341 9393",
"email": "[email protected]"
};
var addressTo = {
"object_purpose": "PURCHASE",
"name": "Mr Hippo",
"street1": "Broadway 1",
"city": "New York",
"state": "NY",
"zip": "10007",
"country": "US",
"phone": "+1 555 341 9393",
"email": "[email protected]"
};
var parcel = {
"length": "5",
"width": "5",
"height": "5",
"distance_unit": "in",
"weight": "2",
"mass_unit": "lb"
};
shippo.shipment.create({
"object_purpose": "PURCHASE",
"address_from": addressFrom,
"address_to": addressTo,
"parcel": parcel,
"async": false
}, function(err, shipment){
// asynchronously called
});
Shippo.setApiKey('<API_TOKEN>');
// To Address
HashMap<String, Object> addressToMap = new HashMap<String, Object>();
addressToMap.put("object_purpose", "PURCHASE");
addressToMap.put("name", "Mr Hippo");
addressToMap.put("company", "Shippo");
addressToMap.put("street1", "215 Clayton St.");
addressToMap.put("city", "San Francisco");
addressToMap.put("state", "CA");
addressToMap.put("zip", "94117");
addressToMap.put("country", "US");
addressToMap.put("phone", "+1 555 341 9393");
addressToMap.put("email", "[email protected]");
// From Address
HashMap<String, Object> addressFromMap = new HashMap<String, Object>();
addressFromMap.put("object_purpose", "PURCHASE");
addressFromMap.put("name", "Ms Hippo");
addressFromMap.put("company", "San Diego Zoo");
addressFromMap.put("street1", "2920 Zoo Drive");
addressFromMap.put("city", "San Diego");
addressFromMap.put("state", "CA");
addressFromMap.put("zip", "92101");
addressFromMap.put("country", "US");
addressFromMap.put("email", "[email protected]");
addressFromMap.put("phone", "+1 619 231 1515");
addressFromMap.put("metadata", "Customer ID 123456");
// Parcel
HashMap<String, Object> parcelMap = new HashMap<String, Object>();
parcelMap.put("length", "5");
parcelMap.put("width", "5");
parcelMap.put("height", "5");
parcelMap.put("distance_unit", "in");
parcelMap.put("weight", "2");
parcelMap.put("mass_unit", "lb");
// Shipment
HashMap<String, Object> shipmentMap = new HashMap<String, Object>();
shipmentMap.put("address_to", addressToMap);
shipmentMap.put("address_from", addressFromMap);
shipmentMap.put("parcel", parcelMap);
shipmentMap.put("object_purpose", "PURCHASE");
shipmentMap.put("async", false);
Shipment shipment = Shipment.create(shipmentMap);
APIResource resource = new APIResource ('<API_TOKEN>');
// to address
Hashtable toAddressTable = new Hashtable();
toAddressTable.Add("object_purpose", "PURCHASE");
toAddressTable.Add("name", "Mr Hippo");
toAddressTable.Add("company", "Shippo");
toAddressTable.Add("street1", "215 Clayton St.");
toAddressTable.Add("city", "San Francisco");
toAddressTable.Add("state", "CA");
toAddressTable.Add("zip", "94117");
toAddressTable.Add("country", "US");
toAddressTable.Add("phone", "+1 555 341 9393");
toAddressTable.Add("email", "[email protected]");
// from address
Hashtable fromAddressTable = new Hashtable();
fromAddressTable.Add("object_purpose", "PURCHASE");
fromAddressTable.Add("name", "Ms Hippo");
fromAddressTable.Add("company", "San Diego Zoo");
fromAddressTable.Add("street1", "2920 Zoo Drive");
fromAddressTable.Add("city", "San Diego");
fromAddressTable.Add("state", "CA");
fromAddressTable.Add("zip", "92101");
fromAddressTable.Add("country", "US");
fromAddressTable.Add("email", "[email protected]");
fromAddressTable.Add("phone", "+1 619 231 1515");
fromAddressTable.Add("metadata", "Customer ID 123456");
Hashtable parcelTable = new Hashtable ();
parcelTable.Add ("length", "5");
parcelTable.Add ("width", "5");
parcelTable.Add ("height", "5");
parcelTable.Add ("distance_unit", "in");
parcelTable.Add ("weight", "2");
parcelTable.Add ("mass_unit", "lb");
resource.CreateShipment(new Hashtable(){
{ "address_to", toAddressTable},
{ "address_from", fromAddressTable},
{ "parcel", parcelTable},
{ "object_purpose", "PURCHASE"},
{ "async", false}});
The API will respond with the JSON serialized Shipment object:
{
"object_state": "VALID",
"object_status": "SUCCESS",
"object_purpose": "PURCHASE",
"object_created": "2013-12-01T06:24:20.121Z",
"object_updated": "2013-12-01T06:24:20.121Z",
"object_id": "5e40ead7cffe4cc1ad45108696162e42",
"object_owner": "[email protected]",
"address_from": "4f406a13253945a8bc8deb0f8266b245",
"address_to": "4c7185d353764d0985a6a7825aed8ffb",
"address_return": "4f406a13253945a8bc8deb0f8266b245",
"parcel": "ec952343dd4843c39b42aca620471fd5",
"submission_date": "2013-12-03T12:00:00.000Z",
"insurance_amount": "",
"insurance_currency": "",
"extra": {},
"customs_declaration": "",
"reference_1": "",
"reference_2": "",
"rates_url": "https://api.goshippo.com/shipments/5e40ead7cffe4cc1ad45108696162e42/rates/",
"rates_list": [
{
"object_state": "VALID",
"object_purpose": "PURCHASE",
"object_created": "2013-12-01T06:24:21.121Z",
"object_updated": "2013-12-01T06:24:21.121Z",
"object_id": "545ab0a1a6ea4c9f9adb2512a57d6d8b",
"object_owner": "[email protected]",
"shipment": "5e40ead7cffe4cc1ad45108696162e42",
"attributes": [],
"amount": "5.50",
"currency": "USD",
"amount_local": "5.50",
"currency_local": "USD",
"provider": "USPS",
"provider_image_75": "https://cdn2.goshippo.com/providers/75/USPS.png",
"provider_image_200": "https://cdn2.goshippo.com/providers/200/USPS.png",
"servicelevel_name": "Priority Mail",
"servicelevel_token":"usps_priority",
"servicelevel_terms": "",
"days": 2,
"arrives_by": null,
"duration_terms": "Delivery in 1 to 3 business days.",
"trackable": true,
"insurance": false,
"insurance_amount_local": "0.00",
"insurance_currency_local": null,
"insurance_amount": "0.00",
"insurance_currency": null,
"messages": [],
"carrier_account": "078870331023437cb917f5187429b093",
"test": false
},
...
],
"carrier_accounts": [],
"metadata": "Customer ID 123456",
"messages": []
}
The response contains a list of rates for the Shipment. If you haven't added your own carrier accounts, you should only see USPS and DHL Express rates (for international shipments) at the moment.
2. Create the Transaction Object
The creation of a shipping label is handled by the Transaction endpoint. The Transaction object represents a shipping label purchase and is based on the shipping rate you want to purchase from step 1.
You can send an optional label_file_type in the transaction call. If you don't specify this value, the API will use to the default file format, which you can set on the settings page.
curl https://api.goshippo.com/transactions \
-H "Authorization: ShippoToken <API_TOKEN>" \
-d rate="cf6fea899f1848b494d9568e8266e076"
-d label_file_type="PDF"
-d async=false
# Get the first rate in the rates results.
# Customize this based on your business logic.
rate = shipment.rates_list.first
# Purchase the desired rate.
transaction = Shippo::Transaction.create(
:rate => rate["object_id"],
:label_file_type => "PDF",
:async => false )
# label_url and tracking_number
if transaction["object_status"] == "SUCCESS"
puts "Label sucessfully generated:"
puts "label_url: #{transaction.label_url}"
puts "tracking_number: #{transaction.tracking_number}"
else
puts "Error generating label:"
puts transaction.messages
end
# Get the first rate in the rates results.
# Customize this based on your business logic.
rate = shipment.rates_list[0]
# Purchase the desired rate.
transaction = shippo.Transaction.create(
rate=rate.object_id,
label_file_type="PDF",
async=False )
# Retrieve label url and tracking number or error message
if transaction.object_status == "SUCCESS":
print transaction.label_url
print transaction.tracking_number
else:
print transaction.messages
// Get the first rate in the rates results.
// Customize this based on your business logic.
$rate = $shipment["rates_list"][0];
// Purchase the desired rate.
$transaction = Shippo_Transaction::create( array(
'rate' => $rate["object_id"],
'label_file_type' => "PDF",
'async' => false ) );
// Retrieve label url and tracking number or error message
if ($transaction["object_status"] == "SUCCESS"){
echo( $transaction["label_url"] );
echo("\n");
echo( $transaction["tracking_number"] );
}else {
echo( $transaction["messages"] );
}
// Get the first rate in the rates results.
// Customize this based on your business logic.
var rate = shipment.rates_list[0];
// Purchase the desired rate.
shippo.transaction.create({
"rate": rate.object_id,
"label_file_type": "PDF",
"async": false
}, function(err, transaction) {
// asynchronous callback
});
// Get the first rate in the rates results.
// Customize this based on your own business logic
Rate rate = shipment.ratesList[0];
HashMap<String, Object> transactionMap = new HashMap<String, Object>();
transactionMap.put("rate", rate.objectId);
transactionMap.put("async", false);
// Purchase the desired rate
Transaction transaction = Transaction.create(transactionParameters);
if (transaction.getObjectStatus().equals("SUCCESS")) {
System.out.println(String.format("Label url : %s",
transaction.getLabelUrl()));
System.out.println(String.format("Tracking number : %s",
transaction.getTrackingNumber()));
} else {
System.out.println(String.format("An Error has occured while generating your label. Messages : %s",
transaction.getMessages()));
}
// Get the first rate in the rates results.
// Customize this based on your business logic.
Rate rate = shipment.RatesList[0];
HashMap transactionParameters = new HashMap();
transactionParameters.Add("rate", rate.ObjectId);
transactionParameters.Add("async", false);
// Purchase the desired rate.
Transaction transaction = resource.CreateTransaction(transactionParameters);
if (transaction.getObjectStatus().equals("SUCCESS")){
Console.WriteLine("Label url: " + transaction.getLabelUrl());
Console.WriteLine("Tracking number: " +
transaction.getTrackingNumber());
} else{
Console.WriteLine("Error generating label. Messages: " +
transaction.getMessages());
}
The API will respond with the JSON serialized Transaction object:
{
"object_state": "VALID",
"object_status": "SUCCESS",
"object_created": "2013-12-27T19:14:48.273Z",
"object_updated": "2013-12-27T19:14:48.273Z",
"object_id": "64bba01845ef40d29374032599f22588",
"object_owner": "[email protected]",
"was_test": false,
"rate": "cf6fea899f1848b494d9568e8266e076",
"tracking_number": "ZW70QJC",
"tracking_status": {
"object_created": "2013-12-27T23:17:41.411Z",
"object_id": "a21b3d6831c14ceaba6730179ce6e784",
"status": "UNKNOWN",
"status_details": "",
"status_date": "2013-12-28T12:04:04.214Z"
},
"tracking_history": [],
"tracking_url_provider": "https://tools.usps.com/go/TrackConfirmAction.action?tLabels=ZW70QJC",
"label_url": "https://shippo-delivery.s3.amazonaws.com/96.pdf?Signature=PEdWrp0mFWAGwJp7FW3b%2FeA2eyY%3D&Expires=1385930652&AWSAccessKeyId=AKIAJTHP3LLFMYAWALIA",
"commercial_invoice_url": "",
"metadata": "",
"messages": []
}
Congrats! You've created your first shipment. You can find the shipping label URL under label_url, and shipment tracking number amongst other response attributes.
Recommended Configurations
For detailed tutorials on different shipping configurations and advanced functionalities, see our navigation sidebar. Or you can surf through our API references to explore all our supported services.
We recommend reviewing the following information:
- Add carrier accounts - to use carriers other than our default ones, you will need to add your own account credential and connect your own carrier account.
- Retrieve carrier account object_ids - each carrier, whether default or your own, will have its own unique identifier. Many endpoints will require this information, so keep it handy.
- Learn about shipment tracking - every shipment created through the Shippo API is automatically tracked. You can also use the the Tracking endpoint to track other packages with just the carrier information and a tracking number.
- Create a shipping label in a single API call - if you already know what service level you'd like to purchase for your shipment, there's no need to retrieve a list of rates. Learn how to create a shipping label by passing in a carrier and service level token.
- Purchase a batch of shipping labels at once - instead of creating one shipping label per request and generating one PDF per shipping label, use batch label creation to purchase up to 10,000 labels in one API request, and get create up to 100 labels per PDF.
- Reference: Available carrier, service level, and parcel template tokens.