Home / Blog / Amazon Wholesale Price List Analysis: Check a Supplier List via API

Amazon Wholesale Price List Analysis: Check a Supplier List via API

Turn a supplier's barcode-and-cost sheet into an Amazon shortlist: match each EAN or UPC to an ASIN, read the Buy Box price, the number of sellers and whether Amazon sells it, estimate monthly units and subtract VAT, fees and cost - up to three credits per line, in Python.

September 29, 2026
5 min read
SellerMagnet Team
Share & Bookmark
Blueprint flow from a supplier price list through barcode matching, offers and estimates to a profit shortlist

Amazon wholesale price list analysis turns a supplier's barcode-and-cost sheet into a shortlist. For each line, match the EAN or UPC to an ASIN with /api/amazon-asin-converter, read the Buy Box price, the New sellers and whether Amazon sells it with /api/amazon-product-offers, and get monthly units from /api/amazon-product-search-estimated-sells. Subtract VAT, your fees and the cost, then sort by profit. A profitable line costs three credits, one per call.

Key Takeaways

  • Up to three calls per line: the converter for the ASIN, offers for price and competition, an estimate of units for profitable lines.
  • Check barcodes locally first: a malformed code is a billed 400 and a barcode without a match a billed 404.
  • The API returns no Amazon fees: enter your category's referral rate and your fulfilment fee from Amazon's fee schedule.
  • On European stores the Buy Box price includes VAT, and Amazon's referral fee is a share of the total the buyer pays.
  • The converter returns the first product that matches a barcode, so check the match and the pack size before ordering.

What does a wholesale price list check need?

Two columns from the supplier - barcode and unit cost - and three numbers from you: VAT rate, referral fee and fulfilment fee. A barcode is a GTIN: 12 digits for a UPC-A, 13 for an EAN. The converter looks it up and returns the ASIN, the product's barcodes and its title; the UPC and EAN to ASIN guide covers the lookup itself. The rest decides whether a line is worth buying: the table shows the verdicts the script gives.

Verdicts per price list line (starting thresholds - adjust them to your category).
VerdictWhenNext step
ShortlistROI at least 20 %, Amazon not sellingCheck brand approval, order a test quantity
Thin marginProfit above 0, ROI under 20 %Negotiate the cost or skip
Amazon sells itAmazon is a New sellerSkip unless you can match Amazon
No profit at this costProfit 0 or lessSkip
No featured offerNo Buy Box price todayCheck the listing by hand
No match on AmazonConverter answers 404Search by title, else create a listing

Prepare the sheet first. Name the columns barcode, cost and optionally fee, convert case costs to unit costs, and format the barcode column as text: spreadsheets turn long numbers into 4.00638E+12 and drop leading zeros. The script refuses such codes instead of paying for a lookup of the wrong product.

How do I check a supplier list against Amazon in Python?

gtin13() normalises each barcode and rejects a wrong check digit before any call is made. check() then calls the converter and the offer listing for one line - and the sales estimate only when the line makes a profit - and returns price, competition, sales rank, profit and ROI; a failed estimate leaves units empty instead of dropping the line. get_with_retry() comes from retry.py, new_session() and ApiError from sellermagnet.py - both in the Python quickstart.

wholesale.py - check a supplier price list against one Amazon store

"""Wholesale price list check: barcode and cost in; ASIN, Buy Box, competition, units and profit out."""
import csv
import re
import sys
import threading
from concurrent.futures import ThreadPoolExecutor

import requests

from retry import get_with_retry
from sellermagnet import ApiError, new_session

MARKETPLACE = "APJ6JRA9NG5V4"          # amazon.it; the converter and estimates cover 11 marketplaces
VAT = 0.22                             # Italy's standard rate; use 0 on amazon.com (prices exclude sales tax)
REFERRAL, REFERRAL_MIN = 0.15, 0.30    # your category's rate and minimum from Amazon's fee schedule
FULFILMENT = 4.50                      # per-unit fulfilment fee when the list has no "fee" column
MIN_ROI = 0.20
_local = threading.local()


def session():
    if not hasattr(_local, "session"):
        _local.session = new_session()
    return _local.session


def gtin13(raw: str) -> str | None:
    """UPC-A, EAN-13 or EAN-8 as a 13-digit code with a valid check digit, else None (not worth a credit)."""
    if not re.fullmatch(r"[\d\s-]+", (raw or "").strip()):
        return None                                      # e.g. Excel's 4.00638E+12
    digits = re.sub(r"\D", "", raw)
    if len(digits) not in (8, 12, 13):
        return None
    code = digits.zfill(13)
    total = sum(int(c) * (3 if i % 2 else 1) for i, c in enumerate(code[:12]))
    return code if (10 - total % 10) % 10 == int(code[12]) else None


