# Migrating from pokemontcg.io

pokemontcg.io's API stops on **March 1, 2027**. RarityDB serves the same `/v2` endpoints with the same response shape, so most apps switch with two changes:

1. Base URL: `https://api.pokemontcg.io/v2` → `https://raritydb.com/v2`
2. Key: create one at [your account](https://raritydb.com/account) and send it in the same `X-Api-Key` header (or `Authorization: Bearer`). A key is required on every call; pokemontcg.io allowed a few keyless ones.

```bash
curl -H "X-Api-Key: $RARITYDB_KEY" "https://raritydb.com/v2/cards?q=name:charizard%20set.id:base1&select=id,name"
```

```json
{"data":[{"id":"base1-4","name":"Charizard"}],"page":1,"pageSize":250,"count":1,"totalCount":1}
```

## Endpoints

| Endpoint | Notes |
|---|---|
| `GET /v2/cards` | `q`, `page`, `pageSize` (max 250, default 250), `orderBy`, `select` |
| `GET /v2/cards/:id` | pokemontcg.io IDs (`sv3pt5-6`) or ours (`sv03.5-006`); `select` |
| `GET /v2/sets`, `GET /v2/sets/:id` | Same parameters |
| `GET /v2/types`, `/v2/subtypes`, `/v2/supertypes`, `/v2/rarities` | `{"data": [...]}` |

Errors look like pokemontcg.io's: `{"error": {"message": "...", "code": 404}}`. Rate limits are your plan's (see [Authentication and limits](https://raritydb.com/docs/authentication)).

## IDs

Every card and set pokemontcg.io had keeps its pokemontcg.io ID, so stored IDs keep working. Sets released after pokemontcg.io stopped updating, and cards it never listed, use our IDs (TCGdex's), like `me1-1`. Both forms work anywhere an ID is accepted.

## Search syntax (`q`)

The same Lucene-style syntax:

| Example | Meaning |
|---|---|
| `name:charizard` | Name contains the word "charizard" (case-insensitive) |
| `name:"charizard ex"` | A phrase |
| `name:char*` | Wildcard |
| `!name:charizard` | Exact name |
| `-types:water` | Not |
| `hp:[150 TO *]`, `nationalPokedexNumbers:{* TO 152}` | Inclusive `[ ]` / exclusive `{ }` ranges; also `set.releaseDate:[2023/01/01 TO *]` |
| `types:fire OR types:water`, `(subtypes:mega OR subtypes:vmax) set.series:sword*` | OR and parentheses; terms side by side are ANDed |

Fields: `id`, `name`, `supertype`, `subtypes`, `types`, `hp`, `evolvesFrom`, `number`, `artist`, `rarity`, `flavorText`, `regulationMark`, `nationalPokedexNumbers`, `convertedRetreatCost`, `attacks.name`, `abilities.name`, `weaknesses.type`, `resistances.type`, `legalities.standard|expanded|unlimited`, and `set.id`, `set.name`, `set.series`, `set.ptcgoCode`, `set.releaseDate`, `set.total`, `set.printedTotal`, `set.legalities.*`. Sets take the same `set.` fields without the prefix.

Unlike pokemontcg.io, an unknown field is an error (400) rather than an empty result, so typos don't fail silently.

`orderBy` takes `name`, `number`, `hp`, `rarity`, `supertype`, `nationalPokedexNumbers`, `id`, `set.releaseDate`, `set.name`, `set.series`, `set.id` for cards (`-` for descending, comma-separated), and `name`, `releaseDate`, `series`, `id`, `total`, `printedTotal`, `ptcgoCode` for sets. Without it, cards come in set release order, then card number.

## What's different

- **English cards only**, like pokemontcg.io. Japanese and other Asian cards are in the [GraphQL API](https://raritydb.com/docs/finding-things), with English names.
- **Card data comes from TCGdex**, so a little wording differs:
  - **Set names:** "Base Set", not "Base".
  - **Rarities:** "Ultra Rare" and "Secret Rare", where pokemontcg.io uses era-specific labels like "Rare Holo GX" or "Rare Rainbow".
  - **Text:** attack and ability text writes Energy as symbols ("{W}" rather than "Water").
  - **Rule boxes:** `rules` is filled for Trainers and Energy, but not with the "Pokémon ex rule" box.
  - **Not included:** `level` and `evolvesTo`.
  - **Matched to pokemontcg.io's style:**
    - card numbers ("6", not "006");
    - names ("Venusaur-EX", "Nidoran ♂");
    - subtypes ("MEGA" on Mega Evolution cards, "Pokémon Tool");
    - rarity casing ("Double Rare", and "Rare Holo" for holo-only rares).

  We check this against the live pokemontcg.io API: on modern sets most cards match field for field.
- **Images** are TCGdex scans (`images.small` / `images.large`). A few sets have no scan yet.
- **Prices:** `cardmarket.prices` has Cardmarket's daily EUR figures with the same field names. `tcgplayer` has the product `url` but no `prices`: TCGplayer USD prices come through [your own price-provider key](https://raritydb.com/docs/prices) on the GraphQL API.
- **Legalities** list `unlimited` plus `standard` / `expanded` where legal, from the current rotation; pokemontcg.io's may lag behind. We don't track bans.

## Beyond the compatibility layer

The `/v2` endpoints are a bridge. The [GraphQL API](https://raritydb.com/docs/getting-started) has everything they have plus printings (1st edition, reverse holo, stamps), sealed products, pull rates, Japanese cards, photo identification, condition grading and fake checks. You can migrate endpoint by endpoint: the IDs are the same in both.
