Introduction
The CollectorsStashMarket API gives you programmatic access to real-time TCG card prices, historical sales data, market intelligence and user features across 12 trading card games.
All responses are JSON. The API follows REST conventions and uses standard HTTP status codes. Authentication is via API key.
Supported TCGs
| Slug | Name | Cards | Sources |
|---|---|---|---|
| pokemon | Pokémon TCG | ~20,500 | TCGPlayer, CardMarket, eBay graded |
| mtg | Magic: The Gathering | ~30,000 | TCGPlayer, CardMarket, Scryfall, eBay graded |
| yugioh | Yu-Gi-Oh! | ~15,000 | TCGPlayer, CardMarket, eBay graded |
| onepiece | One Piece Card Game | ~3,000 | TCGPlayer |
| lorcana | Disney Lorcana | ~600 | TCGPlayer |
| fab | Flesh and Blood | ~14,000 | TCGPlayer, PriceCharting |
| digimon | Digimon Card Game | ~1,900 | TCGPlayer |
| starwars | Star Wars Unlimited | ~700 | TCGPlayer |
| grandarc | Grand Archive | ~4,400 | GATCG.com |
| dragonball | Dragon Ball Super CCG | ~4,500 | TCGPlayer |
| riftbound | Riftbound | ~100 | Limited |
| keyforge | KeyForge | ~36 | Demo |
Pricing & Limits
Every API key belongs to a subscription tier that governs your daily request allowance, per-minute rate limit, number of keys, and access to premium features. View the full pricing page →
| Tier | Req / day | Req / min | API keys | Price | Features |
|---|---|---|---|---|---|
| Free | 500 | 60 | 1 | Gratis | 1 prijsbron, basis endpoints |
| Starter | 5.000 | 120 | 2 | €9 / mo | Alle bronnen, 7d prijsgeschiedenis |
| Pro | 25.000 | 300 | 5 | €29 / mo | Volledige geschiedenis, trends & analyse |
| Business | 200.000 | 1.000 | 10 | €79 / mo | Bulk-endpoints, webhooks |
| Unlimited | ∞ | ∞ | 25 | €199 / mo | Geen limieten, prioriteitsondersteuning |
Authentication
Every request needs a valid API key. Three options — pick the one that fits your stack.
Option 1 — Authorization Header Recommended
Authorization: Bearer csm_your_key_here
Option 2 — Query Parameter
GET /api/search?q=Charizard&api_key=csm_your_key_here
Option 3 — X-API-Key Header
X-API-Key: csm_your_key_here
Getting a key
Log in with your CollectorsStashMarket account at collectorstashmarket.com, then enable developer access — one click, no waiting.
Keys are prefixed csm_ and shown only once. Store them in environment variables, never in source code.
Base URL
https://collectorstashmarket.com/api
Current version: v1 (implicit — no version prefix in URLs). Breaking changes will be introduced as /api/v2/ with at least 90 days deprecation notice.
Rate Limits
| Tier | Req / day | Req / min | Price |
|---|---|---|---|
| Free | 500 | 60 | Gratis |
| Starter | 5.000 | 120 | €9 / mo |
| Pro | 25.000 | 300 | €29 / mo |
| Business | 200.000 | 1.000 | €79 / mo |
| Unlimited | ∞ | ∞ | €199 / mo |
Response headers
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 423
X-RateLimit-Reset: 1746489600 # Unix timestamp when daily limit resets (midnight UTC)
Retry-After: 42 # Only present on 429 responses
Daily limits reset at midnight UTC. On 429, wait for Retry-After seconds before retrying. See Pricing & Limits for full tier details.
Errors
All error responses follow this shape:
{ "detail": "Card not found", "status": 404 }
| Status | Meaning | Cause |
|---|---|---|
| 200 | OK | Success |
| 201 | Created | Resource created (POST) |
| 204 | No Content | Deleted (DELETE) |
| 400 | Bad Request | Invalid or missing parameters |
| 401 | Unauthorized | Missing or invalid API key / session |
| 403 | Forbidden | You don't have access to this resource |
| 404 | Not Found | Card, set or TCG not in database |
| 409 | Conflict | Duplicate (alert already exists, etc.) |
| 422 | Unprocessable | Validation error (wrong type, range) |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Server Error | Bug on our end — please report it |
Pagination
List endpoints use page-based pagination.
| Param | Type | Default | Description |
|---|---|---|---|
| page | int | 1 | Page number (1-indexed) |
| size / per_page | int | 50 | Results per page (max 200) |
{
"items": [...],
"total": 20543,
"page": 1,
"pages": 411,
"size": 50
}
Quickstart
import requests
API_KEY = "csm_your_key_here"
BASE = "https://collectorstashmarket.com/api"
H = {"Authorization": f"Bearer {API_KEY}"}
# Search for Charizard
cards = requests.get(f"{BASE}/search", headers=H, params={"q": "Charizard", "tcg": "pokemon"}).json()
for c in cards["results"]:
print(f"{c['name']} #{c['number']} — ${c.get('market_price', '?')}")
# Get full price breakdown
prices = requests.get(f"{BASE}/cards/3782/prices", headers=H).json()
print("TCGPlayer:", prices.get("tcgplayer", {}).get("market_price"))
print("CardMarket:", prices.get("cardmarket", {}).get("market_price"))
# Graded sales (eBay)
for g in prices.get("ebay_graded", []):
print(f" {g['grading_company']} {g['grade']}: ${g['market_price']}")
# Stash Score
score = requests.get(f"{BASE}/cards/3782/stash-score", headers=H).json()
print(f"Stash Score: {score['score']}/100 — {score['label']}")
# Market movers
movers = requests.get(f"{BASE}/market/movers", headers=H, params={"tcg":"pokemon","limit":5}).json()
for c in movers.get("gainers", []):
print(f"↑ {c['name']}: +{c['change_7d']:.1f}% (7d)")const KEY = 'csm_your_key_here';
const BASE = 'https://collectorstashmarket.com/api';
const hdr = { Authorization: `Bearer ${KEY}` };
const get = (path, params = {}) => {
const url = new URL(BASE + path);
Object.entries(params).forEach(([k,v]) => url.searchParams.set(k, v));
return fetch(url, { headers: hdr }).then(r => r.json());
};
// Search + prices + score in parallel
const [results, prices, score] = await Promise.all([
get('/search', { q: 'Black Lotus', tcg: 'mtg', per_page: 5 }),
get('/cards/3782/prices'),
get('/cards/3782/stash-score'),
]);
console.log(results.results[0].name, score.label);
console.log('TCGPlayer:', prices.tcgplayer?.market_price);
// Market movers
const movers = await get('/market/movers', { tcg: 'pokemon', limit: 10 });
movers.gainers.forEach(c => console.log(`↑ ${c.name}: +${c.change_7d?.toFixed(1)}%`));export KEY="csm_your_key_here"
export BASE="https://collectorstashmarket.com/api"
# Search
curl -s -H "Authorization: Bearer $KEY" "$BASE/search?q=Charizard&tcg=pokemon&per_page=5" | jq '.results[].name'
# All prices for a card
curl -s -H "Authorization: Bearer $KEY" "$BASE/cards/3782/prices" | jq '.'
# Stash Score
curl -s -H "Authorization: Bearer $KEY" "$BASE/cards/3782/stash-score"
# Top market movers (Pokemon)
curl -s -H "Authorization: Bearer $KEY" "$BASE/market/movers?tcg=pokemon&limit=10" | jq '.gainers[].name'
# Platform stats
curl -s -H "Authorization: Bearer $KEY" "$BASE/stats"<?php
define('KEY', 'csm_your_key_here');
define('BASE', 'https://collectorstashmarket.com/api');
function api(string $path, array $q = []): array {
$url = BASE . $path . ($q ? '?' . http_build_query($q) : '');
$ctx = stream_context_create(['http' => ['header' => 'Authorization: Bearer ' . KEY]]);
return json_decode(file_get_contents($url, false, $ctx), true);
}
$search = api('/search', ['q' => 'Black Lotus', 'tcg' => 'mtg', 'per_page' => 5]);
foreach ($search['results'] as $c)
echo "{$c['name']} — \${$c['market_price']}\n";
$prices = api('/cards/3782/prices');
echo "TCGPlayer: $" . ($prices['tcgplayer']['market_price'] ?? '?') . "\n";
echo "CardMarket: $" . ($prices['cardmarket']['market_price'] ?? '?') . "\n";TCGs
Returns all 12 supported TCGs with card count, set count and price stats.
Query Params
| Param | Type | Default | Description |
|---|---|---|---|
| page | int | 1 | Page number |
| size | int | 50 | Per page |
Response
{ "items": [{ "id": 1, "name": "Pokémon TCG", "slug": "pokemon", "total_cards": 20543, "total_sets": 187 }], "total": 12 }Returns a single TCG. slug is one of: pokemon, mtg, yugioh, onepiece, lorcana, fab, digimon, starwars, grandarc, dragonball.
Sets
Query Params
| Param | Type | Default |
|---|---|---|
| page | int | 1 |
| size | int | 50 |
Response
{ "items": [{ "id": 1, "name": "Base Set", "code": "BASE1", "release_date": "1999-01-09", "total_cards": 102 }], "total": 187 }Returns a single set including metadata and total card count.
Response
{ "set_id": 1, "set_name": "Base Set", "total_cards": 102, "cards_with_prices": 102, "avg_market_price": 24.50, "total_set_value": 2499.00, "most_valuable_card": { "id": 3782, "name": "Charizard", "market_price": 185.50 } }| Param | Type | Default |
|---|---|---|
| limit | int | 10 |
Cards
Query Params
| Param | Type | Default | Description |
|---|---|---|---|
| set_id | int | optional | Filter to a specific set |
| sort | str | number_asc | number_asc, number_desc, name_asc, price_desc |
| page | int | 1 | Page |
| size | int | 50 | Per page (max 200) |
Response
{ "items": [{ "id": 3782, "name": "Charizard", "number": "4", "rarity": "Holo Rare", "card_type": "Pokémon", "image_url": "https://images.pokemontcg.io/base1/4_hires.png", "set": { "id": 1, "name": "Base Set" }, "market_price": 185.50 }], "total": 102 }Full card detail including attributes JSON (hp, types, subtypes, etc.), set, TCG, and local image URL.
| Param | Type | Default |
|---|---|---|
| variant | str | normal |
{ "tcgplayer": "https://tcgplayer.com/...", "cardmarket": "https://cardmarket.com/...", "cardtrader": "https://cardtrader.com/..." }Pass up to 3 comma-separated card IDs. Returns an array of card objects with prices for comparison.
GET /api/compare?ids=3782,3783,3784| Param | Type | Default |
|---|---|---|
| tcg | str | optional |
| limit | int | 20 |
{ "total_cards": 127945, "total_sets": 1582, "total_prices": 1231433, "total_tcgs": 12, "ebay_graded_records": 68964, "last_price_update": "2026-05-05T12:00:00Z" }Prices
Price data is aggregated from multiple sources and updated every 2 hours. All prices in USD unless noted.
Sources: tcgplayer, cardmarket, cardtrader, scryfall (MTG only), ebay_graded (array of grades).
{
"card_id": 3782,
"card_name": "Charizard",
"tcgplayer": { "low_price": 120.00, "market_price": 185.50, "high_price": 250.00, "currency": "USD", "variant": "holofoil", "updated_at": "2026-05-05T12:00:00Z" },
"cardmarket": { "low_price": 105.00, "market_price": 162.00, "high_price": 220.00, "currency": "EUR", "updated_at": "2026-05-05T10:00:00Z" },
"cardtrader": { "market_price": 178.00, "currency": "USD", "updated_at": "2026-05-05T11:30:00Z" },
"ebay_graded": [
{ "grading_company": "PSA", "grade": "10", "market_price": 4250.00, "sample_size": 47 },
{ "grading_company": "PSA", "grade": "9", "market_price": 850.00, "sample_size": 134 },
{ "grading_company": "BGS", "grade": "9.5", "market_price": 1800.00, "sample_size": 23 },
{ "grading_company": "CGC", "grade": "10", "market_price": 2100.00, "sample_size": 31 }
]
}| Param | Type | Default | Description |
|---|---|---|---|
| days | int | 90 | Lookback in days (max 365) |
| source | str | optional | tcgplayer, cardmarket, etc. |
| variant | str | optional | normal, holofoil, reverseHolofoil |
{
"card_id": 3782,
"snapshots": [
{ "date": "2026-05-05", "source": "tcgplayer", "market_price": 185.50, "low_price": 120.00, "high_price": 250.00 },
{ "date": "2026-05-04", "source": "tcgplayer", "market_price": 179.00, "low_price": 118.00, "high_price": 240.00 }
],
"analysis": { "change_7d": 3.6, "change_30d": 12.1, "change_90d": 28.4, "volatility": 0.08, "trend": "bullish" }
}Market Intelligence
| Param | Type | Default | Description |
|---|---|---|---|
| tcg | str | optional | Filter by TCG slug |
| limit | int | 20 | Results per category |
| min_price | float | 1.0 | Minimum market price filter |
{
"gainers": [{ "id": 3782, "name": "Charizard", "tcg": "pokemon", "market_price": 185.50, "change_7d": 12.3, "change_30d": 28.1 }],
"losers": [...],
"most_volatile": [...]
}Cards where prices differ significantly between TCGPlayer and CardMarket. Useful for identifying underpriced listings.
| Param | Type | Default |
|---|---|---|
| tcg | str | optional |
| min_gap_pct | float | 10 |
| limit | int | 20 |
{ "total_cards_tracked": 127945, "avg_change_7d": 0.8, "biggest_gainer": { "name": "...", "change_7d": 45.2 }, "biggest_loser": { "name": "...", "change_7d": -22.1 } }Returns per-TCG price coverage, average prices, and last update timestamps.
| Param | Type | Default |
|---|---|---|
| tcg | str | optional |
| limit | int | 10 |
/api/market/movers. This endpoint is maintained for backwards compatibility.Search
| Param | Type | Default | Description |
|---|---|---|---|
| q | str | required | Search query (min 2 chars). Searches card name + set name. |
| tcg | str | optional | Limit to TCG slug |
| set_id | int | optional | Limit to set ID |
| rarity | str | optional | e.g. Holo Rare, Ultra Rare |
| min_price | float | optional | Minimum market price |
| max_price | float | optional | Maximum market price |
| page | int | 1 | Page number |
| per_page | int | 20 | Results per page (max 100) |
{
"results": [{ "id": 3782, "name": "Charizard", "number": "4", "rarity": "Holo Rare", "image_url": "...", "set_name": "Base Set", "tcg_slug": "pokemon", "market_price": 185.50, "change_7d": 3.6 }],
"total": 42,
"page": 1,
"per_page": 20
}Stash Score
A proprietary 0–100 opportunity signal per card. Computed from price momentum (7d/30d), position within the price range, and liquidity. Updated with each price refresh.
Score Interpretation
| Score | Label | Meaning |
|---|---|---|
| 75–100 | Buy Opportunity | Rising momentum, near 30d low |
| 65–74 | Strong Hold | Positive trend, stable position |
| 41–64 | Stable | Neutral — no clear signal |
| 26–40 | Watch | Declining or volatile |
| 0–25 | Sell Opportunity | Near 30d high, declining momentum |
Response
{ "score": 78, "label": "Buy Opportunity", "color": "#22c55e", "signals": ["📈 Rising +12% (7d)", "💎 Near 30-day low"] }Price Intelligence
Advanced correlated price data with FX conversion, source confidence scoring and cross-source comparison.
Returns price data with confidence scores and FX-converted values across all sources.
Individual listings from all sources before aggregation.
Historical snapshots of correlated prices. Use for charting.
| Param | Type | Description |
|---|---|---|
| from | str | USD, EUR, GBP |
| to | str | Target currency |
{ "from": "USD", "to": "EUR", "rate": 0.921, "updated_at": "2026-05-05T12:00:00Z" }Search raw price listings across all sources with filtering by source, date range, and price range.
Returns all active price sources with listing counts and last update times.
Forces a re-correlation of price data for a card across all sources. Returns the updated intelligence object.
Predictions
{ "card_id": 3782, "current_price": 185.50, "predicted_7d": 192.00, "predicted_30d": 210.00, "confidence": 0.72, "trend": "bullish", "model": "linear_regression", "data_points": 90 }Returns cards where the model predicts the largest price change in the next 7–30 days.
Collection Requires Auth
All collection endpoints require a valid user session (Bearer token from login or session cookie).
Returns all cards in the authenticated user's collection with current market prices.
{ "total_value": 2450.00, "total_cards": 87, "change_7d_pct": 3.2, "change_7d_abs": 76.00, "biggest_gainer": { "name": "Charizard", "change_7d": 12.3 }, "biggest_loser": { "name": "Blastoise", "change_7d": -4.1 }, "by_tcg": [{ "tcg": "pokemon", "cards": 45, "value": 1800.00 }], "by_rarity": [{ "rarity": "Holo Rare", "cards": 12, "value": 890.00 }] }Top 10 cards by (market_price × quantity). Useful for portfolio overview.
[{ "set_id": 1, "set_name": "Base Set", "owned": 94, "total": 102, "pct": 92.2 }]{ "rising_cards": { "count": 5, "card_ids": [3782, 891] }, "cards_without_alert": { "count": 12 }, "almost_complete_sets": { "count": 2, "set_ids": [1, 4] } }Detailed analytics including price timeline, value distribution by TCG, and performance rankings.
{ "card_id": 3782, "quantity": 1, "variant": "holofoil", "condition": "NM", "price_paid": 150.00, "graded": false }Returns 204 No Content.
Wishlist Requires Auth
Returns all wishlist cards with current price vs target price delta.
{ "card_id": 3782, "max_price": 150.00 }Returns 204 No Content.
{ "on_wishlist": true, "entry_id": 42, "max_price": 150.00 }Alerts Requires Auth
Price alerts notify you by email when a card's price hits your target condition.
Alert Types
| Type | Description | Extra field |
|---|---|---|
| target_price | Alert when price drops to/below target | target_price |
| price_drop_pct | Alert when price drops by X% | threshold_pct |
| price_rise_pct | Alert when price rises by X% | threshold_pct |
| near_30d_low | Alert when within 10% of 30-day low | — |
{ "card_id": 3782, "alert_type": "target_price", "target_price": 150.00, "condition": "below" }Triggered alerts sorted by most recent. Includes read/unread status.
{ "unread_count": 3 }Returns 200 with {"marked": N}.
Decks Requires Auth
Browse public decks from all users. Sortable by popularity, value, date.
{ "pokemon": ["Standard", "Expanded", "Unlimited"], "mtg": ["Standard", "Modern", "Legacy", "Vintage", "Commander", "Pioneer", "Pauper"] }Returns all decks owned by the authenticated user.
{ "name": "My Charizard Deck", "tcg": "pokemon", "format": "Standard", "is_public": true, "description": "Charizard-based aggro" }Full deck including card list with counts and current market prices per card.
{ "deck_id": 12, "total_value": 450.00, "currency": "USD", "most_expensive_card": { "name": "Charizard", "value": 185.50 } }Checks each card in the deck against MTG format legality rules. Returns card-by-card legality + overall deck status.
Parse a plaintext deck list and resolve card IDs. Supports PTCGO, Arena, and plain-text formats.
{ "text": "4 Charizard ex\n2 Pidgeot ex\n4 Rare Candy\n4 Ultra Ball" }Creates a copy of an existing deck (yours or a public deck) under a new name.
{ "card_id": 3782, "quantity": 1, "slot": "main" }Returns 204 No Content.
Seller / Listings
| Param | Type | Description |
|---|---|---|
| card_id | int | Filter by card |
| tcg | str | Filter by TCG |
| condition | str | NM, LP, MP, HP, DMG |
| max_price | float | Maximum listing price |
{ "card_id": 3782, "variant": "holofoil", "condition": "NM", "language": "EN", "price": 175.00, "quantity": 1, "description": "PSA ready, perfect centering", "photo_url": "https://..." }Update price, quantity, condition or description. Only the owner can update.
Returns 204. Only the owner can delete.
Upload your CardMarket export CSV (multipart/form-data, field: file) to bulk-import all your listings at once.
Upload a TCGPlayer inventory export CSV to bulk-import listings.
Upload a listing photo (multipart/form-data, field: file). Returns {"url": "https://..."}. Max 5MB, JPEG/PNG/WebP.
Messages Requires Auth
Returns messages sorted newest first. Includes read/unread status.
{ "to_username": "collector42", "subject": "Your Charizard listing", "body": "Hi, is this still available?" }{ "unread_count": 2 }Returns 204. Only the sender or recipient can delete.
Forum
Forum read endpoints are available on all tiers including Free. Write endpoints (creating threads and replies) require authentication.
Returns all forum categories with thread and post counts.
Paginated thread list for a specific forum category. Sorted by most recent reply.
Returns the full thread with all replies in chronological order.
Returns pinned announcements from the CollectorsStashMarket team.
{ "title": "Base Set Charizard price prediction 2027?", "body": "With the upcoming sets..." }{ "body": "I think..." }API Key Management Requires Auth
[{ "id": 1, "key_prefix": "csm_a3f9...", "name": "My App", "is_active": true, "created_at": "2026-05-01T12:00:00Z", "last_used_at": "2026-05-05T09:30:00Z", "request_count": 842, "daily_limit": 1000, "requests_today": 156 }]The full key is shown only once. Store it immediately. Maximum 5 keys per account.
// Request: { "name": "My Price Tracker" }
// Response: { "id": 2, "key": "csm_a3f9...(full)", "key_prefix": "csm_a3f9", "name": "My Price Tracker" }{ "name": "Production App" }Permanently deactivates the key. Cannot be undone. Returns 204.
Health & Stats
{ "status": "healthy", "database": "connected", "total_cards": 127945, "total_prices": 1231433, "last_price_update": "2026-05-05T12:00:00Z" }Card counts, price coverage %, and last update time broken down per TCG and per source.
Changelog
v1.0.0 — 2026-05-05 Current
- Initial public API release
- 12 TCGs, 127,000+ cards, 1M+ price records
- TCGPlayer, CardMarket, CardTrader, Scryfall price sources
- eBay graded price history via PriceCharting (PSA/BGS/CGC grades 1–10)
- Stash Score endpoint (0–100 opportunity signal)
- Price Intelligence with FX conversion (USD/EUR/GBP)
- Market Intelligence: movers, best deals, trends, predictions
- Collection, Wishlist, Alerts, Decks endpoints
- Seller marketplace API with bulk CSV import
- Forum and private messaging
- API key management (max 5 keys, 1,000 req/day free)
Roadmap
- Webhooks — push events (price alert, new listing) to your endpoint
- GraphQL — flexible queries across cards, sets and prices
- WebSocket streams — real-time price subscriptions
- SDK packages — Python, JavaScript, PHP client libraries
- Pro tier — 10,000 req/day + priority support
- Image API — card image CDN with standardized dimensions
Support
- Email: api@collectorstashmarket.com
- Forum: collectorstashmarket.com/forum
- Response time: 48h for free tier, 4h for Pro