facebook pixel
Published on

Migrating deprecated Amazon feed types to the JSON_LISTINGS_FEED format

Amazon ​announced​ a few months ago that they will be deprecating all listings-related feed types in March 2025. This includes the feeds that most sellers are using to update their pricing and inventory, update product images and relationships, and create new products of any product type. Here are the feed types that are being deprecated:

  • POST_PRODUCT_DATA
  • POST_FLAT_FILE_LISTINGS_DATA
  • POST_FLAT_FILE_INVLOADER_DATA
  • POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA
  • POST_PRODUCT_PRICING_DATA
  • POST_INVENTORY_AVAILABILITY_DATA
  • POST_PRODUCT_IMAGE_DATA
  • POST_PRODUCT_OVERRIDES_DATA
  • POST_PRODUCT_RELATIONSHIP_DATA
  • POST_FLAT_FILE_CONVERGENCE_LISTINGS_DATA
  • POST_FLAT_FILE_BOOKLOADER_DATA
  • POST_UIEE_BOOKLOADER_DATA

If you're using any of those feed types in your listings management workflow, you will need to either switch to using the ​Listings API​, or the ​JSON_LISTINGS_FEED​, which is in essence a way to make bulk calls to the Listings API to avoid rate-limiting.

NOTE

We've developed a tool to help you migrate to the new format with minimal code. If you don't want to bother learning the ins and outs of the new feed format, you can check out the tool here.

The Listings API (and the JSON Listings Feed) use JSON Schema specifications to define product types' attributes, which is better than the old XML and flat-file format in that it's easier to validate programmatically, but worse in that it's much less easily human-readable, and migrating is quite complicated.

There is an official Amazon guide on ​building listings management workflows​, and another guide focused on ​migrating existing listings management systems​. There's a lot of good information there, but suffice to say, there are now many more steps to creating or updating a listing than there once were.

Use cases

There are two main use cases for the old feed types: updating inventory and listing attributes (prices, quantities, images, etc.), and creating new products or updating existing product attributes (things like hazmat data, product-type-specific information, etc). The JSON Listings Feed supports both of these use cases, but the process for each is different. I'm mostly going to talk about the JSON Listings Feed in this piece, but the process for the Listings API is very similar.

Updating inventory and listing attributes

This is the simpler of the two use cases, and supplants these deprecated feed types:

  • POST_PRODUCT_PRICING_DATA
  • POST_PRODUCT_IMAGE_DATA
  • POST_PRODUCT_OVERRIDES_DATA
  • POST_PRODUCT_RELATIONSHIP_DATA
  • POST_FLAT_FILE_INVLOADER_DATA
  • POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA
  • POST_INVENTORY_AVAILABILITY_DATA
  • Parts of POST_FLAT_FILE_BOOKLOADER_DATA
  • Parts of POST_UIEE_BOOKLOADER_DATA

There's a fairly comprehensive guide to the mappings between those old feed types' fields and their corresponding Listings API fields here. The reason this use case is simpler is that there is a limited set of inventory and listing attributes, and they are the same across all product types.

The main tasks you perform with this feed type are updating inventory availability and quantities, adjusting pricing, switching fulfillment channels, and changing product images and relationships. The format of the JSON Listings Feed is a bit harder to understand than the flat-file or XML formats, but here's the basic idea:

Creating new products and updating attributes on existing products

This use case is more complicated, and replaces the functionality of these deprecated feed types:

  • POST_PRODUCT_DATA
  • POST_FLAT_FILE_LISTINGS_DATA
  • POST_FLAT_FILE_CONVERGENCE_LISTINGS_DATA
  • Parts of POST_FLAT_FILE_BOOKLOADER_DATA
  • Parts of POST_UIEE_BOOKLOADER_DATA

Should I use the Listings API or the JSON Listings Feed?

In theory, if you're going to be updating fewer than 5 listings per second (or 18,000 listings per hour), you should be fine using the Listings API's endpoints, which have the advantage of being synchronous (whereas getting results back from the JSON Listings Feed is asynchronous). However, if you're already using feeds for your listings management workflow, it might be easier to switch to the JSON Listings Feed, because you can keep using your existing feed management infrastructure. The JSON Listings Feed also makes it possible to send create, update, and delete requests in a single feed, whereas the Listings API has separate endpoints for each type of operation.

The data format of the Listings API endpoints and the JSON Listings Feed are identical, so you can easily switch between the two – the JSON Listings Feed just wraps the content of multiple Listings API calls into a single JSON file.

JSON_LISTINGS_FEED format

At a high level, every JSON Listings Feed looks like this:

{
    "header": {
        "sellerId": "A21X5J1Y5Y1Y1Y1Y1X",
        "version": "2.0",
        "issueLocale": "en_US"
    },
    "messages": [...]
}

In the header, sellerId is your Amazon-assigned seller ID, which you can find here, which is specific to the Amazon region you're selling in, or your vendor code if you're an Amazon Vendor. version is always 2.0, and issueLocale is the locale/language that you want any error messages to be sent in.

