API Updates

Amazon SP-API Major Update 2025: Complete XML to JSON Feed Migration Guide

📅 July 31, 2025⏱️ 20 min read👤 SpapiHub Team

Amazon SP-API Major Update: The Journey from XML to JSON - 2025 Feed Type Deprecation Deep Dive

Introduction

If you received this email from Amazon on July 31st, congratulations - you've officially entered the new era of SP-API:

"You are receiving this email as a notification to inform you that the following XML and Flat File Listings Feeds type values and operations have been successfully removed today, 7/31/2025..."

That's right, the XML Feeds that have been with us for years have finally reached their end of life. As someone who's been working with Amazon APIs for nearly a decade, I'd be lying if I said I wasn't a bit nostalgic. But technology marches forward, and today let's dive into what this transformation means for us developers.

1. The Complete List of Deprecated Feed Types

Let's take a moment to say goodbye to these old friends:

  • POST_PRODUCT_DATA - Product data upload
  • POST_INVENTORY_AVAILABILITY_DATA - Inventory updates
  • POST_PRODUCT_OVERRIDES_DATA - Product override data
  • POST_PRODUCT_PRICING_DATA - Pricing data
  • POST_PRODUCT_IMAGE_DATA - Image data
  • POST_PRODUCT_RELATIONSHIP_DATA - Product relationships (variation relationships, etc.)
  • POST_FLAT_FILE_INVLOADER_DATA - Inventory loader
  • POST_FLAT_FILE_LISTINGS_DATA - Product listing data
  • POST_FLAT_FILE_PRICEANDQUANTITYONLY_UPDATE_DATA - Price and quantity updates

Starting today, all calls to these APIs will fail. If your systems are still using these endpoints, it's time to accelerate your migration efforts.

2. Why Transition from XML to JSON?

2.1 Technical Considerations

Let's be honest - while XML is structurally rigorous, it feels somewhat cumbersome in modern web development:

<!-- The old XML way -->
<Message>
    <MessageID>1</MessageID>
    <OperationType>Update</OperationType>
    <Product>
        <SKU>ABC-123</SKU>
        <StandardProductID>
            <Type>ASIN</Type>
            <Value>B00EXAMPLE</Value>
        </StandardProductID>
        <Quantity>100</Quantity>
    </Product>
</Message>

In contrast, JSON is much more concise:

{
  "sku": "ABC-123",
  "product_id": {
    "type": "ASIN",
    "value": "B00EXAMPLE"
  },
  "quantity": 100
}

2.2 Development Efficiency Improvements

  • Smaller data footprint: JSON format reduces data transmission by 30-40% on average compared to XML
  • Faster parsing: Modern programming languages have native JSON support
  • Easier debugging: JSON readability is significantly better than XML
  • More flexible schema validation: JSON Schema is as expressive as XSD but easier to understand

3. New Implementation Methods Explained

3.1 Single Item Operations: Using putListingsItem

For creating or updating individual items, the Listings Items API is now recommended. Check the putListingsItem API documentation for detailed information.

PHP Example:

<?php
// Create or fully update a listing
function createOrUpdateListing($sellerId, $sku, $productData) {
    $client = new \GuzzleHttp\Client();
    
    $requestBody = [
        'productType' => 'SHIRT',
        'attributes' => [
            'title' => [
                ['value' => 'Amazing Cotton T-Shirt']
            ],
            'description' => [
                ['value' => 'High quality 100% cotton t-shirt']
            ],
            'bullet_points' => [
                ['value' => ['Comfortable fit', 'Machine washable', 'Available in multiple colors']]
            ],
            'brand' => [
                ['value' => 'YourBrand']
            ],
            // Inventory and pricing information
            'fulfillment_availability' => [
                [
                    'fulfillment_channel_code' => 'DEFAULT',
                    'quantity' => 100
                ]
            ],
            'purchasable_offer' => [
                [
                    'currency' => 'USD',
                    'marketplace_id' => 'ATVPDKIKX0DER',
                    'our_price' => [
                        [
                            'schedule' => [
                                ['value_with_tax' => 19.99]
                            ]
                        ]
                    ]
                ]
            ]
        ]
    ];
    
    $response = $client->request('PUT', 
        "https://sellingpartnerapi-na.amazon.com/listings/2021-08-01/items/{$sellerId}/{$sku}", 
        [
            'headers' => [
                'Authorization' => 'Bearer ' . getAccessToken(),
                'Content-Type' => 'application/json',
                'x-amz-access-token' => getAccessToken()
            ],
            'json' => $requestBody
        ]
    );
    
    return json_decode($response->getBody(), true);
}

Postman Example:

