Validation

There are often differences – sometimes minor, sometimes substantial – between the required fields in the existing XML and flat file feeds, and the required fields in the new JSON feed. This is particularly true when working with the POST_PRODUCT_DATA and POST_FLAT_FILE_LISTINGS_DATA feed types, where the feed attributes vary substantially depending on the product type being created. The new JSON-based feed typically has many more requirements for a given product type than the older product feeds.

To help you manage this, we've built two validators that you can run the converted feed data through to check if there are attributes that are missing or invalid. The validators can point you to the exact XML tag or flat file field you need to add or modify, and in some cases, the validators can fix the errors without any further intervention on your part.

Before submitting a POST_PRODUCT_DATA or POST_FLAT_FILE_LISTINGS_DATA feed for the first time for a given product type, we highly recommend first running a sample feed with only a few products through the two validators, to check if you need to make any changes before you start converting feeds in bulk.

Installation

This section assumes that you already have the Highside Labs private Composer repository configured, as described in Installation.

The validator classes are in a separate package from the rest of the feed transformer, because they are the one part of the tool that requires PHP 8.2+ instead of PHP 7.1+. To install the package, run:

$ composer require highsidelabs/amazon-feed-validator

Validators

There are two validator classes, JsonSchemaValidator and AmazonValidator. They share an interface. When testing, we recommend starting with the JsonSchemaValidator and moving on to the AmazonValidator after fixing any errors caught by the JsonSchemaValidator, because the AmazonValidator makes actual requests to the Selling Partner API on your behalf.

JSON Schema Validator

This validator checks the converted feed data against Amazon's JSON Schema for the product type that's being sent in your feed. Each product type has its own specific JSON Schema, which the validator will fetch from the Selling Partner API for you. It will then fix any validation issues that it's able to resolve on its own, and return an array of issues that you need to handle, if there are any.

Here's what that looks like in practice:

use SellingPartnerApi\FeedTransformer\Transformer;
use SellingPartnerApi\FeedTransformer\FeedTypes\Product;
use SellingPartnerApi\FeedValidator\JsonSchemaValidator;
use SellingPartnerApi\SellingPartnerApi;

$feedPath = 'path/to/POST_PRODUCT_DATA.xml';
$marketplaceId = 'ATVPDKIKX0DER';  // US Selling Partner API marketplace ID
$json = Transformer::fromFile(
    Product::$feedType,
    $feedPath,
    $marketplaceId,
    [ /* options */ ]
);

// The JsonSchemaValidator needs your Selling Partner API credentials to retrieve the
// JSON Schema document from Amazon on your behalf
$sellerConnector = SellingPartnerApi::seller(
    clientId: 'amzn1.application-oa2-client.asdfqwertyuiop...',
    clientSecret: 'amzn1.oa2-cs.v1.1234567890asdfghjkl...',
    refreshToken: 'Atzr|IwEBIA...',
    endpoint: Endpoint::NA,  // Or Endpoint::EU, Endpoint::FE, Endpoint::NA_SANDBOX, etc.
);

$jsonValidator = new JsonSchemaValidator($sellerConnector, $marketplaceId);
$validationErrors = $jsonValidator->validate(Product::$feedType, $json);

if ($validationErrors === []) {
    // Write the converted data out to a file to be sent to Amazon
    $jsonFeedPath = 'path/to/new/feed.json';
    file_put_contents($jsonFeedPath, json_encode($json));
} else {
    // Handle the validation errors
}

Because the JsonSchemaValidator can and will modify the JSON data in order to fix validation errors, call the JsonSchemaValidator::changes() method after your first time using the validator for a particular product type. If it returns a list of messages describing changes it has made to the JSON data, you should run every converted feed for that product type through the JsonSchemaValidator to make sure it makes the necessary fixes before you submit the converted feed to Amazon.

If for any reason you don't want the validator to modify your converted feed data in order to fix it, pass ['fix' ⇒ false] as the third parameter to JsonSchemaValidator::validate().

If there are validation errors that the validator can't fix, the validation error messages should make it pretty clear what you need to change. Often you will need to add a particular field or tag, and the name of the field/tag usually makes it pretty self-explanatory what the value should be. If it's unclear what data you need to add, just shoot us an email and we'll help you get it sorted out.

Amazon Validator

Once your data is running through the JsonSchemaValidator cleanly, you can use the AmazonValidator to confirm that Amazon will accept your data. This validator actually submits the feed data to Amazon in validation-only mode, so the contents of the feed won't affect your listings in any way. The rate limit for validation-only mode is quite low, so we do not recommend validating feeds of more than 5 items at a time, as you will likely run into rate limits. This validator is only meant for testing a feed for a particular product type, not for ongoing use in production.

The AmazonValidator's interface is the same as the JsonSchemaValidator's, so usage looks basically identical:

use SellingPartnerApi\FeedTransformer\Transformer;
use SellingPartnerApi\FeedTransformer\FeedTypes\Product;
use SellingPartnerApi\FeedValidator\AmazonValidator;
use SellingPartnerApi\SellingPartnerApi;

$feedPath = 'path/to/POST_PRODUCT_DATA.xml';
$marketplaceId = 'ATVPDKIKX0DER';  // US Selling Partner API marketplace ID
$json = Transformer::fromFile(
    Product::$feedType,
    $feedPath,
    $marketplaceId,
    [ /* options */ ]
);

