Card catalogBetaRequest access →

Docs

Transaction-level trading card sales data, updated continuously. Access via REST endpoints and an MCP server with 7 AI analysis tools.

Quickstart

Quickstart

Get your first response in under a minute.

1. Get a free API key

Sign up at thecardapi.com → No credit card required. Your key arrives instantly.

2. Make your first request

Shell
curl "https://thecardapi.com/api/v1/market/sales?q=psa+10+ohtani&limit=5" \
  -H "x-market-api-key: tca_your_key_here"

3. Explore

Use the playground to build and test queries interactively before writing any code. The full parameter reference is in the GET /sales section below.

Authentication

Authentication

All requests require an x-market-api-key header (REST) or an Authorization: Bearer header (MCP). The same key works for both. Get one free — no credit card required.

HTTP
# REST API
GET /api/v1/market/sales
x-market-api-key: tca_your_key_here

# MCP Server
POST /api/mcp
Authorization: Bearer tca_your_key_here

Don't have a key? Get one free →

Base

Base URL

REST API

https://thecardapi.com/api/v1/market

All REST paths below are relative to this base.

MCP Server

https://www.thecardapi.com/api/mcp

JSON-RPC 2.0 over streamable HTTP. See the MCP Server section.

Endpoints

Endpoints

MethodPathDescription
GET/salesSearch and filter sales records
GET/sales/{id}Single sale by ID
GET/dailyAggregate stats for a date
GET/platformsPlatform list with last updated date
GET/coverageLatest data freshness status
GET/sales/export/csvDownload filtered sales as CSV
POST/webhookAdd a webhook endpoint (max 5) — available on all paid plans
GET/webhookList active webhook endpoints
DELETE/webhook/{endpoint_id}Remove a webhook endpoint

MCP tools are invoked via POST /api/mcp — see the MCP Tools section for individual tool references.

GET

GET /sales

Search and filter individual sale records. Results are ordered by date descending by default. Your plan's lookback window is enforced on date_from automatically.

ParameterTypeDescription
qstringoptionalFull-text search on listing title (min 4 chars). Supports boolean syntax: (term1,term2) for OR, -term for NOT, "exact phrase" for phrase match.
platformstringoptionalFilter by platform. Values: ebay · goldin. See GET /platforms for the full list.
listing_typestringoptionalComma-separated: auction, fixed_price, best_offer
date_fromdateoptionalStart date YYYY-MM-DD. Clamped to your plan's lookback window.
date_todateoptionalEnd date YYYY-MM-DD
price_minnumberoptionalMinimum sale price (USD)
price_maxnumberoptionalMaximum sale price (USD)
print_run_minintegeroptionalMinimum print run (e.g. 1 for 1/1 only)
print_run_maxintegeroptionalMaximum print run (e.g. 99 to filter to /99 and lower numbered cards)
shipping_maxnumberoptionalMaximum buyer shipping cost in USD. Use shipping_max=0 for free-shipping listings only. Filters to records where shipping_price ≤ this value (null shipping_price records are excluded).
categorystringoptionalFilter by card category: sports, tcg, non_sport. eBay records indexed from June 6, 2026 onward. Auction house sources (Goldin, REA, etc.) return null until backfilled.
sortstringoptionaldate_desc (default) | date_asc | price_desc | price_asc
pageintegeroptionalPage number (default: 1)
limitintegeroptionalResults per request (default: 25, max: 1,000). Same cap on all plans.
cursorstringoptionalOpaque cursor from a previous response's next_cursor field. Efficiently paginate large result sets without offset drift. When provided, page is ignored. Available on all plans.
indexed_afterdatetimeoptionalISO 8601 UTC. Return only records indexed after this time. Useful for incremental sync.

Cursor pagination

Every response includes a next_cursor field in pagination when more results exist. Pass it as ?cursor= on the next request to fetch the next page — no offset drift, no missed records. Available on all plans.

# Page 1 — no cursor needed
GET /v1/market/sales?q=psa+10+trout&limit=1000
→ pagination.next_cursor: "eyJwZ19pZCI6IDE4N..."

# Page 2 — pass the cursor
GET /v1/market/sales?q=psa+10+trout&limit=1000&cursor=eyJwZ19pZCI6IDE4N...
→ pagination.next_cursor: "eyJwZ19pZCI6IDE2N..."  # or null if last page

CSV export