def number(text: str) -> float | None:
    try:
        return float(text.strip().replace(",", "."))      # "12,50" -> 12.5; no thousands separators
    except (AttributeError, ValueError):
        return None


def check(item: dict) -> dict:
    cost, fee = number(item.get("cost")), number(item.get("fee") or "")
    fee = FULFILMENT if fee is None else fee
    row = {"barcode": item["barcode"], "cost": cost, "asin": None, "title": "", "price": None, "new_sellers": None,
           "amazon": None, "units": None, "rank": None, "profit": None, "roi": None, "monthly_profit": None,
           "note": ""}
    code = gtin13(item["barcode"])
    if not code or not cost or cost <= 0:
        return {**row, "note": "bad barcode or cost - not sent"}
    try:
        match = get_with_retry(session(), "amazon-asin-converter", asin=code, marketplaceId=MARKETPLACE,
                               conversion_direction="ean-to-asin")
    except ApiError as err:
        return {**row, "note": "no match on Amazon" if err.status == 404 else f"error {err.status}"}
    except requests.RequestException as err:
        return {**row, "note": type(err).__name__}
    row.update(asin=match["asin"], title=(match.get("productTitle") or "")[:40])
    if code not in {e.zfill(13) for e in match.get("eanList") or []}:
        row["note"] = "check the match"                  # the first product found for this code
    try:
        offers = get_with_retry(session(), "amazon-product-offers", asin=row["asin"], marketplaceId=MARKETPLACE)
    except ApiError as err:
        return {**row, "note": f"error {err.status}"}
    except requests.RequestException as err:
        return {**row, "note": type(err).__name__}
    new = [x for x in offers.get("offers") or [] if x.get("condition") == "New"]
    price = (offers.get("buyBox") or {}).get("totalPrice")
    row.update(new_sellers=len({x.get("sellerId") for x in new}),
               amazon=any(x.get("sellerName") == "Amazon" for x in new))
    if not isinstance(price, (int, float)) or price <= 0:
        return {**row, "note": ", ".join(filter(None, [row["note"], "no featured offer"]))}
    price = round(price, 2)                              # landed Buy Box price, VAT included in the EU
    profit = price / (1 + VAT) - max(price * REFERRAL, REFERRAL_MIN) - fee - cost
    row.update(price=price, profit=round(profit, 2), roi=round(profit / cost, 2))
    if profit <= 0:
        return row                                       # no estimate needed: one credit saved
    try:
        est = get_with_retry(session(), "amazon-product-search-estimated-sells", asin=row["asin"],
                             marketplaceId=MARKETPLACE)
    except (ApiError, requests.RequestException):
        return row                                       # price and competition still count
    row.update(units=est["estimated_monthly_sales"], rank=est.get("sales_rank"),
               monthly_profit=round(profit * est["estimated_monthly_sales"] / (row["new_sellers"] + 1)))
    return row                                           # monthly profit: an even split with today's sellers


def verdict(r: dict) -> str:
    if r["profit"] is None:
        return r["note"]
    if r["profit"] <= 0:
        return "no profit at this cost"
    if r["amazon"]:
        return "Amazon sells it"
    return "shortlist" if r["roi"] >= MIN_ROI else "thin margin"


if __name__ == "__main__":
    with open(sys.argv[1], newline="", encoding="utf-8-sig") as fh:
        items = [i for i in csv.DictReader(fh) if (i.get("barcode") or "").strip()]
    if not items:
        sys.exit("no rows with a 'barcode' column - name the columns barcode, cost and optionally fee")
    with ThreadPoolExecutor(max_workers=4) as pool:
        rows = list(pool.map(check, items))
    for r in rows:
        r["verdict"] = verdict(r)
    rows.sort(key=lambda r: (r["verdict"] != "shortlist", -(r["monthly_profit"] or 0)))
    with open("wholesale_check.csv", "w", newline="", encoding="utf-8") as fh:
        writer = csv.DictWriter(fh, fieldnames=list(rows[0]) if rows else ["barcode"])
        writer.writeheader()
        writer.writerows(rows)
    for r in rows:
        note = f" ({r['note']})" if r["note"] and r["profit"] is not None else ""
        print(f"{r['barcode']:<15} {r['asin'] or '-':<11} {str(r['price']):>7} sellers={r['new_sellers']} "
              f"units={r['units']} roi={r['roi']} month={r['monthly_profit']}  {r['verdict']}{note}")

The supplier sheet as CSV, then the run

