Scanner Endpoints
Full reference for every Card Scanner API endpoint.
POST /recognize
The main endpoint. Runs the full pipeline: detect the card in the photo → match against the database.
Consumes 1 scan credit.
curl -X POST https://scanner.cardprices.io/recognize \
-H "X-API-Key: pub_live_YOUR_KEY" \
-F "[email protected]" \
-F "game=yugioh"Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
game | string | yugioh | Required. Game key — see Supported Games. |
top_k | integer | 5 | How many candidate matches to return (1–20). |
include_variants | boolean | true | Include all print variants for each match. |
debug | boolean | false | Include timing breakdown in response. |
Response
{
"success": true,
"game": "yugioh",
"cards_detected": 1,
"matches": [
{
"rank": 1,
"product_id": "100001",
"confidence": 0.97,
"confidence_percent": 97.0,
"hash_distance": 4,
"orb_score": 88,
"name": "Blue-Eyes White Dragon",
"set_code": "LOB-EN001",
"variants": [
{
"card_id": "abc123",
"name": "Blue-Eyes White Dragon",
"identifier": "LOB-EN001",
"rarity": "Ultra Rare",
"set_name": "Legend of Blue Eyes White Dragon",
"set_edition": "1st Edition"
}
],
"image_path": "mongodb_cache/yugioh/100001.jpg"
}
]
}success: false with an empty matches array means no card was found in the photo.
POST /match
Match a pre-cropped card image. Skips the detection step — use this if you've already isolated the card yourself.
Consumes 1 scan credit.
curl -X POST https://scanner.cardprices.io/match \
-H "X-API-Key: pub_live_YOUR_KEY" \
-F "file=@cropped_card.jpg" \
-F "game=pokemon"Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
game | string | yugioh | Game key. |
top_k | integer | 5 | Number of candidates to return (1–20). |
Response
{
"success": true,
"game": "pokemon",
"matches": [
{
"rank": 1,
"product_id": "200045",
"confidence": 0.94,
"hash_distance": 6,
"orb_score": 72,
"path": "mongodb_cache/pokemon/200045.jpg"
}
]
}POST /detect
Detect cards in an image and return bounding boxes. Does not identify or match the cards.
Free — does not consume scan credits.
curl -X POST https://scanner.cardprices.io/detect \
-H "X-API-Key: pub_live_YOUR_KEY" \
-F "[email protected]"Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
max_cards | integer | 10 | Maximum cards to detect (1–50). |
Response
{
"success": true,
"cards_detected": 3,
"detections": [
{
"index": 0,
"bbox": [142, 88, 412, 590],
"confidence": 0.98,
"width": 270,
"height": 502
}
]
}bbox is [x_min, y_min, x_max, y_max] in pixels.
GET /card/:game/:product_id
Retrieve full metadata and all print variants for a card by its product_id (the numeric ID returned in match results).
curl https://scanner.cardprices.io/card/yugioh/100001 \
-H "X-API-Key: pub_live_YOUR_KEY"Response
{
"product_id": "100001",
"game": "yugioh",
"info": {
"name": "Blue-Eyes White Dragon",
"rarity": "Ultra Rare",
"image": "https://..."
},
"variants": [
{
"card_id": "abc123",
"name": "Blue-Eyes White Dragon",
"identifier": "LOB-EN001",
"rarity": "Ultra Rare",
"set_name": "Legend of Blue Eyes White Dragon",
"set_edition": "1st Edition",
"is_matched": false
}
]
}GET /games
List all games and whether their recognition database is built and ready.
curl https://scanner.cardprices.io/games \
-H "X-API-Key: pub_live_YOUR_KEY"Response
[
{ "game": "yugioh", "status": "ready", "total_cards": 12847 },
{ "game": "pokemon", "status": "ready", "total_cards": 15320 },
{ "game": "magic", "status": "ready", "total_cards": 28403 }
]status is one of "ready", "building", or "error".
GET /health
Public health check. No API key required.
curl https://scanner.cardprices.io/health{
"status": "healthy",
"games_ready": 23,
"games_total": 23
}Full Example: Scan a Card
const formData = new FormData()
formData.append("file", imageFile)
const res = await fetch(
"https://scanner.cardprices.io/recognize?game=yugioh&top_k=3",
{
method: "POST",
headers: { "X-API-Key": "pub_live_YOUR_KEY" },
body: formData,
}
)
const result = await res.json()
if (!result.success) {
console.log("No card found in photo")
} else {
const top = result.matches[0]
console.log(`${top.name} — ${top.confidence_percent}% confidence`)
// → "Blue-Eyes White Dragon — 97.00% confidence"
}