Skip to content
Crypto-only, prepaid. Top up a balance and we draw from it monthly — nothing is ever charged automatically.
tcggraph

Prices: Cardmarket and TCGplayer

Every card carries a European quote and a North American one, in their native currencies. This page covers how to pick between them and how to read what each marketplace reports.

Two markets, one card

Trading cards do not have a price. They have a price in a market. A Pokémon card that settles at $80 on TCGplayer can sit at €55 on Cardmarket, and the gap is not a conversion artefact — European print runs, distribution and demand genuinely differ from American ones. An API that gives you one number and calls it “the price” is quietly wrong for half the world.

So every card in TCGGraph carries at least two quotes: tcgplayer in USD for North America, and cardmarket in EUR for Europe. Neither is converted from the other. Both are the marketplace’s own numbers, in the marketplace’s own currency.

prices[]
{
  "prices": [
    {
      "source": "tcgplayer",
      "region": "NA",
      "finish": "holofoil",
      "condition": "NM",
      "currency": "USD",
      "market": 2380.34,
      "low": 1805,
      "high": 6000
    },
    {
      "source": "cardmarket",
      "region": "EU",
      "finish": "holofoil",
      "condition": "NM",
      "currency": "EUR",
      "market": 1832.38,
      "low": 1282.38,
      "high": 2617.08,
      "trend": 1832.38,
      "avg1": 1784.13,
      "avg7": 1797.50,
      "avg30": 1867.76,
      "sellers": 38
    }
  ]
}

Choosing a source

Every card always returns every quote it has, so a plain request needs no extra parameters. What the source parameter changes is which quote filtering and sorting run against. Price bounds are read in that source’s currency, so source=cardmarket&minPrice=50 means €50, not $50.

# Sort and filter on the European market
GET /v1/cards?game=pokemon&source=cardmarket&minPrice=50&sort=-price

# region=EU is the same thing, without naming a vendor
GET /v1/cards?game=pokemon&region=EU&minPrice=50&sort=-price

The response echoes the decision back as meta.priceSource, which is worth asserting on in tests. Getting a USD sort when you meant a EUR one is the kind of bug that surfaces as a mildly wrong list rather than an error.

{
  cards(
    filter: { game: POKEMON, source: CARDMARKET, minPrice: 50 }
    sort: PRICE_DESC
    limit: 20
  ) {
    pageInfo { totalCount priceSource }
    nodes {
      name
      prices {
        source
        currency
        market
        trend
        avg7
        avg30
        sellers
      }
    }
  }
}

What Cardmarket reports

Cardmarket exposes more of its own statistics than TCGplayer does, and they are the fields European sellers actually price against. We serve them under stable names rather than passing the marketplace’s vocabulary through unchanged.

CardmarketTCGGraphNotes
trendtrendCardmarket's own trend price. We also copy it to market.
avgavg30Their all-time average is not comparable across reprints; we serve the 30-day window instead.
avg1avg1Mean of yesterday's sales.
avg7avg7Mean of the last seven days.
avg30avg30Mean of the last thirty days.
lowlowCheapest live article in any condition.
lowFoillowServed on the foil finish row rather than as a separate field.
countArticlessellersHow many live listings the quote is drawn from.
idProductexternalIds.cardmarketIdKept so you can deep-link to the product page.

trend is the one to reach for when repricing. It is Cardmarket’s own smoothed estimate and it is what sellers on the platform anchor to, so a listing generated from avg30 will look mispriced next to the competition even when it is a defensible number. Use avg1 and avg7 to detect movement, not to set a price.

sellers is the depth behind the quote. A trend price drawn from four live articles is a rumour; the same price drawn from two hundred is a market. Gate any automated repricing on it.

Condition ladders do not line up

The two marketplaces grade differently, and they do not use the same number of rungs. Cardmarket runs seven grades from Mint down to Poor; TCGplayer runs five. We keep each marketplace’s own grade on its own quote rather than inventing a shared scale that would misrepresent both.

TCGplayerClosest CardmarketNotes
NM — Near MintNMThe default both marketplaces quote.
LP — Lightly PlayedEXCardmarket's Excellent is the closest grade.
MP — Moderately PlayedGDGood.
HP — Heavily PlayedLPLight Played, despite the initials.
DMG — DamagedPL / POPlayed or Poor, depending on the listing.

The full Cardmarket ladder is MT (Mint), NM (Near Mint), EX (Excellent), GD (Good), LP (Light Played), PL (Played), PO (Poor). Note that LP means Lightly Played on TCGplayer and Light Played on Cardmarket, but they sit at different points on their respective ladders — TCGplayer’s is second from the top, Cardmarket’s is fifth. Mapping them onto each other by string equality is the single most common mistake in this area.

Reading the spread

Because both quotes are native, the difference between them is real information rather than rounding. Cross-border sellers use it to decide which market to list in; collectors use it to decide which market to buy from.

type Quote = { source: string; currency: string; market: number };

const EUR_PER_USD = 0.92;

/** Positive means the card is dearer in Europe than in the States. */
function spread(prices: Quote[]) {
  const us = prices.find((p) => p.source === "tcgplayer")?.market;
  const eu = prices.find((p) => p.source === "cardmarket")?.market;
  if (us === undefined || eu === undefined) return null;

  return ((eu / EUR_PER_USD - us) / us) * 100;
}

Convert only at the point of display, and only with a rate you control. We do not fold a conversion into the stored data, because a price that silently moves when the currency market does is impossible to reconcile against a sale that already happened.

Finishes and languages

  • Cardmarket treats a foil as a separate product with its own listings, so foil and nonfoil arrive as separate rows on prices, distinguished by finish.
  • European printings exist in English, German, French, Italian, Spanish and Portuguese, and they do not trade at the same price. Non-English printings resolve to their own card records rather than being collapsed into the English one.
  • Sealed product is not priced here. These endpoints cover singles; sealed has a different shape and a different set of buyers.

Freshness

Both sources are refreshed on the same schedule and stamped with updatedAt, so you never have to work out which half of a card’s pricing is stale. Daily closes are kept for both markets, which means you can chart a European price series without having collected it yourself. See the REST reference for the history endpoint, or the Cardmarket overview for what the European coverage includes game by game.