Pokémon Card Detection API
One photo in, structured cards out. Send an image and get every Pokémon card it contains as clean JSON: name, set, number, rarity, Cardmarket ID and live pricing.
The API runs on your existing NeoSatoshi subscription. Detections draw from the same monthly credit balance as the app, so there is no separate API plan to buy.
Synchronous REST
·
Bearer-token auth
·
Multi-card per image
Live examples
Single card
1 card
Click to enlarge
One card in, one fully parsed card object out: identity, set, rarity, Cardmarket id, price and confidence.

Cinderace ex
Scarlet & Violet Black Star Promos
#163
4.36 €
CM 796939Multiple cards in one photo
9 cards
Click to enlarge
Nine cards detected in a single binder photo, each returned as its own object in the cards array, with its own confidence.

Celebi & Bisaflor-GX
Team Up
#1
42.64 €
CM 367097
Eevee
SM Black Star Promos
#SM184
19.53 €
CM 370819
Ludicolo
Phantasmal Flames
#95
1.98 €
CM 857670
Zytomega
Scarlet & Violet Black Star Promos
#212
0.98 €
CM 836658
Gallopa
Destined Rivals
#189
5.46 €
CM 826063
Delibird
Mega Evolution
#152
2.70 €
CM 851223
Eevee
SWSH Black Star Promos
#SWSH095
3.79 €
CM 547026
Eevee
SWSH Black Star Promos
#SWSH127
5.25 €
CM 568799
Eevee
SWSH Black Star Promos
#SWSH190
3.67 €
CM 609464Japanese card
1 card
Click to enlarge
Japanese cards are detected too: the Japanese name is returned in name_ja and the card is matched to its set and Cardmarket id.

