Bulk Pokemon Card Price API: Complete Guide
Processing thousands of Pokemon card prices? This guide covers the two bulk Pokemon card price API patterns the PokemonPriceTracker API supports — fetching entire sets in one call with fetchAllInSet, and paginating large result sets with limit/offset — plus how credits are billed so you can plan your usage.
Authentication
All requests go to https://www.pokemonpricetracker.com/api/v2/ and require an API key in theAuthorization header:
curl -H "Authorization: Bearer YOUR_API_KEY" \ "https://www.pokemonpricetracker.com/api/v2/cards?setId=1407&limit=50"
You can create a free API key from the API page — no credit card required.
Pattern 1: Fetch an Entire Set with fetchAllInSet
The most common bulk need is "give me every card in a set." Instead of guessing the set size and paginating, pass fetchAllInSet=true together with a set identifier (setId, set, or setName) and the API returns every card in that set in a single response:
// Every card in a set, one request
GET /api/v2/cards?setId=1407&fetchAllInSet=true
{
"data": [
{
"tcgPlayerId": "...",
"name": "...",
"setName": "...",
"cardNumber": "...",
"rarity": "...",
"prices": {
"market": 12.34,
"low": 9.99,
"sellers": 41,
"listings": 120,
"primaryPrinting": "Holofoil",
"lastUpdated": "2026-07-10T12:30:00.000Z"
}
// ... image URLs, variants, printingsAvailable, etc.
}
// ... every other card in the set
],
"metadata": {
"total": 102,
"count": 102,
"hasMore": false,
"fetchAllInSet": true,
"fetchedAllCards": true,
"apiCallsConsumed": {
"total": 102,
"breakdown": { "cards": 102, "history": 0, "ebay": 0 },
"costPerCard": 1
}
}
}setIdis the numeric TCGPlayer group ID (e.g.1407). UseGET /api/v2/setsto list all sets with their IDs and card counts.setorsetNameaccept the set name instead if you don't have the ID.- Billing:
fetchAllInSetis billed on the set size — a 102-card set costs 102 credits at the basic per-card rate. - You can combine it with
includeHistory=trueorincludeEbay=true; the API chunks the query internally so large sets with heavy joins still work.
Pattern 2: Paginated Batches with limit and offset
For arbitrary slices — filtered queries, price ranges, search results — use standard pagination. The maximum limit per request depends on how much data you attach to each card:
- Basic card data only: up to 200 cards per request
- With
includeHistoryorincludeEbay: up to 100 cards per request - With both: up to 25 cards per request (each card carries a lot of joined data)
// Page through all cards above $50, 200 at a time GET /api/v2/cards?minPrice=50&limit=200&offset=0 GET /api/v2/cards?minPrice=50&limit=200&offset=200 // ... keep going while metadata.hasMore is true
Every response includes metadata.total, metadata.count, and metadata.hasMore, so your loop knows exactly when to stop.
How Credits Are Billed
Understanding billing is the key to efficient bulk processing:
- Basic card query: 1 credit per card
- + price history (
includeHistory=true): +1 credit per card - + eBay graded sales (
includeEbay=true): +1 credit per card - + Cardmarket EUR prices (
includeCardmarket=true, Beta, paid plans): +1 credit per card
Important: requests are billed on the requested limit
List requests are billed on the limit you ask for (default 50), not the number of cards actually returned. If a filter only matches 12 cards but you requested limit=200, you're billed for 200. Set limit to what you actually need, and prefer fetchAllInSet=true for whole sets — it bills on the exact set size.
Every response reports the actual charge in metadata.apiCallsConsumed and theX-API-Calls-Consumed header, and the X-RateLimit-* headers show your remaining daily credits.
Implementation Example
Fetch Every Set, Then Every Card
const BASE = 'https://www.pokemonpricetracker.com/api/v2';
const HEADERS = { 'Authorization': `Bearer ${process.env.PPT_API_KEY}` };
// 1. List all sets (with card counts, so you can budget credits)
async function getSets() {
const res = await fetch(`${BASE}/sets`, { headers: HEADERS });
const { data } = await res.json();
return data; // [{ id, tcgPlayerId, name, cardCount, ... }]
}
// 2. Pull every card in one set
async function getAllCardsInSet(setId) {
const res = await fetch(
`${BASE}/cards?setId=${setId}&fetchAllInSet=true`,
{ headers: HEADERS }
);
if (res.status === 429) {
// Rate limited — check headers, back off, retry
throw new Error('Rate limited: ' + res.headers.get('Retry-After'));
}
const { data, metadata } = await res.json();
console.log(`${metadata.count} cards, ${metadata.apiCallsConsumed.total} credits`);
return data;
}Paginating a Filtered Query
async function getAllMatches(params) {
const results = [];
const limit = 200; // max for basic card data
let offset = 0;
let hasMore = true;
while (hasMore) {
const qs = new URLSearchParams({ ...params, limit, offset });
const res = await fetch(`${BASE}/cards?${qs}`, { headers: HEADERS });
const { data, metadata } = await res.json();
results.push(...data);
hasMore = metadata.hasMore;
offset += limit;
}
return results;
}
// Example: all Ultra Rare cards priced $10+
const cards = await getAllMatches({ rarity: 'Ultra Rare', minPrice: 10 });Rate Limit Management
Bulk workloads run into two independent limits — daily credits and per-minute call caps:
- Free: 100 credits/day, 60 calls/minute
- API ($9.99/mo): 20,000 credits/day, 60 calls/minute
- Business ($99/mo): 200,000 credits/day, 500 calls/minute — required for commercial use
Best practices:
- Read the
X-RateLimit-*response headers to track remaining credits instead of counting locally - Implement exponential backoff on HTTP 429 responses
- Prices update once daily, so there's no benefit to re-fetching the same card more than once per day — cache aggressively
- Only request
includeHistory/includeEbayon the cards that need them; keep bulk sweeps at the 1-credit basic tier - Paid plans can also buy prepaid credits as pay-as-you-go overage on top of the daily allowance
Enterprise Use Cases
Collection Management Platforms
Challenge:
A collection tracking app needs to refresh prices for 10,000+ cards daily across thousands of user collections.
Approach:
- Group the cards users hold by set, then refresh each set once with
fetchAllInSet=true - Run the refresh once per day — prices update daily, so more frequent polling wastes credits
- Store results in your own database and serve user portfolios from there
- On the Business plan (200,000 credits/day) a 10,000-card refresh uses 5% of the daily allowance
Market Analysis Tools
Challenge:
An analytics platform tracks price trends across entire sets and eras.
Approach:
- Sweep basic prices daily with
fetchAllInSet(1 credit/card) and build your own history - Pull deep history on demand with
includeHistory=true&days=180for the specific cards being analyzed - Add
includeEbay=trueonly where graded-market data matters
Getting Started with Bulk Operations
- Estimate your daily credit need: cards × cost per card × refreshes per day
- List sets first:
GET /api/v2/setsgives you IDs and card counts for budgeting - Start with one set: verify your parsing against a single
fetchAllInSetresponse - Add error handling: handle 429 responses — returned for both per-minute rate limits and exhausted daily credits (the JSON body says which)
- Scale up: spread large refreshes across the day to stay under per-minute caps
Choosing the Right Plan for Bulk Work
The Free plan (100 credits/day) covers testing against a couple of small sets. The API plan ($9.99/mo, 20,000 credits/day) handles personal projects tracking a few thousand cards. For commercial applications and large daily refreshes, the Business plan ($99/mo) provides 200,000 credits/day and a 500 calls/minute cap.
Explore Business Plan →Start Building with Bulk Fetches Today
Ready to pull entire sets of Pokemon card prices? The full endpoint reference, including every parameter shown in this guide, is in the API documentation.
Conclusion
Bulk Pokemon card price processing on PokemonPriceTracker comes down to two tools: fetchAllInSet=true for complete sets, and limit/offset pagination (up to 200 cards per request) for everything else. Because billing follows the requested limit, matching your request size to your actual need — and caching daily — is what keeps large workloads cheap and fast.