Download a filtered result set as a CSV file. Same filter params as GET /sales — no cursor or page. Available on Starter and above.

CSV rows count against your shared daily budget — the same pool as API calls. A Builder user who pulls 30K rows via the API has 20K remaining, usable via API or CSV.

curl "https://thecardapi.com/api/v1/market/sales/export/csv?q=psa+10+ohtani&date_from=2026-01-01" \
  -H "x-market-api-key: tca_your_key_here" \
  -o sales.csv

Search syntax

(psa,bgs) — title contains "psa" OR "bgs"
-reprint — title does NOT contain "reprint"
-(lot,album) — title contains neither "lot" nor "album"
"topps chrome" — exact phrase match
ohtani (psa,bgs) -(lot,album) -reprint — combine all forms

Response

Response schema

JSON
{
  "data": [
    {
      "id":                    "137222685761",
      "platform":              "eBay",
      "listing_type":          "auction",
      "title":                 "2021 Bowman Chrome Kyle Harrison Auto PSA 10",
      "sale_date":             "2026-05-14",
      "sold_at":               "2026-05-14T00:00:00Z",
      "price":                 47.50,
      "currency":              "USD",
      "price_confirmed":       true,
      "bids":                  12,
      "image_url":             "https://i.ebayimg.com/...",
      "thumbnail_url":         "https://i.ebayimg.com/...",
      "listing_url":           "https://www.ebay.com/itm/137222685761",
      "cert":                  "93265128",
      "condition":             null,
      "grade":                 "10",
      "grader":                "PSA",
      "grading_company":       "Professional Sports Authenticator",
      "has_autograph_grade":   false,
      "has_grade_qualifier":   false,
      "label":                 null,
      "grade_qualifier":       null,
      "autograph_grade":       null,
      "player":                "Kyle Harrison",
      "manufacturer":          "Bowman",
      "card_set":              "2021 Bowman Chrome",
      "card_number":           "BCP-42",
      "year":                  2021,
      "season":                "2021",
      "league":                "Major League (MLB)",
      "sport":                 "Baseball",
      "team":                  "San Francisco Giants",
      "features":              ["Auto", "Rookie"],
      "print_run":             null,
      "shipping_price":        4.99,
      "category":              "sports"
    }
  ],
  "pagination": {
    "total":       258817,
    "page":        1,
    "limit":       25,
    "pages":       10353,
    "has_more":    true,
    "next_cursor": "eyJwZ19pZCI6IDE4NzUwMDAwLCAic29ydCI6ICJkYXRlX2Rlc2MifQ=="
  },
  "meta": {
    "coverage_date_from":  "2026-05-01",
    "coverage_date_to":    "2026-05-17",
    "platforms_covered":   ["eBay", "Goldin", "Lelands", "SCP Auctions", "Hakes", "REA"],
    "generated_at":        "2026-05-17T10:00:00Z"
  }
}
FieldTypeCoverageDescription
idstring100%Unique sale identifier (platform-prefixed)
platformstring100%Platform name. Values: eBay · Goldin · Lelands · SCP Auctions · Hakes · REA
listing_typestring100%auction · fixed_price · best_offer
titlestring100%Raw listing title
sale_datestring100%YYYY-MM-DD of the sale
sold_atstring100%ISO 8601 timestamp (UTC). Day-boundary precision: ends in T00:00:00Z unless exact time was captured.
pricenumber100%Final sale price in USD. For eBay: all-in buyer price. For Goldin: hammer price only — buyer also pays ~22% buyer's premium on top. For best_offer: the true negotiated price.
currencystring100%Always USD
price_confirmedboolean100%true = confirmed final price. false = fast-settle estimate (auction BIN/BO, updated to true within minutes once confirmed).
bidsinteger|null~60%Number of bids (auction only)
image_urlstring|null~85%Full-size listing image URL
thumbnail_urlstring|null~85%Thumbnail image URL
listing_urlstring|null~99%Direct link to the sold listing on eBay (or other marketplace). Note: eBay may redirect logged-in users to a product catalog page. To view the original sold listing, open the URL in an Incognito/Private browsing window. This redirect does not affect programmatic/API access.
certstring|null~12%Grading certificate number
conditionstring|null~8%Raw condition string from listing
gradestring|null~12%Numeric grade (e.g. "10", "9.5", "Auth")
graderstring|null~12%Grader abbreviation: PSA · BGS · CGC · SGC
grading_companystring|null~12%Full grading company name
has_autograph_gradeboolean|null~12%Whether the slab has a separate auto grade
has_grade_qualifierboolean|null~12%Whether the grade has a qualifier (e.g. OC, MK)
grade_qualifierstring|null~3%Qualifier type (e.g. "OC", "MK", "ST")
labelstring|null~10%Grading label variant (e.g. "Gold Label")
autograph_gradestring|null~4%Autograph sub-grade where graded separately
playerstring|null~0.3%Player name. Populated for catalog-matched records. null if not yet matched.
manufacturerstring|null~0.4%Card manufacturer (e.g. Topps, Panini, Bowman). Populated for catalog-matched records.
card_setstring|null~0.4%Set name (e.g. 2022 Topps Update Series). Populated for catalog-matched records.
card_numberstring|null~0.4%Set card number (e.g. #295 or BCP-42). Distinct from print run (/299).
yearinteger|null~0.3%Card year. Populated for catalog-matched records.
seasonstring|null~0.3%Sports season (e.g. 2024-25). Populated for catalog-matched records.
leaguestring|null~0.3%League name (e.g. Major League (MLB), National Basketball Association (NBA)).
sportstring|null~0.4%Sport (e.g. Baseball, Basketball, Hockey). Populated for catalog-matched records.
teamstring|null~0.3%Team name at time of card printing. Populated for catalog-matched records.
featuresstring[]~0.3%Array of card features extracted from listing (e.g. ["Auto", "Rookie", "Patch"]). Empty array if not populated.
print_runinteger|null~36%Print run (denominator of serial fraction). /99 → 99. /10 → 10. 1/1 → 1. Null for unlisted base cards. Filter with print_run_min / print_run_max.
shipping_pricenumber|null~67%Buyer shipping cost in USD. 0.00 = free shipping. Null when not provided by the seller (eBay NRT only — always null for other sources). Filter with shipping_max.
categorystring|null~99%*Card category. Values: sports · tcg · non_sport. eBay records indexed June 6, 2026+. Auction house sources return null until backfilled. Filter with ?category=sports. (*eBay Jun 6, 2026+ only)
listing_type: "best_offer" — the pricefield is the true final negotiated price, not the listing price. Most data providers don't expose this. We do.
Goldin price note — for platform: "goldin" records, price is the hammer price— what the auctioneer called at close. The buyer also pays a buyer's premium (~22% current, ~20% pre-2022) on top. eBay prices are all-in. Factor this in when comparing values across platforms.

Error

Error codes

StatusMeaning
401Invalid or missing API key
403Action requires a higher plan or beta access
404Resource not found
422Validation error — check parameter types and ranges
429Daily sales limit reached. Resets at midnight UTC. Upgrade for more.
500Server error — try again shortly

Webhooks

Webhooks

$9/mo add-on · Available on all paid plans · 7-day free trial. Get started →

Register up to 5 HTTPS endpoints and receive every new card sale pushed to them within seconds of indexing — no polling required. Sales are delivered as signed batches of up to 1,000 records. Your cursor advances on each successful delivery so you never miss a record and never receive the same one twice. NRT data (near-real-time eBay results) is not included — that is a separate Custom plan add-on.

Add an endpoint

HTTP
POST /api/v1/market/webhook
x-market-api-key: tca_your_key_here
Content-Type: application/json

{
  "url":    "https://your-server.com/webhook",
  "secret": "your-hmac-signing-secret",
  "label":  "prod-receiver"
}

Max 5 active endpoints per key. label is optional.

List endpoints

HTTP
GET /api/v1/market/webhook
x-market-api-key: tca_your_key_here
JSON
{
  "endpoints": [
    { "id": 1, "url": "https://your-server.com/webhook", "label": "prod-receiver", "created_at": "2026-06-20T10:00:00Z" },
    { "id": 2, "url": "https://your-server.com/backup",  "label": "backup",         "created_at": "2026-06-20T10:01:00Z" }
  ],
  "count": 2,
  "max":   5
}

Remove an endpoint

HTTP
DELETE /api/v1/market/webhook/{endpoint_id}
x-market-api-key: tca_your_key_here

Delivery payload

Each POST to your endpoint contains a batch of sale records — the same schema as GET /v1/market/sales.

JSON
POST https://your-endpoint.com/webhook
Content-Type: application/json
X-Webhook-Signature: sha256=<hmac-sha256>

{
  "event":     "sales.batch",
  "timestamp": "2026-06-20T06:09:00Z",
  "count":     47,
  "data": [
    {
      "id":           "ebay-387214905012",
      "title":        "2011 Topps Update Mike Trout RC BGS 9.5",
      "price":        4200.00,
      "listing_type": "auction",
      "sold_at":      "2026-06-20T06:00:24Z",
      "print_run":    null,
      ...
    }
  ]
}

Verify the signature

Every delivery includes X-Webhook-Signature: sha256=<hex>. Verify against the raw request body before processing.

Python
import hashlib, hmac

def verify_webhook(body: bytes, secret: str, sig_header: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, sig_header)
DetailValue
Price$9/mo add-on · 7-day free trial · Available on all paid plans
Max endpoints5 active endpoints per API key
Delivery latency~30s from indexing (auction close → indexed → delivered)
Batch sizeUp to 1,000 records per delivery
Retry policy3 attempts with backoff (0s / 5s / 30s). Cursor holds on all-fail.
Poll cadenceEvery 30 seconds
SignatureHMAC-SHA256 — X-Webhook-Signature: sha256=<hex>
Event typesales.batch
NRT dataNot included — NRT is a separate Custom plan add-on

Rate

Rate limits

The only enforced limits are sales rows returned per day and how far back you can query.

PlanSales/dayLookback
Free5,0003 days
Starter10,00014 days
Builder50,00030 days
Pro200,00090 days
EnterpriseCustomUnlimited

Daily counters reset at 00:00:00 UTC each day. API calls and CSV exports draw from the same shared budget — a Builder user who downloads 30K rows via CSV has 20K remaining for API calls that day.

Max limit is 1,000 rows per request on all plans. View full pricing →

Pro add-ons

Full Daily Feed ($99/mo) — unlimited pulls for sale_date = yesterday. Your normal daily cap still applies to all other date ranges.
Unlimited Lookback ($99/mo) — removes the 90-day lookback window. Query the full historical dataset with no date restriction.

Both add-ons require an active Pro subscription. See add-ons →

Every response from /v1/market/sales includes rate limit headers so you can track usage programmatically:

HeaderDescription
X-RateLimit-LimitYour plan's daily sales cap
X-RateLimit-RemainingSales rows remaining today
X-RateLimit-ResetUnix timestamp of next reset (00:00:00 UTC)

MCP

MCP Server

The MCP (Model Context Protocol) server exposes 7 analysis tools over a single streamable HTTP endpoint. Any MCP-compatible client — Claude Desktop, Claude Code, Cursor, Windsurf, ChatGPT Desktop, LangChain — can connect with one URL.

Endpoint

POST https://www.thecardapi.com/api/mcp

Protocol: JSON-RPC 2.0 · Transport: streamable HTTP

Discover available tools

JSON
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "tools/list"
}

