Skip to content
pokemontcgapi.com
Documentation

List sealed products

Booster boxes, elite trainer boxes, tins, blisters and collections, with names in six locales and images.

GET/v1/sealed1 credit per 50 products requested (the limit), rounded up; include=index costs the samefree plan

Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=600

Objects returned

No key yet? One call gets you one: POST /v1/accounts/free with an Idempotency-Key header and your email address returns a working key in the response. Keep the original Idempotency-Key and body for response replay for up to 24 hours, under the conditions in the quickstart. The trial is 800 credits over 30 days once the address is confirmed, no card; paid plans start at 29 € a month. See the quickstart and the pricing.

Current quotes are at `GET /v1/sealed/{id}/prices` (2 credits). Sealed lists accept include=index for index_eur and last_price_at only; include=prices returns 400 INVALID_INCLUDE with details.prices_route pointing to the quote endpoint.

id on a sealed product is its sku — a readable, stable string such as evolving-skies-booster-box — and the same value opens /v1/sealed/{id} and /v1/sealed/{id}/prices. languages lists the languages the product physically exists in, which is a different thing from the locales of its name.

meta.total_count is always present: the sealed catalogue is small enough that counting it costs an index scan, so you get the number instead of guessing from has_more.

Unknown parameters return 400

An unknown query parameter returns 400 INVALID_PARAMETER before credits are reserved. details.param names the rejected parameter, details.valid_params lists the accepted names, and details.did_you_mean suggests a likely correction when one exists. Use cursor, not page or offset.

Query parameters

Query parameters
NameTypeDefaultDescription
includestring—The only relation here is index: with include=index every row carries index_eur and last_price_at, at the same 1 credit per 50 products requested as the bare list. include=prices returns 400 INVALID_INCLUDE with details.prices_route: quotes are at GET /v1/sealed/{id}/prices (2 credits). Without an include the rows are catalogue only, and orderBy on those two fields is a 400. A single product on /v1/sealed/{id} always carries them.
qstring—Free text on the product name — in the locale given by lang, if any — or an exact sku. Not the card query grammar: there are no fields or ranges here, because "evolving skies booster box" is the whole question.
setstring—Set code, slug or alternate id, as on /v1/sets/{code}. Products of a set that is not in the catalogue carry set_code: null and cannot be reached this way.
kindstring—Product kind, as printed in kind: BOOSTER_BOX, ETB, TIN, BLISTER, COLLECTION, BOOSTER_PACK, BOOSTER_BUNDLE, STARTER_DECK, BUILD_AND_BATTLE, PREMIUM_COLLECTION, SLEEVED_BOOSTER and twelve more. Read the values off the list rather than hardcoding them; an unknown kind returns an empty page, not an error.
langstring—Locale for name: en, ja, fr, de, es, it. A product without a name in that locale falls back to English.
orderBystring-release_daterelease_date, name, sku, updated_at or set, and with include=index also index_eur and last_price_at, with a leading - for descending. Every order ends on sku as the tiebreaker.
order_bystring—Accepted snake_case spelling of orderBy; the same sort keys and cursor rules apply.
limitinteger50Rows per page, 1 to 250. Card and sealed lists cost 1 credit per 50 rows requested, rounded up: 50 costs 1, 51 costs 2, 250 costs 5, so ask for multiples of 50. Above 250 you get LIMIT_EXCEEDED — follow links.next instead of raising it.
cursorstring—Opaque keyset cursor from links.next. Never construct one; it carries the sort order it was issued for and is rejected if orderBy changes mid-run.

Headers

Headers
NameTypeDefaultDescription
X-Api-Key requiredstring—Your API key. Authorization: Bearer <key> is accepted as an alias.
If-None-Matchstring—Send back the ETag you stored. The API returns a strong ETag on every catalogue response, and a 304 is a header exchange: no body, no database row read.

Example request

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"

Example response

200 OK · Cache-Control: public, max-age=60, s-maxage=300, stale-while-revalidate=600

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"
  }
}

Errors

Every error body carries error.code, error.message and error.request_id. Switch on the code, never on the message.

Errors returned by this endpoint
StatusCodeWhen
401MISSING_API_KEYNo X-Api-Key header and no bearer token on a route that requires one.
401INVALID_API_KEYThe key does not match any account.
400INVALID_PARAMETERA query parameter has the wrong type or an unsupported value — a non-integer limit, an unknown lang, an unknown region, a sort key that is not sortable.
400INVALID_CURSORThe cursor is malformed, or was issued for a different orderBy than the one on this request.
400INVALID_INCLUDEA name in include is not a known relation.
400LIMIT_EXCEEDEDlimit is above 250, or a batch request carries more than 100 ids.
429QUOTA_EXCEEDEDTrial credits, monthly credits or the daily cap are exhausted, and details says which: daily_cap with retry_after_s is the trial daily cap, which resets at midnight UTC; renews: true with resets_at is the monthly quota of a paid plan; renews: false is the trial allowance, which never comes back. details.next_step carries the plan, prices and owner action, or email verification when it unlocks the full trial.
403PLAN_REQUIREDThe feature is outside the plan (movers require Growth; photo recognition has 5 calls after Free email confirmation, then requires Growth), or the account subscription is canceled or suspended. Centering requires Growth or higher; Developer is excluded. After email confirmation the trial includes 5 measure and 5 confirm calls independently; grade and standards use trial credits without separate call counters. Before email confirmation, the message starts with “Confirm your email…”. Follow details.next_step when present.
403TRIAL_EXPIREDThe trial has ended: the account is on the trial and its 30 days from signup are over, and this route costs credits. details.trial_expired_at is the date, details.trial_days the length, and details.next_step the owner handoff. Zero-cost routes — /v1/me, /v1/me/usage, the key routes and /v1/billing/checkout — still answer.

The full taxonomy, with what to do about each code, is on the errors page.

view this page as markdown