Documentation

Thin markets and price expiry

Some cards rarely sell. This page explains what that does to a price, when a price expires, and which fields tell you how far to trust it. It applies to v1 and v2 alike; only the field names differ.

TL;DR:A variant priced at $100 or more that goes 14 days without a reported price expires: its price becomes null, its status says expired, and the value that expired is kept in lastKnownPrice (v1) or last_price (v2). Price history and statistics are never changed.

Why thin markets look odd

A variant's price is the last price the market recorded for that condition. It is never smoothed, clamped, or overridden. For cards that rarely trade raw, such as vintage chase cards, ultra-rare promos, and most graded grades, a single condition can go months between sales. One mislisted sale can therefore set the price for a long time, and conditions can look inverted (Moderately Played above Near Mint).

How a price expires

Marketplaces eventually correct or age out bad sales and stop reporting a price for that condition altogether. When that happens we do not keep serving the last value forever: a variant priced at $100 or more that goes 14 days without a reported price expires to a null price until a new sale is recorded. Expiry has been in effect since 2026-10-01.

Expiry changes price and nothing else. The variant reports an expired status and carries the value that expired. Its last-observed timestamp, price history and window statistics are left untouched. When a new sale arrives, the status returns to current. Graded variants never expire, because a slab that trades a few times a year is normal rather than a sign of a stale market.

The fields, in v1 and v2

Meaningv1v2
Current price (null when expired or never priced)pricemarkets[].price
Why the price is what it is: current, expired or unpricedpriceStatusmarkets[].price_status
The value that expired (null unless expired)lastKnownPricemarkets[].last_price
When the price was last observedlastUpdatedmarkets[].updated_at
Price changes in the last 90 dayspriceChangesCount90dmarkets[].periods.90d.changes_count

The status takes one of three values. current: a market report is in effect. expired: the last price aged out, so the price is null and the last observed value is carried alongside it. unpriced: this condition has never had a price. Full field references: Variant object (v1) and Variant object (v2).

json — expired-variant.v1.json
expired-variant.v1.json
{
  "id": "one-piece-card-game-…-secret-rare_near-mint_foil",
  "price": null,
  "priceStatus": "expired",
  "lastKnownPrice": 4400.43,
  "lastUpdated": 1782360444
}

Incremental syncs

An expiry counts as a price change, so a sync that uses updated_after receives the expired variant once, with its null price. If your sync assumes every returned price is non-null, handle null or branch on the status field. Outside of updated_after, a card whose every variant is null is omitted from browse responses unless you pass include_null_prices=true.

Judging confidence yourself

The response carries what you need:

  • Treat a variant with 0 price changes in 90 days, or a last-observed time older than 14 days, as low confidence.
  • Treat a condition priced above the next-better condition of the same card as a flag, and clamp it client-side if your use case needs a strict ladder.

For the vast majority of the catalog these checks never fire. JustTCG is a sales-data API, not a valuation service: when there is no market activity, we would rather show you that than invent a number.