Skip to content
pokemontcgapi.com
Documentation

Quickstart

Get a key, make your first request, and page a full set correctly — in about three minutes.

Three steps. The only prerequisite is something that can send an HTTP header.

1. Get a key

  1. Ask for a key at pokemontcgapi.com/free-api-key. No card, no call.
  2. Copy the key from the dashboard. It is shown once — we store an Argon2 hash, not the key, so we cannot show it to you again.
  3. Put it in your environment as PTCG_API_KEY.

Secret keys are server-side

A key starting ptcg_live_ belongs on a server. For browser code use a ptcg_pub_ key, which is catalogue-only and pinned to a referrer allow-list. See authentication.

2. Make a request

Search is the endpoint you will use most. This asks for the two most recent Charizard holo rares:

curl -s -G "https://api.pokemontcgapi.com/v1/cards" \
  --data-urlencode 'q=name:charizard rarity:"rare holo"' \
  --data-urlencode "orderBy=-release_date" \
  --data-urlencode "limit=2" \
  -H "X-Api-Key: $PTCG_API_KEY"

Collections always come back in the same envelope:

envelope.json
{
  "data": [ /* rows */ ],
  "meta": { "limit": 2, "count": 2, "has_more": true },
  "links": { "next": "https://api.pokemontcgapi.com/v1/cards?...&cursor=eyJrIjpb..." }
}

3. Page a whole set

The only correct way to page is to follow links.next until it disappears. Do not rebuild the URL, do not add a page parameter — there is not one — and do not change orderBy mid-run.

page-a-set.ts
const key = process.env.PTCG_API_KEY ?? "";
let next: string | null = "https://api.pokemontcgapi.com/v1/sets/obf/cards?limit=250";
const all: unknown[] = [];

while (next) {
  const res = await fetch(next, { headers: { "X-Api-Key": key } });
  if (!res.ok) throw new Error((await res.json()).error.code);

  const page = await res.json();
  all.push(...page.data);
  next = page.links?.next ?? null;
}

// 230 on 2026-08-27, each id exactly once. obf sits just past the 250
// ceiling, so it is the smallest set that actually exercises the cursor.
console.log(all.length);

The query syntax page is the one that pays for itself: most of what people ask support is already expressible in q. After that, caching and ETags — a 304 costs no credits, so a well-behaved client is a cheap client.

What the trial gives you

Five requests per second, 800 credits granted once, and a daily cap of 200. The credits do not renew: they exist to answer "does this API have what I need", and most calls spend one of them. Rate limits has the cost of the ones that spend more.

view this page as markdown