Returns

Setup your reverse-logistics and returns easily through the API.

  1. Scan-based return labels : These labels are free to print. You won't get charged unless it gets used. It's a great option if you want to add return labels to all your outbound packages. All Shippo return labels are scan-based, available for USPS, FedEx, and UPS shipments only. At the moment, you can only generate return labels for the same carrier that your outbound shipment was sent with
  2. Return address : For failed deliveries or return shipments, you can specify a different return address than the initial outbound location

Generate a return label

Returns for USPS, FedEx, and UPS

To generate a pay-on-use return label, create a new Shipment object and set an is_return field as true inside the extra attribute.

Note

For USPS, FedEx, and UPS, do not swap the addresses yourself -- the Shippo API will take care of this for you. This means that the original address_to of the outbound transaction becomes the address_from for the return label.

cURLRubyPythonPHPtypescriptJavaC#
Copy
Copied
curl https://api.goshippo.com/shipments/ \
    -H "Authorization: ShippoToken <API_Token>" \
    -H "Content-Type: application/json" \
    -d '{
        "address_from": {
            "name": "Mr. Hippo",
            "street1": "215 Clayton St.",
            "city": "San Francisco",
            "state": "CA",
            "zip": "94117",
            "country": "US",
            "metadata": "merchant address"
        },
        "address_to": {
            "name": "Mrs. Hippo",
            "street1": "965 Mission St.",
            "city": "San Francisco",
            "state": "CA",
            "zip": "94105",
            "country": "US",
            "metadata": "customer address"
        },
        "parcels": ["7df2ecf8b4224763ab7c71fae7ec8274"],
        "shipment_date": "2023-12-03T12:00:00.000Z",
        "extra": { "is_return": true },
        "async": false
    }'
Copy
Copied
# Create address_from, address_to and parcel variables first
shipment_return = Shippo::Shipment.create(
    :address_from => address_from,
    :address_to => address_to,
    :parcels => parcel,
    :extra => {:is_return => true},
    :async => false
)
Copy
Copied
# Create address_from, address_to and parcel variables first
shipment_return = shippo_sdk.shipments.create(
    components.ShipmentCreateRequest(
        address_from=address_from,
        address_to=address_to,
        parcels=[parcel],
        extra=components.ShipmentExtra(
            is_return=True
        ),
        async_=False
    )
)
Copy
Copied
// Create $fromAddress, $toAddress and $parcel variables first
$shipment_return = Shippo_Shipment::create(
    array(
        "address_from" => $fromAddress,
        "address_to" => $toAddress,
        "parcels" => array($parcel),
        "extra" => array("is_return" => true),
        "async" => false
    )
);
Copy
Copied
// Create addressFrom, addressTo and parcel variables first
const shipmentReturn = await shippo.shipments.create({
    addressFrom: addressFrom,
    addressTo: addressTo,
    parcels: [parcel],
    extra: {
        isReturn: true
    },
    async: false
});
Copy
Copied
HashMap<String, Object> returnShipmentMap = new HashMap<String, Object>();
returnShipmentMap.put("address_from", addressFromMap);
returnShipmentMap.put("address_to", addressToMap);
returnShipmentMap.put("parcels", parcelMap);
HashMap<String, Object> extraMap = new HashMap<String, Object>();
extraMap.put("is_return", true);
returnShipmentMap.put("extra", extraMap);
returnShipmentMap.put("async", false);

Shipment.create(returnShipmentMap);
Copy
Copied
Shipment shipmentReturn = await sdk.Shipments.CreateAsync(
    new ShipmentCreateRequest()
    {
        AddressFrom = addressFrom,
        AddressTo = addressTo,
        Parcels = new List<Shippo.Models.Components.Parcels>() { parcel },
        Extra = new ShipmentExtra()
        {
            IsReturn = true
        },
        Async = false,
    }
);

After creating the Shipment, follow the normal process of retrieving rates to select the service level that you'd like to use for the return, and proceed to create your return label.

When the return label is generated, it will be valid for a period of time. After this time, carriers may still accept these labels but it can cause the shipment to be flagged, returned, or destroyed without being eligible for a refund. Depending on your carrier, generated return labels are valid for different periods of time.

Carrier Return label validity
USPS 1 year
FedEx 2 years
UPS 100 days