Chansey
ラッキー
Mask of Change
#113
17.69 €
30d avg
CM 767547Try it
Live test box
betaAPI key
Public demo key. Limited to 10 detections per day per network. Create your own key in Settings for your plan's full credit balance.
Quick examples
Run a detection on a known image with just your API key, no upload needed.
Card image (JPEG or PNG)
No image selected
POSTs to https://europe-west1-neosatoshi.cloudfunctions.net/detectApi
Quickstart
Create an API key
Create a key in your dashboard settings. It uses your existing plan's credit balance, with no separate API subscription.
POST an image
Base64-encode a JPEG or PNG and POST it as JSON with your key in the Authorization header.
Read the cards
The response returns an array of detected cards with set, number, rarity, Cardmarket ID and pricing.
Authentication
HTTP header
Authorization: Bearer <API_KEY>Keep your key server-side. Never embed it in client-side or mobile app code where it can be extracted. Requests without a valid key return 401.
Endpoint reference
https://europe-west1-neosatoshi.cloudfunctions.net/detectApiRequest body is JSON: a single field image containing a base64-encoded JPEG or PNG. One image can contain many cards; the response returns all of them.
Request parameters
| Field | Type | Required | Description |
|---|---|---|---|
image | string | Yes | Base64-encoded JPEG or PNG of one or more cards. |
Example request body
JSON
{
"image": "<base64-encoded JPEG or PNG>"
}Code examples
bash
# Encode the image and POST it to the Detection API.
IMAGE_B64=$(base64 -i card.jpg)
curl -X POST https://europe-west1-neosatoshi.cloudfunctions.net/detectApi \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d "{\"image\": \"$IMAGE_B64\"}"Response schema
| Field | Type | Description |
|---|---|---|
request_id | string | Unique id for the request. Include it when contacting support. |
count | number | Number of confidently detected cards in the image. |
cards | array | List of detected cards (see fields below). |
cards[].name | string | Card name in its printed language. |
cards[].name_ja | string | null | Japanese name, when known; otherwise null. |
cards[].language | string | Detected card language, e.g. "en" or "ja". |
cards[].set | object | Set id, name and the card number within the set. |
cards[].rarity | string | Printed rarity, e.g. "Illustration Rare". |
cards[].cardmarket_id | number | Cardmarket product id (idProduct) for the exact card, the canonical Cardmarket identifier. Null for a few cards (e.g. 1st-edition). |
cards[].reverse_holo | boolean | Detected as a Reverse Holo print (gated by rarity and era, so old cards are never falsely flagged). |
cards[].first_edition | boolean | Detected as a 1st Edition print. |
cards[].is_energy_card | boolean | The card is an Energy card. |
cards[].is_card_back | boolean | The photo shows a card back. When true, the identity fields are not reliable. |
cards[].prices | object | Pricing block. cardmarket.trend / low / avg7 / avg30 in EUR, plus a currency field. |
cards[].images | object | Reference image URLs (small, large), served from our CDN where available (cards_en / cards_de), otherwise a third-party fallback. See the attribution note below. |
cards[].confidence | number | Detection confidence from 0 to 1. |
cards[].image_quality | object | Input photo quality flags: blurred and unusual_dimensions (booleans). |
cards[].alternatives | array | Lower-scored candidate matches, each with name, set, number and score. |
credits.remaining | number | Credits left on your account after this request. |
Example response
200 · JSON
{
"request_id": "req_abc123",
"count": 2,
"cards": [
{
"name": "Charizard ex",
"name_ja": null,
"language": "en",
"set": { "id": "sv3pt5", "name": "151", "number": "006" },
"rarity": "Illustration Rare",
"cardmarket_id": 746497,
"reverse_holo": false,
"first_edition": false,
"is_energy_card": false,
"is_card_back": false,
"prices": {
"cardmarket": { "trend": 3.93, "low": 2.50, "avg7": 4.05, "avg30": 4.21, "currency": "EUR" }
},
"images": {
"small": "https://d1m1gwcombja0u.cloudfront.net/public_images/cards_en/sv3pt5/sv3pt5-006_small.webp",
"large": "https://d1m1gwcombja0u.cloudfront.net/public_images/cards_en/sv3pt5/sv3pt5-006.png"
},
"confidence": 0.97,
"image_quality": { "blurred": false, "unusual_dimensions": false },
"alternatives": [
{ "name": "Charizard", "set": "Base", "number": "004", "score": 0.81 }
]
}
],
"credits": { "remaining": 4985 }
}About the reference images
The images URLs are reference images for identification, served from our own CDN where available (the cardmarket_id, set and number remain the stable references). Where we don't yet host an image, the URL falls back to a third-party source (e.g. the Pokémon TCG API / pokemontcg.io) and is subject to that source' terms. Card artwork is © The Pokémon Company / Nintendo / Creatures / GAME FREAK.
Errors
| Status | Meaning | How to handle |
|---|---|---|
| 400 | Bad image | The image is missing, not base64, or not a JPEG/PNG. Fix the payload. |
| 401 | Invalid or missing key | Check the Authorization header and your key. |
| 402 | Out of credits | Top up your balance before retrying. |
| 405 | Method not allowed | The endpoint only accepts POST (and OPTIONS for CORS preflight). |
| 422 | No card detected | No card was found. Improve lighting/framing and retry. No credit charged. |
| 429 | Rate limited | Back off and retry with exponential backoff. |
| 500 | Transient error | Temporary issue. Retry the request after a short delay. |
| 504 | Detection timed out | The pipeline did not finish in time (often a cold start). Retry; warm requests are fast. Use a client timeout of at least 120s. |
Detection is synchronous. Warm requests return in a few seconds; the first request after an idle period can take longer while the pipeline warms up. If it exceeds the limit you receive a 504 — retry, and set a client timeout of at least 120s.
Credits & rate limits
Charged per confident card
One credit is charged for each card the model confidently detects, not per image. A clean photo with three cards costs three credits.
Uncertain cards are free
When the model is visually uncertain about a card, no credit is charged for it. An unclear card in the photo is free, so you never pay for guesses.
Your live balance is returned on every successful call as credits.remaining. Excessive request rates return 429; use exponential backoff. Need higher throughput? See the streaming mode below.
Async / WebSocket mode
For high-volume and streaming use cases, an asynchronous WebSocket mode is on the way. It will let you stream images and receive detections as they complete, without per-request HTTP overhead. Email us if you want early access.
Ready to integrate?
Create an API key in your settings and start detecting cards in minutes. Detections use the same credit balance as the app.