Building custom repricing automation? This guide covers everything developers need to integrate with Amazon's Selling Partner API (SP-API) for pricing automation, including endpoints, authentication, and best practices.
Understanding Amazon SP-API
Amazon's Selling Partner API (SP-API) is the successor to the legacy MWS API. It provides programmatic access to Amazon seller data, including pricing, inventory, and orders. For repricing, you'll primarily use the Pricing API and Catalog Items API.
Prerequisites
Before you start, you'll need: an Amazon Seller Central account (Professional plan), AWS account, and approved developer application. The approval process can take 2-4 weeks.
Key API Endpoints for Repricing
GET /pricing/{marketplace}/offers
Retrieve competitive pricing for products. Returns your price and competitor prices.
GET
Rate: 1 request/second
Required Scope: sellingpartnerapi::pricing
GET /catalog/v0/items/{asin}
Get product details including attributes, identifiers, and sales rank.
GET
Rate: 2 requests/second
Required Scope: catalog
PUT /listings/{marketplace}/items/{sku}
Update your product price. This is how you actually reprice.
PUT
Rate: 2 requests/second
Required Scope: sellingpartnerapi::listings
GET /orders/v0/orders
Retrieve order data to understand sales velocity and demand.
GET
Rate: 1 request/second
Required Scope: orders
Authentication Setup
SP-API uses OAuth 2.0 with JWT tokens. Here's the authentication flow:
const response = await fetch('https://api.amazon.com/auth/o2/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `grant_type=refresh_token&refresh_token=${REFRESH_TOKEN}&client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}`
});
const { access_token, expires_in } = await response.json();
Request Signing
All SP-API requests must be signed using AWS Signature Version 4:
const signedRequest = {
method: 'GET',
url: 'https://sellingpartnerapi-na.amazon.com/pricing/2022-07-01/offers',
params: {
MarketplaceId: 'ATVPDKIKX0DER',
Asins: 'B08N5WRWNW'
},
headers: {
'x-amz-access-token': access_token,
'host': 'sellingpartnerapi-na.amazon.com',
'amz-date': new Date().toISOString()
}
};
Building a Repricing Integration
Step 1: Fetch Competitive Prices
async function getCompetitorPrices(asins) {
const response = await spApiRequest({
endpoint: '/pricing/2022-07-01/offers',
params: {
MarketplaceId: 'ATVPDKIKX0DER',
Asins: asins.join(',')
}
});
return response.payload;
}
const prices = {
"B08N5WRWNW": {
product: {
asin: "B08N5WRWNW",
competitive_pricing: {
competitors: [
{ "condition": "new", "prices": [
{ "landed_price": { "amount": 29.99, "currency_code": "USD" }}
]}
]
}
}
}
};
Step 2: Apply Your Repricing Logic
async function calculateNewPrice(asin, competitors, myPrice) {
const floorPrice = 20.00;
const ceilingPrice = 45.00;
const lowestCompetitor = competitors
.filter(c => c.condition === 'new')
.map(c => c.prices[0].landed_price.amount)
.sort((a, b) => a - b)[0];
let newPrice = Math.max(floorPrice, Math.min(ceilingPrice, lowestCompetitor - 0.01));
if (Math.abs(newPrice - myPrice) >= 0.05) {
return newPrice;
}
return null;
}
Step 3: Update Your Price
async function updatePrice(sku, newPrice) {
const response = await spApiRequest({
method: 'PUT',
endpoint: `/listings/2022-07-01/items/${SELLER_ID}/${sku}`,
body: {
patches: [{
op: 'replace',
path: '/summaries/attributes/purchasable_offer',
value: [{
marketplaces: ['ATVPDKIKX0DER'],
our_price: [{
schedule: [{ quantity_upper_bound: "1", value_with_tax: { amount: newPrice, currency_code: "USD" }}]
}]
}]
}]
}
});
return response;
}
Rate Limiting Best Practices
| Endpoint |
Rate Limit |
Best Practice |
| Pricing Offers |
1 req/sec |
Batch ASINs (20 per request) |
| Catalog Items |
2 req/sec |
Cache responses (24hr TTL) |
| Listings Items |
2 req/sec |
Throttle price updates |
| Orders |
1 req/sec |
Sync daily, not real-time |
Pro Tip: Implement Exponential Backoff
When you hit rate limits, implement exponential backoff (1s, 2s, 4s, 8s...) instead of retrying immediately. Amazon's API will block abusive clients.
Error Handling
async function spApiRequest(config) {
try {
const response = await fetch(config.url, config);
const data = await response.json();
if (!response.ok) {
switch (response.status) {
case 429:
await sleep(1000);
return spApiRequest(config);
case 401:
await refreshToken();
return spApiRequest(config);
default:
throw new Error(`API Error: ${data.error_description}`);
}
}
return data;
} catch (error) {
console.error('SP-API Error:', error);
throw error;
}
}
Complete Repricing Worker Example
export default {
async scheduled(controller, env) {
const skus = await getMySkus();
const asins = skus.map(s => s.asin);
const prices = await getCompetitorPrices(asins);
for (const sku of skus) {
const competitors = prices[sku.asin]?.product?.competitive_pricing?.competitors;
const newPrice = await calculateNewPrice(sku.asin, competitors, sku.currentPrice);
if (newPrice) {
await updatePrice(sku.sku, newPrice);
console.log(`${sku.asin}: $${sku.currentPrice} -> $${newPrice}`);
}
await sleep(1000);
}
}
};
Pre-Built vs. Custom Integration
When to Build Custom
✓
You need unique repricing logic not available in tools
✓
You're an enterprise with complex requirements
✓
You want to integrate with internal systems
✓
You have development resources available
When to Use Pre-Built Tools
✓
Standard repricing strategies fit your needs
✓
Limited development resources
✓
Ongoing maintenance is a concern
Security Considerations
- Never expose credentials — Use environment variables and secrets managers
- Rotate tokens — Refresh tokens expire; implement auto-refresh
- Log access — Track all API calls for auditing
- Rate limit your application — Don't become the problematic client
- Validate inputs — Sanitize all data before API calls
Need Repricing Without the Code?
Skip the API integration. Get pre-built repricing with SP-API integration, intelligent pricing, and zero maintenance.
Start Free Trial — $29/mo
Amazon API
SP-API
Developer Guide
Pricing Automation
Integration