Skip to content
pokemontcgapi.com

Sealed product price API

Booster box and sealed Pokémon product prices over an API

Booster boxes, cases, Elite Trainer Boxes, tins, blisters and collection boxes as first-class objects, each tied to its set, with names in several languages, an image and current prices.

Kinds
Booster box, case, ETB, tin, blister, collection and more
Search
q, set, kind, lang, sorted by release, name or value
Prices
GET /v1/sealed/{id}/prices, same row format as cards
List cost
1 credit per 50 products requested, with or without include=index

Sealed product is where a lot of the money in this hobby sits, and it is usually an afterthought in card APIs: a string in a notes field, if anything. Here a sealed product has an id, a kind, the set it belongs to, a pack count where that makes sense, an image, and its own price route.

GET /v1/sealed?set=evs&kind=BOOSTER_BOX answers "what does an Evolving Skies booster box cost" in one call. With include=index every row includes index_eur and last_price_at. The EUR figure is there where a catalogue price is known, and last_price_at says when a price was last recorded.

One call, and what comes back

Searching sealed products. The response is a real one from production: note kind, set_code and pack_count next to the price fields.

GET/v1/sealed1 credit · from Trialfull reference
request.tsrequest.py
curl -s -G "https://api.pokemontcgapi.com/v1/sealed" \
  --data-urlencode "q=evolving skies" \
  --data-urlencode "kind=BOOSTER_BOX" \
  --data-urlencode "limit=2" \
  -H "X-Api-Key: $PTCG_API_KEY"
const url = new URL("https://api.pokemontcgapi.com/v1/sealed");
url.searchParams.set("q", "evolving skies");
url.searchParams.set("kind", "BOOSTER_BOX");
url.searchParams.set("limit", "2");

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/sealed",
    params={"q": "evolving skies", "kind": "BOOSTER_BOX", "limit": "2"},
    headers={"X-Api-Key": os.environ["PTCG_API_KEY"]},
)
res.raise_for_status()
payload = res.json()
response.json
{
  "data": [
    {
      "id": "evolving-skies-6-booster-box-case",
      "sku": "evolving-skies-6-booster-box-case",
      "slug": "evolving-skies-6-booster-box-case",
      "name": "Evolving Skies 6 Booster Box Case",
      "kind": "BOOSTER_BOX",
      "set_code": "evs",
      "set_name": "Evolving Skies",
      "image_url": "https://img.pokemontcgapi.com/media/boxes/evolving-skies-6-booster-box-case-normal.webp?e=1791763200&s=Zp2fL8qKw3xVn1tRc7bYdM",
      "release_date": null,
      "pack_count": 216,
      "languages": [],
      "index_eur": 15495,
      "last_price_at": "2026-09-02T00:38:55.286Z",
      "created_at": "2026-05-23T12:43:56.128Z",
      "updated_at": "2026-09-02T15:56:54.473Z"
    },
    {
      "id": "evolving-skies-booster-box",
      "sku": "evolving-skies-booster-box",
      "slug": "evolving-skies-booster-box",
      "name": "Evolving Skies Booster Box",
      "kind": "BOOSTER_BOX",
      "set_code": "evs",
      "set_name": "Evolving Skies",
      "image_url": "https://img.pokemontcgapi.com/media/boxes/evolving-skies-booster-box-normal.webp?e=1791763200&s=Hq6dS1nXt9wBk4yPm2vLcJ",
      "release_date": null,
      "pack_count": 36,
      "languages": [],
      "index_eur": 1750,
      "last_price_at": "2026-09-02T00:36:37.317Z",
      "created_at": "2026-05-23T12:43:56.069Z",
      "updated_at": "2026-09-02T15:56:54.473Z"
    }
  ],
  "meta": {
    "limit": 2,
    "count": 2,
    "total_count": 3,
    "has_more": true
  },
  "links": {
    "next": "https://api.pokemontcgapi.com/v1/sealed?cursor=eyJrIjpbbnVsbF0sImlkIjoiZXZvbHZpbmctc2tpZXMtYm9vc3Rlci1ib3giLCJzIjoicmVsZWFzZV9kYXRlOmRlc2Msc2t1OmFzYyJ9&kind=BOOSTER_BOX&limit=2&q=evolving+skies"
  }
}

The product and its quotes

A product's current prices come from GET /v1/sealed/{id}/prices for 2 credits, in the same row format as cards: source, variant, basis, currency, date. A list costs 1 credit per 50 products requested, rounded up, with or without include=index. A single product includes the index fields, which can be null when no catalogue price is known.

Cards and sealed in one portfolio

Because a sealed product points at its set by set_code, the same set page in your app can show the cards, the products that contain them and what each is worth. The /v1/changes feed reports sealed products too, so a mirror stays current without re-reading the list.

What it is not

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

Pokémon only
The sealed catalogue is filtered to Pokémon TCG products. Other games are not served.
Release dates are partial
release_date is null on many products. Sort by name or by value when the date matters to your UI, or fall back to the release date of the set.
Fewer sources than cards
Not every price source covers sealed product. Read GET /v1/sealed/{id}/prices for what exists rather than assuming the card sources apply.

Questions people ask before signing up

Is there an API for Pokémon booster box prices?
Yes. GET /v1/sealed lists sealed products, filterable by set and kind, and GET /v1/sealed/{id}/prices returns the current price rows for one product, each with its source, basis and date.
Which sealed product types are covered?
Booster boxes and cases, Elite Trainer Boxes, tins, blisters, collection boxes and similar retail products, each with a kind field you can filter on. The live count is on GET /v1/status. Coverage, measured live
Can I track the value of a sealed collection?
Yes. Ask for the list with include=index and store index_eur daily for each product that has a catalogue price; for the others it is null. last_price_at says when a price was last recorded. The call costs 1 credit per 50 products requested (the limit), rounded up, the same as the plain list. Use case: price tracker
Is sealed product available on the trial?
Yes, the catalogue and the current prices both. The trial key reads sealed lists and single products the same way a paid key does; what grows with the plan is the price history behind them. Free trial key

Keep reading