Documentation

Identifiers

Updated

Every card and variant now carries two identifiers: a stable UUID (recommended) and a human-readable slug (legacy). This page explains both, how slugs are composed, and what changes in v2.

TL;DR:Start reading the new uuid field on cards and variants and use it as your primary key. The existing id (a slug) keeps working and remains useful as a human-readable label, but it is no longer the recommended way to reference a card.

Two identifiers, one card

We are migrating identity from slug-based IDs to UUIDs for both cards and variants. Slugs are derived from mutable text (names, sets, rarities), so they are not stable. Upstream renames and edge cases caused collisions and duplicates over time. UUIDs are content-addressed and never change.

uuidRecommended

Stable, globally-unique, and deterministic. The canonical key we upsert on internally. Prefer this for storage, joins, and lookups.

f8c3de3d-1fea-5d7c-a8b0-29f63c4c3454
idLegacy / slug

Human-readable and great for debugging or URLs. Still returned and still queryable, but can change and is not recommended as a primary key.

pokemon-battle-academy-fire-energy-22-charizard-stamped

Slugs (legacy, human-readable)

A slug is a composite identifier: several source fields are individually sanitized, slugified, and joined with dashes. The card slug is built from game · set · name · rarity; a variant slug appends the normalized condition and printing after an underscore.

Anatomy of a slug

Example: pokemon-battle-academy-fire-energy-22-charizard-stamped-promo

pokemon-battle-academy-fire-energy-22-charizard-stamped-promo
  • game

    The game the card belongs to.

  • set

    Slugified set name.

  • name

    Card name, including parenthetical qualifiers.

  • rarity

    Slugified rarity (e.g. common, uncommon, rare, promo).

A variant slug extends the card slug with its condition and printing, e.g. …charizard-stamped-promo_near-mint.

How each segment is generatedAdvanced — only needed if you reconstruct slugs yourself

Every text field passes through the same two steps before being joined. If you reconstruct slugs on your end, mirror this order exactly.

  1. 1. Sanitize special characters.A handful of characters that slugification would otherwise silently strip are first rewritten to a word, so meaningfully different cards don't collapse to the same slug (see the table below).
  2. 2. Slugify. Lowercase and trim → apostrophes become dashes → remaining punctuation (. , ! ? : ; ( )) is removed → spaces become dashes → any non-word characters are dropped → repeated dashes collapse to one → leading/trailing dashes are trimmed.

Special-character mapping

These substitutions are applied to all text fields (name, rarity, etc.) before slugification. They are what keep Unown (?) and Unown (!), or the asterisk alt-art markers Mega Man* and Mega Man**, from colliding.

CharacterReplaced withExample
?" question"Unown (?) → …unown-question
!" exclamation"Unown (!) → …unown-exclamation
+" plus"Energy+ → …energy-plus
*" star"Mega Man* → …mega-man-star

Condition normalization

For variant slugs, the raw condition is first normalized to a canonical value before slugification. Any grade suffix is dropped to its base — Near Mint (Holofoil) becomes Near Mint — and sealed product collapses to Sealed.

javascript — normalize-condition.js
normalize-condition.js
// Sealed / unopened product → "Sealed"
// Otherwise, collapse any suffix to the base grade:
"Near Mint"        // "Near Mint …"        → "Near Mint"
"Lightly Played"   // "Lightly Played …"   → "Lightly Played"
"Moderately Played"// "Moderately Played …"→ "Moderately Played"
"Heavily Played"   // "Heavily Played …"   → "Heavily Played"
"Damaged"          // "Damaged …"          → "Damaged"

Preparing for API v2

In v2, UUIDs become the primary idon both objects, and today's slug-based IDs move to a dedicated slug field. Adopting uuid now means a one-line rename when you upgrade.

v1 (today)v2Notes
card.idcard.slugHuman-readable slug, now demoted to a secondary field.
card.uuidcard.idThe stable UUID becomes the canonical card ID.
variant.idvariant.slugHuman-readable variant slug.
variant.uuidvariant.idThe stable UUID becomes the canonical variant ID.
Nothing breaks today: v1 responses are unchanged except for the additive uuid field. Migrate at your own pace by reading uuid now, so the eventual switch to v2 is just id → slug and uuid → id.