cat supplier.csv
# barcode,cost,fee
# 0711719577294,280.00,
# 4006381333931,"2,10",2.90
# 5901234123457,5.00,
# 12345,1.00,
# 8001234567897,9.50,
# 8009876543217,15.00,
# 012345678905,7.80,0
export SELLERMAGNET_API_KEY=your-key-here
python wholesale.py supplier.csv && head -3 wholesale_check.csv

Example result, best lines first (illustrative values)

4006381333931   B0EXAMPLE1     12.9 sellers=3 units=600 roi=1.73 month=546  shortlist
012345678905    B0EXAMPLE4    24.99 sellers=5 units=None roi=1.15 month=None  shortlist (check the match)
0711719577294   B0CLTBHXWQ   469.99 sellers=2 units=250 roi=0.11 month=2520  thin margin
8001234567897   B0EXAMPLE2    29.99 sellers=5 units=150 roi=0.64 month=152  Amazon sells it
5901234123457   -              None sellers=None units=None roi=None month=None  no match on Amazon
12345           -              None sellers=None units=None roi=None month=None  bad barcode or cost - not sent
8009876543217   B0EXAMPLE3     None sellers=1 units=None roi=None month=None  no featured offer

How is the profit per unit calculated?

Profit is the Buy Box price without VAT, minus the referral fee, the fulfilment fee and your cost. The Buy Box price is the landed price of the featured offer - item plus shipping - and on European stores it includes that country's VAT, so the script divides by 1 + VAT. Amazon calculates the referral fee on the total amount the buyer pays, with a minimum per item (0.30 in USD or EUR in most categories), so it is taken from the full price. ROI is profit divided by cost.

Blueprint bar chart splitting a 100 euro Buy Box price into VAT, referral fee, fulfilment fee, cost and profit
One 100.00 EUR sale on amazon.it at 22 % VAT, 15 % referral fee, 4.50 fulfilment and 45.00 cost.

Monthly profit splits the estimated units evenly between today's New sellers and you. That is a rough planning number, not a forecast: real sales depend on how often your offer is the featured one. The sales estimator guide explains where the unit estimate comes from.

What the numbers cannot tell you

  • Brand and category approval. Whether your account may sell a brand or category is shown in Seller Central, not in product data - check it before ordering.
  • Pack sizes. The converter returns the first product found for a barcode. Compare the title with the supplier's unit; a six-pack listing priced against a single unit's cost looks like a bargain.
  • Sellers beyond the first page. The offers call reads the first page of the offer listing, so on busy listings the seller count is a lower bound - the offer listing guide explains what it contains.
  • Other Amazon fees. Storage, hazmat and oversize charges are not in the formula; Amazon's Revenue Calculator shows the full fee for one product.
  • Tomorrow's price. One check is a snapshot; a price that is high today because a competitor is out of stock can drop next week. For shortlisted lines, the Buy Box history guide shows how price and holder moved over months.

How much does a price list cost to check?

Three credits per profitable line, one per call, plus one for every retried 502 or 503. Lines with a bad barcode are filtered before any call, a barcode without a match stops after the converter's billed 404, and a line without a featured offer or profit skips the estimate. A 1,000-line list therefore costs at most 3,000 credits plus any billed retries - see pricing for plans. The converter and estimates cover 11 marketplaces (US, UK, DE, FR, IT, ES, JP, CA, IN, MX, BR); elsewhere they answer a free 400.

Blueprint table of price list line outcomes, the API calls each one makes and its credits
Credits per line: only profitable lines use all three calls.

Frequently Asked Questions

How do I analyze a wholesale price list for Amazon?

Match each barcode to an ASIN, read the Buy Box price, sellers and Amazon's presence, estimate monthly units, then subtract VAT, fees and cost to get profit and ROI per line.

How many credits does a supplier list cost?

Three per profitable line (converter, offers and estimate), plus any retried 502 or 503. A line without profit costs two, a barcode without a match one, a malformed barcode nothing.

Does the API return Amazon's fees?

No. Enter your category's referral rate and minimum and your fulfilment fee from Amazon's fee schedule; the script applies them to every line.

Can it tell whether I am allowed to sell a brand?

No. Brand and category approval is shown in Seller Central for your account; check it for shortlisted lines before you order.

Which Amazon stores does it work on?

The converter and sales estimates cover US, UK, DE, FR, IT, ES, JP, CA, IN, MX and BR. Set MARKETPLACE and VAT for the store you sell on.

Bottom line: three calls per line turn a supplier's sheet into a sorted list of what is profitable, how crowded it is and whether Amazon sells it - before you spend money on stock. A free account includes 150 credits, enough for a 50-line list.

Ready to Extract Amazon Data at Scale?

Start building with SellerMagnet API today. Real-time product data, competitive pricing, and review analytics at your fingertips.

150 free API credits • No credit card required • Cancel anytime