REST reference
The primary interface. Predictable URLs, plain JSON, and one filter grammar that works the same way for every game.
Base URL
https://api.tcggraph.com/v1The API is versioned by date. The current version is 2026-08-01, pinned per key and overridable with the TCGGraph-Version header. Breaking changes never land on an existing version.
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /v1/games | List every supported game with counts and metadata. |
| GET | /v1/games/{slug} | Retrieve one game, including its schema declaration. |
| GET | /v1/sets | List sets, filterable by game, series and release window. |
| GET | /v1/sets/{code} | Retrieve one set and its card list. |
| GET | /v1/cards | Query cards with cross-game and game-specific filters. |
| GET | /v1/cards/{id} | Retrieve a single card with all printings. |
| GET | /v1/cards/search | Full-text and fuzzy search across all games. |
| GET | /v1/prices/{cardId} | Current prices across every tracked marketplace. |
| GET | /v1/prices/{cardId}/history | Daily price history with range and interval. |
| POST | /v1/bulk/exports | Request a full-catalog export in JSON, NDJSON or Parquet. |
| POST | /v1/webhooks | Register a signed webhook endpoint. |
Filtering
Filters are query parameters. Anything that is not a reserved parameter is matched against gameData, so game-specific filters need no special syntax.
# Cross-game filters
?game=pokemon # restrict to one game
?name=charizard # case-insensitive substring
?text=discard # search rules text
?rarity=Rare+Holo # exact rarity match
?set=151 # set code or name
?artist=miki+kudo # illustrator
?minPrice=50&maxPrice=500 # market price band
?source=cardmarket # price filters read the EU market, in EUR
?region=EU # same thing, without naming a vendor
# Game-specific filters map straight onto gameData
?game=pokemon&hp=330&types=Fire
?game=yugioh&attribute=LIGHT&atk=3000
?game=disney-lorcana&ink=AMETHYST&inkable=falseEvery card returns every quote it has regardless of source. What that parameter changes is which quote the price filters and the price sort read from, and the bounds are in that source’s currency — source=cardmarket&minPrice=50 means €50, not $50. The price reference covers both markets in full.
Pagination and sorting
?page=2&limit=50 # limit maxes out at 100
?sort=-price # name, price, released; prefix - to reverseResponse shape
{
"data": [ /* Card objects */ ],
"meta": {
"page": 1,
"limit": 20,
"totalCount": 137,
"totalPages": 7,
"hasMore": true,
"priceSource": "tcgplayer"
}
}meta.priceSource echoes back which market the price filters ran against, which is worth asserting on in tests. A USD sort when you meant a EUR one surfaces as a mildly wrong list rather than an error.
Core card fields
Present on every card in every game.
| Field | Type | Description |
|---|---|---|
| id | String | Globally unique, stable card identifier. |
| oracleId | String | Groups every printing and language of the same card. |
| game | Enum | Which game the card belongs to. |
| name | String | Card name in the requested language. |
| normalizedName | String | Accent-folded, lowercased name for fuzzy search. |
| set | Object | Set object: code, name, series, releasedAt, cardCount. |
| collectorNumber | String | Number printed on the card. |
| rarity | String | Publisher rarity, normalised per game. |
| rarityRank | Int | Cross-game 0–100 scarcity score for sorting. |
| artist | String | Illustrator credit. |
| flavorText | String | Non-rules flavour text. |
| text | String | Primary rules text, plain-text normalised. |
| language | Enum | BCP-47 language code of this printing. |
| finishes | [String] | Available finishes for this printing. |
| images | Object | small, normal, large, png and art-crop URLs on the TCGGraph CDN. |
| prices | [Object] | Per-source, per-condition, per-finish pricing with timestamps. |
| priceHistory | [Object] | Daily close prices, up to 5 years of history. |
| legalities | Object | Format legality map for the card's game. |
| externalIds | Object | tcgplayerId, cardmarketId, scryfallId, publisher SKUs and more. |
| gameData | Object | The game-specific payload. Typed per game in GraphQL. |
| updatedAt | String | ISO-8601 timestamp of the last change to this record. |
Game-specific fields
Each game declares its own gameData shape. The per-game reference pages list every field:
- Pokémon Trading Card Game — 11 fields
- Magic: The Gathering — 13 fields
- One Piece Card Game — 9 fields
- Yu-Gi-Oh! Trading Card Game — 11 fields
- Disney Lorcana — 9 fields
- Star Wars: Unlimited — 9 fields
- Digimon Card Game — 10 fields
- Grand Archive — 9 fields