Pokémon card price API
A Pokémon card price API that says where every number comes from
Daily price points 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
- One point a day per card; each source declares its own minimum delay
- Start
- 800 trial credits, no card, 30 days
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.
curl -s "https://api.pokemontcgapi.com/v1/cards/base1-4/prices" \
-H "X-Api-Key: $PTCG_API_KEY"const url = new URL("https://api.pokemontcgapi.com/v1/cards/base1-4/prices");
const res = await fetch(url, {
headers: { "X-Api-Key": process.env.PTCG_API_KEY ?? "" },
});
if (!res.ok) {
const { error } = await res.json();
throw new Error(`${error.code}: ${error.message} (${error.request_id})`);
}
const { data, meta } = await res.json();import os, httpx
res = httpx.get(
"https://api.pokemontcgapi.com/v1/cards/base1-4/prices",
headers={"X-Api-Key": os.environ["PTCG_API_KEY"]},
)
res.raise_for_status()
payload = res.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 a plan withholds, it names
The trial reads every current price and 7 days of history, in English-language rows. Developer (€29/month) adds 30 days of history and the rows of the other printing languages; Growth (€79/month) adds graded quotes, the complete history and the movers feed. Whatever a plan does not cover is listed 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 points are published daily, so a nightly sync is the natural shape. 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
- One point a day, and every source carries a minimum delay that
GET /v1/prices/sourceslists next to its name. 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?
- A point is published daily for each covered card, carrying the latest value the source reported. Each source has a minimum delay listed at GET /v1/prices/sources, and every row carries its as_of date, so you never have to guess how old a figure is. Price methodology
- Which marketplaces do the prices come from?
- European asking prices in EUR, US guide figures in USD, graded medians, and a composite EUR index computed by us. The current list, with the basis and the delay of each source, is at GET /v1/prices/sources; the methodology page explains what each one measures. Price methodology
- 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, the same as the bare list.