Skip to content
pokemontcgapi.com

Pokémon card price API

A Pokémon card price API that says where every number comes from

Daily prices for Pokémon TCG cards and sealed products over REST. Every row names its source, whether it is an asking price, a guide figure or a sale, the printing and condition it applies to, and the day it is for.

Sources
Cardmarket, CardTrader, TCGplayer, PriceCharting, eBay, plus a composite EUR index
Currencies
EUR and USD, never converted into each other
Freshness
Daily, each source published with its stated delay
Start
800 credits, once, valid 30 days, no card

Most card price feeds hand you one number called "market price" and leave you to guess what it measures. That is fine for a widget and useless for a valuation: an asking price, a guide figure and a completed sale are three different facts, and a collection worth real money should not be summed across them by accident.

Here the price is a row, not a number. It carries source, variant (low, market, trend, rolling averages, graded median, index), basis (ASKING, GUIDE, SOLD or DERIVED), currency, locale, printing, condition, grading, as_of and, where the source reports it, sample_n. You choose which rows your product trusts, and you can show your users why.

For lists and portfolios there is also one comparable figure per card: index_eur, a composite index in euro computed from the raw-card rows, with the sample size behind it. It is on every single-card response, and on list rows with include=index.

One call, and what comes back

One card, every current price row your plan covers, and the composite index. This is a real response from production, not a mock.

GET/v1/cards/{id}/prices2 credits · from Trialfull reference
curl -s "https://api.pokemontcgapi.com/v1/cards/base1-4/prices" \
  -H "X-Api-Key: $PTCG_API_KEY"
response.json
{
  "data": {
    "card_id": "base1-4",
    "index": {
      "eur": 556.23,
      "as_of": "2026-09-02",
      "sample_n": 16,
      "by_locale": [
        {
          "locale": "en",
          "printing": null,
          "eur": 556.23,
          "as_of": "2026-09-02",
          "sample_n": 16
        },
        {
          "locale": "fr",
          "printing": null,
          "eur": 900.58,
          "as_of": "2026-09-02",
          "sample_n": 3
        },
        {
          "locale": "de",
          "printing": null,
          "eur": 399.95,
          "as_of": "2026-09-02",
          "sample_n": 5
        },
        {
          "locale": "es",
          "printing": null,
          "eur": 1313.14,
          "as_of": "2026-09-02",
          "sample_n": 8
        },
        {
          "locale": "it",
          "printing": null,
          "eur": 400.64,
          "as_of": "2026-09-02",
          "sample_n": 11
        }
      ]
    },
    "quotes": [
      {
        "source": "CARDMARKET",
        "variant": "LOW",
        "basis": "ASKING",
        "amount": 599.9,
        "currency": "EUR",
        "locale": "en",
        "condition": "NEAR_MINT",
        "printing": null,
        "grading": null,
        "as_of": "2026-09-01",
        "sample_n": null,
        "provenance": "Cardmarket"
      },
      {
        "source": "CARDTRADER",
        "variant": "LOW",
        "basis": "ASKING",
        "amount": 1250.64,
        "currency": "EUR",
        "locale": "en",
        "condition": "NEAR_MINT",
        "printing": null,
        "grading": null,
        "as_of": "2026-09-01",
        "sample_n": 4,
        "provenance": "CardTrader"
      },
      {
        "source": "TCGPLAYER",
        "variant": "LOW",
        "basis": "GUIDE",
        "amount": 510,
        "currency": "USD",
        "locale": "en",
        "condition": null,
        "printing": "HOLOFOIL",
        "grading": null,
        "as_of": "2026-07-30",
        "sample_n": null,
        "provenance": "TCGplayer"
      },
      {
        "source": "EBAY",
        "variant": "MEDIAN_GRADED",
        "basis": "ASKING",
        "amount": 400,
        "currency": "USD",
        "locale": "en",
        "condition": null,
        "printing": null,
        "grading": {
          "company": "PSA",
          "score": "1"
        },
        "as_of": "2026-08-26",
        "sample_n": 7,
        "provenance": "eBay"
      },
      {
        "source": "PRICECHARTING",
        "variant": "MEDIAN_GRADED",
        "basis": "GUIDE",
        "amount": 20061.4,
        "currency": "USD",
        "locale": "en",
        "condition": null,
        "printing": null,
        "grading": {
          "company": "PSA",
          "score": "10"
        },
        "as_of": "2026-08-24",
        "sample_n": null,
        "provenance": "PriceCharting"
      }
    ]
  },
  "meta": {
    "quotes": 5,
    "delayed_hours": 0
  }
}

What each plan reads

The trial key is 800 credits, granted once and valid for 30 days, with no credit card. It reaches every catalogue route and the current prices, with 7 days of price history.

Developer (€29/month) adds 30 days of history and price rows in every printing language. Growth (€79/month) adds graded quotes, the complete price history and the movers feed. What a plan does not cover is never silently dropped: the response names it in meta.withheld, so "no graded rows" is never mistaken for "nobody grades this card".

Quota is counted in credits, and each response says what it cost in X-Credits-Cost. A card with its prices is 2 credits, a batch of current prices is 4 per 25 cards, a price history is 5. Errors and 304 Not Modified cost nothing.

Built for a job that runs every night

Price rows change once a day, so the efficient integration is a nightly sync, not a call per page view. GET /v1/prices/current takes up to 50 card ids in one request; ETag and If-None-Match turn an unchanged answer into a free, bodiless 304; and GET /v1/changes tells you which cards moved since your last run so you re-read only those.

Cursor pagination ends every sort on id, so a full walk of the catalogue never repeats or drops a row, and every error is JSON with a stable error.code you can branch on.

What it is not

Read this before you build on it. Every line here is a support ticket somebody else already opened.

Not real-time
Prices are daily and most sources are published with a 24-hour delay. This is a reference, not an order book: do not build an arbitrage bot on it.
eBay rows are asking prices
The eBay figures are medians of what sellers are asking for graded slabs, not completed sales. The row says basis: "ASKING"; keep it that way in your UI.
Currencies are not converted
A Cardmarket row is in EUR and a TCGplayer row is in USD because that is what the source publishes. The only cross-source figure is the EUR index.

Questions people ask before signing up

Is there a free Pokémon card price API?
There is a free trial: 800 credits, granted once, valid for 30 days, no credit card. It includes current prices and 7 days of history, which is enough to build and test an integration. It does not renew; paid plans start at €29/month. Free trial key
How often are prices updated?
Once a day per source. Each source has a declared minimum delay, listed live at GET /v1/prices/sources, and every row carries the day it refers to in as_of, so your application never has to guess how old a number is. Price methodology
Which marketplaces do the prices come from?
Cardmarket and CardTrader for European asking prices in EUR, TCGplayer and PriceCharting for US guide figures in USD, PriceCharting and eBay for graded cards, and a composite EUR index computed by us. The current list, with the basis of each, is at GET /v1/prices/sources.
Can I get the price of many cards in one call?
Yes. GET /v1/prices/current takes up to 50 card ids and costs 4 credits per 25. For a whole list with one comparable figure per card, add include=index to a card search: 1 credit per 50 rows.

Keep reading