{
    "productType": "SHIRT",
    "attributes": {
        "title": [
            {
                "value": "Amazing Cotton T-Shirt"
            }
        ],
        "description": [
            {
                "value": "High quality 100% cotton t-shirt"
            }
        ],
        "fulfillment_availability": [
            {
                "fulfillment_channel_code": "DEFAULT",
                "quantity": 100
            }
        ]
    }
}

3.2 Bulk Operations: JSON_LISTINGS_FEED

When handling large volumes of items (like updating thousands of SKUs daily), the Feed API is more efficient. See createFeed documentation and createFeedDocument documentation for details.

PHP Bulk Update Example:

<?php
// Step 1: Create Feed Document
function createFeedDocument() {
    $client = new \GuzzleHttp\Client();
    
    $response = $client->request('POST', 
        'https://sellingpartnerapi-na.amazon.com/feeds/2021-06-30/documents',
        [
            'headers' => [
                'Authorization' => 'Bearer ' . getAccessToken(),
                'Content-Type' => 'application/json'
            ],
            'json' => [
                'contentType' => 'application/json'
            ]
        ]
    );
    
    return json_decode($response->getBody(), true);
}

// Step 2: Upload Feed Content
function uploadFeedContent($url, $feedContent) {
    $client = new \GuzzleHttp\Client();
    
    $feedData = [
        'header' => [
            'sellerId' => 'YOUR_SELLER_ID',
            'version' => '2.0',
            'feedId' => time(),
            'report' => [
                'includedData' => ['issues', 'status'],
                'apiVersion' => '2021-08-01'
            ]
        ],
        'messages' => [
            [
                'messageId' => 1,
                'sku' => 'SKU-001',
                'operationType' => 'UPDATE',
                'productType' => 'PRODUCT',
                'attributes' => [
                    'fulfillment_availability' => [
                        [
                            'fulfillment_channel_code' => 'DEFAULT',
                            'quantity' => 50
                        ]
                    ]
                ]
            ],
            [
                'messageId' => 2,
                'sku' => 'SKU-002',
                'operationType' => 'UPDATE',
                'productType' => 'PRODUCT',
                'attributes' => [
                    'fulfillment_availability' => [
                        [
                            'fulfillment_channel_code' => 'DEFAULT',
                            'quantity' => 75
                        ]
                    ]
                ]
            ]
        ]
    ];
    
    $response = $client->request('PUT', $url, [
        'body' => json_encode($feedData),
        'headers' => [
            'Content-Type' => 'application/json'
        ]
    ]);
    
    return $response->getStatusCode() === 200;
}

// Step 3: Create Feed
function createFeed($feedDocumentId) {
    $client = new \GuzzleHttp\Client();
    
    $response = $client->request('POST', 
        'https://sellingpartnerapi-na.amazon.com/feeds/2021-06-30/feeds',
        [
            'headers' => [
                'Authorization' => 'Bearer ' . getAccessToken(),
                'Content-Type' => 'application/json'
            ],
            'json' => [
                'feedType' => 'JSON_LISTINGS_FEED',
                'marketplaceIds' => ['ATVPDKIKX0DER'],
                'inputFeedDocumentId' => $feedDocumentId
            ]
        ]
    );
    
    return json_decode($response->getBody(), true);
}

3.3 Querying Item Information

Use the getListingsItem API to retrieve detailed item information:

PHP Example:

<?php
function getListingDetails($sellerId, $sku) {
    $client = new \GuzzleHttp\Client();
    
    $response = $client->request('GET', 
        "https://sellingpartnerapi-na.amazon.com/listings/2021-08-01/items/{$sellerId}/{$sku}",
        [
            'headers' => [
                'Authorization' => 'Bearer ' . getAccessToken(),
                'x-amz-access-token' => getAccessToken()
            ],
            'query' => [
                'marketplaceIds' => 'ATVPDKIKX0DER',
                'includedData' => 'attributes,issues,offers,fulfillmentAvailability'
            ]
        ]
    );
    
    return json_decode($response->getBody(), true);
}

Postman Example:

GET https://sellingpartnerapi-na.amazon.com/listings/2021-08-01/items/{{sellerId}}/{{sku}}?marketplaceIds=ATVPDKIKX0DER&includedData=attributes,issues

Headers:
Authorization: Bearer {{access_token}}
x-amz-access-token: {{access_token}}

3.4 Partial Updates

Use the patchListingsItem API to update only specific fields:

PHP Example:

