Historical data • date_from / date_to filtering

Card Price History API

Query historical trading card sales data by date range. Individual transaction records from eBay, Goldin, Heritage, and more — spanning from today back to the full database history. One endpoint: GET /sales with a date_from parameter.

How historical data works

The Card API uses a single GET /sales endpoint for both recent and historical data. Pass date_from and optionally date_to to retrieve any date window your subscription covers.

There's no separate historical endpoint, no separate pricing, and no pagination limit on historical depth — iterate through pages using offset the same way you would for recent data.

Free

7 days

$0/mo

Recent comps, AI agent use cases

Pro

30 days

$49/mo

Trend analysis, price modeling

Enterprise

Full history

Custom

Backtesting, academic research

Historical data use cases

Price trend analysis

Track how a card's market value has changed over time. Pull monthly sales, calculate rolling averages, standard deviations, or percentile distributions to characterize the market for any card or set.

Portfolio valuation

Value a card collection at a point in time. Pull 30 days of comps for each card in the portfolio, calculate the appropriate market price, and track changes week over week.

Price modeling and ML

Train models on historical transaction data. The raw per-transaction records are ideal for regression models predicting card values from grade, year, player stats, or other features.

Market timing research

Identify seasonal patterns, player-event correlation (post-award, retirement, Hall of Fame induction), and cross-platform price divergence over time.

Auction result archives

Build a searchable archive of past auction results from Goldin, Heritage, and REA — useful for dealers, appraisers, and collectors who need verifiable historical comps.

Arbitrage detection

Compare historical price variance across platforms for the same card to identify platform-specific pricing inefficiencies and buying opportunities.

Pull 30 days of price history

Paginate through all sales for a card in the last 30 days and build a daily price series:

Python
import requests
from collections import defaultdict
from datetime import date, timedelta

API_KEY = "tca_your_key_here"
BASE    = "https://thecardapi.com/api/v1/market"

def price_history(card: str, days: int = 30) -> dict[str, list[float]]:
    date_from = (date.today() - timedelta(days=days)).isoformat()
    daily: dict[str, list[float]] = defaultdict(list)

    offset, limit = 0, 500
    while True:
        r = requests.get(
            f"{BASE}/sales",
            params={"q": card, "date_from": date_from, "limit": limit, "offset": offset},
            headers={"x-market-api-key": API_KEY},
        )
        r.raise_for_status()
        batch = r.json()["data"]
        for sale in batch:
            daily[sale["sale_date"]].append(sale["sale_price"])
        if len(batch) < limit:
            break
        offset += limit

    return dict(daily)

history = price_history("Wander Franco Rookie PSA 10", days=30)
for dt in sorted(history):
    prices = history[dt]
    avg = sum(prices) / len(prices)
    print(f"{dt}: {len(prices)} sales, avg ${avg:,.0f}, range ${min(prices):,.0f}–${max(prices):,.0f}")
JavaScript
const API_KEY = "tca_your_key_here";
const BASE    = "https://thecardapi.com/api/v1/market";

async function priceHistory(card, days = 30) {
  const dateFrom = new Date(Date.now() - days * 864e5).toISOString().slice(0, 10);
  const daily    = {};
  let offset = 0;
  const limit = 500;

  while (true) {
    const url    = new URL(`${BASE}/sales`);
    url.searchParams.set("q",         card);
    url.searchParams.set("date_from", dateFrom);
    url.searchParams.set("limit",     limit);
    url.searchParams.set("offset",    offset);

    const { data } = await fetch(url, {
      headers: { "x-market-api-key": API_KEY },
    }).then((r) => r.json());

    for (const sale of data) {
      (daily[sale.sale_date] ??= []).push(sale.sale_price);
    }

    if (data.length < limit) break;
    offset += limit;
  }

  return daily;
}

const history = await priceHistory("Wander Franco Rookie PSA 10", 30);
for (const [dt, prices] of Object.entries(history).sort()) {
  const avg = prices.reduce((a, b) => a + b, 0) / prices.length;
  console.log(`${dt}: ${prices.length} sales, avg $${avg.toFixed(0)}`);
}

Date filtering parameters

ParameterFormatDescription
date_fromYYYY-MM-DDStart of the date window (inclusive). Defaults to 7 days ago if omitted.
date_toYYYY-MM-DDEnd of the date window (inclusive). Defaults to today if omitted.
qstringFull-text search: card name, player, set, grade (e.g. PSA 10, BGS 9.5).
platformstringFilter by source: eBay, Goldin, Heritage, REA, Fanatics-Vault, Alt, Pristine.
listing_typestringFilter by sale type: Auction, FixedPrice, or BestOffer.
limitintegerRecords per page. Maximum 500.
offsetintegerPagination offset. Increment by limit to page through large result sets.

Frequently asked questions

How far back does the card price history API go?

Lookback depth depends on your subscription. Free: 7 days. Pro: 30 days. Enterprise: full database history. All tiers use the same endpoint — just pass date_from.

Does the API return individual sales or averaged prices?

Individual sale records only. Every record includes sale_price, sale_date, platform, listing_type, and title. You get raw transaction data and can calculate whatever aggregates your application needs.

Which platforms are included in the price history?

eBay (auction, fixed price, and Best Offer accepted prices), Goldin, Heritage Auctions, REA, Fanatics Vault, Alt, and Pristine. All are normalized to a single JSON schema.

How do I paginate through large historical datasets?

Use the offset and limit parameters. Set limit to 500 (maximum) and increment offset by 500 per request. Continue until the response contains fewer records than the limit. No separate pagination token required.

Is there an additional cost for historical data access?

No. Historical data is included in your subscription tier and uses the same per-request quota as recent data. Enterprise tier includes unlimited full-history access at no additional charge.

Can I export historical data to CSV or bulk formats?

Yes. The API response is JSON, which you can convert to CSV in any language. Enterprise tier also supports S3 bulk delivery for very large historical exports (millions of records).

Access card price history today

Free tier includes 7-day lookback — enough for AI agents and recent comp tools. Upgrade to Pro for 30-day trend analysis.

Get Free API Key →