Ringkasan
Amazon Selling Partner API (SP-API) adalah API berbasis REST yang memungkinkan akses terprogram ke data penjual untuk pesanan, inventaris, daftar produk, dan pemenuhan. API ini menggunakan otentikasi OAuth 2.0 dengan peran IAM, memerlukan penandatanganan AWS SigV4, dan menerapkan batas kecepatan yang bervariasi per endpoint (0.1 hingga 100 permintaan per detik). Panduan ini mencakup pengaturan akun, otentikasi, endpoint inti, langganan webhook, dan strategi penerapan produksi.
Pendahuluan
Amazon memproses lebih dari 350 juta produk di 200+ marketplace di seluruh dunia. Bagi pengembang yang membangun alat e-commerce, sistem manajemen inventaris, atau platform analitik, integrasi Amazon SP-API bukanlah pilihan, melainkan sebuah keharusan.
Inilah kenyataannya: penjual yang mengelola operasi Amazon kehilangan 20-30 jam setiap minggu untuk entri data manual di seluruh pesanan, inventaris, dan daftar produk. Integrasi SP-API yang solid mengotomatiskan sinkronisasi pesanan, pembaruan inventaris, dan manajemen daftar produk di berbagai marketplace.
Panduan ini membahas seluruh proses integrasi Amazon SP-API. Anda akan mempelajari pengaturan peran IAM, otorisasi OAuth 2.0, penandatanganan permintaan AWS SigV4, manajemen pesanan dan inventaris, langganan notifikasi, dan pemecahan masalah. Pada akhirnya, Anda akan memiliki integrasi Amazon yang siap produksi.
Apa Itu Amazon SP-API?
Amazon Selling Partner API (SP-API) adalah API berbasis REST yang menyediakan akses terprogram ke data Seller Central. Ini menggantikan Marketplace Web Service (MWS) yang lebih lama dengan keamanan, kinerja, dan fungsionalitas yang lebih baik.
Kemampuan Utama
SP-API menangani:
- Pengambilan pesanan dan pembaruan status
- Manajemen inventaris di seluruh marketplace
- Pembuatan, pembaruan, dan penghapusan daftar produk
- Manajemen pengiriman FBA (Fulfillment by Amazon)
- Harga produk dan analisis kompetitif
- Pembuatan laporan dan analitik
- Manajemen Konten A+
- Analitik merek dan data periklanan
Perbandingan SP-API vs MWS
| Fitur | SP-API | MWS (Lama) |
|---|---|---|
| Arsitektur | RESTful JSON | Berbasis XML |
| Otentikasi | OAuth 2.0 + IAM | Token Otentikasi MWS |
| Keamanan | Penandatanganan AWS SigV4 | Token sederhana |
| Batas Kecepatan | Dinamis per endpoint | Kuota tetap |
| Marketplace | Endpoint terpadu | Spesifik wilayah |
| Status | Saat ini | Diusangkan (Des 2025) |
Segera migrasikan integrasi MWS apa pun ke SP-API. Amazon mengumumkan penghentian penuh MWS untuk Desember 2025.
Ikhtisar Arsitektur API
Amazon menggunakan struktur API regional dengan otorisasi terpusat:
https://sellingpartnerapi-na.amazon.com (Amerika Utara)
https://sellingpartnerapi-eu.amazon.com (Eropa)
https://sellingpartnerapi-fe.amazon.com (Timur Jauh)
Semua permintaan memerlukan:
- Tanda tangan AWS SigV4
- Token akses dari alur OAuth
- Izin peran IAM yang sesuai
- ID permintaan untuk pelacakan
Marketplace yang Didukung
| Wilayah | Marketplace | Endpoint API |
|---|---|---|
| Amerika Utara | AS, CA, MX | sellingpartnerapi-na.amazon.com |
| Eropa | Inggris, Jerman, Prancis, Italia, Spanyol, Belanda, Swedia, Polandia, Turki, Mesir, India, UEA, Arab Saudi | sellingpartnerapi-eu.amazon.com |
| Timur Jauh | Jepang, Australia, Singapura, Brasil | sellingpartnerapi-fe.amazon.com |
Memulai: Pengaturan Akun dan IAM
Langkah 1: Buat Akun Pengembang Amazon Anda
Sebelum mengakses SP-API, Anda memerlukan akses akun yang tepat:
- Kunjungi Amazon Developer Central
- Masuk dengan akun Amazon Anda (harus memiliki akses Seller Central)
- Navigasikan ke Selling Partner API di dasbor
- Setujui Perjanjian Pengembang
Langkah 2: Daftarkan Aplikasi Anda
Buat profil aplikasi di Seller Central:
- Masuk ke Seller Central
- Navigasikan ke Aplikasi dan Layanan > Kembangkan Aplikasi
- Klik Tambahkan Aplikasi Baru
- Isi detail aplikasi:
- Nama Aplikasi: Nama yang jelas dan deskriptif
- Jenis Aplikasi: Pilih "Dikembangkan sendiri" atau "Pihak ketiga"
- Kasus Penggunaan: Jelaskan tujuan integrasi Anda
- URI Pengalihan: URL HTTPS untuk callback OAuth
Setelah pengiriman, Anda akan menerima:
- ID Aplikasi: Pengidentifikasi aplikasi publik Anda
- ID Klien: Digunakan dalam URL otorisasi OAuth
- Rahasia Klien: Rahasia API pribadi Anda (jangan pernah mengungkapkannya)
Catatan keamanan: Simpan kredensial dalam variabel lingkungan, jangan pernah dalam kode:
# .env file
AMAZON_APPLICATION_ID="amzn1.application.xxxxx"
AMAZON_CLIENT_ID="amzn1.account.xxxxx"
AMAZON_CLIENT_SECRET="your_client_secret_here"
AMAZON_SELLER_ID="your_seller_id_here"
AWS_ACCESS_KEY_ID="your_aws_access_key"
AWS_SECRET_ACCESS_KEY="your_aws_secret_key"
AWS_REGION="us-east-1"
Langkah 3: Buat Peran IAM untuk SP-API
SP-API memerlukan peran IAM dengan izin khusus:
- Masuk ke Konsol AWS IAM
- Navigasikan ke Peran > Buat Peran
- Pilih Akun AWS Lain sebagai entitas tepercaya
- Masukkan ID akun Amazon untuk wilayah Anda:
- Amerika Utara:
906394416454 - Eropa:
336853085554 - Timur Jauh:
774466381866
Langkah 4: Konfigurasi Kebijakan IAM
Lampirkan kebijakan ini ke peran IAM Anda:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"execute-api:Invoke"
],
"Resource": [
"arn:aws:execute-api:*:*:*/prod/*/sellingpartnerapi/*"
]
}
]
}
Beri nama peran Anda sesuatu yang deskriptif seperti SellingPartnerApiRole dan catat ARN-nya.
Langkah 5: Tautkan Peran IAM ke Aplikasi
Hubungkan peran IAM Anda ke aplikasi SP-API:
- Kembali ke Seller Central > Kembangkan Aplikasi
- Pilih aplikasi Anda
- Klik Edit > ARN Peran IAM
- Masukkan ARN peran IAM Anda
- Simpan perubahan
Amazon memvalidasi peran IAM dalam beberapa menit. Anda akan melihat status "Tertaut" saat siap.
Alur Otentikasi OAuth 2.0
Memahami OAuth SP-API
Amazon menggunakan OAuth 2.0 untuk otorisasi. Berikut adalah alur lengkapnya:
1. Penjual mengklik "Otorisasi" di aplikasi Anda
2. Aplikasi Anda mengalihkan ke URL otorisasi Amazon
3. Penjual masuk dan memberikan izin
4. Amazon mengalihkan kembali dengan kode otorisasi
5. Aplikasi Anda menukarkan kode untuk token LWA (Login with Amazon)
6. Aplikasi Anda menukarkan token LWA untuk token akses SP-API
7. Aplikasi Anda menggunakan token akses untuk panggilan API (ditandatangani SigV4)
8. Segarkan token ketika token akses kedaluwarsa (1 jam)
Langkah 6: Hasilkan URL Otorisasi
Buat URL otorisasi OAuth:
const generateAuthUrl = (clientId, redirectUri, state) => {
const baseUrl = 'https://www.amazon.com/sp/apps/oauth/authorize';
const params = new URLSearchParams({
application_id: process.env.AMAZON_APPLICATION_ID,
client_id: clientId,
redirect_uri: redirectUri,
state: state, // Random string for CSRF protection
scope: 'sellingpartnerapi::notifications'
});
return `${baseUrl}?${params.toString()}`;
};
// Usage
const authUrl = generateAuthUrl(
process.env.AMAZON_CLIENT_ID,
'https://your-app.com/callback',
crypto.randomBytes(16).toString('hex')
);
console.log(`Redirect user to: ${authUrl}`);
Cakupan OAuth yang Diperlukan
Minta hanya izin yang dibutuhkan aplikasi Anda:
| Cakupan | Deskripsi | Kasus Penggunaan |
|---|---|---|
sellingpartnerapi::notifications |
Menerima notifikasi | Langganan Webhook |
sellingpartnerapi::migration |
Migrasi dari MWS | Integrasi lama |
Sebagian besar akses API dikontrol oleh kebijakan IAM, bukan cakupan OAuth.
Langkah 7: Tukarkan Kode dengan Token LWA
Tangani callback OAuth dan tukarkan kode otorisasi:
const exchangeCodeForLwaToken = async (code, redirectUri) => {
const response = await fetch('https://api.amazon.com/auth/o2/token', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
grant_type: 'authorization_code',
client_id: process.env.AMAZON_CLIENT_ID,
client_secret: process.env.AMAZON_CLIENT_SECRET,
redirect_uri: redirectUri,
code: code
})
});
if (!response.ok) {
const error = await response.json();
throw new Error(`LWA Token Error: ${error.error_description}`);
}
const data = await response.json();
return {
access_token: data.access_token,
refresh_token: data.refresh_token,
expires_in: data.expires_in, // Typically 3600 seconds (1 hour)
token_type: data.token_type
};
};
// Handle callback route
app.get('/callback', async (req, res) => {
const { spapi_oauth_code, state } = req.query;
// Verify state matches what you sent (CSRF protection)
if (state !== req.session.oauthState) {
return res.status(400).send('Invalid state parameter');
}
try {
const tokens = await exchangeCodeForLwaToken(spapi_oauth_code, 'https://your-app.com/callback');
// Store tokens in database associated with seller
await db.sellers.update(req.session.sellerId, {
amazon_lwa_access_token: tokens.access_token,
amazon_lwa_refresh_token: tokens.refresh_token,
amazon_token_expires: Date.now() + (tokens.expires_in * 1000)
});
res.redirect('/dashboard');
} catch (error) {
console.error('Token exchange failed:', error);
res.status(500).send('Authentication failed');
}
});
Langkah 8: Tukarkan Token LWA untuk Kredensial SP-API
Gunakan token akses LWA untuk mendapatkan kredensial AWS sementara:
const assumeRole = async (lwaAccessToken) => {
const response = await fetch('https://api.amazon.com/auth/o2/token', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
grant_type: 'client_credentials',
client_id: process.env.AMAZON_CLIENT_ID,
client_secret: process.env.AMAZON_CLIENT_SECRET,
scope: 'sellingpartnerapi::notifications'
})
});
const data = await response.json();
// Exchange for AWS credentials via STS
const stsResponse = await fetch('https://sts.amazonaws.com/', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Bearer ${data.access_token}`
},
body: new URLSearchParams({
Action: 'AssumeRole',
RoleArn: 'arn:aws:iam::YOUR_ACCOUNT:role/SellingPartnerApiRole',
RoleSessionName: 'sp-api-session',
Version: '2011-06-15'
})
});
return stsResponse;
};
Langkah 9: Terapkan Penyegaran Token
Token akses kedaluwarsa setelah 1 jam. Terapkan penyegaran otomatis:
const refreshLwaToken = async (refreshToken) => {
const response = await fetch('https://api.amazon.com/auth/o2/token', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
grant_type: 'refresh_token',
client_id: process.env.AMAZON_CLIENT_ID,
client_secret: process.env.AMAZON_CLIENT_SECRET,
refresh_token: refreshToken
})
});
const data = await response.json();
return {
access_token: data.access_token,
refresh_token: data.refresh_token, // Always save the new refresh token
expires_in: data.expires_in
};
};
// Middleware to ensure valid token
const ensureValidToken = async (sellerId) => {
const seller = await db.sellers.findById(sellerId);
// Check if token expires within 5 minutes
if (seller.amazon_token_expires < Date.now() + 300000) {
const newTokens = await refreshLwaToken(seller.amazon_lwa_refresh_token);
await db.sellers.update(sellerId, {
amazon_lwa_access_token: newTokens.access_token,
amazon_lwa_refresh_token: newTokens.refresh_token,
amazon_token_expires: Date.now() + (newTokens.expires_in * 1000)
});
return newTokens.access_token;
}
return seller.amazon_lwa_access_token;
};
Penandatanganan Permintaan AWS SigV4
Memahami SigV4
Semua permintaan SP-API memerlukan penandatanganan AWS Signature Version 4 (SigV4). Ini memastikan keaslian dan integritas permintaan.
Proses Penandatanganan SigV4
const crypto = require('crypto');
class SigV4Signer {
constructor(accessKey, secretKey, region, service = 'execute-api') {
this.accessKey = accessKey;
this.secretKey = secretKey;
this.region = region;
this.service = service;
}
sign(method, url, body = '', headers = {}) {
const parsedUrl = new URL(url);
const now = new Date();
// Step 1: Create canonical request
const amzDate = now.toISOString().replace(/[:-]|\.\d{3}/g, '');
const dateStamp = amzDate.slice(0, 8);
headers['host'] = parsedUrl.host;
headers['x-amz-date'] = amzDate;
headers['x-amz-access-token'] = this.accessToken;
headers['content-type'] = 'application/json';
const canonicalHeaders = Object.entries(headers)
.sort(([a], [b]) => a.localeCompare(b))
.map(([k, v]) => `${k.toLowerCase()}:${v.trim()}`)
.join('\n');
const signedHeaders = Object.keys(headers)
.sort()
.map(k => k.toLowerCase())
.join(';');
const payloadHash = crypto.createHash('sha256').update(body).digest('hex');
const canonicalRequest = [
method.toUpperCase(),
parsedUrl.pathname,
parsedUrl.search.slice(1),
canonicalHeaders,
'',
signedHeaders,
payloadHash
].join('\n');
// Step 2: Create string to sign
const algorithm = 'AWS4-HMAC-SHA256';
const credentialScope = `${dateStamp}/${this.region}/${this.service}/aws4_request`;
const stringToSign = [
algorithm,
amzDate,
credentialScope,
crypto.createHash('sha256').update(canonicalRequest).digest('hex')
].join('\n');
// Step 3: Calculate signature
const kDate = this.hmac(`AWS4${this.secretKey}`, dateStamp);
const kRegion = this.hmac(kDate, this.region);
const kService = this.hmac(kRegion, this.service);
const kSigning = this.hmac(kService, 'aws4_request');
const signature = this.hmac(kSigning, stringToSign, 'hex');
// Step 4: Add authorization header
const authorization = `${algorithm} Credential=${this.accessKey}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`;
return {
headers: {
...headers,
'Authorization': authorization
},
canonicalRequest,
stringToSign,
signature
};
}
hmac(key, data, encoding = 'buffer') {
return crypto.createHmac('sha256', key).update(data).digest(encoding);
}
}
// Usage
const signer = new SigV4Signer(
process.env.AWS_ACCESS_KEY_ID,
process.env.AWS_SECRET_ACCESS_KEY,
'us-east-1'
);
const signedRequest = signer.sign('GET', 'https://sellingpartnerapi-na.amazon.com/orders/v0/orders', '', {
'x-amz-access-token': accessToken
});
Menggunakan AWS SDK untuk SigV4
Sederhanakan penandatanganan dengan AWS SDK:
const { SignatureV4 } = require('@aws-sdk/signature-v4');
const { Sha256 } = require('@aws-crypto/sha256-js');
const signer = new SignatureV4({
credentials: {
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
},
region: 'us-east-1',
service: 'execute-api',
sha256: Sha256
});
const makeSpApiRequest = async (method, endpoint, accessToken, body = null) => {
const url = new URL(endpoint);
const headers = {
'host': url.host,
'content-type': 'application/json',
'x-amz-access-token': accessToken,
'x-amz-date': new Date().toISOString().replace(/[:-]|\.\d{3}/g, '')
};
const signedRequest = await signer.sign({
method,
hostname: url.hostname,
path: url.pathname,
query: Object.fromEntries(url.searchParams),
headers,
body: body ? JSON.stringify(body) : undefined
});
const response = await fetch(endpoint, {
method,
headers: signedRequest.headers,
body: signedRequest.body
});
if (!response.ok) {
const error = await response.json();
throw new Error(`SP-API Error: ${error.errors?.[0]?.message || response.statusText}`);
}
return response.json();
};
API Pesanan
Mengambil Pesanan
Ambil pesanan dengan opsi pemfilteran:
const getOrders = async (accessToken, options = {}) => {
const params = new URLSearchParams({
createdAfter: options.createdAfter, // ISO 8601 format
createdBefore: options.createdBefore,
orderStatuses: options.orderStatuses?.join(',') || '',
marketplaceIds: options.marketplaceIds?.join(',') || ['ATVPDKIKX0DER'], // US
maxResultsPerPage: options.maxResultsPerPage || 100
});
// Remove empty params
for (const [key, value] of params.entries()) {
if (!value) params.delete(key);
}
const endpoint = `https://sellingpartnerapi-na.amazon.com/orders/v0/orders?${params.toString()}`;
return makeSpApiRequest('GET', endpoint, accessToken);
};
// Usage example
const orders = await getOrders(accessToken, {
createdAfter: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString(), // Last 24 hours
orderStatuses: ['Unshipped', 'PartiallyShipped'],
marketplaceIds: ['ATVPDKIKX0DER'] // US marketplace
});
Struktur Respons Pesanan
{
"payload": {
"orders": [
{
"amazon_order_id": "112-1234567-1234567",
"seller_order_id": "ORDER-001",
"purchase_date": "2026-03-19T10:30:00Z",
"last_update_date": "2026-03-19T14:45:00Z",
"order_status": "Unshipped",
"fulfillment_channel": "AFN", // AFN = FBA, MFN = Merchant
"sales_channel": "Amazon.com",
"order_channel": "Amazon.com",
"ship_service_level": "Std US D2D Dom",
"order_total": {
"currency_code": "USD",
"amount": "89.99"
},
"number_of_items_shipped": 0,
"number_of_items_unshipped": 2,
"payment_execution_detail": [],
"payment_method": "CreditCard",
"payment_method_details": ["CreditCard"],
"marketplace_id": "ATVPDKIKX0DER",
"shipment_service_level_category": "Standard",
"easy_ship_shipment_status": null,
"is_business_order": false,
"is_prime": true,
"is_premium_order": false,
"is_global_express_enabled": false
}
],
"next_token": "eyJleHBpcmF0aW9uVGltZU9mTmV4dFRva2VuIjoxNzEwOTUwNDAwfQ=="
}
}
Mendapatkan Item Pesanan
Ambil item baris terperinci untuk suatu pesanan:
const getOrderItems = async (accessToken, orderId) => {
const endpoint = `https://sellingpartnerapi-na.amazon.com/orders/v0/orders/${orderId}/orderItems`;
return makeSpApiRequest('GET', endpoint, accessToken);
};
// Usage
const orderItems = await getOrderItems(accessToken, '112-1234567-1234567');
// Expected response
{
"payload": {
"order_items": [
{
"asin": "B08N5WRWNW",
"seller_sku": "MYSKU-001",
"title": "Wireless Bluetooth Headphones",
"quantity_ordered": 2,
"quantity_shipped": 0,
"product_info": {
"number_of_items": 2
},
"item_price": {
"currency_code": "USD",
"amount": "44.99"
},
"item_total": {
"currency_code": "USD",
"amount": "89.98"
},
"tax_collection": {
"tax_collection_model": "MarketplaceFacilitator",
"responsible_party": "Amazon Services, Inc."
}
}
]
}
}
Memperbarui Status Pengiriman
Tandai pesanan sebagai dikirim dengan informasi pelacakan:
const confirmShipment = async (accessToken, orderId, shipmentData) => {
const endpoint = `https://sellingpartnerapi-na.amazon.com/orders/v0/orders/${orderId}/shipmentConfirmation`;
const payload = {
packageDetails: {
packageReferenceId: shipmentData.packageReferenceId || '1',
carrier_code: shipmentData.carrierCode, // e.g., 'USPS', 'FEDEX', 'UPS'
tracking_number: shipmentData.trackingNumber,
ship_date: shipmentData.shipDate || new Date().toISOString(),
items: shipmentData.items.map(item => ({
order_item_id: item.orderItemId,
quantity: item.quantity
}))
}
};
return makeSpApiRequest('POST', endpoint, accessToken, payload);
};
// Usage
await confirmShipment(accessToken, '112-1234567-1234567', {
carrierCode: 'USPS',
trackingNumber: '9400111899223456789012',
items: [
{ orderItemId: '12345678901234', quantity: 2 }
]
});
Kode Kurir Umum
| Kurir | Kode Kurir |
|---|---|
| USPS | USPS |
| FedEx | FEDEX |
| UPS | UPS |
| DHL | DHL |
| Canada Post | CANADA_POST |
| Royal Mail | ROYAL_MAIL |
| Australia Post | AUSTRALIA_POST |
| Amazon Logistics | AMZN_UK |
API Inventaris
Mendapatkan Ringkasan Inventaris
Ambil tingkat inventaris di seluruh marketplace:
const getInventorySummaries = async (accessToken, options = {}) => {
const params = new URLSearchParams({
granularityType: options.granularityType || 'Marketplace',
granularityId: options.granularityId || 'ATVPDKIKX0DER', // US
startDateTime: options.startDateTime || '',
sellerSkus: options.sellerSkus?.join(',') || ''
});
const endpoint = `https://sellingpartnerapi-na.amazon.com/fba/inventory/v1/summaries?${params.toString()}`;
return makeSpApiRequest('GET', endpoint, accessToken);
};
// Usage
const inventory = await getInventorySummaries(accessToken, {
granularityId: 'ATVPDKIKX0DER',
sellerSkus: ['MYSKU-001', 'MYSKU-002']
});
Struktur Respons Inventaris
{
"payload": {
"inventorySummaries": [
{
"asin": "B08N5WRWNW",
"seller_sku": "MYSKU-001",
"condition": "NewItem",
"details": {
"quantity": 150,
"fulfillable_quantity": 145,
"inbound_working_quantity": 0,
"inbound_shipped_quantity": 5,
"inbound_receiving_quantity": 0,
"reserved_quantity": 5,
"unfulfillable_quantity": 0,
"warehouse_damage_quantity": 0,
"distributor_damaged_quantity": 0,
"carrier_damaged_quantity": 0,
"defective_quantity": 0,
"customer_damaged_quantity": 0
},
"marketplace_id": "ATVPDKIKX0DER"
}
]
}
}
Memperbarui Inventaris
Catatan: SP-API tidak menyediakan endpoint pembaruan inventaris langsung. Inventaris dikelola melalui:
- Pengiriman FBA - Kirim inventaris ke gudang Amazon
- Pesanan MFN - Inventaris berkurang secara otomatis saat pesanan dikirim
- Pembaruan daftar produk - Sesuaikan jumlah melalui API Daftar Produk
Untuk FBA, buat rencana pengiriman:
const createInboundShipmentPlan = async (accessToken, shipmentData) => {
const endpoint = 'https://sellingpartnerapi-na.amazon.com/fba/inbound/v0/plans';
const payload = {
ShipFromAddress: {
Name: shipmentData.shipFromName,
AddressLine1: shipmentData.shipFromAddress,
City: shipmentData.shipFromCity,
StateOrProvinceCode: shipmentData.shipFromState,
CountryCode: shipmentData.shipFromCountry,
PostalCode: shipmentData.shipFromPostalCode
},
LabelPrepPreference: 'SELLER_LABEL',
InboundPlanItems: shipmentData.items.map(item => ({
SellerSKU: item.sku,
ASIN: item.asin,
Quantity: item.quantity,
Condition: 'NewItem'
}))
};
return makeSpApiRequest('POST', endpoint, accessToken, payload);
};
API Daftar Produk
Mendapatkan Daftar Produk
Ambil daftar produk dengan pemfilteran:
const getListings = async (accessToken, options = {}) => {
const params = new URLSearchParams({
marketplaceIds: options.marketplaceIds?.join(',') || ['ATVPDKIKX0DER'],
itemTypes: options.itemTypes?.join(',') || ['ASIN', 'SKU'],
identifiers: options.identifiers?.join(',') || '',
issuesLocale: options.locale || 'en_US'
});
const endpoint = `https://sellingpartnerapi-na.amazon.com/listings/2021-08-01/items?${params.toString()}`;
return makeSpApiRequest('GET', endpoint, accessToken);
};
// Usage
const listings = await getListings(accessToken, {
identifiers: ['B08N5WRWNW', 'B09JQKJXYZ'],
itemTypes: ['ASIN']
});
Struktur Respons Daftar Produk
{
"identifiers": {
"marketplaceId": "ATVPDKIKX0DER",
"sku": "MYSKU-001",
"asin": "B08N5WRWNW"
},
"attributes": {
"title": "Wireless Bluetooth Headphones",
"description": "Premium wireless headphones with noise cancellation",
"brand": "MyBrand",
"color": "Black",
"size": "One Size",
"item_weight": "0.5 pounds",
"product_dimensions": "7 x 6 x 3 inches"
},
"product_type": "LUGGAGE",
"sales_price": {
"currency_code": "USD",
"amount": "89.99"
},
"list_price": {
"currency_code": "USD",
"amount": "129.99"
},
"fulfillment_availability": [
{
"fulfillment_channel_code": "AFN",
"quantity": 150
}
],
"condition_type": "New",
"status": "ACTIVE",
"procurement": null
}
Membuat atau Memperbarui Daftar Produk
Gunakan submitListingsSubmission untuk operasi batch:
const submitListingUpdate = async (accessToken, listingData) => {
const endpoint = 'https://sellingpartnerapi-na.amazon.com/listings/2021-08-01/items/MYSKU-001';
const payload = {
productType: 'LUGGAGE',
patches: [
{
op: 'replace',
path: '/attributes/title',
value: 'Updated Wireless Bluetooth Headphones - Premium Sound'
},
{
op: 'replace',
path: '/salesPrice',
value: {
currencyCode: 'USD',
amount: '79.99'
}
}
]
};
return makeSpApiRequest('PATCH', endpoint, accessToken, payload);
};
Menghapus Daftar Produk
Hapus atau nonaktifkan daftar produk:
const deleteListing = async (accessToken, sku, marketplaceIds) => {
const params = new URLSearchParams({
marketplaceIds: marketplaceIds.join(',')
});
const endpoint = `https://sellingpartnerapi-na.amazon.com/listings/2021-08-01/items/${sku}?${params.toString()}`;
return makeSpApiRequest('DELETE', endpoint, accessToken);
};
API Laporan
Membuat Jadwal Laporan
Otomatiskan pembuatan laporan:
const createReport = async (accessToken, reportType, dateRange) => {
const endpoint = 'https://sellingpartnerapi-na.amazon.com/reports/2021-06-30/reports';
const payload = {
reportType: reportType,
marketplaceIds: dateRange.marketplaceIds || ['ATVPDKIKX0DER'],
dataStartTime: dateRange.startTime?.toISOString(),
dataEndTime: dateRange.endTime?.toISOString()
};
return makeSpApiRequest('POST', endpoint, accessToken, payload);
};
// Common report types
const REPORT_TYPES = {
ORDERS: 'GET_FLAT_FILE_ALL_ORDERS_DATA_BY_LAST_UPDATE_GENERAL',
ORDER_ITEMS: 'GET_FLAT_FILE_ORDER_ITEMS_DATA_BY_LAST_UPDATE_GENERAL',
INVENTORY: 'GET_MERCHANT_LISTINGS_ALL_DATA',
FBA_INVENTORY: 'GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA',
SETTLEMENT: 'GET_V2_SETTLEMENT_REPORT_DATA_FLAT_FILE',
SALES_AND_TRAFFIC: 'GET_SALES_AND_TRAFFIC_REPORT',
ADVERTISING: 'GET_BRAND_ANALYTICS_SEARCH_TERMS_REPORT'
};
// Usage
const report = await createReport(accessToken, REPORT_TYPES.ORDERS, {
marketplaceIds: ['ATVPDKIKX0DER'],
startTime: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // Last 7 days
endTime: new Date()
});
Mendapatkan Dokumen Laporan
Unduh laporan yang dihasilkan:
const getReportDocument = async (accessToken, reportId) => {
const endpoint = `https://sellingpartnerapi-na.amazon.com/reports/2021-06-30/reports/${reportId}/document`;
return makeSpApiRequest('GET', endpoint, accessToken);
};
// Download and parse report
const downloadReport = async (accessToken, reportId) => {
const documentInfo = await getReportDocument(accessToken, reportId);
const response = await fetch(documentInfo.payload.url);
const content = await response.text();
// Reports are typically tab-delimited or JSON
if (documentInfo.payload.compressionAlgorithm === 'GZIP') {
const decompressed = await decompressGzip(content);
return decompressed;
}
return content;
};
API Notifikasi
Membuat Langganan
Siapkan webhook untuk acara real-time:
const createSubscription = async (accessToken, subscriptionData) => {
const endpoint = 'https://sellingpartnerapi-na.amazon.com/notifications/v1/subscriptions';
const payload = {
payload: {
destination: {
resource: subscriptionData.destinationArn, // SNS topic ARN
name: subscriptionData.name
},
modelVersion: '1.0',
eventFilter: {
eventCode: subscriptionData.eventCode,
marketplaceIds: subscriptionData.marketplaceIds
}
}
};
return makeSpApiRequest('POST', endpoint, accessToken, payload);
};
// Available event types
const EVENT_CODES = {
ORDER_STATUS_CHANGE: 'OrderStatusChange',
ORDER_ITEM_CHANGE: 'OrderItemChange',
ORDER_CHANGE: 'OrderChange',
FBA_ORDER_STATUS_CHANGE: 'FBAOrderStatusChange',
FBA_OUTBOUND_SHIPMENT_STATUS: 'FBAOutboundShipmentStatus',
INVENTORY_LEVELS: 'InventoryLevels',
PRICING_HEALTH: 'PricingHealth'
};
// Usage
await createSubscription(accessToken, {
destinationArn: 'arn:aws:sns:us-east-1:123456789012:sp-api-notifications',
name: 'OrderStatusNotifications',
eventCode: EVENT_CODES.ORDER_STATUS_CHANGE,
marketplaceIds: ['ATVPDKIKX0DER']
});
Menyiapkan Destinasi SNS
Amazon mengirim notifikasi ke topik SNS:
const createSnsDestination = async (accessToken, destinationData) => {
const endpoint = 'https://sellingpartnerapi-na.amazon.com/notifications/v1/destinations';
const payload = {
resource: destinationData.snsTopicArn,
name: destinationData.name
};
return makeSpApiRequest('POST', endpoint, accessToken, { payload });
};
// SNS topic policy must allow Amazon SES to publish
const snsTopicPolicy = {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Principal: {
Service: 'notifications.amazon.com'
},
Action: 'SNS:Publish',
Resource: 'arn:aws:sns:us-east-1:123456789012:sp-api-notifications'
}
]
};
Memproses Notifikasi
Siapkan endpoint SNS untuk menerima notifikasi:
const express = require('express');
const crypto = require('crypto');
const app = express();
app.post('/webhooks/amazon', express.raw({ type: 'application/json' }), async (req, res) => {
const signature = req.headers['x-amz-sns-message-signature'];
const payload = req.body;
// Verify SNS message signature
const isValid = await verifySnsSignature(payload, signature);
if (!isValid) {
console.error('Invalid SNS signature');
return res.status(401).send('Unauthorized');
}
const message = JSON.parse(payload.toString());
// Handle different message types
switch (message.Type) {
case 'SubscriptionConfirmation':
// Auto-confirm subscription
await fetch(message.SubscribeURL);
break;
case 'Notification':
const notification = JSON.parse(message.Message);
await handleSpApiNotification(notification);
break;
}
res.status(200).send('OK');
});
async function handleSpApiNotification(notification) {
const { notificationType, payload } = notification;
switch (notificationType) {
case 'OrderStatusChange':
await syncOrderStatus(payload.amazonOrderId);
break;
case 'OrderChange':
await syncOrderDetails(payload.amazonOrderId);
break;
case 'InventoryLevels':
await updateInventoryCache(payload);
break;
}
}
Batas Kecepatan dan Kuota
Memahami Batas Kecepatan
SP-API menerapkan batas kecepatan dinamis per endpoint:
| Kategori Endpoint | Batas Kecepatan | Batas Burst |
|---|---|---|
| Pesanan | 10 permintaan/detik | 20 |
| Item Pesanan | 5 permintaan/detik | 10 |
| Inventaris | 2 permintaan/detik | 5 |
| Daftar Produk | 10 permintaan/detik | 20 |
| Laporan | 0.5 permintaan/detik | 1 |
| Notifikasi | 1 permintaan/detik | 2 |
| FBA Masuk | 2 permintaan/detik | 5 |
Periksa header x-amzn-RateLimit-Limit dalam respons untuk batas saat ini.
Menerapkan Penanganan Batas Kecepatan
Gunakan backoff eksponensial untuk percobaan ulang:
const makeRateLimitedRequest = async (method, endpoint, accessToken, body = null, maxRetries = 5) => {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await makeSpApiRequest(method, endpoint, accessToken, body);
// Check rate limit headers
const rateLimit = response.headers.get('x-amzn-RateLimit-Limit');
const retryAfter = response.headers.get('Retry-After');
if (retryAfter) {
console.warn(`Rate limited. Retry after: ${retryAfter} seconds`);
}
return response;
} catch (error) {
if (error.message.includes('429') && attempt < maxRetries) {
// Extract retry-after header or use exponential backoff
const retryAfter = error.headers?.get('Retry-After') || Math.pow(2, attempt);
console.log(`Rate limited. Retrying in ${retryAfter}s...`);
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
} else if (error.message.includes('503') && attempt < maxRetries) {
// Service unavailable - exponential backoff
const delay = Math.pow(2, attempt) * 1000;
console.log(`Service unavailable. Retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay));
} else {
throw error;
}
}
}
};
Implementasi Antrian Permintaan
Terapkan antrian untuk tetap dalam batas:
class RateLimitedQueue {
constructor(rateLimit, burstLimit = null) {
this.rateLimit = rateLimit; // requests per second
this.burstLimit = burstLimit || rateLimit * 2;
this.tokens = this.burstLimit;
this.lastRefill = Date.now();
this.queue = [];
this.processing = false;
}
async add(requestFn) {
return new Promise((resolve, reject) => {
this.queue.push({ requestFn, resolve, reject });
this.process();
});
}
refillTokens() {
const now = Date.now();
const elapsed = (now - this.lastRefill) / 1000;
const tokensToAdd = elapsed * this.rateLimit;
this.tokens = Math.min(this.burstLimit, this.tokens + tokensToAdd);
this.lastRefill = now;
}
async process() {
if (this.processing || this.queue.length === 0) return;
this.processing = true;
while (this.queue.length > 0) {
this.refillTokens();
if (this.tokens < 1) {
const waitTime = (1 / this.rateLimit) * 1000;
await new Promise(r => setTimeout(r, waitTime));
continue;
}
this.tokens--;
const { requestFn, resolve, reject } = this.queue.shift();
try {
const result = await requestFn();
resolve(result);
} catch (error) {
reject(error);
}
}
this.processing = false;
}
}
// Usage - Orders API queue (10 req/s)
const ordersQueue = new RateLimitedQueue(10, 20);
const orders = await ordersQueue.add(() => getOrders(accessToken, options));
Praktik Terbaik Keamanan
Manajemen Kredensial
Jangan pernah menuliskan kredensial secara langsung dalam kode sumber Anda. Gunakan variabel lingkungan atau manajer rahasia:
// Buruk - jangan pernah lakukan ini
const AWS_ACCESS_KEY = 'AKIAIOSFODNN7EXAMPLE';
const AWS_SECRET = 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY';
// Baik - gunakan variabel lingkungan
const AWS_ACCESS_KEY = process.env.AWS_ACCESS_KEY_ID;
const AWS_SECRET = process.env.AWS_SECRET_ACCESS_KEY;
// Lebih baik - gunakan AWS Secrets Manager atau yang serupa
const { SecretsManagerClient } = require('@aws-sdk/client-secrets-manager');
const secretsClient = new SecretsManagerClient({ region: 'us-east-1' });
const getCredentials = async () => {
const response = await secretsClient.send({
Name: 'prod/sp-api/credentials'
});
return JSON.parse(response.SecretString);
};
Persyaratan Penyimpanan Token
SP-API memerlukan langkah-langkah keamanan khusus untuk penyimpanan token:
- Enkripsi saat istirahat: Gunakan enkripsi AES-256 untuk token yang disimpan
- Enkripsi saat transit: Selalu gunakan HTTPS/TLS 1.2+
- Kontrol akses: Batasi akses token ke akun layanan tertentu
- Pencatatan audit: Catat semua akses token dan peristiwa penyegaran
- Rotasi otomatis: Segarkan token sebelum kedaluwarsa
const crypto = require('crypto');
class TokenStore {
constructor(encryptionKey) {
this.algorithm = 'aes-256-gcm';
this.key = crypto.createHash('sha256').update(encryptionKey).digest('hex').slice(0, 32);
}
encrypt(token) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(this.algorithm, Buffer.from(this.key), iv);
let encrypted = cipher.update(token, 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag().toString('hex');
return {
iv: iv.toString('hex'),
encryptedData: encrypted,
authTag
};
}
decrypt(encryptedData) {
const decipher = crypto.createDecipheriv(
this.algorithm,
Buffer.from(this.key),
Buffer.from(encryptedData.iv, 'hex')
);
decipher.setAuthTag(Buffer.from(encryptedData.authTag, 'hex'));
let decrypted = decipher.update(encryptedData.encryptedData, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
}
Hak Akses Minimal IAM
Berikan hanya izin yang dibutuhkan aplikasi Anda:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SPAPIOrdersAccess",
"Effect": "Allow",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:*:*:*/prod/*/sellingpartnerapi/orders/*"
},
{
"Sid": "SPAPIInventoryAccess",
"Effect": "Allow",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:*:*:*/prod/*/sellingpartnerapi/fba/inventory/*"
}
]
}
Hindari penggunaan wildcard * dalam produksi. Batasi izin ke endpoint tertentu.
Keamanan Penandatanganan Permintaan
Selalu validasi implementasi SigV4 Anda:
- Gunakan HTTPS untuk semua permintaan
- Sertakan semua header yang diperlukan dalam tanda tangan
- Pastikan stempel waktu berada dalam 5 menit dari server AWS
- Rotasi kredensial AWS secara teratur
- Gunakan peran IAM daripada kredensial jangka panjang bila memungkinkan
// Validate request timestamp
const validateTimestamp = (amzDate) => {
const now = new Date();
const requestTime = new Date(amzDate);
const diff = Math.abs(now - requestTime);
// AWS rejects requests older than 5 minutes
if (diff > 5 * 60 * 1000) {
throw new Error('Request timestamp too old. Sync your server clock.');
}
};
Menguji Integrasi SP-API dengan Apidog
Mengapa Menguji Integrasi SP-API
Integrasi Amazon SP-API melibatkan alur otentikasi yang kompleks, beberapa endpoint, dan batas kecepatan yang ketat. Pengujian membantu Anda:
- Memvalidasi alur otorisasi OAuth 2.0
- Melakukan debug masalah penandatanganan SigV4
- Menguji penanganan kesalahan untuk batas kecepatan
- Mensimulasikan respons untuk pengembangan
- Mendokumentasikan alur kerja API untuk tim Anda
Menyiapkan Apidog untuk Pengujian SP-API
Langkah 1: Impor Spesifikasi OpenAPI SP-API
Apidog mendukung spesifikasi OpenAPI 3.0. Impor spesifikasi SP-API Amazon:
- Unduh spesifikasi OpenAPI SP-API dari repositori Amazon
- Di Apidog, buat proyek baru
- Impor file spesifikasi
- Konfigurasi variabel lingkungan untuk kredensial
Langkah 2: Konfigurasi Variabel Lingkungan
Siapkan variabel spesifik lingkungan:
Base URL (Sandbox): https://sandbox.sellingpartnerapi-na.amazon.com
Base URL (Production): https://sellingpartnerapi-na.amazon.com
LWA Access Token: {{lwa_access_token}}
AWS Access Key: {{aws_access_key}}
AWS Secret Key: {{aws_secret_key}}
Region: us-east-1
Langkah 3: Buat Skrip Pra-permintaan
Otomatiskan penandatanganan SigV4 dengan skrip pra-permintaan Apidog:
// Apidog pre-request script for SigV4 signing
const crypto = require('crypto');
const accessKey = apidog.variables.get('aws_access_key');
const secretKey = apidog.variables.get('aws_secret_key');
const accessToken = apidog.variables.get('lwa_access_token');
const region = apidog.variables.get('region');
const method = apidog.request.method;
const url = new URL(apidog.request.url);
const body = apidog.request.body;
// Generate SigV4 signature
const signer = new SigV4Signer(accessKey, secretKey, region);
const signedHeaders = signer.sign(method, url.href, body, {
'x-amz-access-token': accessToken
});
// Set headers for the request
apidog.request.headers = {
...apidog.request.headers,
...signedHeaders.headers
};
Langkah 4: Buat Skenario Pengujian
Bangun skenario pengujian untuk alur kerja umum:
// Test: Get Orders from Last 24 Hours
// 1. Exchange OAuth code for token
// 2. Call GetOrders endpoint
// 3. Validate response structure
// 4. Extract order IDs
// 5. Call GetOrderItems for each order
const ordersResponse = await apidog.send({
method: 'GET',
url: '/orders/v0/orders',
params: {
createdAfter: new Date(Date.now() - 86400000).toISOString(),
marketplaceIds: 'ATVPDKIKX0DER'
}
});
apidog.assert(ordersResponse.status === 200, 'Orders request failed');
apidog.assert(ordersResponse.data.payload.orders.length > 0, 'No orders found');
// Store order IDs for subsequent requests
const orderIds = ordersResponse.data.payload.orders.map(o => o.amazon_order_id);
apidog.variables.set('order_ids', JSON.stringify(orderIds));
Mensimulasikan Respons SP-API
Gunakan fitur smart mock Apidog untuk mensimulasikan respons SP-API selama pengembangan:
// Mock response for GetOrders
{
"payload": {
"orders": [
{
"amazon_order_id": "112-{{randomNumber}}-{{randomNumber}}",
"order_status": "Unshipped",
"purchase_date": "{{now}}",
"order_total": {
"currency_code": "USD",
"amount": "{{randomFloat 10 500}}"
}
}
],
"next_token": null
}
}
Ini memungkinkan pengembangan frontend untuk dilanjutkan tanpa harus mengakses endpoint Amazon secara langsung.
Melakukan Debug Masalah Umum
Masalah: Ketidakcocokan Tanda Tangan SigV4
Gunakan inspektur permintaan Apidog untuk memverifikasi:
- Semua header yang diperlukan disertakan
- Header diurutkan secara alfabetis
- Permintaan kanonik sesuai dengan harapan AWS
- Stempel waktu berada dalam rentang yang valid
Masalah: Kesalahan Token OAuth
Periksa validitas token dengan permintaan sederhana:
const tokenCheck = await apidog.send({
method: 'GET',
url: '/orders/v0/orders',
params: { createdAfter: new Date().toISOString() }
});
if (tokenCheck.status === 401) {
console.log('Token expired - refresh required');
// Trigger token refresh flow
}
Mengotomatiskan Pengujian dalam CI/CD
Integrasikan pengujian Apidog ke dalam alur CI/CD Anda:
# GitHub Actions example
name: SP-API Integration Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Apidog Tests
uses: apidog/test-action@v1
with:
project-id: ${{ secrets.APIDOG_PROJECT_ID }}
api-key: ${{ secrets.APIDOG_API_KEY }}
environment: sandbox
- name: Notify on Failure
if: failure()
run: |
echo "SP-API tests failed - check Apidog dashboard"
Referensi ID Marketplace
Simpan referensi ini untuk marketplace umum:
| Negara | ID Marketplace |
|---|---|
| Amerika Serikat | ATVPDKIKX0DER |
| Kanada | A2EUQ1WTGCTBG2 |
| Meksiko | A1AM78C64UM0Y8 |
| Britania Raya | A1F83G8C2ARO7P |
| Jerman | A1PA6795UKMFR9 |
| Prancis | A13V1IB3VIYZZH |
| Italia | APJ6JRA9NG5V4 |
| Spanyol | A1RKKUPIHCS9HS |
| Jepang | A1VC38T7YXB528 |
| Australia | A39IBJ37TRP1C6 |
| India | A21TJRUUN4KGV |
| Brasil | A2Q3Y263D00KWC |
Pemecahan Masalah Umum
Masalah: Kesalahan 403 Tidak Sah
Gejala: Menerima kesalahan "Tidak Sah" atau "Akses Ditolak".
Diagnosis:
const error = await response.json();
console.error('Auth error:', error);
// Check: InvalidSignature, AccessDenied, ExpiredToken
Solusi:
- Verifikasi kredensial AWS sudah benar dan aktif
- Periksa ARN peran IAM tertaut ke aplikasi
- Pastikan token OAuth belum kedaluwarsa
- Konfirmasi tanda tangan SigV4 mencakup wilayah yang benar
- Verifikasi header
x-amz-access-tokenada
Masalah: Batas Kecepatan Terlampaui (429)
Gejala: Sering menerima respons HTTP 429.
Solusi:
- Terapkan antrian permintaan dengan pembatasan kecepatan
- Gunakan backoff eksponensial untuk percobaan ulang
- Kumpulkan permintaan bila memungkinkan (gunakan next_token untuk paginasi)
- Pantau header
x-amzn-RateLimit-Limitsecara proaktif - Minta batas yang lebih tinggi melalui Seller Central untuk kasus penggunaan volume tinggi
Masalah: 404 Tidak Ditemukan
Gejala: Endpoint yang valid mengembalikan 404.
Solusi:
- Verifikasi Anda menggunakan endpoint regional yang benar
- Periksa ID marketplace valid untuk wilayah tersebut
- Konfirmasi sumber daya (pesanan, daftar produk) ada
- Pastikan versi API di jalur sudah benar (misalnya,
/v0/,/2021-08-01/)
Masalah: 400 Permintaan Buruk
Gejala: Permintaan gagal dengan kesalahan validasi.
Penyebab Umum:
- Format tanggal tidak valid: Gunakan format ISO 8601 (
2026-03-19T10:30:00Z) - Parameter yang diperlukan hilang: Periksa dokumentasi API untuk bidang yang diperlukan
- ID marketplace tidak valid: Gunakan ID yang benar (misalnya,
ATVPDKIKX0DERuntuk AS) - JSON yang salah format: Validasi sintaks badan permintaan
Solusi:
// Validate dates before sending
const validateIsoDate = (dateString) => {
const date = new Date(dateString);
if (isNaN(date.getTime())) {
throw new Error('Invalid ISO 8601 date format');
}
return dateString;
};
Masalah: Laporan Tetap dalam INIT_STATE
Gejala: Laporan tidak pernah mencapai status DONE.
Solusi:
- Tunggu lebih lama - beberapa laporan membutuhkan 15-30 menit
- Periksa apakah jenis laporan tersedia untuk akun Anda
- Verifikasi rentang tanggal tidak terlalu besar (coba rentang yang lebih kecil)
- Polling status laporan setiap 30 detik, jangan terus-menerus
- Beberapa jenis laporan memerlukan izin khusus
Masalah: Notifikasi Tidak Sampai
Gejala: Langganan dibuat tetapi tidak ada notifikasi yang diterima.
Diagnosis:
- Periksa status langganan melalui API
- Verifikasi kebijakan topik SNS mengizinkan Amazon SES
- Konfirmasi URL endpoint dapat diakses secara publik
- Periksa log CloudWatch untuk upaya pengiriman
Solusi:
- Pastikan topik SNS memiliki kebijakan sumber daya yang benar
- Verifikasi endpoint HTTPS dengan sertifikat SSL yang valid
- Kembalikan 200 OK dalam 30 detik untuk semua notifikasi
- Konfirmasi otomatis pesan
SubscriptionConfirmation
Daftar Periksa Penerapan Produksi
Sebelum tayang langsung:
- [ ] Daftarkan aplikasi di Seller Central produksi
- [ ] Konfigurasi peran IAM produksi dengan izin hak akses minimal
- [ ] Perbarui semua URI pengalihan ke URL produksi
- [ ] Terapkan penyimpanan token yang aman (basis data terenkripsi)
- [ ] Tambahkan logika penyegaran token otomatis
- [ ] Siapkan pembatasan kecepatan dan antrian permintaan
- [ ] Konfigurasi destinasi SNS untuk notifikasi
- [ ] Terapkan penanganan kesalahan yang komprehensif
- [ ] Tambahkan pencatatan untuk semua panggilan API dengan ID permintaan
- [ ] Siapkan pemantauan untuk penggunaan batas kecepatan
- [ ] Buat runbook untuk masalah umum
- [ ] Uji dengan beberapa ID marketplace
- [ ] Dokumentasikan alur OAuth untuk onboarding penjual
- [ ] Terapkan logika percobaan ulang dengan backoff eksponensial
- [ ] Siapkan peringatan untuk kegagalan otentikasi
Pemantauan dan Pemberian Peringatan
Lacak metrik ini:
const metrics = {
apiCalls: {
total: 0,
successful: 0,
failed: 0,
rateLimited: 0
},
rateLimitUsage: {
orders: { current: 0, limit: 10 },
inventory: { current: 0, limit: 2 },
listings: { current: 0, limit: 10 }
},
oauthTokens: {
active: 0,
expiring_soon: 0,
refresh_failures: 0
},
notifications: {
received: 0,
processed: 0,
failed: 0
},
reports: {
pending: 0,
completed: 0,
failed: 0
}
};
// Alert on high failure rate
const failureRate = metrics.apiCalls.failed / metrics.apiCalls.total;
if (failureRate > 0.05) { // More than 5% failure rate
sendAlert('SP-API failure rate above 5%');
}
// Alert on rate limit approaching
for (const [endpoint, usage] of Object.entries(metrics.rateLimitUsage)) {
if (usage.current / usage.limit > 0.8) {
sendAlert(`${endpoint} rate limit at 80% capacity`);
}
}
Kasus Penggunaan Dunia Nyata
Sinkronisasi Inventaris Multi-Marketplace
Penjual elektronik global menggunakan SP-API untuk menyinkronkan inventaris di 12 marketplace:
- Tantangan: Pembaruan inventaris manual menyebabkan penjualan berlebih di marketplace UE
- Solusi: Sistem inventaris pusat dengan webhook SP-API dan antrian terbatas kecepatan
- Hasil: Nol insiden penjualan berlebih, penghematan waktu 25 jam/minggu
Alur implementasi:
- Notifikasi SNS memicu pada peristiwa
InventoryLevels - Sistem pusat menghitung jumlah baru
- Panggilan API terbatas kecepatan memperbarui setiap marketplace
- Konfirmasi dicatat ke basis data audit
Pemenuhan Pesanan Otomatis
Penyedia logistik pihak ketiga mengotomatiskan pemrosesan pesanan:
- Tantangan: 200+ pesanan harian memerlukan entri data manual di seluruh sistem
- Solusi: Integrasi SP-API dengan sistem manajemen gudang
- Hasil: Pesanan secara otomatis dialihkan ke gudang dalam 2 menit setelah penempatan
Poin integrasi utama:
- Webhook mendengarkan peristiwa
OrderStatusChange - Detail pesanan dikirim ke WMS melalui API REST
- Nomor pelacakan dikembalikan dan diperbarui melalui SP-API
- Pelanggan menerima notifikasi pengiriman otomatis
Dasbor Analisis
Alat analitik penjual mengumpulkan data di 500+ akun penjual:
- Tantangan: Penjual tidak memiliki pelaporan terpadu di seluruh marketplace
- Solusi: Agregasi data multi-penjual berbasis OAuth dengan manajemen token
- Hasil: Dasbor real-time dengan metrik penjualan, inventaris, dan periklanan
Data yang dikumpulkan melalui SP-API:
- Pesanan dan item pesanan di semua marketplace
- Tingkat inventaris FBA dan pengiriman masuk
- Kinerja daftar produk dan data harga
- Analitik merek dan laporan istilah pencarian
Kesimpulan
Amazon SP-API menyediakan akses komprehensif ke fungsionalitas Seller Central dengan keamanan dan kinerja yang lebih baik dibandingkan MWS lama. Poin-poin penting:
- Peran OAuth 2.0 + IAM memerlukan manajemen kredensial yang cermat dan penyegaran token otomatis
- Penandatanganan AWS SigV4 wajib untuk semua permintaan - gunakan SDK atau pustaka yang terbukti
- Batas kecepatan bervariasi per endpoint (0.5 hingga 100 req/s) dan memerlukan pemantauan proaktif
- Notifikasi melalui SNS memungkinkan sinkronisasi pesanan dan inventaris secara real-time
- Penanganan kesalahan yang tepat dan logika percobaan ulang sangat penting untuk keandalan produksi
- Apidog menyederhanakan pengujian API dan kolaborasi tim untuk integrasi SP-API
Bagian FAQ
Apa itu Amazon SP-API?
Amazon Selling Partner API (SP-API) adalah API berbasis REST yang menyediakan akses terprogram ke data Seller Central termasuk pesanan, inventaris, daftar produk, dan laporan. Ini menggantikan sistem MWS yang lebih lama dengan keamanan yang ditingkatkan melalui OAuth 2.0 dan penandatanganan AWS SigV4.
Bagaimana cara mendapatkan kredensial Amazon SP-API?
Daftarkan aplikasi Anda di Seller Central di bawah Aplikasi dan Layanan > Kembangkan Aplikasi. Anda akan menerima ID Klien, Rahasia Klien, dan ID Aplikasi. Anda juga perlu membuat peran IAM di AWS dan menautkannya ke aplikasi Anda.
Apakah Amazon SP-API gratis untuk digunakan?
Ya, akses SP-API gratis untuk penjual Amazon yang terdaftar. Namun, batas kecepatan berlaku dan bervariasi per endpoint (0.5 hingga 100 permintaan per detik). Batas yang lebih tinggi memerlukan persetujuan dari Amazon untuk kasus penggunaan volume tinggi tertentu.
Otentikasi apa yang digunakan SP-API?
SP-API menggunakan OAuth 2.0 untuk otorisasi dikombinasikan dengan peran AWS IAM untuk kontrol akses. Semua permintaan API memerlukan penandatanganan AWS Signature Version 4 (SigV4) dengan kredensial sementara yang diperoleh melalui alur OAuth.
Bagaimana cara menangani batas kecepatan SP-API?
Terapkan antrian permintaan untuk tetap dalam batas per-endpoint. Pantau header x-amzn-RateLimit-Limit untuk melacak penggunaan. Gunakan backoff eksponensial saat menerima respons HTTP 429 (Terlalu Banyak Permintaan). Endpoint yang berbeda memiliki batas yang berbeda.
Bisakah saya menguji SP-API tanpa akun penjual aktif?
Ya. Amazon menyediakan lingkungan sandbox untuk pengembangan SP-API. Daftarkan aplikasi Anda dalam mode sandbox untuk menguji integrasi tanpa memengaruhi data penjual aktif. Perhatikan bahwa tidak semua endpoint tersedia di sandbox.
Bagaimana cara kerja webhook dengan SP-API?
SP-API menggunakan Amazon SNS untuk notifikasi. Buat langganan untuk jenis peristiwa tertentu (pesanan, inventaris, dll.), konfigurasikan topik SNS, dan terapkan endpoint HTTPS untuk menerima notifikasi. Konfirmasi otomatis pesan langganan.
Apa yang terjadi ketika token OAuth kedaluwarsa?
Token akses LWA kedaluwarsa setelah 1 jam. Gunakan token penyegaran untuk mendapatkan token akses baru sebelum kedaluwarsa. Terapkan penyegaran token otomatis dalam middleware Anda untuk mencegah kegagalan otentikasi selama panggilan API.
Bagaimana cara migrasi dari MWS ke SP-API?
Penghentian MWS dijadwalkan pada Desember 2025. Migrasi memerlukan: pembaruan otentikasi dari token MWS ke OAuth 2.0, implementasi penandatanganan SigV4, pembaruan URL endpoint, dan modifikasi parsing permintaan/respons dari XML ke JSON.
Mengapa saya mendapatkan kesalahan 403 Tidak Sah?
Penyebab umum meliputi: token OAuth kedaluwarsa, konfigurasi peran IAM yang salah, tanda tangan SigV4 tidak valid, header x-amz-access-token hilang, atau peran IAM tidak tertaut ke aplikasi. Periksa detail respons kesalahan untuk kode kesalahan tertentu.
