Card Grading API — AI Card Grading for Developers & Agents

One REST API for the whole job: identify a trading card from a photo, predict its grade, get cached price estimates, and request 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

Commercial grading API subscriptions: $250/month for 5,000 grades or $449/month for 10,000. One front/back card pair uses one grade. These plans cover grading only; prepaid API credits cover identification and other modules separately.

What the API does

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.

Pokémon Card API — identify any Pokémon card from a photo

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 (included in the prepaid scan modules; excluded from commercial subscription grading). It also identifies sports cards — parallels, print runs, and all.

Card Scanner & Recognition API

The API works as a TCG card scanner: POST an image (multipart upload or a public URL) and get structured JSON back. Send both front and back photos 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.

Card Price API — cached card-value estimates

The prepaid market module returns cached price estimates: a raw (ungraded) estimate and graded estimates in USD, derived from previously collected sales data. Coverage and freshness vary; a missing estimate is not a zero value. 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.

Predict your PSA grade before you submit

The grade module predicts how a card would grade professionally, with sub-grades for centering, corners, edges, and surface, and prepaid scans may include a written justification. Commercial subscription grades return numerical condition scores only. 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.

Let AI agents grade and price cards (MCP server)

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 for the prepaid API. For the commercial trial, start_grading_trial creates an account and Stripe checkout link in one call, without granting prepaid credits. Your operator enters payment details on Stripe and confirms automatic monthly billing. subscribe_grading prepares checkout for an existing key; check_credits shows separate prepaid and subscription balances, active unlimited trial access and its deadline. grade_card automatically uses your trial or subscription for grading only, or set billingSource=prepaid to request grading with identification. Use get_grade_result for subscription results and get_scan_result for prepaid scans.

Quickstart

1. Register — get an API key + free trial credits

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."
# }

2. Submit a scan

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" }
# }

3. Poll for the result

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.

Pricing

Commercial monthly grading subscriptions

5,000 complete front-and-back card grades for $250/month, or 10,000 for $449/month. These subscriptions cover grading only. Identification, authentication, price estimates and market analysis are excluded. Compare plans, create an API account and subscribe.

API data and privacy: grading-only requests use temporary image processing; prepaid scans store images. Review this before integrating with your users' photos.

Start a seven-day unlimited grading trial

A payment method is required. New accounts get seven days of unlimited grading only; then the selected monthly price is charged automatically. Cancel before trial end to avoid the first charge. One trial per API account. Ordinary rate limits and one card at a time apply. Trial grades never spend prepaid credits or your later monthly allowance.

For MCP, ask your agent to call start_grading_trial with applicationName, ownerEmail and plan=grading_5000. Save the returned key securely, show the owner the Stripe checkout link and monthly price, then wait for them to finish checkout. Agents must never collect payment-card details in chat. See the ready-to-paste agent instructions.

# REST alternative: register once; save the returned key securely.
curl https://cardgrader.ai/v1/agents -H "Content-Type: application/json" \
  -d '{ "name": "My app", "contactEmail": "owner@example.com", "commercialOnly": true }'
# Set CG_KEY securely to the returned apiKey; never put it in a URL.
curl https://cardgrader.ai/v1/subscriptions/checkout \
  -H "Authorization: Bearer $CG_KEY" -H "Content-Type: application/json" \
  -d '{ "plan": "grading_5000" }'
# The owner opens checkoutUrl and completes Stripe checkout.
curl https://cardgrader.ai/v1/subscriptions/me -H "Authorization: Bearer $CG_KEY"

Do not begin grading until the verified balance shows unlimitedGrading: true and a future trialEndsAtUtc, or a paid allowance. Trial balances report gradesRemaining: null; it means unlimited, not zero. At expiry, grading stops without a successful payment even if a webhook is delayed. Canceled trials remain usable through their original deadline.

Use POST /v1/grades for subscription grading. It returns a completed result directly, with one grade charged for both sides. Include Idempotency-Key, keep it with your request, and send one card at a time per account. Unused grades expire at the end of the paid billing period; plan changes start at renewal.

curl https://cardgrader.ai/v1/grades \
  -H "Authorization: Bearer $CG_KEY" \
  -H "Idempotency-Key: card-2026-001" \
  -F "front=@front.jpg" -F "back=@back.jpg"

