Docs

Migrate from pokemontcg.io

Endpoints and fields of the Pokémon TCG API, mapped to Rarity.

The Pokémon TCG API is deprecated: it no longer takes registrations, and existing keys work through March 1, 2027. This guide maps its v2 API, as its public documentation describes it, to Rarity.

What changes first

pokemontcg.ioRarity
Base URLhttps://api.pokemontcg.io/v2https://api.rarity.dev/v1
KeyX-Api-Key headerAuthorization: Bearer rar_live_..., optional
Required headersnoneUser-Agent with your app and a contact, and Accept
Paginationpage, pageSize up to 250cursor, limit up to 100
End of the listcompare page and totalCounthas_more
Pricesdecimalsintegers in minor units: 275 is 2.75
LanguagesEnglishlang=en and lang=ja

A Rarity search needs no game filter, but a Pokémon client should send game=pokemon: other games are in the same catalog.

Endpoints

pokemontcg.ioRarity
GET /v2/cardsGET /v1/cards?game=pokemon
GET /v2/cards/{id}GET /v1/cards/{id}, with a Rarity id
GET /v2/setsGET /v1/sets?game=pokemon
GET /v2/sets/{id}no single-set read: page through GET /v1/sets?game=pokemon and match code in your client
GET /v2/typesno equivalent
GET /v2/subtypesno equivalent
GET /v2/supertypesno equivalent: category on the card
GET /v2/raritiesno equivalent

Rarity adds GET /v1/cards/suggest for autocomplete, POST /v1/cards/collection for up to 100 lookups in one call, GET /v1/changes to sync, and GET /v1/bulk for the whole catalog.

# pokemontcg.io
curl -H 'X-Api-Key: ...' \
  'https://api.pokemontcg.io/v2/cards?q=name:charizard&pageSize=50&orderBy=name'

# Rarity
curl -A 'my-app/1.0 (you@example.com)' \
  'https://api.rarity.dev/v1/cards?game=pokemon&lang=en&q=name:charizard&limit=50&order=name'
pokemontcg.ioRarity
q=name:charizardq=name:charizard
q=set.id:sv3set=OBF or q=set:OBF, with a Rarity set code
q=rarity:Promorarity=promo
q=supertype:Trainercategory=trainer
page, pageSizecursor, limit
orderByorder=number or order=name
selectno equivalent: a card comes whole

Rarity's q= follows the Scryfall syntax, not Lucene: or and parentheses work, a term is negated with -, and * is a prefix only at the end of the last word. Details are in the reference for search.

Card ids

Rarity does not know pokemontcg.io ids such as base1-4, and Rarity ids are opaque. Match each stored card once and keep the new id:

  1. Find the Rarity set by name in GET /v1/sets?game=pokemon.
  2. Look the cards up in a batch with POST /v1/cards/collection, by game, set and number.

The print also carries external_ids.tcgplayer and external_ids.cardmarket, the product ids of those sites.

Check the result by hand on a few sets. Rarity's Pokémon catalog comes from TCGplayer, so set codes and numbers follow TCGplayer: a number can read 001/015 where pokemontcg.io has 1.

Card fields

pokemontcg.ioRarity
idid, a different value
namename
supertypecategory, in lowercase
subtypesattributes.stage for evolution stages; no equivalent for the rest
hpattributes.hp
typesattributes.type, one string, and colors, in lowercase
abilities[].type, .name, .textattributes.abilities[].kind, .name, .text
attacks[].name, .text, .damageattributes.attacks[].name, .text, .damage
attacks[].costattributes.attacks[].cost, a string of energy symbols such as RR
weaknessesattributes.weakness, a string such as Wx2
resistancesattributes.resistance, a string
retreatCostattributes.retreat_cost, a string
setset, the set code. Read the set from GET /v1/sets
numbercollector_number
artistno equivalent today: illustrator is null on Pokémon
rarityrarity, in lowercase, and it can be null
legalitieslegalities, a list of format, status and since
images.small, images.largeimage, one URL
tcgplayer.pricesprices.tcgplayer.finishes
cardmarket.pricesprices.cardmarket.finishes
tcgplayer.updatedAt, cardmarket.updatedAtupdated_at under each source, a full timestamp
level, evolvesFrom, evolvesTo, rules, ancientTrait, flavorText, nationalPokedexNumbers, regulationMark, convertedRetreatCostno equivalent
tcgplayer.url, cardmarket.urlno equivalent: build a link from external_ids

attributes holds only strings, because a value like 100+ is not a number. GET /v1/games/pokemon publishes its schema. legalities is empty for Pokémon today, so don't build a format check on it yet.

Set fields

pokemontcg.ioRarity
idcode, a different value
namename
ptcgoCodesource_code, often the same value
releaseDaterelease_date, as YYYY-MM-DD, and it can be null
updatedAtupdated_at
series, printedTotal, total, legalities, imagesno equivalent

Every set has search_uri, a ready URL for its cards.

Prices

Amounts move from a flat object with decimal values to one object per finish, in minor units. A missing measure is absent, not null or 0.

pokemontcg.ioRarity
tcgplayer.prices.normalprices.tcgplayer.finishes.normal
tcgplayer.prices.holofoilprices.tcgplayer.finishes.holofoil
tcgplayer.prices.reverseHolofoilprices.tcgplayer.finishes.reverse_holofoil
tcgplayer.prices.1stEditionHolofoil, 1stEditionNormala separate print, the 1st Edition one, with its own id
low, mid, high, market, directLowlow, mid, high, market, direct_low
cardmarket.prices.trendPriceprices.cardmarket.finishes.<finish>.trend
cardmarket.prices.averageSellPriceprices.cardmarket.finishes.<finish>.avg
cardmarket.prices.lowPriceprices.cardmarket.finishes.<finish>.low
cardmarket.prices.avg1, avg7, avg30prices.cardmarket.finishes.<finish>.avg1, avg7, avg30
cardmarket.prices.reverseHoloTrend and the other reverseHolo valuesthe same measures under prices.cardmarket.finishes.reverse_holofoil
germanProLow, suggestedPrice, lowPriceExPlusno equivalent

<finish> is the print's base finish, which is normal or holofoil. Read the keys of finishes rather than assuming one.

prices: {} means Rarity has no certain link between the print and a product of that source, not that the card has no market. Rarity also adds prices.pricecharting for graded prices.

GET /v1/catalogs/price_sources states each source's market, currency, attribution and commercial terms. Check them before you resell or display prices.

Rate limits and errors

Without a key you get 30 requests a minute and 1,000 a day. A free key gives you 60 requests a minute per key and 2,000 a day per organization. Send If-None-Match, because a 304 does not count. Errors have a stable code and a doc_url, listed in the error pages.

On this page