Card Grading
This page describes the Card Grading service API, which uses AI and machine learning to automate the grading of trading cards and sports cards.
It detects the card in an image, identifies its exact location, as well as the position of its corners and edges. It then computes grades for individual corners and edges, overall surface, and centering — similar to the methods used by companies like PSA, Beckett, CGC, and others.
The system also identifies whether the image shows
the Front
or Back
of the card, whether the card has an Autograph
,
and whether it is a TCG
(trading card game) or sports card (sport
).
This API follows the general rules of Ximilar API as described in Section First steps.
Because this API works with external images — which may vary in quality (e.g., low resolution, blur, compression) — it is best suited for soft grading or pre-grading of trading cards (TCG or sports cards).
This API provides several endpoints available at the following URLs:
https://api.ximilar.com/card-grader/v2/grade # detailed grading: centering, corners, edges, surface
https://api.ximilar.com/card-grader/v2/condition # quick condition check: Near Mint, Played, Damaged
https://api.ximilar.com/card-grader/v2/centering # analyzes centering: left/right, top/bottom
https://api.ximilar.com/card-grader/v2/localize # detects card position, corners, and edges
For the most accurate results, please provide high-resolution images (ideally with the shorter side at least 2000px), unedited or unprocessed by smartphones, and without sleeves or slabs.
If you need to process a large number of requests per day or month and don’t require immediate results, use our asynchronous requests with webhooks.
Grade Card
This endpoint accepts a single image record and returns:
- The positions of the card, its corners and edges.
- The individual grades for each of these elements (card, corners, edges).
- Individual results stored in the
corners
,edges
, andcard
fields. - An overall (averaged) grade named
final
in thegrades
field, along with the repeated individual grades.
The _tags
field contains data such as the card Category
(e.g., Trading Card Game
or Sport
),
whether the card is Damaged
, whether it has an Autograph
, and which Side
is shown (Front
or Back
).
All grades range from 1 to 10, where 1 is the worst and 10 is the best.
The final grade of the card is calculated as the geometric mean of the individual grades (surface, corners, edges and centering).
The formula used:
final
= geomean(geomean(CORNERS), geomean(EDGES), SURFACE, CENTERING)
If you provide both the front and back sides of the card,
the final grade is calculated using a 70% weight for the front and 30% for the back by default.
You can adjust this ratio using the front_weight
parameter (range: 0.0 to 1.0).
Based on the final grade, the system assigns a condition label:
Poor
, Fair
, Good
, Very Good
, Excellent
, Near Mint
, Mint
, or Gem Mint
.
Grading visualizations are available through one of the following fields:
_full_url_card
provides the original image with detected objects (corners, edges, surface) and their grades._exact_url_card
shows the extracted card with centering visualization.
This endpoint can process up to two images per request, with each image taking approximately 10–20 seconds to analyze.
For best results, submit both the Front
and Back
sides of the same card in a single request
– this counts as one card for credit usage and allows the system to compute a weighted average grade (70% front, 30% back).
You can use the Side
field in each image record to indicate whether it shows the front or back of the card.
Required attributes
- Name
Authorization
- Type
- string
- Description
API token for authentication.
- Name
records
- Type
- array
- Max
- Maximum:2
- Description
List of photos to analyze. Must contain either of
_url
or_base64
field. Maximum number/batch of records is 2 (front and back of the same card).
Returns
HTTP error code 2XX, if the method was OK, and other HTTP error code, if the method failed. The body of the response is a JSON object with the following fields:
- Name
records
- Type
- array
- Description
An array of processed records, each containing:
corners
– Corner detection results with gradesedges
– Edge detection results with gradescard
– Card analysis results including:polygon
– Card corner coordinatesbound_box
– Card bounding boxsurface
– Surface gradecentering
– Centering analysis with ratios and a grade_tags
– Additional metadata about the card
versions
– Version information for each analysed component ("detection", "points", "corners", "edges", etc.)grades
– Overall grades for corners, edges, surface, centering, and final grade_full_url_card
– URL to detailed card visualization_exact_url_card
– URL to card centering visualization
Request
curl --request POST \
--url https://api.ximilar.com/card-grader/v2/grade \
--header 'Authorization: Token __API_TOKEN__' \
--header 'content-type: application/json' \
--data '{"records": [{"_url": "__IMAGE_URL"}]}'
{
"records": [
{
"_url": "https://images.ximilar.com/examples/demo/grading/4.jpeg",
"_status": {
"code": 200,
"text": "OK",
"request_id": "46caef8b-456a-49cc-a1f3-f94d8011ae38"
},
"_id": "8a5526ab-19c1-4a48-a0ab-227d8dcba834",
"_width": 4608,
"_height": 3456,
"_objects": [
{
"name": "Card",
"id": "e0f155e9-2978-4524-bae2-3d7d3377c2c4",
"bound_box": [
1431,
560,
3282,
3103
],
"prob": 0.9410721063613892
}
],
"_points": [
[
1602.688,
590.482
],
[
3141.4448,
639.832
],
[
3238.056,
3038.524
],
[
1487.3504,
3050.932
]
],
"corners": [
{
"name": "UPPER_LEFT",
"bound_box": [
1527,
515,
1740,
728
],
"point": [
1602,
590
],
"grade": 4.0
},
{
"name": "UPPER_RIGHT",
"bound_box": [
3002,
564,
3215,
777
],
"point": [
3141,
639
],
"grade": 2.5
},
{
"name": "DOWN_RIGHT",
"bound_box": [
3099,
2899,
3312,
3112
],
"point": [
3238,
3038
],
"grade": 3.5
},
{
"name": "DOWN_LEFT",
"bound_box": [
1412,
2911,
1625,
3124
],
"point": [
1487,
3050
],
"grade": 3.0
}
],
"edges": [
{
"name": "UPPER",
"polygon": [
[
1750,
515
],
[
2992,
564
],
[
2992,
787
],
[
1750,
738
]
],
"grade": 4.0
},
{
"name": "RIGHT",
"polygon": [
[
2992,
787
],
[
3215,
787
],
[
3312,
2889
],
[
3089,
2889
]
],
"grade": 6.0
},
{
"name": "DOWN",
"polygon": [
[
1635,
2901
],
[
3089,
2889
],
[
3089,
3112
],
[
1635,
3124
]
],
"grade": 5.5
},
{
"name": "LEFT",
"polygon": [
[
1527,
738
],
[
1750,
738
],
[
1635,
2901
],
[
1412,
2901
]
],
"grade": 5.0
}
],
"card": [
{
"name": "CARD",
"polygon": [
[
1602,
590
],
[
3141,
639
],
[
3238,
3038
],
[
1487,
3050
]
],
"bound_box": [
1292,
421,
3420,
3241
],
"_tags": {
"Category": [
{
"prob": 0.9976,
"name": "Card/Sport Card",
"id": "44b6f95c-b3a5-4f5e-84d0-e6d441f19b3a"
}
],
"Damaged": [
{
"prob": 0.91033,
"name": "OK",
"id": "8d77cbf2-96de-4e45-b518-ea09cf77483a"
}
],
"Autograph": [
{
"prob": 0.92005,
"name": "Yes",
"id": "00058dcb-592a-4504-9794-2097f24100f7"
}
],
"Side": [
{
"prob": 0.91008,
"name": "Front",
"id": "3ebc6fc4-41d4-4432-99f1-5f8c50f10413"
}
]
},
"surface": {
"grade": 3.5
},
"centering": {
"left/right": "57/43",
"top/bottom": "68/32",
"bound_box": [
77,
92,
1691,
2419
],
"pixels": [
77,
92,
59,
44
],
"offsets": [
0.044,
0.0377,
0.0338,
0.0181
],
"grade": 6.0
}
}
],
"versions": {
"detection": "e21f943b",
"points": "f6cac813_4",
"corners": "7516607f_1",
"edges": "b949c1b8_1",
"surface": "7ba660de_11",
"centering": "5bb1214a_4",
"final": "7516607f_1-b949c1b8_1-7ba660de_11-5bb1214a_4-e21f943b-f6cac813_4"
},
"grades": {
"corners": 3.0,
"edges": 5.0,
"surface": 3.5,
"centering": 6.0,
"final": 4.0,
"condition": "Very Good"
},
"_full_url_card": "__PATH_TO_CARD_IMAGE__",
"_exact_url_card": "__PATH_TO_CARD_IMAGE__"
}
],
"statistics": {
"processing time": 8.783197402954102
},
"status": {
"code": 200,
"text": "OK",
"request_id": "46caef8b-456a-49cc-a1f3-f94d8011ae38",
"proc_id": "9a896cc6-b709-45ae-ab2e-f68f956a7406"
}
}
Get Card Condition
Given a single image record, this method returns the position of the card (as an object = bounding box).
For the largest card detected in the image, it will also provide Condition
.
You can specify the condition naming mode
you want to receive.
Currently supported modes:
ebay
(default):- Conditions for TCG:
Near Mint
,Lightly Played
,Moderately Played
,Damaged
- Conditions for Sport:
Near Mint
,Excellent
,Very Good
,Poor
- Conditions for TCG:
tcgplayer
:- Conditions:
Near Mint
,Lightly Played
,Moderately Played
,Heavily Played
,Damaged
- Conditions:
ximilar
:- Conditions:
Gem Mint
,Mint
,Near Mint
,Excellent
,Very Good
,Good
,Fair
,Poor
- Conditions:
cardmarket
:- Conditions:
Mint
,Near Mint
,Excellent
,Good
,Light Played
,Played
,Poor
- Conditions:
Maximum number of images (records) in one request is 10.
Required attributes
- Name
Authorization
- Type
- string
- Description
API token for authentication.
- Name
records
- Type
- array
- Max
- Maximum:10
- Description
List of photos to analyze. Must contain either of
_url
or_base64
field. Maximum number of records (batch) is 10.
Optional attributes
- Name
mode
- Type
- string
- Default
- Default:ebay
- Description
Default mode if is
ebay
. You can change that by specifyingtcgplayer
,ximilar
, orcardmarket
.
Request
curl --request POST \
--url https://api.ximilar.com/card-grader/v2/condition \
--header 'Authorization: Token __API_TOKEN__' \
--header 'content-type: application/json' \
--data '{"records": [{"_url": "__IMAGE_URL"}], "mode": "tcgplayer"}'
{
"records": [
{
"_url": "__URL_IMG__",
"_status": {
"code": 200,
"text": "OK",
"request_id": "ef16a269-8c2f-442c-84fa-ad1920c3f664"
},
"_id": "4f878b2e-5d8f-4e2a-ae1f-09e65ffdcf70",
"_width": 1600,
"_height": 1600,
"_objects": [
{
"name": "Card",
"id": "e0f155e9-2978-4524-bae2-3d7d3377c2c4",
"bound_box": [177, 142, 1185, 1523],
"prob": 0.9539390802383423,
"area": 0.54376875,
"Category": [
{
"prob": 0.98074,
"name": "Card/Trading Card Game"
}
],
"Condition": [
{
"value": 6.46723,
"name": "Card Condition TCG",
"label": "Lightly Played",
"mode": "tcgplayer"
}
]
}
]
}
],
"status": {
"code": 200,
"text": "OK"
},
"statistics": {
"processing time": 1.1068902015686035
}
}
Get Card Centering
Given a single image record, this method returns the position of the card along with centering analysis.
Visualization of the grading can be accessed via the _clean_url_card
and _exact_url_card
fields.
The _tags
field provides the card Category
, information on whether the card has an Autograph
,
and the card's Side
. The centering
information is stored in the card
field of the record.
Maximum number of images (records) in one request is 2.
Required attributes
- Name
Authorization
- Type
- string
- Description
API token for authentication.
- Name
records
- Type
- array
- Max
- Maximum:2
- Description
List of photos to analyze. Must contain either of
_url
or_base64
field. Maximum number (batch) of records is 2 (front and back of the same card).
Optional attributes
- Name
transparent
- Type
- boolean
- Description
If your image contains a card with a pre-processed alpha channel (i.e., the background is already transparent), set this to
true
. This improves processing accuracy and speed by focusing only on the visible card content.
- Name
skip-location
- Type
- boolean
- Description
If your image contains a perfectly aligned card, use this option to skip the card localization step. In such cases, automatic localization may produce incorrect results.
- Name
no-image-output
- Type
- boolean
- Description
If
true
, no output image will be generated, which will lead to a faster API response.
Request
curl --request POST \
--url https://api.ximilar.com/card-grader/v2/centering \
--header 'Authorization: Token __API_TOKEN__' \
--header 'content-type: application/json' \
--data '{"records": [{"_url": "__IMAGE_URL"}]}'
{
"records": [
{
"_url": "__URL_CARD__",
"_status": {
"code": 200,
"text": "OK",
"request_id": "cb697010-b0f7-4a47-86a9-f6bb5c3df5f4"
},
"_id": "1ea2e7de-5020-40ff-970e-d3286aa09e3c",
"_width": 4891,
"_height": 4891,
"_objects": [
{
"name": "Card",
"id": "e0f155e9-2978-4524-bae2-3d7d3377c2c4",
"bound_box": [1033, 1097, 3722, 4096],
"prob": 1.0
}
],
"card": [
{
"name": "CARD",
"polygon": [[2118, 1219], [3600, 1910], [2637, 3974], [1155, 3283]],
"bound_box": [1033, 1097, 3722, 4096],
"_tags": {
"Category": [{"prob": 0.98706, "name": "Card/Trading Card Game"}],
"Autograph": [{"prob": 0.98546, "name": "Yes"}],
"Side": [{"prob": 0.98038, "name": "Back"}]
},
"centering": {
"left/right": "46/54",
"top/bottom": "49/51",
"bound_box": [57, 71, 1567, 2201],
"pixels": [57, 71, 68, 76],
"offsets": [0.0351, 0.0312, 0.0420, 0.0337],
"grade": 9.5
}
}
],
"grades": {
"centering": 9.5
}
}
],
"status": {
"code": 200,
"text": "OK"
},
"statistics": {
"processing time": 10.295928001403809
}
}
Get Card Location
Given a single image record, this endpoint returns the positions of corners
,
edges
and the overall position of the card
in the image.
Required attributes
- Name
Authorization
- Type
- string
- Description
API token for authentication.
- Name
records
- Type
- array
- Description
List of images to analyze. Must contain either
_url
or_base64
field.
Optional attributes
- Name
transparent
- Type
- boolean
- Description
If your image contains a card with a pre-processed background/foreground (e.g. isolated card on a transparent background), set this to
true
. This applies to input images with an alpha channel and a transparent background. Enabling this makes the processing more precise and faster.
Request
curl --request POST \
--url https://api.ximilar.com/card-grader/v2/localize \
--header 'Authorization: Token __API_TOKEN__' \
--header 'content-type: application/json' \
--data '{"records": [{"_url": "__IMAGE_URL"}]}'
{
"records": [
{
"_url": "__URL_CARD__",
"_status": {
"code": 200,
"text": "OK",
"request_id": "3a7fa006-c72b-4bb7-9e44-213c291b8cb3"
},
"_id": "c488d900-44d9-4f5a-9d74-9c841658c029",
"_width": 801,
"_height": 1116,
"_objects": [
{
"name": "Card",
"id": "e0f155e9-2978-4524-bae2-3d7d3377c2c4",
"bound_box": [189, 3, 784, 683],
"prob": 0.7105523943901062
}
],
"corners": [
{
"name": "UPPER_LEFT",
"bound_box": [155, 129, 219, 193],
"point": [178, 152]
}
],
"edges": [
{
"name": "UPPER",
"polygon": [[222, 129], [731, 4], [731, 71], [222, 196]]
}
],
"card": [
{
"name": "CARD",
"polygon": [[178, 152], [776, 27], [764, 686], [213, 662]],
"bound_box": [164, 0, 800, 707]
}
]
}
],
"status": {
"code": 200,
"text": "OK"
},
"statistics": {
"processing time": 3.519575595855713
}
}
Crop Card
Given a single image record of a card scan (with a white background), this endpoint returns a URL to a new image where the background has been cropped out.
The background of a card scan must be white.
Required attributes
- Name
Authorization
- Type
- string
- Description
API token for authentication.
- Name
records
- Type
- array
- Description
List of images to analyze. Must contain either
_url
or_base64
field.
Optional attributes
- Name
use_ai
- Type
- boolean
- Default
- Default:false
- Description
Specifies whether to use an AI model for cropping the card. By default (
false
), the system uses standard computer vision techniques. The AI-based method is still under development and may produce inferior results.
Request
curl --request POST \
--url https://api.ximilar.com/card-grader/v2/crop_level \
--header 'Authorization: Token __API_TOKEN__' \
--header 'content-type: application/json' \
--data '{"records": [{"_url": "__IMAGE_URL"}]}'
{
"records": [
{
"_url": "__URL_CARD__",
"_status": {
"code": 200,
"text": "OK",
"request_id": "372f0556-7145-495c-8feb-d91ea9e13d44"
},
"_id": "36d86202-8398-4954-bb57-24f8ea565013",
"_width": 749,
"_height": 1053,
"_img_url": "__URL_CROPPED_CARD__"
}
],
"status": {
"code": 200,
"text": "OK"
},
"statistics": {
"processing time": 0.8681676387786865
}
}