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 uploadPOST_INVENTORY_AVAILABILITY_DATA
- Inventory updatesPOST_PRODUCT_OVERRIDES_DATA
- Product override dataPOST_PRODUCT_PRICING_DATA
- Pricing dataPOST_PRODUCT_IMAGE_DATA
- Image dataPOST_PRODUCT_RELATIONSHIP_DATA
- Product relationships (variation relationships, etc.)POST_FLAT_FILE_INVLOADER_DATA
- Inventory loaderPOST_FLAT_FILE_LISTINGS_DATA
- Product listing dataPOST_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:
- Deep Dive into JSON Schema - Automating schema parsing and UI form generation
- Complete ProductType Guide - Detailed breakdown of ProductTypes for all categories
- Bulk Listing Architecture - System evolution from 0 to 100k daily listings
- Multi-Marketplace Strategies - Special requirements and optimizations for different regions
- Advanced Variation Handling - Techniques for complex variation relationships
- 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:
- SP-API Chinese Documentation
- SP-API Official Documentation
- JSON Schema Validator
- SP-API PHP SDK
- Postman Collection Templates
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