<?php
// Update inventory quantity only
function updateInventoryOnly($sellerId, $sku, $quantity) {
    $client = new \GuzzleHttp\Client();
    
    $patchData = [
        'productType' => 'PRODUCT',
        'patches' => [
            [
                'op' => 'replace',
                'path' => '/attributes/fulfillment_availability',
                'value' => [
                    [
                        'fulfillment_channel_code' => 'DEFAULT',
                        'quantity' => $quantity
                    ]
                ]
            ]
        ]
    ];
    
    $response = $client->request('PATCH', 
        "https://sellingpartnerapi-na.amazon.com/listings/2021-08-01/items/{$sellerId}/{$sku}",
        [
            'headers' => [
                'Authorization' => 'Bearer ' . getAccessToken(),
                'Content-Type' => 'application/json'
            ],
            'json' => $patchData
        ]
    );
    
    return json_decode($response->getBody(), true);
}

4. From XSD to JSON Schema

4.1 Retrieving Product Type Definitions

Use the Product Type Definitions API to get JSON Schema for product types:

<?php
function getProductTypeSchema($productType = 'SHIRT') {
    $client = new \GuzzleHttp\Client();
    
    $response = $client->request('GET', 
        "https://sellingpartnerapi-na.amazon.com/definitions/2020-09-01/productTypes/{$productType}",
        [
            'headers' => [
                'Authorization' => 'Bearer ' . getAccessToken()
            ],
            'query' => [
                'marketplaceIds' => 'ATVPDKIKX0DER',
                'requirements' => 'LISTING'  // or 'LISTING_PRODUCT_ONLY', 'LISTING_OFFER_ONLY'
            ]
        ]
    );
    
    $result = json_decode($response->getBody(), true);
    return $result['schema'];
}

4.2 Data Validation

Validate data using JSON Schema:

<?php
use Opis\JsonSchema\Validator;
use Opis\JsonSchema\Schema;

function validateProductData($productData, $schemaData) {
    $validator = new Validator();
    
    // Create schema object
    $schema = Schema::fromJsonString(json_encode($schemaData));
    
    // Validate data
    $result = $validator->validate($productData, $schema);
    
    if ($result->hasErrors()) {
        $errors = [];
        foreach ($result->getErrors() as $error) {
            $errors[] = [
                'path' => $error->dataPointer(),
                'message' => $error->message()
            ];
        }
        return ['valid' => false, 'errors' => $errors];
    }
    
    return ['valid' => true];
}

5. Error Handling and Status Monitoring

5.1 Checking Feed Processing Status

Use the getFeed API to check feed processing status:

<?php
function checkFeedStatus($feedId) {
    $client = new \GuzzleHttp\Client();
    
    $response = $client->request('GET', 
        "https://sellingpartnerapi-na.amazon.com/feeds/2021-06-30/feeds/{$feedId}",
        [
            'headers' => [
                'Authorization' => 'Bearer ' . getAccessToken()
            ]
        ]
    );
    
    $feedInfo = json_decode($response->getBody(), true);
    
    // Check processing status
    switch($feedInfo['processingStatus']) {
        case 'DONE':
            // Get processing report
            if (isset($feedInfo['resultFeedDocumentId'])) {
                return getFeedReport($feedInfo['resultFeedDocumentId']);
            }
            break;
        case 'FATAL':
            // Processing failed
            error_log("Feed processing failed: " . json_encode($feedInfo));
            break;
        case 'IN_QUEUE':
        case 'IN_PROGRESS':
            // Continue waiting
            return ['status' => 'processing'];
    }
    
    return $feedInfo;
}

5.2 Handling Listing Restrictions

Check restrictions before listing using the getListingsRestrictions API:

<?php
function checkListingRestrictions($asin, $condition = 'new') {
    $client = new \GuzzleHttp\Client();
    
    $response = $client->request('GET', 
        'https://sellingpartnerapi-na.amazon.com/listings/2021-08-01/restrictions',
        [
            'headers' => [
                'Authorization' => 'Bearer ' . getAccessToken()
            ],
            'query' => [
                'asin' => $asin,
                'conditionType' => $condition,
                'sellerId' => 'YOUR_SELLER_ID',
                'marketplaceIds' => 'ATVPDKIKX0DER'
            ]
        ]
    );
    
    $restrictions = json_decode($response->getBody(), true);
    
    // Check for restrictions
    foreach ($restrictions['restrictions'] as $restriction) {
        if (!empty($restriction['reasons'])) {
            return [
                'restricted' => true,
                'reasons' => $restriction['reasons']
            ];
        }
    }
    
    return ['restricted' => false];
}

6. Practical Migration Tips

6.1 Building a Universal Request Function

<?php
class SpApiClient {
    private $accessToken;
    private $endpoint = 'https://sellingpartnerapi-na.amazon.com';
    
    public function __construct($accessToken) {
        $this->accessToken = $accessToken;
    }
    
