Address Validation

In order to prevent failed deliveries and address correction surcharges, validate your addresses through our API before you create labels.

Only US addresses can be validated for free.

Please see our pricing page for more information related to Global Address Validation costs.

Address validation logic

The Shippo address validation method verifies an Address by checking whether we have a matching verified deliverable address. The following results are possible:

  • Address is valid: The source address is valid and unique. The API will return a new, cleaned address object with is_complete: true. Additionally, there is a key for validation_results that contains an object with the key is_valid: true and messages will be empty.
  • Address is invalid: The address validator has processed the address, but could not find a match. There are three possible reasons: address doesn't exist, the address isn't deliverable, or the address is too ambiguous. The API will return a new Address object with the validation_results key is_valid: false. The validation_results object's messages field will contain a string with further detail about why the validation failed.
  • Residential or Commercial: The address validator also returns whether the address is residential or commercial via the is_residential flag. If the residential/commercial type could not be determined, the value will be null.

It is also worth noting that if the address object you created is missing information necessary for creating a shipment, the is_complete field will be false.

How to validate addresses

Validating addresses is easy: simply add a parameter validate: true to your Address POST request.

curl https://api.goshippo.com/addresses/ \
    -H "Authorization: ShippoToken <API_TOKEN>" \
    -d name="Shawn Ippotle" \
    -d company="Shippo" \
    -d street1="215 Clayton St." \
    -d city="San Francisco" \
    -d state="CA" \
    -d zip=94117 \
    -d country="US" \
    -d email="shippotle@goshippo.com"\
    -d validate=true
address_from = Shippo::Address.create(
    :name => "Shawn Ippotle",
    :company => "Shippo",
    :street1 => "215 Clayton St.",
    :city => "San Francisco",
    :state => "CA",
    :zip => "94117",
    :country => "US",
    :email => "shippotle@goshippo.com",
    :validate => true
)
address_from = shippo.Address.create(
    name = "Shawn Ippotle",
    company = "Shippo",
    street1 = "215 Clayton St.",
    city = "San Francisco",
    state = "CA",
    zip = "94117",
    country = "US",
    email = "shippotle@goshippo.com",
    validate = True
)
$fromAddress = Shippo_Address::create( array(
    "name" => "Shawn Ippotle",
    "company" => "Shippo",
    "street1" => "215 Clayton St.",
    "city" => "San Francisco",
    "state" => "CA",
    "zip" => "94117",
    "country" => "US",
    "email" => "shippotle@goshippo.com",
    "validate" => true
));
shippo.address.create({
    "name":"Shawn Ippotle", 
    "company":"Shippo",
    "street1":"215 Clayton St.",
    "city":"San Francisco",
    "state":"CA",
    "zip":"94117",
    "country":"US",
    "email":"shippotle@goshippo.com",
    "validate": true
}, function(err, address) {
    // asynchronously called
});
HashMap<String, Object> addressMap = new HashMap<String, Object>();
addressMap.put("name", "Mr. Hippo");
addressMap.put("company", "Shippo");
addressMap.put("street1", "215 Clayton St.");
addressMap.put("city", "San Francisco");
addressMap.put("state", "CA");
addressMap.put("zip", "94117");
addressMap.put("country", "US");
addressMap.put("phone", "+1 555 341 9393");
addressMap.put("email", "support@goshipppo.com");
addressMap.put("validate", "true");

Address createAddress = Address.create(addressMap);
resource.CreateAddress(new Hashtable(){
    {"name", "Mr. Hippo"},
    {"company", "Shippo"},
    {"street1", "215 Clayton St."},
    {"city", "San Francisco"},
    {"state", "CA"},
    {"zip", "94117"},
    {"country", "US"},
    {"phone", "+1 555 341 9393"},
    {"email", "support@goshipppo.com"},
    {"validate", "true"}});

You will get a response in the following format:

{
    "object_created": "2015-03-30T23:47:11.574Z",
    "object_updated": "2015-03-30T23:47:11.596Z",
    "object_id": "67183b2e81e9421f894bfbcdc4236b16",
    "is_complete": false,
    "validation_results": {
        "is_valid": false,
        "messages": [
            {
                "source": "USPS",
                "code": "Address Not Found",
                "text": "The address as submitted could not be found. Please check for excessive abbreviations in the street address line or in the City name."
            }
        ]
    },
    "object_owner": "shippotle@goshippo.com",
    "name": "Shawn Ippotle",
    "company": "Shippo",
    "street_no": "",
    "street1": "215 HIPPO ST.",
    "street2": "",
    "city": "SAN FRANCISCO",
    "state": "CA",
    "zip": "94107",
    "country": "US",
    "phone": "",
    "email": "shippotle@goshippo.com",
    "is_residential": null,
    "metadata": "",
    "test": true
}

Validate existing address objects

