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.
| Verdict | When | Next step |
|---|---|---|
| Shortlist | ROI at least 20 %, Amazon not selling | Check brand approval, order a test quantity |
| Thin margin | Profit above 0, ROI under 20 % | Negotiate the cost or skip |
| Amazon sells it | Amazon is a New seller | Skip unless you can match Amazon |
| No profit at this cost | Profit 0 or less | Skip |
| No featured offer | No Buy Box price today | Check the listing by hand |
| No match on Amazon | Converter answers 404 | Search 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.

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.

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.