---
title: "Batch cards"
method: GET
path: "/v1/cards/batch"
tags: ["cards"]
---

# Batch cards

`GET /v1/cards/batch`

## Request

- Base URL: `https://api.pokemontcgapi.com`
- URL: `https://api.pokemontcgapi.com/v1/cards/batch`
- Auth: API key in header `X-Api-Key`

Resolve up to 100 card ids and report missing ids with verified historical alternatives.

## Query parameters

- `ids` string, required
- `select` string
- `include` string
- `lang` string

## Headers

- `If-None-Match` string

## Response `200`

Success

- object
  - `data` Card[], required
    - `id` string: Public id, `{set_code}-{number}`. Stable, unique and guessable — `bs-4` is the Base Set Charizard.
    - `legacy_id` string, nullable: Alternate string id in `{set}-{number}` form (`base1-4`). Accepted anywhere an id is accepted, so ids you already store keep working without a translation table.
    - `name` string: Printed name. Localised when `lang` is set, with English as fallback.
    - `number` string: Collector number as printed. A **string**: `TG12`, `SV107`, `1S` and `H1` all exist.
    - `number_sort` integer, nullable: Numeric part extracted for sorting. Null on numbers with no leading digits.
    - `supertype` string, nullable: `Pokémon`, `Trainer` or `Energy`. Three values, and `GET /v1/reference` returns the live list under `supertypes`.
    - `subtypes` string[]: Printed subtypes, recomposed into one array — stage, suffix, Trainer kind and Energy kind all land here, so `q=subtypes:"Stage 2"` finds every Stage 2 printing. Populated on **38%** of the catalogue (20,082 cards), 26 distinct values.
    - `types` string[]: Energy types. Populated on **43%** of the catalogue (22,363 cards). Empty where we hold no game text for the printing, which is mostly the Japanese and Chinese ones.
    - `hp` integer, nullable: Hit points. Populated on 100% of the sample. Null for cards with no printed HP.
    - `level` string, nullable: Reserved; still empty after the 2026-09-03 enrichment, because no source we hold carries it.
    - `evolves_from` string, nullable: Name of the printing this one evolves from. **14%** of the catalogue (7,158 cards) — that is the share that evolves from something, not a coverage gap.
    - `evolves_to` string[]: Names this one evolves into. **15%** (7,624 cards). Derived from the evolution graph rather than read off the card, so it names whatever evolves from this Pokémon anywhere in the catalogue.
    - `rarity` string, nullable: Printed rarity. Free text across eras and print lines — 62 distinct values on 2026-09-18, and the list moves, so read them from `GET /v1/reference` under `rarities` rather than hardcoding an enum.
    - `regulation_mark` string, nullable: Single letter used by Standard rotation. Present only on the modern print runs that carry one.
    - `flavor_text` string, nullable: The italic prose under the artwork. **20%** of the catalogue (10,284 cards); many printings simply do not carry one.
    - `abilities` string[], nullable: Abilities, Poké-Powers, Poké-Bodies and their kin. **8%** of the catalogue (4,042 cards) — the real share of printings that have one. Shape: `name`, `text`, `type`.
    - `attacks` string[], nullable: Attacks in printed order. **33%** of the catalogue (17,207 cards), which is 83% of the Western printings. Shape: `name`, `cost`, `converted_cost`, `damage`, `text`. `damage` is a **string**: `100`, `180+` and `30×` all occur.
    - `weaknesses` string[], nullable: Weaknesses. **31%** of the catalogue (16,124 cards). Shape: `type`, `value` — and `value` is a string that carries its own operator, `×2` or `+20`.
    - `resistances` string[], nullable: Resistances, same shape as weaknesses. **9%** (4,741 cards): most printings have none.
    - `retreat_cost` string[]: One entry per energy needed to retreat, as symbols. **31%** of the catalogue (16,161 cards); also empty on the printings that retreat for free.
    - `converted_retreat_cost` integer, nullable: The length of `retreat_cost`, precomputed so a range filter is possible. **33%** (17,061 cards) — slightly more than `retreat_cost`, because a free retreat is `0` here and `[]` there.
    - `rules` string[]: Rule box text, which for a Trainer is the card effect. **6%** of the catalogue (2,951 cards).
    - `national_pokedex_numbers` integer: National Pokédex numbers. **42%** of the catalogue (21,738 cards). Multiple entries on cards depicting more than one Pokémon.
    - `tcgplayer_id` integer, nullable: External marketplace id, for joining against data you already licence. Present for joining, not a licence to resell their data.
    - `cardmarket_id` integer, nullable: External marketplace id, same caveat.
    - `jp_twin_id` string, nullable: The Japanese printing of the same card, as an id you can request back. Present where the pairing is known.
    - `index_eur` number, nullable: Our composite index in EUR, denormalised onto the card so you can sort and filter on price in the same query that reads the card. The row behind it is the `PTCG_INDEX` entry under `include=prices`.
    - `last_price_at` string, date-time, nullable: When a price was last observed for this card. Sortable, so "recently repriced" is one query.
    - `row_version` integer: Incremented by a database trigger on every real update, so an unchanged re-import does not bump it.
    - `created_at` string, date-time: ISO 8601, UTC.
    - `updated_at` string, date-time: ISO 8601, UTC.
    - `set_code` string: Code of the owning set. Denormalised so the common render needs no `include`.
    - `set_name` string: Name of the owning set.
    - `set_total` integer, nullable: Cards present in the catalogue, including secret rares but excluding variants such as reverse holos. Null when the set has no cards.
    - `ptcgo_code` string, nullable: Set code as used by the game client, e.g. `BS`.
    - `release_date` string, date, nullable: `YYYY-MM-DD`. A date, never a timestamp — the hour was never recorded.
    - `print_region` string: `WEST`, `JP` or `CN`. `KR` is a valid value in the schema and matches no rows today.
    - `series` string, nullable: Series name, e.g. `Base`. Null on print lines whose series we have not mapped — most Japanese sets today.
    - `artist_name` string, nullable: Illustrator name. Named `artist_name`, not `artist`: `artist` belongs to `include`, and a field that changes type depending on another parameter is what breaks typed clients.
    - `artist_slug` string, nullable: Slug for `/v1/artists/{slug}`.
  - `requested` integer, required: Requested ids, including repetitions and unresolved ids.
  - `found` integer, required: Distinct cards returned in data.
  - `missing` object[]: Every unresolved id once, ignoring case, in first-occurrence order and spelling after trimming. Absent when all ids resolve.
    - `id` string, required
    - `suggested_id` string: Only present when an existing historical candidate has this legacy id in a different canonical set.
  - `withheld` string[]: Index or price restrictions; absent when none apply.

## Other responses

- `304`: Not Modified — the ETag you sent still matches. No body, no quota.
- `400`: INVALID_PARAMETER, LIMIT_EXCEEDED, INVALID_SELECT_FIELD, INVALID_INCLUDE
- `401`: MISSING_API_KEY, INVALID_API_KEY
- `403`: PLAN_REQUIRED, TRIAL_EXPIRED, CARD_ALLOWANCE_EXCEEDED
- `429`: QUOTA_EXCEEDED

---

[API](https://skmtc.dev/pokemontcgapi/apis/pokemon-tcg-api.md) · [All operations](https://skmtc.dev/pokemontcgapi/apis/pokemon-tcg-api/llms.txt) · [OpenAPI document](https://skmtc.dev/pokemontcgapi/apis/pokemon-tcg-api/revisions/9e4ee9a375da?raw)
