Loading...
Loading...
List products on Amazon, eBay, and Walmart with two-way inventory sync, automated listing creation, and order import into your store
npx skill4agent add finsilabs/awesome-ecommerce-skills marketplace-connectors| Platform | Recommended Approach | Key Apps |
|---|---|---|
| Shopify | Use a marketplace app — no custom code needed | Codisto ($39/month) for Amazon + eBay + Walmart; LitCommerce ($19/month) for multi-channel listing management |
| WooCommerce | Use a plugin for standard integrations | WooCommerce Amazon Fulfillment (free, amazon.com) for FBA; WP-Lister Pro for Amazon ($99) for full listing and order management |
| BigCommerce | Use App Marketplace connectors | Sellbrite ($79/month, marketplace.bigcommerce.com) syncs Amazon, eBay, Walmart, and Etsy; ChannelAdvisor for enterprise multi-channel |
| Custom / Headless | Direct API integration | Build using Amazon SP-API, eBay REST API, and Walmart Marketplace API; use a queue for order imports and inventory sync |
// lib/amazon/auth.ts — LWA OAuth token with caching
let tokenCache: { accessToken: string; expiresAt: number } | null = null;
export async function getAccessToken(): Promise<string> {
if (tokenCache && tokenCache.expiresAt > Date.now() + 60000) return tokenCache.accessToken;
const res = await fetch('https://api.amazon.com/auth/o2/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: process.env.AMAZON_REFRESH_TOKEN!,
client_id: process.env.AMAZON_CLIENT_ID!,
client_secret: process.env.AMAZON_CLIENT_SECRET!,
}),
});
const data = await res.json();
tokenCache = { accessToken: data.access_token, expiresAt: Date.now() + data.expires_in * 1000 };
return tokenCache.accessToken;
}export async function updateAmazonInventory(sellerId: string, sku: string, quantity: number) {
const accessToken = await getAccessToken();
// SP-API also requires AWS Signature V4 — use @smithy/signature-v4
return fetch(`https://sellingpartnerapi-na.amazon.com/listings/2021-08-01/items/${sellerId}/${encodeURIComponent(sku)}`, {
method: 'PATCH',
headers: { 'x-amz-access-token': accessToken, 'Content-Type': 'application/json' },
body: JSON.stringify({
productType: 'PRODUCT',
patches: [{ op: 'replace', path: '/attributes/fulfillment_availability', value: [{
fulfillment_channel_code: 'DEFAULT',
quantity,
marketplace_id: 'ATVPDKIKX0DER', // US marketplace
}] }],
}),
});
}export async function pollAmazonOrders() {
const lastPolledAt = await db.syncState.getLastPolled('amazon') ?? new Date(Date.now() - 3_600_000);
const accessToken = await getAccessToken();
const params = new URLSearchParams({
MarketplaceIds: 'ATVPDKIKX0DER',
CreatedAfter: lastPolledAt.toISOString(),
OrderStatuses: 'Unshipped,PartiallyShipped',
});
const res = await fetch(`https://sellingpartnerapi-na.amazon.com/orders/v0/orders?${params}`, {
headers: { 'x-amz-access-token': accessToken },
});
const { payload } = await res.json();
for (const amazonOrder of payload.Orders ?? []) {
// Idempotent: skip if already imported
if (await db.orders.findByExternalId(amazonOrder.AmazonOrderId)) continue;
await orderQueue.add('import-order', {
externalId: amazonOrder.AmazonOrderId,
channel: 'amazon',
// ...map order fields
}, { jobId: `amazon-${amazonOrder.AmazonOrderId}` });
}
await db.syncState.updateLastPolled('amazon', new Date());
}export async function syncInventoryAcrossChannels(sku: string, quantity: number, source: string) {
const tasks = [];
if (source !== 'amazon') {
tasks.push(updateAmazonInventory(process.env.AMAZON_SELLER_ID!, sku, quantity)
.catch(err => console.error(`Amazon sync failed for ${sku}:`, err)));
}
if (source !== 'ebay') {
tasks.push(ebayClient.updateInventoryItem(sku, quantity)
.catch(err => console.error(`eBay sync failed for ${sku}:`, err)));
}
// Run all syncs in parallel; individual failures logged but don't block others
await Promise.allSettled(tasks);
}| Problem | Solution |
|---|---|
| Amazon listing succeeds but goes inactive | Check for listing suppressions in the Listings API response; common causes include missing required attributes for the product type |
| Inventory oversells due to sync lag | Set a safety stock buffer in your marketplace app settings; always run a final inventory check at checkout |
SP-API returns | Each SP-API operation has separate rate limits; use the Feeds API for bulk inventory updates instead of individual PATCH calls |
| Shopify marketplace app not importing orders | Check that the app has Write permissions for Orders in your Shopify admin under Apps → App permissions |
| eBay listing rejected for policy violation | Pre-screen product titles for restricted terms before automating; review eBay's Prohibited Items policy |