// The AmazonValidator needs your Selling Partner API credentials to make validation-
// only calls to the SP API on your behalf
$sellerConnector = SellingPartnerApi::seller(
    clientId: 'amzn1.application-oa2-client.asdfqwertyuiop...',
    clientSecret: 'amzn1.oa2-cs.v1.1234567890asdfghjkl...',
    refreshToken: 'Atzr|IwEBIA...',
    endpoint: Endpoint::NA,
);

$jsonValidator = new AmazonValidator($sellerConnector, $marketplaceId);
$validationErrors = $jsonValidator->validate(Product::$feedType, $json);

if ($validationErrors === []) {
    // Write the converted data out to a file to be sent to Amazon
    $jsonFeedPath = 'path/to/new/feed.json';
    file_put_contents($jsonFeedPath, json_encode($json));
} else {
    // Handle the validation errors
}

Fixing validation errors

Validation errors are returned as a map of SKUs to SKU-specific errors. They look something like this (these are errors from a POST_PRODUCT_FEED for the SHOES product type):

[
    'SHOES-SKU-TEST-1' => [
        [
            'field' => "Message/Product/ProductData/Shoes/ClassificationData/HeelHeight",
            'error' => "This field is required",
            'fieldDescription' => "The attribute indicates Heel of the product"
        ],
        [
            'field' => "Message/Product/ProductData/Shoes/SupplierPackageType",
            'error' => "This field is required",
            'fieldDescription' => "Provide the packaging used to contain the item as shipped from the supplier (seller/vendor) to the fulfillment center."
        ],
        [
            'field' => "Message/Product/ProductData/Shoes/ClassificationData/WaterResistanceLevel",
            'error' => "This field is required",
            'fieldDescription' => "Provide the degree to which the item can resist water",
            'enum' => ['Not Water Resistant', 'Water Repellent', 'Water Resistant', 'Waterproof']
        ],
        [
            "field" => "Message/Product/ProductData/Shoes/ClassificationData/HeelHeight/@unitOfMeasure"
            "error" => "Does not have a value in the enumeration [\"centimeters\",\"inches\"]"
        ],
        [
            'field' => "Message/Product/DescriptionData/Battery/AreBatteriesRequired",
            'error' => "This field is required",
            'fieldDescription' => "Select \"yes\" if batteries are required to power the item (or if the item is a battery) or \"no\" if they are not. Please note that an internal rechargeable battery is also considered a battery",
            'enum' => ['Yes', 'No']
        ],
        // ...
    ],
    'SHOES-SKU-TEST-2' => [
         // ...
     ],
     // ...
]

This tells you that you need to add the following data to your POST_PRODUCT_DATA feed, in addition to whatever tags are already in there:

<?xml version="1.0" encoding="UTF-8"?>
<AmazonEnvelope xsi:noNamespaceSchemaLocation="amzn-envelope.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Header>
        <DocumentVersion>1.01</DocumentVersion>
        <MerchantIdentifier>merchant-id</MerchantIdentifier>
    </Header>
    <MessageType>Product</MessageType>
    <PurgeAndReplace>false</PurgeAndReplace>

    <Message>
        <MessageID>1</MessageID>
        <OperationType>Update</OperationType>
        <Product>
            <SKU>SHOES-SKU-TEST-1</SKU>
            <DescriptionData>
                <!-- ... -->
                <Battery>
                    <AreBatteriesRequired>Yes</AreBatteriesRequired>
                </Battery>
                <PackageDimensions>
                    <Height unitOfMeasure="inches">2.25</Height>
                </PackageDimensions>
            </DescriptionData>
            <ProductData>
                <Shoes>
                    <!-- ... -->
                    <ClassificationData>
                        <HeelHeight unitOfMeasure="inches"></HeelHeight>
                        <WaterResistanceLevel>Water Resistant</WaterResistanceLevel>
                    </ClassificationData>
                    <SupplierPackageType>Retail Box</SupplierPackageType>
                </Shoes>
            </ProductData>
        </Product>
    </Message>
</AmazonEnvelope>

You may need to go through a few rounds of feed format modification and re-validation to complete all the new required fields.

Xpaths in validation error messages

Note that occasionally, the Xpath specified in a validation error may seem unrelated to the product type you're working with. This is because there are often many similar Xpaths that map to the same JSON field in the converted feed, and sometimes the transformer will be unable to determine which of the multiple Xpaths is most closely related to the product type you're working with. Even though the Xpath may seem wrong, it will still be converted to the correct product attribute in the converted feed.

For instance, this validation error could be returned when validating a converted POST_PRODUCT_TYPE feed:

[
    'field' => 'Message/Product/ProductData/Sports/FabricType',
    'error' => 'This field is required',
    'fieldDescription' => 'List all fabrics separated by \',\'. Indicate with % composition. Always add "Viscose" or "Rayon" instead of "Bamboo", and "Azlon" for Soy'
]

Even though the Message/Product/ProductData/Sports tag probably would not normally be present in SHOES product feeds, specifying the Message/Product/ProductData/Sports/FabricType tag will still fix the validation error and ensure your feed has all the data that Amazon requires.

Last updated