get_amazon_order_details
Retrieve detailed Amazon order information including items, pricing, shipping, and payment data by providing an order ID and region code.
Instructions
Get comprehensive details for a specific Amazon order by order ID. Returns full order data including: items (ASIN, name, price, quantity, seller, condition), financial breakdown (subtotal, shipping, tax, VAT, promotions, total), shipping address, payment methods, and optionally shipment tracking and transaction history.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| order_id | Yes | Amazon order ID in format XXX-XXXXXXX-XXXXXXX (e.g., 123-4567890-1234567) | |
| region | Yes | Amazon region code where the order was placed | |
| include_shipments | No | Extract shipment info from order detail page (default: true) | |
| fetch_tracking_numbers | No | Extract actual carrier tracking number (e.g., AZ218181365JE) by visiting the 'Track package' page. Adds ~2s per shipment. | |
| include_transactions | No | Include payment transaction details (default: false) |
Implementation Reference
- src/index.ts:187-224 (schema)Tool schema definition including input validation schema for get_amazon_order_details{ name: "get_amazon_order_details", description: "Get comprehensive details for a specific Amazon order by order ID. Returns full order data including: items (ASIN, name, price, quantity, seller, condition), financial breakdown (subtotal, shipping, tax, VAT, promotions, total), shipping address, payment methods, and optionally shipment tracking and transaction history.", inputSchema: { type: "object", properties: { order_id: { type: "string", description: "Amazon order ID in format XXX-XXXXXXX-XXXXXXX (e.g., 123-4567890-1234567)", }, region: { type: "string", description: "Amazon region code where the order was placed", enum: getRegionCodes(), }, include_shipments: { type: "boolean", description: "Extract shipment info from order detail page (default: true)", default: true, }, fetch_tracking_numbers: { type: "boolean", description: "Extract actual carrier tracking number (e.g., AZ218181365JE) by visiting the 'Track package' page. Adds ~2s per shipment.", default: false, }, include_transactions: { type: "boolean", description: "Include payment transaction details (default: false)", default: false, }, }, required: ["order_id", "region"], }, },
- src/index.ts:752-839 (handler)Main handler in the MCP tool call switch statement. Validates params, calls fetchOrders with orderId to trigger single-order mode, formats and returns the response.case "get_amazon_order_details": { const regionParam = args?.region as string | undefined; const regionError = validateRegion(regionParam, args); if (regionError) return regionError; const region = regionParam!; const currentPage = await getPage(); const orderId = args?.order_id as string; const includeShipments = args?.include_shipments as boolean | undefined; const fetchTrackingNumbers = args?.fetch_tracking_numbers as | boolean | undefined; const includeTransactions = args?.include_transactions as | boolean | undefined; // Use the same fetchOrders logic that works for get_amazon_orders const result = await fetchOrders(currentPage, amazonPlugin, { region, orderId, // This triggers single-order mode includeItems: true, includeShipments: includeShipments ?? true, fetchTrackingNumbers: fetchTrackingNumbers ?? false, includeTransactions: includeTransactions ?? false, }); const order = result.orders[0]; return { content: [ { type: "text", text: JSON.stringify( { status: result.errors.length > 0 ? "error" : "success", params: { orderId, region, includeShipments, fetchTrackingNumbers, includeTransactions, }, order: order ? { id: order.id, date: order.date?.toISOString(), total: order.total, shipping: order.shipping, tax: order.tax, recipient: order.recipient, payments: order.payments, itemCount: order.items?.length || 0, shipmentCount: order.shipments?.length || 0, } : null, items: result.items.map((i) => ({ name: i.name, asin: i.asin, quantity: i.quantity, unitPrice: i.unitPrice, condition: i.condition, seller: i.seller?.name, subscriptionFrequency: i.subscriptionFrequency, })), shipments: result.shipments.map((s) => ({ shipmentId: s.shipmentId, status: s.status, delivered: s.delivered, trackingId: s.trackingId, carrier: s.carrier, trackingLink: s.trackingLink, itemCount: s.items?.length || 0, })), transactions: result.transactions.map((t) => ({ date: t.date.toISOString(), amount: t.amount, vendor: t.vendor, cardInfo: t.cardInfo, })), errors: result.errors, }, null, 2, ), }, ], }; }
- src/tools/fetch-orders.ts:143-536 (handler)Core single-order extraction logic in fetchOrders function. Navigates to invoice/detail pages, extracts items, financials, shipments, transactions for the specific orderId.// If specific orderId requested, skip order list and go directly to invoice/detail if (orderId) { console.error( `[fetch-orders] Fetching single order: ${orderId} (region: ${region})`, ); onProgress?.(`Fetching order ${orderId}...`, 0, 1); // Create header for this order const header: OrderHeader = { id: orderId, orderId, date: null, total: { amount: 0, currency, currencySymbol, formatted: "" }, detailUrl: `https://www.${domain}/gp/your-account/order-details?orderID=${orderId}`, platform: "amazon", region, }; const enrichedOrder: EnrichedOrder = { ...header }; // Go to invoice page and extract items directly (inline, with timeouts) const invoiceUrl = `https://www.${domain}/gp/css/summary/print.html?orderID=${orderId}`; console.error(`[fetch-orders] Navigating to invoice: ${invoiceUrl}`); await page.goto(invoiceUrl, { waitUntil: "domcontentloaded", timeout: 15000, }); const currentUrl = page.url(); console.error(`[fetch-orders] Current URL: ${currentUrl}`); await page .waitForSelector('[data-component="purchasedItems"], table, .a-box', { timeout: 3000, }) .catch(() => {}); // Check for error banners (e.g., "We're unable to load your order details") const errorBanner = await page .locator( '[data-component="errorbanner"], .a-alert-error, .a-alert-info', ) .first(); const errorBannerCount = await errorBanner.count().catch(() => 0); if (errorBannerCount > 0) { const errorText = await errorBanner .textContent({ timeout: 500 }) .catch(() => ""); if ( errorText?.includes("unable to load") || errorText?.includes("problem loading") ) { console.error( `[fetch-orders] Error detected: ${errorText.slice(0, 200)}`, ); result.errors.push( `Order page error: ${errorText.slice(0, 200).trim()}`, ); } } // Try to extract items - first try data-component, then fall back to extractFromInvoice const itemContainers = await page .locator('[data-component="purchasedItems"]') .all(); console.error( `[fetch-orders] Found ${itemContainers.length} purchasedItems containers on invoice page`, ); // Invoice pages often don't have data-component, try the full invoice extractor if (itemContainers.length === 0) { console.error( `[fetch-orders] No data-component items found, using extractFromInvoice`, ); const invoiceData = await extractFromInvoice(page, header); // Copy over invoice data (amounts, recipient, payments) regardless of items console.error( `[fetch-orders] Invoice data: subtotal=${invoiceData.subtotal?.formatted}, total=${invoiceData.total?.formatted}, vat=${invoiceData.vat?.formatted}, shipping=${invoiceData.shipping?.formatted}`, ); if (invoiceData.subtotal) enrichedOrder.subtotal = invoiceData.subtotal; if (invoiceData.total) enrichedOrder.grandTotal = invoiceData.total; if (invoiceData.shipping) enrichedOrder.shipping = invoiceData.shipping; if (invoiceData.tax) enrichedOrder.tax = invoiceData.tax; if (invoiceData.vat) enrichedOrder.vat = invoiceData.vat; if (invoiceData.gift) enrichedOrder.promotion = invoiceData.gift; if (invoiceData.recipientName) { enrichedOrder.recipient = invoiceData.recipientName; if (invoiceData.shippingAddress) { // Prepend recipient name as line1 if address doesn't start with it const addressWithName = [ invoiceData.recipientName, ...invoiceData.shippingAddress, ]; enrichedOrder.shippingAddress = parseInvoiceAddressLines(addressWithName); } } if (invoiceData.payments && invoiceData.payments.length > 0) { enrichedOrder.payments = invoiceData.payments; // Also set paymentMethod from first payment const firstPayment = invoiceData.payments[0]; enrichedOrder.paymentMethod = { type: firstPayment.method, lastFour: firstPayment.lastFour, }; } // Convert invoice items to full Item type if found if (invoiceData.items && invoiceData.items.length > 0) { // Create enriched header with all order data for items const enrichedHeader: OrderHeader = { ...header, recipient: typeof enrichedOrder.recipient === "string" ? enrichedOrder.recipient : undefined, subtotal: enrichedOrder.subtotal, shipping: enrichedOrder.shipping, tax: enrichedOrder.tax, vat: enrichedOrder.vat, promotion: enrichedOrder.promotion, grandTotal: enrichedOrder.grandTotal, shippingAddress: enrichedOrder.shippingAddress, paymentMethod: enrichedOrder.paymentMethod, }; const items = invoiceData.items.map((ii) => ({ id: ii.asin || ii.name.slice(0, 50), asin: ii.asin, name: ii.name, quantity: ii.quantity, unitPrice: ii.unitPrice, totalPrice: { ...ii.unitPrice, amount: ii.unitPrice.amount * ii.quantity, formatted: `${currencySymbol}${(ii.unitPrice.amount * ii.quantity).toFixed(2)}`, }, url: ii.asin ? `https://www.${domain}/dp/${ii.asin}` : "", orderHeader: enrichedHeader, condition: ii.condition, seller: ii.seller ? { name: ii.seller } : undefined, subscriptionFrequency: ii.subscriptionFrequency, platformData: { source: "invoice" }, })); console.error( `[fetch-orders] extractFromInvoice found ${items.length} items`, ); enrichedOrder.items = items; result.items = items; } } // Only use inline extraction if we found data-component containers (detail page) // Otherwise extractFromInvoice already handled it above if (itemContainers.length > 0) { // Create enriched header with all order data for items const enrichedHeader: OrderHeader = { ...header, recipient: typeof enrichedOrder.recipient === "string" ? enrichedOrder.recipient : undefined, subtotal: enrichedOrder.subtotal, shipping: enrichedOrder.shipping, tax: enrichedOrder.tax, vat: enrichedOrder.vat, promotion: enrichedOrder.promotion, grandTotal: enrichedOrder.grandTotal, shippingAddress: enrichedOrder.shippingAddress, paymentMethod: enrichedOrder.paymentMethod, }; const extractedItems: Item[] = []; for (const container of itemContainers) { try { // Title + ASIN const titleLink = container .locator('[data-component="itemTitle"] a') .first(); const titleCount = await titleLink.count().catch(() => 0); if (titleCount === 0) continue; const name = await titleLink .textContent({ timeout: 500 }) .catch(() => ""); if (!name?.trim()) continue; const href = await titleLink .getAttribute("href", { timeout: 500 }) .catch(() => ""); const asinMatch = href?.match(/\/dp\/([A-Z0-9]+)/i); const asin = asinMatch ? asinMatch[1] : undefined; // Price const priceEl = container .locator('[data-component="unitPrice"] .a-offscreen') .first(); const priceText = await priceEl .textContent({ timeout: 500 }) .catch(() => ""); const priceMatch = priceText?.match(/[£$€]?([\d,.]+)/); const priceAmount = priceMatch ? parseFloat(priceMatch[1].replace(",", "")) : 0; // Quantity (check badge first, then quantity component) let quantity = 1; const qtyBadge = container .locator(".od-item-view-qty span") .first(); const qtyBadgeCount = await qtyBadge.count().catch(() => 0); if (qtyBadgeCount > 0) { const qtyText = await qtyBadge .textContent({ timeout: 500 }) .catch(() => ""); const qtyMatch = qtyText?.match(/(\d+)/); if (qtyMatch) quantity = parseInt(qtyMatch[1], 10); } // Seller let seller: string | undefined; const sellerEl = container .locator('[data-component="orderedMerchant"]') .first(); const sellerCount = await sellerEl.count().catch(() => 0); if (sellerCount > 0) { const sellerText = await sellerEl .textContent({ timeout: 500 }) .catch(() => ""); const sellerMatch = sellerText?.match(/Sold by:\s*(.+)/i); if (sellerMatch) seller = sellerMatch[1].trim(); } // Condition let condition: string | undefined; const condEl = container .locator('[data-component="itemCondition"]') .first(); const condCount = await condEl.count().catch(() => 0); if (condCount > 0) { const condText = await condEl .textContent({ timeout: 500 }) .catch(() => ""); const condMatch = condText?.match(/Condition:\s*(.+)/i); if (condMatch) condition = condMatch[1].trim(); } // Subscription frequency let subscriptionFrequency: string | undefined; const freqEl = container .locator('[data-component="deliveryFrequency"]') .first(); const freqCount = await freqEl.count().catch(() => 0); if (freqCount > 0) { const freqText = await freqEl .textContent({ timeout: 500 }) .catch(() => ""); const freqMatch = freqText?.match(/Auto-delivered:\s*(.+)/i); if (freqMatch) subscriptionFrequency = freqMatch[1].trim(); } extractedItems.push({ id: asin || name.trim().slice(0, 50), asin, name: name.trim(), quantity, unitPrice: { amount: priceAmount, currency, currencySymbol, formatted: `${currencySymbol}${priceAmount.toFixed(2)}`, }, totalPrice: { amount: priceAmount * quantity, currency, currencySymbol, formatted: `${currencySymbol}${(priceAmount * quantity).toFixed(2)}`, }, url: asin ? `https://www.${domain}/dp/${asin}` : "", orderHeader: enrichedHeader, condition, seller: seller ? { name: seller } : undefined, subscriptionFrequency, platformData: { source: "invoice" }, }); } catch { continue; } } console.error( `[fetch-orders] Extracted ${extractedItems.length} items from data-component`, ); // Store items if (extractedItems.length > 0) { enrichedOrder.items = extractedItems; result.items = extractedItems; } } // If no items found from invoice, try the detail page if (result.items.length === 0 && result.errors.length === 0) { console.error( `[fetch-orders] No items from invoice, trying detail page extraction`, ); await page.goto(header.detailUrl, { waitUntil: "domcontentloaded", timeout: 15000, }); await page .waitForSelector('[data-component="purchasedItems"], .a-box', { timeout: 2000, }) .catch(() => {}); // Check for error banners on detail page const detailErrorBanner = await page .locator( '[data-component="errorbanner"], .a-alert-error, .a-alert-info', ) .first(); const detailErrorCount = await detailErrorBanner.count().catch(() => 0); if (detailErrorCount > 0) { const errorText = await detailErrorBanner .textContent({ timeout: 500 }) .catch(() => ""); if ( errorText?.includes("unable to load") || errorText?.includes("problem loading") ) { console.error( `[fetch-orders] Detail page error: ${errorText.slice(0, 200)}`, ); result.errors.push( `Order detail error: ${errorText.slice(0, 200).trim()}`, ); } } if (result.errors.length === 0) { const items = await plugin.extractItems(page, header).catch(() => []); if (items.length > 0) { console.error( `[fetch-orders] Found ${items.length} items from detail page`, ); enrichedOrder.items = items; result.items = items; } } } // Get shipments from detail page if requested if (includeShipments) { console.error(`[fetch-orders] Fetching shipments from detail page`); // Only navigate if not already there if (!page.url().includes("order-details")) { await page.goto(header.detailUrl, { waitUntil: "domcontentloaded", timeout: 15000, }); await page .waitForSelector('[data-component="shipments"], .a-box', { timeout: 2000, }) .catch(() => {}); } const shipments = await plugin .extractShipments(page, header, fetchTrackingNumbers) .catch(() => []); enrichedOrder.shipments = shipments; result.shipments = shipments; console.error(`[fetch-orders] Found ${shipments.length} shipments`); } // Get transactions if requested if (includeTransactions) { const transactions = await plugin .extractTransactions(page, header) .catch(() => []); result.transactions = transactions; console.error( `[fetch-orders] Found ${transactions.length} transactions`, ); } result.orders = [enrichedOrder]; result.totalFound = 1; return result; }
- src/tools/fetch-orders.ts:67-67 (helper)Interface documentation noting orderId param support for get_amazon_order_details tool./** Filter to a specific order ID (for get_amazon_order_details) */