JSON requests use { "frontImageUrl": "https://…/front.jpg", "backImageUrl": "https://…/back.jpg" }. The response includes grading, billingSource, gradesCharged: 1 for a paid allowance (0 during the unlimited trial), creditsCharged: 0 and a result link to GET /v1/grades/{id}. It contains no identification or value fields. Failed grades are refunded; retry failures with a new key.

GET /v1/agents/me returns the existing credits balance plus balances.prepaidCredits and balances.gradingSubscription, including remaining monthly grades, status and period dates. For extra services on the same account, buy prepaid credits and use /v1/scans. Monthly allowances never pay for identification or full scans.

Prepaid scans at /v1/scans cost credits, summed across the modules you request. Live prices: GET /v1/pricing.

Commercial use, including paid apps, is allowed under the API Terms of Use: credit "Grading by CardGrader.AI" with a link wherever results appear, and present grades as AI estimates.

ModuleCreditsWhat 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.

Credit packs

PackCreditsPrice (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.

Authentication & limits

Endpoints

EndpointAuthPurpose
POST /v1/agentsnoneRegister; returns API key + trial credits.
GET /v1/agents/mekeyIdentity + credit balance.
POST /v1/scanskeySubmit a card scan (costs credits).
GET /v1/scans/{id}keyPoll status / fetch results.
GET /v1/pricingnoneLive module costs + packs.
GET /v1/credits/packsnonePurchasable credit packs.
POST /v1/credits/purchasekeyStripe Checkout URL for a pack.
GET /v1/subscriptions/plansnoneMonthly grading-only plans.
POST /v1/subscriptions/checkoutkeyHosted subscription checkout; body { "plan": "grading_5000" }.
GET /v1/subscriptions/mekeySeparate prepaid and monthly grading balances.
POST /v1/subscriptions/portalkeyManage payment method and cancel renewal.
POST /v1/subscriptions/change-plankeyChange plan at next renewal.
POST /v1/subscriptions/cancelkeyCancel renewal and pending tier changes; retain paid-period access.
GET /v1/grades/{id}keyRetrieve your saved grading-only result, free.
POST /v1/gradeskeyGrading only; one monthly grade per front/back pair.

Full request/response schemas: openapi.json (OpenAPI 3.1).

Honest constraints

Error model

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"
}

Error code reference

invalid_api_key (401)
Missing, malformed, revoked, or disabled API key. Register via POST /v1/agents if you have none.
rate_limited (429)
Rate limit exceeded. Back off and retry shortly.
registration_limit (429)
This IP created the maximum number of agents in the last 24 hours. Reuse an existing key.
invalid_name / invalid_contact_email / invalid_operator_url (400)
Registration field validation failed; the detail explains the rule.
registration_failed (500)
The backing account could not be created. Safe to retry.
invalid_body / missing_front_image / invalid_image_url / invalid_image / image_too_large (400)
Scan input validation failed: bad JSON, missing/invalid front image, non-image file, or a file over 15MB.
invalid_modules (400)
Unknown module value, empty list, or full combined with other modules. Valid: identify, grade, market, full.
deep_unsupported (400)
Deep scans require the CardGrader mobile app's guided multi-angle capture. Use full instead.
invalid_idempotency_key (400)
Idempotency-Key must be 1–64 characters of [A-Za-z0-9_-].
idempotency_conflict (409)
This key belongs to a request that failed mid-flight (and was refunded). Retry with a new key.
insufficient_credits (402)
Balance too low. The error includes creditsRemaining and purchaseUrl.
subscription_grading_only (402/403)
The subscription covers grading only at /v1/grades. Purchase prepaid credits for other modules at /v1/scans.
subscription_required (402)
No current paid grading period exists. Subscribe or renew, or explicitly use prepaid scans.
grading_allowance_exhausted (402)
The monthly allowance is spent. Wait for renewal or purchase prepaid credits; no automatic prepaid charge occurs.
grade_in_flight (429)
Wait for the current commercial grade before submitting another card.
scan_not_found (404)
No scan with this id exists for your agent.
pricing_unavailable / enqueue_failed (500)
Server-side failure. For enqueue_failed your credits were refunded — retry with a new Idempotency-Key.
invalid_pack (400)
Unknown pack key; the detail lists valid keys.
stripe_error / spt_stripe_error (502)
Stripe rejected or failed the request. No credits were granted; retry later.
spt_not_enabled (501)
Shared payment tokens are not enabled on this server. Omit sharedPaymentToken to get a Checkout URL.
spt_payment_incomplete (402)
The shared-payment-token charge did not complete. No credits were granted.

Notes for agents