An eBay Best Offer accepted price API answers a question eBay itself won't: what did the buyer actually pay?
When a listing sells through an accepted Best Offer, eBay's sold page shows the original asking price, struck through. The negotiated price stays hidden. If you build comps, price inventory or run a valuation tool, those asking prices quietly push every number you calculate upward.
Here is a real example from last week. A PSA 10 Charizard VMAX 074/073 (Champion's Path) sold on October 25, 2026:
| What eBay shows | What the buyer paid |
|---|---|
| $349.00 (asking price) | $307.00 (accepted offer) |
That's $42, or 12%, off the price you'd have recorded. In the same search, 11 of 60 recent sales closed on a Best Offer. Average those in at the asking price and your "market value" is fiction.
This post shows how to get the real number with one request.
The short version
curl -H "Authorization: Bearer $COMPSNIPER_API_KEY" \
"https://api.compsniper.com/v1/scrape?keyword=psa+10+charizard+vmax+074&count=100&bestOfferPrice=true"
Add bestOfferPrice=true to a sold search and every sale that closed on an accepted offer gains two fields:
{
"title": "2020 Pokemon SWSH FA Charizard Vmax 074/073 Champion's Path Secret PSA 10",
"bestOfferAccepted": true,
"soldPrice": "349.00",
"acceptedOfferPrice": "307.00",
"acceptedOfferPriceStatus": "found",
"endedAt": "2026-10-25"
}
-
soldPriceis untouched: it's still the listed price, so you can see the discount. -
acceptedOfferPriceis what the buyer paid. -
acceptedOfferPriceStatustells you where that price stands:found,pending(still being looked up, check back shortly) ornot_available.
No eBay developer account, no seller access to the transaction, no scraping on your side. The free plan includes 100 requests a month, and the accepted price costs nothing extra.
Why the official eBay APIs don't help here
If you've tried to solve this with eBay's own tools, you've hit these walls:
-
Trading API
GetBestOffersonly returns offers on your own listings. Useless for market comps. - Browse API returns active listings only. No sold prices at all.
-
Finding API
findCompletedItemswas decommissioned in February 2025. - Marketplace Insights API is a limited release for approved partners, and it isn't taking most new developers.
So the accepted price on other sellers' sales is simply not available from eBay to a regular developer. That's the gap this fills.
Python: comps with the real accepted prices
import os
import statistics
import requests
def sold_comps(keyword, count=100):
r = requests.get(
"https://api.compsniper.com/v1/scrape",
headers={"Authorization": f"Bearer {os.environ['COMPSNIPER_API_KEY']}"},
params={"keyword": keyword, "count": count, "bestOfferPrice": "true"},
timeout=90,
)
r.raise_for_status()
return r.json()["items"]
def real_price(item):
"""Use the accepted offer when we have it, otherwise the sold price."""
if item.get("bestOfferAccepted") and item.get("acceptedOfferPriceStatus") == "found":
return float(item["acceptedOfferPrice"])
return float(item["soldPrice"])
items = sold_comps("psa 10 charizard vmax 074")
asking = [float(i["soldPrice"]) for i in items]
paid = [real_price(i) for i in items]
print(f"median from eBay's displayed prices: ${statistics.median(asking):,.2f}")
print(f"median from what buyers paid: ${statistics.median(paid):,.2f}")
for i in items:
if i.get("acceptedOfferPriceStatus") == "found":
print(f"{i['endedAt']} asked ${i['soldPrice']} paid ${i['acceptedOfferPrice']} {i['title'][:60]}")
Prefer a package? pip install compsniper wraps the same calls with retries built in.
JavaScript (Node 18+, no dependencies)
const params = new URLSearchParams({
keyword: "psa 10 charizard vmax 074",
count: "100",
bestOfferPrice: "true",
});
const res = await fetch(`https://api.compsniper.com/v1/scrape?${params}`, {
headers: { Authorization: `Bearer ${process.env.COMPSNIPER_API_KEY}` },
});
if (!res.ok) throw new Error(`API error ${res.status}`);
const { items } = await res.json();
const realPrice = (i) =>
i.bestOfferAccepted && i.acceptedOfferPriceStatus === "found"
? Number(i.acceptedOfferPrice)
: Number(i.soldPrice);
for (const i of items.filter((x) => x.bestOfferAccepted)) {
console.log(i.endedAt, "asked", i.soldPrice, "paid", i.acceptedOfferPrice ?? "(pending)", i.title);
}
What to do with pending
Accepted prices aren't always ready the moment a sale appears. A row marked pending is still being looked up. Two simple strategies:
-
For a live price check, use the accepted price where it's
foundand fall back to the sold price elsewhere (thereal_pricehelper above). -
For a database, store the item ID and re-check later.
GET /v1/best-offer-prices?itemIds=...returns the latest status for up to 100 sales at once, so you can fill in the gaps on a schedule.
One more detail: accepted prices are returned for sales in US dollars on ebay.com. On other eBay sites, accepted-offer rows come back as not_available.
Where this matters most
- Graded cards and collectibles: offers are everywhere, and a 10 to 15% gap on a $300 card is the difference between profit and loss.
- Resale pricing tools: your users trust your "sold for" number. Asking prices make it wrong in the direction that hurts them.
- Inventory valuation: one inflated comp per category compounds across thousands of SKUs.
- Arbitrage bots: buying at the "market price" when the market really clears 12% lower is how bots lose money.
Try it
- Create a free account at compsniper.com and copy your API key.
- Run the curl above with your own search.
- Compare the two medians.
Full reference: Accepted Best Offer prices docs. Runnable examples: ebay-best-offer-price-api on GitHub.
Over to you: when you price items from eBay sold listings today, are you counting Best Offer sales at the asking price, or throwing them out entirely?
Top comments (0)