NewThe Catalog API is live — 15M+ cards with permanent UCIDs. Included with Pro.Explore →
The Card API
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.

Supported Best Offer records include the confirmed accepted price. The listing_type field lets you filter BestOffer, Auction, and FixedPrice records 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.

Daily eBay sales updates

Newly indexed eBay sale records are added daily. The free tier includes 3 days of lookback; Pro includes 90 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 endpoint returns eBay sales across all listing types. Use listing_type=auction, listing_type=fixed_price, or listing_type=best_offer to scope results.

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
platformeBayCurrently: eBay
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?
Supported Best Offer records include the confirmed accepted price rather than the original asking price. Use listing_type=BestOffer to query those transactions separately.
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?
New eBay sale records are added daily across supported card categories.
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: 3 days. Pro tier: 90 days. Enterprise: full historical data. The /card-price-history-api page has more details on historical access.

Access true eBay sold prices

Free tier: 5,000 sales/day, 3-day lookback, no credit card required.

Get Free API Key →