Best Offer accepted prices — not listing prices

eBay Sold Card Prices API

Access eBay's completed card sales as structured JSON — including the true accepted price on Best Offer transactions. Filter by date, price, listing type, and full-text card search. Start in minutes with the free tier.

Why Best Offer prices matter for card analytics

A significant fraction of eBay card sales close via Best Offer. The seller lists at a higher price, a buyer submits an offer below asking, and the deal closes at the negotiated price. The problem: eBay's completed listings page shows the listing price for Best Offer sales — not the accepted offer.

This means nearly every price guide, comp tool, and data aggregator that pulls from eBay completed listings is systematically reporting inflated prices for Best Offer transactions. A card listed at $500 that sold for $375 via Best Offer gets reported as a $500 sale.

The Card API has separate ingestion for Best Offer transactions that captures the true accepted price. Every record includes a listing_type field so you can filter to BestOffer, Auction, or FixedPrice and analyze each type independently.

Typical listing price

$500

What most tools report

True Best Offer price

$375

What the card actually sold for

Overstatement

33%

Typical gap on mid-range cards

eBay coverage in detail

All three listing types

Auction (hammer price), Fixed Price (buy it now), and Best Offer (true accepted price). All three are included in the same endpoint and tagged with listing_type on every record. You can filter to one type or receive all three together.

38+ card categories

Baseball, basketball, football, hockey, soccer, Pokemon, Magic: The Gathering, non-sport, memorabilia, golf, tennis, boxing, UFC/MMA, racing, wrestling, and more. Everything eBay categorizes under Trading Cards and related sections.

195,000+ eBay records per day

eBay is the largest source in the database. New completed listings are ingested continuously throughout the day. The free tier includes access to 7 days of lookback; Pro extends to 30 days.

Full listing metadata on every record

Each record includes: id, title (full listing title as entered by seller), platform, listing_type, sale_price, sale_date, listing_url (direct eBay link), and category.

Additional platforms alongside eBay

The same endpoint also returns data from Goldin, Heritage, Fanatics-Vault, REA, Alt, and Pristine. Use platform=eBay to scope to eBay only, or omit the parameter to query across all sources simultaneously.

Code examples

Query eBay Best Offer sales with exact filters.

Python — filter to Best Offer sales only

import requests, statistics

resp = requests.get(
    "https://thecardapi.com/api/v1/market/sales",
    params={
        "q": "Shohei Ohtani Rookie",
        "platform": "eBay",
        "listing_type": "BestOffer",
        "date_from": "2025-04-01",
        "limit": 500,
    },
    headers={"x-market-api-key": "YOUR_API_KEY"},
)
sales = resp.json()["data"]
prices = [s["sale_price"] for s in sales]
print(f"Best Offer sales: {len(sales)}")
print(f"Median: ${statistics.median(prices):,.0f}")
print(f"Mean:   ${statistics.mean(prices):,.0f}")

JavaScript — compare auction vs. Best Offer prices

async function compareListingTypes(cardQuery) {
  const base = "https://thecardapi.com/api/v1/market/sales";
  const headers = { "x-market-api-key": "YOUR_API_KEY" };
  const dateFrom = new Date(Date.now() - 30 * 864e5).toISOString().slice(0, 10);

  const [auctionRes, bestOfferRes] = await Promise.all([
    fetch(`${base}?q=${encodeURIComponent(cardQuery)}&platform=eBay&listing_type=Auction&date_from=${dateFrom}&limit=500`, { headers }),
    fetch(`${base}?q=${encodeURIComponent(cardQuery)}&platform=eBay&listing_type=BestOffer&date_from=${dateFrom}&limit=500`, { headers }),
  ]);

  const auctions   = (await auctionRes.json()).data;
  const bestOffers = (await bestOfferRes.json()).data;

  const avg = (arr) => arr.reduce((s, x) => s + x.sale_price, 0) / arr.length;

  console.log(`Auction avg:     $${avg(auctions).toFixed(0)}  (n=${auctions.length})`);
  console.log(`Best Offer avg:  $${avg(bestOffers).toFixed(0)}  (n=${bestOffers.length})`);
  console.log(`BO discount:     ${((1 - avg(bestOffers) / avg(auctions)) * 100).toFixed(1)}%`);
}

compareListingTypes("Mike Trout 2011 Topps Update PSA 10");

curl

# Best Offer sales only — last 30 days
curl "https://thecardapi.com/api/v1/market/sales?q=Shohei+Ohtani+Rookie&platform=eBay&listing_type=BestOffer&date_from=2025-04-01" \
  -H "x-market-api-key: YOUR_API_KEY"

Query parameters

ParameterExampleDescription
qShohei Ohtani PSA 10Full-text search across all card titles
platformeBayeBay | Goldin | Heritage | Fanatics-Vault | REA | Alt | Pristine
listing_typeBestOfferAuction | FixedPrice | BestOffer
date_from2025-04-01Start date (YYYY-MM-DD). 7-day max on free tier.
date_to2025-04-30End date (YYYY-MM-DD). Defaults to today.
min_price100Minimum sale price in USD
max_price5000Maximum sale price in USD
limit500Records per page (max 500)
offset0Pagination offset for large result sets

Frequently asked questions

Why don't most APIs show the true eBay Best Offer price?
eBay's public-facing completed listings page shows the listing price for Best Offer sales, not the accepted offer price. This is because eBay treats the accepted offer amount as transaction-private. Most scrapers and APIs pull from the completed listings page and therefore report the listing price rather than the negotiated sale price. The Card API has separate ingestion for Best Offer transactions that captures the true accepted price.
How much lower are Best Offer prices versus listing prices?
In the sports card market, Best Offer sales typically close 15–35% below the listing price, depending on card category, price point, and how urgently the seller wants to move the item. High-value cards ($500+) often see larger discounts than lower-value items. This means price guides that show listing prices for Best Offer transactions can systematically overstate actual market prices.
Does the API cover all eBay Trading Cards categories?
Yes. The Card API covers all 38+ eBay Trading Cards subcategories including Baseball Cards, Basketball Cards, Football Cards, Hockey Cards, Soccer Cards, Pokemon, Magic: The Gathering, non-sport, and sports memorabilia. All categories are available on all tiers including the free tier.
Can I filter eBay results to only Best Offer sales?
Yes. Use the listing_type=BestOffer parameter to filter results to only Best Offer sales. You can combine this with the platform=eBay parameter to scope results to eBay only. The listing_type field on every record also identifies whether any given sale was Auction, FixedPrice, or BestOffer.
How frequently is eBay data updated?
eBay data is ingested continuously throughout the day. The database adds over 195,000 eBay records per day across all card categories. New completed listings typically appear in the API within a few hours of the sale closing.
Is there a way to get historical eBay card prices?
Yes. Use the date_from and date_to parameters to filter by any date range within your plan's lookback window. Free tier: 7 days. Pro tier: 30 days. Enterprise: full historical data. The /card-price-history-api page has more details on historical access.

Access true eBay sold prices

Free tier: 10,000 sales/day, 7-day lookback, no credit card required.

Get Free API Key →