Claude Desktop

JSON
{
  "mcpServers": {
    "thecardapi": {
      "command": "npx",
      "args": ["mcp-remote", "https://www.thecardapi.com/api/mcp",
               "--header", "Authorization: Bearer YOUR_API_KEY"]
    }
  }
}

Claude Code

Shell
claude mcp add thecardapi \
  --transport http \
  --url https://www.thecardapi.com/api/mcp \
  --header "Authorization: Bearer YOUR_API_KEY"

Cursor / Windsurf

JSON
{
  "mcpServers": {
    "thecardapi": {
      "url": "https://www.thecardapi.com/api/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}

See the full MCP integration guide → for all clients.

MCP

MCP Tools

Each tool is called via method: "tools/call" with a name and arguments object.

search_cards

Find recent sold prices for any card. Returns individual sale records sorted by date. Supports filtering by grader, grade, listing type, date range, and price range.

Parameters

querystringoptionalFull-text search — e.g. 'PSA 10 Luka Doncic 2018 Prizm Silver'
platformstringoptionalFilter by platform (e.g. ebay)
graderstringoptionalpsa | cgc | beckett | sgc
gradestringoptional10 | 9.5 | 9 | 8.5 | 8 | 7 | auth | 10pristine
listing_typestringoptionalAuction | FixedPrice | BestOffer
date_fromstringoptionalStart date YYYY-MM-DD
date_tostringoptionalEnd date YYYY-MM-DD
price_minnumberoptionalMinimum sale price
price_maxnumberoptionalMaximum sale price
limitintegeroptionalResults to return (1–20, default: 10)

Example call

JSON
{
  "jsonrpc": "2.0", "id": "1",
  "method": "tools/call",
  "params": {
    "name": "search_cards",
    "arguments": {
      "query":        "PSA 10 Luka Doncic 2018 Prizm Silver",
      "listing_type": "BestOffer",
      "limit":        10
    }
  }
}

Response (abbreviated)

JSON
{
  "total_returned": 10,
  "results": [
    {
      "id":           "ebay-137222685761",
      "title":        "2018 Panini Prizm Silver Luka Doncic PSA 10",
      "platform":     "eBay",
      "listing_type": "BestOffer",
      "price":        4800.00,
      "sale_date":    "2026-05-16",
      "sold_at":      "2026-05-16T14:23:00Z",
      "bids":         null,
      "grader":       "PSA",
      "grade":        "10",
      "slab_serial":  "84566824",
      "listing_url":  "https://www.ebay.com/itm/137222685761"
    }
  ],
  "note": "BestOffer prices reflect the true final negotiated amount, not the list price."
}
grade_impact_analysis

See exactly how PSA/BGS grade affects price for a specific card. Returns a full price ladder sorted grade-high to grade-low, plus the grade where the value jump is sharpest.

Parameters

querystringrequiredCard to analyze — e.g. 'Luka Doncic 2018 Prizm Silver'
graderstringoptionalpsa (default) | cgc | beckett | sgc
lookback_daysintegeroptionalDays of history to include (default: 90)

Example call

JSON
{
  "jsonrpc": "2.0", "id": "1",
  "method": "tools/call",
  "params": {
    "name": "grade_impact_analysis",
    "arguments": {
      "query":         "Luka Doncic 2018 Prizm Silver",
      "grader":        "psa",
      "lookback_days": 90
    }
  }
}

Response (abbreviated)

JSON
{
  "query":        "Luka Doncic 2018 Prizm Silver",
  "grader":       "PSA",
  "lookback_days": 90,
  "total_sales":  49,
  "price_ladder": [
    { "grade": "10", "sales": 6,  "avg_price": 9200, "median_price": 8750, "min_price": 7800, "max_price": 11200 },
    { "grade": "9",  "sales": 28, "avg_price": 3400, "median_price": 3250, "min_price": 2800, "max_price": 4100 },
    { "grade": "8",  "sales": 12, "avg_price": 1950, "median_price": 1875, "min_price": 1600, "max_price": 2300 },
    { "grade": "7",  "sales": 3,  "avg_price": 850,  "median_price": 820,  "min_price": 750,  "max_price": 980  }
  ],
  "best_value_grade": {
    "grade":  "9",
    "reason": "Stepping up to 10 costs 171% more — this is the steepest value jump in the price ladder."
  }
}
grader_comparison

PSA vs CGC vs SGC vs BGS for the same card at the same grade. Find which grader commands the highest market premium.

Parameters

querystringrequiredCard to compare — e.g. 'Wembanyama 2023 Prizm Silver'
gradestringrequiredGrade to compare across graders — e.g. 10 | 9.5 | 9 | 8.5 | 8
lookback_daysintegeroptionalDays of history (default: 90)

Example call

JSON
{
  "jsonrpc": "2.0", "id": "1",
  "method": "tools/call",
  "params": {
    "name": "grader_comparison",
    "arguments": {
      "query": "Wembanyama 2023 Prizm Silver",
      "grade": "9"
    }
  }
}

Response (abbreviated)

JSON
{
  "query":        "Wembanyama 2023 Prizm Silver",
  "grade":        "9",
  "lookback_days": 90,
  "by_grader": [
    { "grader": "PSA", "sales": 18, "avg_price": 1450, "median_price": 1380 },
    { "grader": "BGS", "sales": 7,  "avg_price": 1210, "median_price": 1175 },
    { "grader": "CGC", "sales": 4,  "avg_price": 980,  "median_price": 950  },
    { "grader": "SGC", "sales": 2,  "avg_price": 890,  "median_price": 890  }
  ],
  "takeaway": "PSA commands the highest avg price at $1450",
  "comparisons": [
    { "grader": "BGS", "pct_cheaper_than_top": 17 },
    { "grader": "CGC", "pct_cheaper_than_top": 32 },
    { "grader": "SGC", "pct_cheaper_than_top": 39 }
  ]
}
price_momentum

Is this card trending up or down? Compares a recent time window against the prior window of equal length, with volume data. Upper bound is always yesterday so partial-day data never skews the result.

Parameters

querystringrequiredCard to analyze — e.g. 'Prizm Silver Wembanyama'
lookback_daysintegeroptionalLength of each comparison window in days (default: 7)
graderstringoptionalOptional — filter by grader: psa | cgc | beckett | sgc
gradestringoptionalOptional — filter by grade (e.g. 10, 9.5)

Example call

JSON
{
  "jsonrpc": "2.0", "id": "1",
  "method": "tools/call",
  "params": {
    "name": "price_momentum",
    "arguments": {
      "query":         "Wembanyama Prizm Silver",
      "lookback_days": 14
    }
  }
}

Response (abbreviated)

JSON
{
  "query":       "Wembanyama Prizm Silver",
  "window_days": 14,
  "recent_window": {
    "from": "2026-05-03", "to": "2026-05-16",
    "sales": 42, "avg_price": 1380
  },
  "prior_window": {
    "from": "2026-04-19", "to": "2026-05-02",
    "sales": 35, "avg_price": 1150
  },
  "price_change_pct":  20.0,
  "volume_change_pct": 20.0,
  "momentum": "rising",
  "note": "'rising' means both price and volume increased vs the prior window of the same length."
}
grading_value_calculator

Should you grade this card? Real cost math (PSA/CGC/SGC/BGS fees + shipping, all tiers including bulk) vs actual market comps. Returns expected profit at each grade, break-even analysis, and honest caveats.

Parameters

querystringrequiredCard to evaluate — e.g. '1986 Fleer Jordan 57'
raw_purchase_pricenumberrequiredWhat you paid (or plan to pay) for the raw ungraded card
target_gradestringoptionalGrade you hope to achieve: 10 | 9.5 | 9 | 8.5 (default: 10)
graderstringoptionalpsa (default) | cgc | beckett | sgc
submission_tierstringoptionalbulk | economy | standard (default) | express

Example call

JSON
{
  "jsonrpc": "2.0", "id": "1",
  "method": "tools/call",
  "params": {
    "name": "grading_value_calculator",
    "arguments": {
      "query":              "1986 Fleer Jordan 57",
      "raw_purchase_price": 6500,
      "target_grade":       "10",
      "grader":             "psa",
      "submission_tier":    "standard"
    }
  }
}

Response (abbreviated)

JSON
{
  "query":              "1986 Fleer Jordan 57",
  "raw_purchase_price": 6500,
  "grader":             "PSA",
  "target_grade":       "10",
  "grading_costs": {
    "service_tier":       "standard",
    "per_card_fee":       "$79.99",
    "turnaround":         "25 days",
    "shipping_roundtrip": "$40–$60 (continental US)",
    "total_estimate":     "$119.99–$139.99",
    "total_mid_estimate": 130
  },
  "grade_scenarios": [
    { "grade": "10",  "sales": 8,  "avg_price": 42000, "expected_profit": 35370, "is_target": true },
    { "grade": "9",   "sales": 22, "avg_price": 9800,  "expected_profit": 3170,  "is_target": false },
    { "grade": "8",   "sales": 11, "avg_price": 4200,  "expected_profit": -2330, "is_target": false }
  ],
  "math": {
    "if_card_grades_at_target": "$42000 (avg sale price)",
    "minus_raw_cost":           "-$6500",
    "minus_grading_and_ship":   "-$130 (midpoint estimate)",
    "expected_profit":          "$+35370",
    "break_even_grade":         "8"
  },
  "caveats": [
    "Grading outcome is NOT guaranteed — these numbers assume the card achieves each grade.",
    "Only 8 comps found at 10 — price estimate may be unreliable."
  ]
}
slab_lookup

Enter a PSA/BGS/SGC/CGC serial number and see every time that specific graded card sold. Like Carfax, but for slabs — full ownership price history with appreciation trend.

Parameters

slab_serialstringrequiredThe serial or cert number on the graded slab label — e.g. '84566824'
lookback_daysintegeroptionalLimit to sales within this many days (default: all-time)

Example call

JSON
{
  "jsonrpc": "2.0", "id": "1",
  "method": "tools/call",
  "params": {
    "name": "slab_lookup",
    "arguments": {
      "slab_serial": "84566824"
    }
  }
}

Response (abbreviated)

JSON
{
  "found":       true,
  "slab_serial": "84566824",
  "card":        "2018 Panini Prizm Silver Luka Doncic PSA 10",
  "grader":      "PSA",
  "grade":       "10",
  "total_sales": 3,
  "sales": [
    { "date": "2025-07-22", "price": 3600, "platform": "eBay", "listing_type": "Auction"   },
    { "date": "2025-11-08", "price": 3850, "platform": "eBay", "listing_type": "BestOffer" },
    { "date": "2026-03-12", "price": 4200, "platform": "eBay", "listing_type": "Auction"   }
  ],
  "appreciation_pct": 16.7,
  "trend":   "rising",
  "summary": "From $3600 → $4200 (16.7% rising)"
}

Code

Code examples

Python — REST API

Python
import requests

API_KEY = "tca_your_key_here"
BASE    = "https://thecardapi.com/api/v1/market"
HEADERS = {"x-market-api-key": API_KEY}

# Search recent Ohtani auctions
r = requests.get(f"{BASE}/sales", headers=HEADERS, params={
    "q":            "Shohei Ohtani",
    "listing_type": "auction",
    "price_min":    50,
    "limit":        50,
})
for sale in r.json()["data"]:
    print(sale["sale_date"], sale["price"], sale["title"][:60])

# Incremental sync — only records indexed since your last poll
r = requests.get(f"{BASE}/sales", headers=HEADERS, params={
    "indexed_after": "2026-05-15T10:00:00Z",
    "limit":         100,
})

Python — MCP tools/call

Python
import requests

MCP_URL = "https://www.thecardapi.com/api/mcp"
HEADERS = {"Authorization": "Bearer tca_your_key_here", "Content-Type": "application/json"}

def call_tool(name: str, arguments: dict) -> dict:
    payload = {
        "jsonrpc": "2.0", "id": "1",
        "method":  "tools/call",
        "params":  {"name": name, "arguments": arguments},
    }
    r = requests.post(MCP_URL, headers=HEADERS, json=payload)
    result = r.json()
    if result.get("error"):
        raise RuntimeError(result["error"]["message"])
    import json
    return json.loads(result["result"]["content"][0]["text"])

# Grade ladder for Mantle cards over $1,000
data = call_tool("grade_impact_analysis", {
    "query":         "Mickey Mantle",
    "grader":        "psa",
    "lookback_days": 30,
})
for row in data["price_ladder"]:
    avg = "{:,.0f}".format(row['avg_price'])
    print(f"PSA {row['grade']}: ${avg} avg ({row['sales']} sales)")

cURL

Shell
# REST — search for PSA 10 cards
curl "https://thecardapi.com/api/v1/market/sales?q=psa+10&limit=25" \
  -H "x-market-api-key: tca_your_key_here"

# MCP — call price_momentum tool
curl https://www.thecardapi.com/api/mcp \
  -H "Authorization: Bearer tca_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":"1","method":"tools/call","params":{"name":"price_momentum","arguments":{"query":"Wembanyama Prizm Silver"}}}'

Node.js

JavaScript
const res = await fetch(
  "https://thecardapi.com/api/v1/market/sales?q=topps+chrome&limit=50",
  { headers: { "x-market-api-key": "tca_your_key_here" } }
);
const { data, pagination } = await res.json();
console.log(`${pagination.total} results`);

LangChain (Python)

Python
import asyncio
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent
from langchain_anthropic import ChatAnthropic

async def main():
    async with MultiServerMCPClient({
        "thecardapi": {
            "url":       "https://www.thecardapi.com/api/mcp",
            "transport": "streamable_http",
            "headers":   {"Authorization": "Bearer tca_your_key_here"},
        }
    }) as client:
        tools  = await client.get_tools()
        model  = ChatAnthropic(model="claude-sonnet-4-6")
        agent  = create_react_agent(model, tools)
        result = await agent.ainvoke({
            "messages": "Is grading my 1986 Fleer Jordan worth it at $6,500?"
        })
        print(result["messages"][-1].content)

asyncio.run(main())

Ready to start building?

Free tier includes 5,000 sales/day with 3-day lookback. No credit card required.