To validate existing addresses, simply append /validate to an address GET call:

curl https://api.goshippo.com/addresses/d799c2679e644279b59fe661ac8fa488/validate/ \
    -H "Authorization: ShippoToken <API_TOKEN>"
Shippo::Address.get("d799c2679e644279b59fe661ac8fa488").validate()
shippo.Address.validate('d799c2679e644279b59fe661ac8fa488')
Shippo_Address::validate('d799c2679e644279b59fe661ac8fa488');
shippo.address.validate("d799c2679e644279b59fe661ac8fa488", function(err, address) {
    // asynchronously called
});
Address.validate("d799c2679e644279b59fe661ac8fa488");
resource.ValidateAddress("d799c2679e644279b59fe661ac8fa488");

This call returns the same response JSON as the sample response above.


Global Address Validation

The way to validate global addresses (non-US) would operate the same as US addresses. The key difference that you'll notice is in the response that you get back. Global address validation has additional messages for specifying the precision of the address that is returned (i.e. street level, neighborhood level, state level, rooftop level, etc...).

If you attempt to validate a non-US address using your Test API token, we will simply pass back the address information without preforming any validation. Please be aware that if you simply switch from using your Test token to using your Live token, you will incur charges for using your Live token for validating Global addresses.

{
  "object_created": "2017-07-26T17:52:37.305Z",
  "object_updated": "2017-07-26T17:52:37.351Z",
  "object_id": "b7f9709df3914d1ca6efe4c30e7b0572",
  "is_complete": true,
  "validation_results": {
    "is_valid": true,
    "messages": [
      {
        "source": "Shippo Address Validator",
        "type": "address_correction",
        "code": "administrative_area_change",
        "text": "The administrative area (state or province) was added or changed."
      },
      {
        "source": "Shippo Address Validator",
        "code": "geocoded_rooftop",
        "text": "The record was geocoded down to rooftop level, meaning the point is within the property boundaries (most often the center)."
      },
      {
        "source": "Shippo Address Validator",
        "code": "premises_full",
        "text": "The address has been verified to the Premise (House or Building) Level, which is the highest level possible with the reference data."
      }
    ]
  },
  "object_owner": "hippo@goshippo.com",
  "name": "Hippo Shippo",
  "company": "Shippo",
  "street_no": "2",
  "street1": "Unter den Linden",
  "street2": "",
  "street3": "",
  "city": "Berlin",
  "state": "",
  "zip": "10117",
  "country": "DE",
  "longitude": "13.39751",
  "latitude": "52.51785",
  "phone": "14151234567",
  "email": "hippo@goshippo.com",
  "is_residential": null,
  "metadata": "",
  "test": false
}

Messages

The messaging structure for global addresses will give details about what was changed and the specificity of your results. You will find these messages in the "messages" field which is an array comprised of all messages returned in processing your address validation request.

{
  ...
  "is_complete": true,
  "validation_results": {
    "is_valid": true,
    "messages": [
      {
        "source": "Shippo Address Validator",
        "type": "address_correction",
        "code": "administrative_area_change",
        "text": "The administrative area (state or province) was added or changed."
      },
      {
        "source": "Shippo Address Validator",
        "type": "geocode_level",
        "code": "geocoded_rooftop",
        "text": "The record was geocoded down to rooftop level, meaning the point is within the property boundaries (most often the center)."
      },
      {
        "source": "Shippo Address Validator",
        "type": "address_warning",
        "code": "premises_full",
        "text": "The address has been verified to the Premise (House or Building) Level, which is the highest level possible with the reference data."
      }
    ]
  },
  "object_owner": "hippo@goshippo.com",
  ...
}

"source": This describes where the message is coming from, which should be "Shippo Address Validator" in this case.

"type": These are generalized tokens that you can use for understanding the type of message that was created. Below is a comprehensive list of the message types that can be returned:

"address_error" "address_warning" "address_error" "service_error"
"address_correction" "geocode_level" "geocode_error"

"code": Below are the some example message codes that can be returned:

"verification_error""unknown_street""component_mismatch_error"
"multiple_match""sub_premise_number_invatdd""sub_premise_number_missing"
"premise_number_invatdd""premise_number_missing""box_number_invatdd"

"text": This is a text description of the message. Below are some examples of the text that will accompany the above message codes.

  • "The address could not be verified at least up to the postal code level"
  • "Street could not be matched to a unique street name. Please add more details to the street name."
  • "The address matched multiple records, please enter more information to locate a unique address. "

Bypass address validation for label purchase (USPS, UPS, & LaserShip only)

When purchasing shipping labels you can bypass the carrier's built-in address validation by setting the Shipment object's Extra field bypass_address_validation to true.

You'll want to include this in the "extra" field in order to bypass:

{
  /* insert other required shipment fields */
  "extra": {
    "bypass_address_validation": true
  }
}