One REST API for the whole job: identify a trading card from a photo, predict its grade, price it from real sold sales, and get market analysis — Pokémon, sports, and other TCGs. Built for developers and AI agents: register in one call, no human signup required.
Machine-readable surface:
OpenAPI 3.1 spec ·
llms.txt ·
MCP server at /mcp
Every scan starts with a photo. You pick the modules you want — identify,
grade, market, or full for everything in one pass. Grading is the
flagship, but identification, pricing, and market analysis each stand on their own.
Send a photo of any Pokémon card and the API returns its name, set, number, year, and
variant — you don't need to know what the card is first. That's the difference from
catalog APIs like pokemontcg.io or TCGdex: those answer "give me the data for card X"; this one
answers "what card is this?" It's the same identification engine behind our
free Pokémon card value checker, exposed as the
identify module (and included in every other module). It also identifies sports
cards — parallels, print runs, and all.
The API works as a TCG card scanner: POST an image (multipart upload or a public URL) and get structured JSON back. Front image required, back image optional but recommended for grading. JPEG/PNG up to 15MB. No SDK needed — if you can send a multipart request, you're done; the quickstart below is three curl commands.
The market module returns what a card is actually worth: a raw (ungraded) estimate and
graded estimates in USD, built from real sold sales data — not asking prices. The
gradedValueSpread breaks value out per grade level (PSA 8/9/10 and so on) with a
confidence rating, so you can compute grading ROI programmatically. Values are estimates, not
financial advice.
The grade module predicts how a card would grade professionally, with sub-grades for
centering, corners, edges, and surface, plus a written justification. Collectors use it to
pre-screen cards before paying for professional grading; marketplaces and inventory tools use it
to attach condition data to listings at scale. It's an estimate from photos — sharp,
glare-free images grade more accurately than blurry ones.
AI agents can use CardGrader.AI without writing any HTTP code: connect to the MCP server at
https://cardgrader.ai/mcp and the same capabilities are exposed as tools. The
register_agent tool self-onboards a new agent — it returns an API key and trial
credits, no human in the loop. Same modules, same credits, same pricing as the REST API below.
One POST, no signup. Include contactEmail to get 3 trial credits instead of 1.
The key is returned exactly once — store it.
curl -X POST https://cardgrader.ai/v1/agents \
-H "Content-Type: application/json" \
-d '{ "name": "my-card-bot", "contactEmail": "you@example.com" }'
# 201
# {
# "agentId": 42,
# "apiKey": "cgk_...", <- shown once, store it
# "tier": "registered",
# "credits": 3,
# "docsUrl": "https://cardgrader.ai/api-docs",
# "message": "Store this key securely; it cannot be retrieved again."
# }
Send a card photo as a multipart file upload or a public image URL. Authenticate with
Authorization: Bearer cgk_... (or X-Api-Key). Set an
Idempotency-Key so retries never double-charge.
# multipart file upload
curl -X POST https://cardgrader.ai/v1/scans \
-H "Authorization: Bearer cgk_..." \
-H "Idempotency-Key: scan-001" \
-F "front=@card-front.jpg" \
-F "back=@card-back.jpg" \
-F "modules=full"
# or JSON with image URLs
curl -X POST https://cardgrader.ai/v1/scans \
-H "Authorization: Bearer cgk_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: scan-001" \
-d '{ "frontImageUrl": "https://example.com/front.jpg", "backImageUrl": "https://example.com/back.jpg", "modules": ["full"] }'
# 202
# {
# "id": 12345,
# "status": "queued",
# "modules": ["full"],
# "creditsCharged": 2,
# "creditsRemaining": 1,
# "links": { "self": "/v1/scans/12345" }
# }
Polling is free. Scans are queue-backed; results typically land in 30–120 seconds.
curl https://cardgrader.ai/v1/scans/12345 \
-H "Authorization: Bearer cgk_..."
# while running: { "id": 12345, "status": "processing", "progressPercent": 40, "statusMessage": "..." }
# when done:
# {
# "id": 12345,
# "status": "completed",
# "modules": ["full"],
# "completedAt": "2026-06-11T18:05:00Z",
# "identification": { "name": "...", "subject": "...", "category": "...", "year": "...",
# "set": "...", "number": "...", "parallel": "...", "printRun": "" },
# "grading": { "grade": 8.5, "predictedGrade": 8.5,
# "subGrades": { "centering": 9.0, "corners": 8.5, "edges": 8.5, "surface": 8.0 },
# "summary": "...", "justification": "..." },
# "value": { "rawEstimate": 145.0, "gradedEstimate": 320.0, "currency": "USD",
# "gradedValueSpread": [ { "grade": 9.0, "value": 420.0, "confidence": "Medium" } ] },
# "market": { "insights": "...", "gradingRecommendation": "...", "context": "..." }
# }
The response contains only the sections for the modules you requested. Failed scans return a generic error — internal worker details are never exposed.
Every scan costs credits, summed across the modules you request. Live prices:
GET /v1/pricing.
| Module | Credits | What you get |
|---|---|---|
grade |
1 | Identification + AI condition grading with sub-grades (centering, corners, edges, surface). |
identify |
1 | Card identification: name, subject, set, year, number, parallel, print run. |
market |
1 | Identification + value estimates, graded-value spread, and market insights. |
full |
2 | The complete fast-scan pipeline: identification, grading, pricing, and market analysis. |
deep |
3 | Deep scan (multi-angle capture) — requires the CardGrader mobile app's guided capture; not available via the v1 API. |
Trial credits at registration: 1 (anonymous) or 3 (with contactEmail).
deep scans require the CardGrader mobile app's guided multi-angle capture and
return 400 deep_unsupported via this API.
| Pack | Credits | Price (USD) |
|---|---|---|
starter — Starter |
25 | $5.00 |
builder — Builder |
120 | $19.00 |
scale — Scale |
400 | $49.00 |
curl -X POST https://cardgrader.ai/v1/credits/purchase \
-H "Authorization: Bearer cgk_..." \
-H "Content-Type: application/json" \
-d '{ "pack": "starter" }'
# 200 -> { "checkoutUrl": "https://checkout.stripe.com/...", "pack": "starter",
# "credits": 25, "priceUsd": 5.00, "expiresAt": "..." }
Open checkoutUrl in a browser to pay; credits are granted automatically within
seconds of payment. When a scan request returns 402 insufficient_credits, the
error includes your balance and points at /v1/credits/packs.
cgk_ + 40 characters. Send Authorization: Bearer cgk_... or X-Api-Key: cgk_....X-Credits-Remaining header./v1 endpoints; registration 5/hour/IP and max 3 new agents per IP per 24h.GET /v1/agents/me returns your identity and balance, free of charge.| Endpoint | Auth | Purpose |
|---|---|---|
POST /v1/agents | none | Register; returns API key + trial credits. |
GET /v1/agents/me | key | Identity + credit balance. |
POST /v1/scans | key | Submit a card scan (costs credits). |
GET /v1/scans/{id} | key | Poll status / fetch results. |
GET /v1/pricing | none | Live module costs + packs. |
GET /v1/credits/packs | none | Purchasable credit packs. |
POST /v1/credits/purchase | key | Stripe Checkout URL for a pack. |
Full request/response schemas: openapi.json (OpenAPI 3.1).
All errors are RFC 9457
application/problem+json with a stable machine-readable code extension:
{
"type": "https://cardgrader.ai/api-docs/errors#insufficient_credits",
"title": "Insufficient Credits",
"status": 402,
"detail": "Your credit balance is too low for this request. Purchase a credit pack to continue.",
"code": "insufficient_credits",
"creditsRemaining": 0,
"purchaseUrl": "/v1/credits/packs"
}
POST /v1/agents if you have none.detail explains the rule.full combined with other modules. Valid: identify, grade, market, full.full instead.Idempotency-Key must be 1–64 characters of [A-Za-z0-9_-].creditsRemaining and purchaseUrl.enqueue_failed your credits were refunded — retry with a new Idempotency-Key.detail lists valid keys.sharedPaymentToken to get a Checkout URL.Idempotency-Key on POST /v1/scans retries — replays return the original scan without charging.