    public function request($method, $path, $params = []) {
        $client = new \GuzzleHttp\Client();
        
        $options = [
            'headers' => [
                'Authorization' => 'Bearer ' . $this->accessToken,
                'x-amz-access-token' => $this->accessToken,
                'Content-Type' => 'application/json'
            ]
        ];
        
        if ($method === 'GET' && !empty($params)) {
            $options['query'] = $params;
        } else if (!empty($params)) {
            $options['json'] = $params;
        }
        
        try {
            $response = $client->request($method, $this->endpoint . $path, $options);
            return json_decode($response->getBody(), true);
        } catch (\GuzzleHttp\Exception\ClientException $e) {
            $errorBody = json_decode($e->getResponse()->getBody(), true);
            throw new Exception('API Error: ' . json_encode($errorBody));
        }
    }
}

6.2 Best Practices for Bulk Data Processing

<?php
// Optimized bulk inventory update
function batchUpdateInventory($inventoryUpdates) {
    $chunks = array_chunk($inventoryUpdates, 1000); // 1000 items per batch
    
    foreach ($chunks as $chunk) {
        $messages = [];
        foreach ($chunk as $index => $update) {
            $messages[] = [
                'messageId' => $index + 1,
                'sku' => $update['sku'],
                'operationType' => 'UPDATE',
                'productType' => 'PRODUCT',
                'attributes' => [
                    'fulfillment_availability' => [
                        [
                            'fulfillment_channel_code' => 'DEFAULT',
                            'quantity' => $update['quantity']
                        ]
                    ]
                ]
            ];
        }
        
        // Submit this batch
        submitFeedBatch($messages);
        
        // Avoid rate limiting
        sleep(1);
    }
}

7. Our Real-World Experience

7.1 From Early Adoption to Scale

We were among the first to adopt the JSON Listings API when Amazon launched it. Over the years, we've successfully listed over 1 million products through SP-API, covering virtually all major marketplaces including the US, Europe, Japan, and Australia.

7.2 Lessons Learned and Key Insights

Here are some critical points from our experience:

1. Choosing the Right ProductType Many developers struggle with selecting the correct ProductType. Our approach:

  • Search for similar products' ASINs using keywords
  • Use getCatalogItem to retrieve the productType for that ASIN
  • When in doubt, use the searchDefinitionsProductTypes API

2. Smart JSON Schema Parsing Amazon's JSON Schema is complex, and manual parsing is error-prone. We've developed automated tools that:

  • Automatically identify required fields
  • Dynamically adjust required items based on conditionalRequired rules
  • Provide intelligent hints for optional values and format requirements

3. Technical Architecture for Mass Listing To achieve daily listing volumes in the tens of thousands:

  • Multi-threading/queue processing to maximize API rate limits
  • Intelligent retry mechanisms for handling temporary errors
  • Real-time monitoring systems for immediate issue detection and resolution

7.3 Coming Soon: More In-Depth Content

This article is just the beginning. I'll be sharing more advanced content in the coming weeks:

SP-API Listing Mastery Series:

  1. Deep Dive into JSON Schema - Automating schema parsing and UI form generation
  2. Complete ProductType Guide - Detailed breakdown of ProductTypes for all categories
  3. Bulk Listing Architecture - System evolution from 0 to 100k daily listings
  4. Multi-Marketplace Strategies - Special requirements and optimizations for different regions
  5. Advanced Variation Handling - Techniques for complex variation relationships
  6. Error Handling Best Practices - Comprehensive guide to error codes and solutions

Follow me for cutting-edge SP-API insights! If you found this article helpful, please like 👍, bookmark ⭐, and comment 💬. Drop your most pressing questions in the comments - topics with the most engagement will get detailed tutorials first.

7.4 Special Note

If your business involves handling sensitive data (like buyer information or order details), you may need to apply for PII (Personally Identifiable Information) permissions. The application process has certain requirements, including detailed use case descriptions and data security measures. If you're facing challenges with PII permission applications, feel free to reach out - we have extensive experience to share.

Conclusion

The transition from XML to JSON is more than just a format change - it's an upgrade to the entire product management philosophy. The new API design is more RESTful, faster, provides better error messages, and offers a dramatically improved developer experience.

While the migration process might be painful, it's definitely worth it in the long run. I strongly recommend starting your migration efforts now rather than waiting until the last minute.

Remember, technical debt is like credit card debt - the longer you wait, the more interest you pay. Act now while there's still time!


Resources:

Next Episode Preview: "JSON Schema Deep Dive - Master Amazon Product Attribute Auto-Population in 5 Minutes" - Stay tuned!


Published on spapihub.com - Your go-to resource for SP-API development

Tags

SP-APIJSON ListingsFeed MigrationXML DeprecationAmazon APIProduct ListingsBulk UploadJSON SchemaputListingsItempatchListingsItemJSON_LISTINGS_FEED

Ready to Get Started with SP-API?

Our expert team can help you navigate the approval process and implement a robust SP-API integration for your business.

Get Professional Help