Whether you're building a portfolio dashboard, an insurance-claim helper or a "what's my binder worth" landing page — the API gives you bulk price lookups across 5 sources (TCGPlayer, Cardmarket, CardTrader, eBay graded, PriceCharting).
curl -H "Authorization: Bearer $CSM_KEY" \
"https://collectorstashmarket.com/api/cards/3782/prices" \
| jq '.prices | map(select(.market_price)) | min_by(.market_price)'
import csv, os, requests
CSM, KEY = "https://collectorstashmarket.com", os.environ["CSM_KEY"]
HDR = {"Authorization": f"Bearer {KEY}"}
# condition multipliers (industry default — tune to your buy-list)
COND_MULT = {"MINT": 1.00, "NM": 0.95, "LP": 0.80, "MP": 0.55, "HP": 0.35, "DMG": 0.20}
def market_eur(card_id):
rows = requests.get(f"{CSM}/api/cards/{card_id}/prices", headers=HDR, timeout=10).json().get("prices", [])
eur = [r["market_price"] for r in rows if r.get("currency") == "EUR" and r.get("market_price")]
return sum(eur) / len(eur) if eur else None # mean across sources
total = 0.0
with open("collection.csv") as f:
for row in csv.DictReader(f): # cols: card_id, qty, condition
price = market_eur(int(row["card_id"]))
if price is None: continue
total += price * int(row["qty"]) * COND_MULT.get(row["condition"], 0.90)
print(f"Collection value: €{total:,.2f}")
POST /api/cards/batch-prices (Business+)type BatchRow = { card_id: number; market: number; low: number; mid: number; high: number; currency: string };
const ids = [3782, 11172, 9669, 891 /* ... up to 500 per call */];
const r = await fetch("https://collectorstashmarket.com/api/cards/batch-prices", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.CSM_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ card_ids: ids, currency: "EUR" }),
});
const { rows }: { rows: BatchRow[] } = await r.json();
const total = rows.reduce((s, x) => s + (x.mid ?? 0), 0);
console.log(`Total mid-market: €${total.toFixed(2)}`);
// app/Console/Commands/ValueCollection.php
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Http;
class ValueCollection extends Command {
protected $signature = "csm:value {user}";
public function handle(): int {
$rows = \DB::table("collections")->where("user_id", $this->argument("user"))->get();
$key = env("CSM_KEY");
$total = 0.0;
foreach ($rows->chunk(500) as $chunk) {
$resp = Http::withToken($key)->post(
"https://collectorstashmarket.com/api/cards/batch-prices",
["card_ids" => $chunk->pluck("card_id")->all(), "currency" => "EUR"],
)->json("rows");
foreach ($resp as $r) $total += $r["mid"] ?? 0;
}
$this->info("Collection value: €" . number_format($total, 2));
return 0;
}
}
// Convert EUR-priced cards to USD on the fly for a US-facing app
import Fastify from "fastify";
const app = Fastify();
app.get("/value/:user", async (req: any) => {
const ids = await db.collectionCardIds(req.params.user); // your DB
const fx = await fetch("https://api.frankfurter.app/latest?from=EUR&to=USD").then(r => r.json());
const rate = fx.rates.USD;
const r = await fetch("https://collectorstashmarket.com/api/cards/batch-prices", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.CSM_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ card_ids: ids, currency: "EUR" }),
}).then(x => x.json());
const eur = r.rows.reduce((s: number, x: any) => s + (x.mid ?? 0), 0);
return { eur, usd: +(eur * rate).toFixed(2), fx_rate: rate };
});
app.listen({ port: 3000 });