Returns for other carriers

If you need to generate a label for return shipments for carriers other than USPS, FedEx, and UPS, you can create a normal shipping label just with the addresses swapped.

However, normal shipping labels have a limited shipping window and the label may be rejected after that, so we do not recommend inserting them into your outbound package. Instead, you can provide a method for customers to contact your support services, and you can provide them with the link to the label.

Copy
Copied
curl https://api.goshippo.com/shipments/ \
    -H "Authorization: ShippoToken <API_Token>" \
    -H "Content-Type: application/json" \
    -d '{
        "address_from": {
            "name": "Mrs. Hippo",
            "street1": "965 Mission St.",
            "city": "San Francisco",
            "state": "CA",
            "zip": "94105",
            "country": "US",
            "metadata": "customer address"
        },
        "address_to": {
            "name": "Mr. Hippo",
            "street1": "215 Clayton St.",
            "city": "San Francisco",
            "state": "CA",
            "zip": "94117",
            "country": "US",
            "metadata": "merchant address"
        },
        "parcels": ["7df2ecf8b4224763ab7c71fae7ec8274"],
        "shipment_date": "2023-12-03T12:00:00.000Z",
        "async": false
    }'

Return Address

When creating an outbound Shipment for USPS, FedEx and UPS, you can specify a address_return that's different from your original shipping address (address_from). This can be useful if you want returned shipments to go back to a different place. For instance:

  1. Failed deliveries: the Shipment will be returned to a different facility than the original outbound destination.
  2. Scan-based labels: the Shippo API automatically swaps the  address_from  and  address_to  during the return label creation process. You can pass any address  object_id  or nested object in the corresponding fields -- they don't need to match the outbound addresses.
cURLRubyPythonPHPtypescriptJavaC#
Copy
Copied
curl https://api.goshippo.com/shipments/\
    -H "Authorization: ShippoToken <API_Token>"\
    -d address_from="d799c2679e644279b59fe661ac8fa488"\
    -d address_to="42236bcf36214f62bcc6d7f12f02a849"\
    -d address_return="1d3tb2c51chj77ci27b7dfne3fibp264"\
    -d parcels=["7df2ecf8b4224763ab7c71fae7ec8274"]\
    -d shipment_date="2023-12-03T12:00:00.000Z"\
    -d async=false
Copy
Copied
# Create address_from, address_to, address_return and parcel variables first
shipment_return = Shippo::Shipment.create(
    :address_from => address_from,
    :address_to => address_to,
    :address_return => address_return,
    :parcels => parcel,
    :async => false
)
Copy
Copied
# Create address_from, address_to, address_return and parcel variables first
shipment_return = shippo_sdk.shipments.create(
    components.ShipmentCreateRequest(
        address_from=address_from,
        address_to=address_to,
        address_return=address_return,
        parcels=[parcel],
    )
)
Copy
Copied
// Create $fromAddress, $toAddress, $returnAddress and $parcel variables first
$shipment_return = Shippo_Shipment::create(
    array(
        "address_from" => $fromAddress,
        "address_to" => $toAddress,
        "address_return" => $returnAddress,
        "parcels" => array($parcel),
        "async" => false
    )
);
Copy
Copied
// Create addressFrom, addressTo, addressReturn and parcel variables first
const shipmentReturn = await shippo.shipments.create({
    addressFrom: addressFrom,
    addressTo: addressTo,
    addressReturn: addressReturn,
    parcels: [parcel],
    async: false
});
Copy
Copied
HashMap<String, Object> returnShipmentMap = new HashMap<String, Object>();
returnShipmentMap.put("address_from", addressFromMap);
returnShipmentMap.put("address_to", addressToMap);
returnShipmentMap.put("address_return", addressReturnMap);
returnShipmentMap.put("parcels", parcelMap);
returnShipmentMap.put("async", false);

Shipment.create(returnShipmentMap);
Copy
Copied
// Create addressFrom, addressTo, addressReturn and parcel variables first
Shipment shipmentReturn = await sdk.Shipments.CreateAsync(
    new ShipmentCreateRequest()
    {
        AddressFrom = addressFrom,
        AddressTo = addressTo,
        AddressReturn = addressReturn,
        Parcels = new List<Shippo.Models.Components.Parcels>() { parcel },
        Async = false,
    }
);