Skip to content
pokemontcgapi.com
Documentation

Cards in a set

Every card in a set, in collection order, with correct paging past 250 rows.

GET/v1/sets/{code}/cards1 creditfree plan

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

Objects returned

An unknown code returns 404 SET_NOT_FOUND, never an empty page. An empty page reads as "this set was emptied" and is the fastest way to get a wrong bug report written about you.

This is the endpoint where a missing sort tiebreaker does the most damage: a set over 250 cards spans several pages, and rows sharing a collector number would land in undefined order at every boundary. Here the sort is (number_sort, number, id) and id is never optional, so pagination never repeats or drops a row, at any page depth.

Path parameters

Path parameters
NameTypeDefaultDescription
code requiredstringSet code, slug or alternate id.

Query parameters

Query parameters
NameTypeDefaultDescription
qstringFurther Lucene filter, applied inside the set.
orderBystringnumberDefaults to collection order. Same keys as search cards. number sorts on the extracted numeric part first, so 1S lands next to 1 and not next to 100.
selectstringComma-separated card fields to return. id is always included. camelCase and snake_case both resolve, so nationalPokedexNumbers works and comes back as national_pokedex_numbers. An unknown name is INVALID_SELECT_FIELD, with the full list in details.valid_fields.
includestringComma-separated relations to expand: prices, translations, images, set, artist. Each one is an extra join, so ask only for what you render. include=prices is how you get the per-source price breakdown. legalities is not an accepted value and is rejected with 400 INVALID_INCLUDE.
langstringLocale for the card name: en, ja, fr, de, es, it — the six with translation rows in the catalogue. A card with no translation in the requested locale falls back to English rather than to null.
limitinteger50Rows per page, 1 to 250. Above 250 you get LIMIT_EXCEEDED — follow links.next instead of raising it.
cursorstringOpaque 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 requiredstringYour API key. Authorization: Bearer <key> is accepted as an alias.
If-None-MatchstringSend 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/sets/bs/cards" \
  --data-urlencode "limit=2" \
  --data-urlencode "select=id,name,number,rarity,index_eur" \
  -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": "bs-1", "name": "Alakazam", "number": "1", "rarity": "Rare Holo", "index_eur": 48.83 },
    { "id": "bs-1s", "name": "Alakazam (1st Edition Shadowless)", "number": "1S", "rarity": "Rare Holo", "index_eur": 49.30 }
  ],
  "meta": { "limit": 2, "count": 2, "has_more": true },
  "links": { "next": "https://api.pokemontcgapi.com/v1/sets/bs/cards?select=id%2Cname%2Cnumber%2Crarity%2Cindex_eur&limit=2&cursor=eyJrIjpbMSwiMVMiXSwiaWQ..." }
}

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.
404SET_NOT_FOUNDNo set with that code, slug or alternate id.
400INVALID_QUERYThe q parameter does not parse, or names a field that does not exist.
400INVALID_CURSORThe cursor is malformed, or was issued for a different orderBy than the one on this request.
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.
400LIMIT_EXCEEDEDlimit is above 250, or a batch request carries more than 100 ids.

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

Print variants are separate rows with their own ids and their own prices — bs-1 and bs-1s above are the same Alakazam in two printings, and each carries its own index_eur. That is why a set can hold more rows than its printed_total.

view this page as markdown