The messages array contains the actual data for the feed. Each message is a JSON object that acts on a single product (referenced by SKU), along with the type of operation to perform (PATCH, UPDATE, PARTIAL_UPDATE, or DELETE). The fields in each message correspond to the attributes of the product type. In terms of HTTP verbs, UPDATE is a PUT request, PARTIAL_UPDATE is a POST request, PATCH is an PATCH, and DELETE is DELETE (the last two are pretty self-explanatory). For the purposes of this post, I'm going to ignore the PARTIAL_UPDATE operation, since its use case is mostly the same as PATCH but it lacks some features that PATCH has.

PATCH

A PATCH message might look like this:

{
  "messageId": 1,
  "sku": "MY_SKU_0001",
  "operationType": "PATCH",
  "productType": "PRODUCT",
  "patches": [
    {
      "op": "replace",
      "path": "/attributes/fulfillment_availability",
      "value": [
        {
          "quantity": 100,
          "fulfillment_channel_code": "DEFAULT"
        }
      ]
    },
    {
      "op": "delete",
      "path": "/attributes/other_offer_image_locator_1",
      "value": [{ "mediaLocation": "https://example.com/image.jpg" }]
    }
  ]
}

Confusingly, there are two different places where you have to specify an action verb if you're sending a PATCH message. The first is the operationType field, which should be PATCH. The second is the op field, which is either replace or delete, depending on whether you're replacing/creating an attribute or deleting an attribute. This gotcha only applies to PATCH messages, and you can ignore it for UPDATE and DELETE messages.

UPDATE

Here's an example of a UPDATE message:

{
  "messageId": 1,
  "sku": "MY_SKU_0001",
  "operationType": "UPDATE",
  "productType": "FLAT_SHEET",
  "attributes": {
    "externally_assigned_product_identifier": [
      {
        "type": "upc",
        "value": "123456789012"
      }
    ],
    "brand": [
      {
        "value": "My Brand",
        "language_tag": "en_US"
      }
    ],
    "bullet_point": [
      {
        "value": "My Bullet Point 1",
        "language_tag": "en_US"
      },
      {
        "value": "My Bullet Point 2",
        "language_tag": "en_US"
      }
    ],
    "country_of_origin": [
      {
        "value": "US"
      }
    ]
    // ...
  }
}

This is not a complete example for the FLAT_SHEET product type, but it shows the general structure of the UPDATE message.

Because UPDATE messages do a full update of the product, all required fields for the product type being updated must be specified. This is a bit more complicated than the PATCH message, but it's also the only way to create a new product. Each product type has its own set of required fields, which are fully specified in that product type's JSON Schema. You can fetch per-product-type JSON Schemas from the Product Type Definitions API. There are also many conditionally required fields, which are also laid out in the JSON Schema. Because the schemas are quite complicated, it's often easier to create an initial UPDATE message with the obviously required fields, and then use the Listings API's VALIDATION_PREVIEW mode to check for any missing attributes. Another option is to use a JSON Schema validator to check for missing attributes, but note that often Amazon will return additional errors even if your feed is compliant with the JSON Schema. The PHP JSON Schema validator I've been using is justinrainbow/json-schema.

DELETE

The DELETE message is straightforward:

{
  "messageId": 1,
  "sku": "MY_SKU_0001",
  "operationType": "DELETE"
}

This message will delete the product with the given SKU from your inventory.

A faster solution

To save you the hassle of reading tons of documentation and spending valuable development time testing the new code, I've developed a tool that allows you to transform your old feeds into the new format with a few lines of code. The tool is available at tools.highsidelabs.co, and is a one-time purchase (no recurring charges).

Once you've purchased the transformer for a given feed type, transforming your old feed to the new format is often as simple as this:

use SellingPartnerApi\FeedTransformer\Transformer;

$json = Transformer::fromFile(
    'POST_PRODUCT_IMAGE_DATA',  // Old feed type
    'path/to/old/feed.xml',     // Path to old feed file
    'ATVPDKIKX0DER'             // Amazon marketplace ID
);

There are some additional steps for certain feed types related to ensuring you have all the required fields specified, but the basic setup is the same. For more details on the specifics of the requirements for each feed type, check out the feed transformer docs.

Click here to get started.

There are a couple feed types the tool don't support yet, most importantly the POST_FLAT_FILE_LISTINGS_DATA feed. I've been limited by the fact that Amazon doesn't yet have an accurate field mapping available for that feed type, so it's impossible to make an accurate transformer for it (see this GitHub issue). I hope to be release a transformer for that feed type once Amazon has a more accurate field mapping available.

In case you aren't using PHP or are using an older version that isn't compatible with the feed transformer packages, I can also offer access to an API that wraps all the feed transformer packages on an as-needed basis. If you're interested in that, get in touch with me at jesse@highsidelabs.co.

To get started converting your old feeds, go to ​tools.highsidelabs.co​​ and select the feed types you need. If you have any questions about the tool or about the migration process in general, email me at ​jesse@highsidelabs.co​. I'm happy to help.

Stay updated on our work