Card Grading
This page describes the Card Grading service API for images. This service provides a card grading system via AI & Machine Learning. The system will find card on an image, identified exact location, detect corners & edges. After that it computes grades for individual edges, corners and then also for grade for whole surface and centering. This is similar how it's done by companies like PSA, Beckett, CGC & others. It will also identify if it is front or back of the cards, if it is autographed and whether it is TCG or SPORT card.
The API follows the general rules of Ximilar API as described in Section First steps.
This service API has several api endpoints running at URLs:
https://api.ximilar.com/card-grader/v2/grade # for extensive grade analysis with centering, corners, edges and surface
https://api.ximilar.com/card-grader/v2/condition # for fast identification of card condition like Near Mint, Moderately Played, Damaged ...
https://api.ximilar.com/card-grader/v2/centering # for analyzing card centering with left/right and top/bottom ratios
https://api.ximilar.com/card-grader/v2/localize # for detecting card location, corners and edges in the image
Because the API is working with your external images that can be lower quality (blurred, low resolution) this API is suitable as a soft-grading or pre-grading of trading card games (TCG) or sports cards. Please provide images in highest resolution possible (ideally 2000px smaller side), ideally not-upscaled or post processed by smartphone and with no sleeve or slab.
If you need to process large number of requests per day or month and don't need to get the results immediately then just use our asynchronous requests with webhooks.
Grade Card
Given a one image record, this method returns position of a card, position of corners and edges. For all of these entities it will also return a grade. The individual results are stored in corners
, edges
, card
fields and the overall (averaged) results are stored in grades
field. You can get visualization of grading via _full_url_card
, _exact_url_card
fields. The _tags
field will give you info whether it is autographed, side of the card and type of the card.
All grades are in range 1-10, where 1 is the worst and 10 is the best. The final grade of card is geometric mean of all grades (surface, corners, edges and centering).
The formula is FINAL_GRADE = geomean(geomean(CORNERS), geomean(EDGES), SURFACE, CENTERING)
If you provide Front
and Back
side of the card then the final grade is 70 % weight of front and 30 % weight of back. You can provide this weight via param front_weight
0.0, 1.0 range. Based on this grade we provide also a condition name Poor
, Fair
, Good
, Very Good
, Excellent
, Near Mint
, Mint
, Gem Mint
.
This endpoint processes up to 2 images per request (10-20 seconds per image). For best results, send both front and back sides of the same card - this counts as one card in terms of credits and provides a weighted average grade (70% front, 30% back). You can specify the Side
field in each record to help identify front/back.
Required attributes
- Name
Authorization
- Type
- string
- Description
API token for authentication.
- Name
records
- Type
- array
- 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. Body of the response is a JSON object with the following fields:
- Name
records
- Type
- array
- Description
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 grade
versions
- Version information for each analysis componentgrades
- Overall grades for corners, edges, surface, centering, and final grade_full_url_card
- URL to full card visualization_exact_url_card
- URL to exact card 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": "__URL_IMAGE_PATH__",
"_status": {
"code": 200,
"text": "OK",
"request_id": "cd3f6eb0-e5c1-48d6-9fa3-0a95287a2589"
},
"_id": "631b7cf6-b25b-4949-b618-b5bed803bd6f",
"_width": 1600,
"_height": 959,
"_objects": [
{
"name": "Card",
"id": "e0f155e9-2978-4524-bae2-3d7d3377c2c4",
"bound_box": [240, 260, 746, 901],
"prob": 0.9428542852401733
}
],
"corners": [
{
"name": "UPPER_LEFT",
"bound_box": [255, 261, 316, 322],
"point": [277, 283],
"grade": 6.5
},
{
"name": "UPPER_RIGHT",
"bound_box": [652, 259, 713, 320],
"point": [692, 281],
"grade": 6.5
},
{
"name": "DOWN_RIGHT",
"bound_box": [659, 831, 720, 892],
"point": [699, 871],
"grade": 7.0
},
{
"name": "DOWN_LEFT",
"bound_box": [254, 814, 315, 875],
"point": [276, 854],
"grade": 7.0
}
],
"edges": [
{
"name": "UPPER",
"polygon": [[319, 261], [649, 259], [649, 323], [319, 325]],
"grade": 7.5
},
{
"name": "RIGHT",
"polygon": [[649, 323], [713, 323], [720, 828], [656, 828]],
"grade": 8.0
},
{
"name": "DOWN",
"polygon": [[318, 811], [656, 828], [656, 892], [318, 875]],
"grade": 7.5
},
{
"name": "LEFT",
"polygon": [[255, 325], [319, 325], [318, 811], [254, 811]],
"grade": 7.0
}
],
"card": [
{
"name": "CARD",
"polygon": [[277, 283], [692, 281], [699, 871], [276, 854]],
"bound_box": [192, 212, 794, 949],
"_tags": {
"Category": [
{
"prob": 0.98526,
"name": "Sport",
"id": "44b6f95c-b3a5-4f5e-84d0-e6d441f19b3a"
}
],
"Damaged": [
{
"prob": 0.97285,
"name": "OK",
"id": "8d77cbf2-96de-4e45-b518-ea09cf77483a"
}
],
"Autograph": [
{
"prob": 0.99019,
"name": "No",
"id": "45ef0f10-f4c5-4065-aaab-89384369b925"
}
],
"Side": [
{
"prob": 0.90916,
"name": "Front",
"id": "3ebc6fc4-41d4-4432-99f1-5f8c50f10413"
}
]
},
"surface": {
"grade": 7.0
},
"centering": {
"left/right": "66/34",
"top/bottom": "59/41",
"bound_box": [0.0474, 0.0474, 0.024900000000000033, 0.03369999999999995],
"grade": 9.0
}
}
],
"versions": {
"detection": "e21f943b",
"points": "f6cac813_3",
"corners": "7516607f_1",
"edges": "b949c1b8_1",
"surface": "7ba660de_10",
"centering": "1e59a11a_1",
"final": "7516607f_1-b949c1b8_1-7ba660de_10-1e59a11a_1-e21f943b-f6cac813_3"
},
"grades": {
"corners": 7.0,
"edges": 7.5,
"surface": 7.0,
"centering": 9.0,
"final": 7.5
},
"_full_url_card": "https://s3-eu-west-1.amazonaws.com/ximilar-tmp-images/card-grading/2d4d1fc5-5909-403e-b86a-c10be0f5b73a.webp",
"_exact_url_card": "https://s3-eu-west-1.amazonaws.com/ximilar-tmp-images/card-grading/e258fc6d-39f0-4ce7-afd5-931018d91e7c.webp"
}
],
"status": {
"code": 200,
"text": "OK",
"request_id": "cd3f6eb0-e5c1-48d6-9fa3-0a95287a2589",
"proc_id": "f50ecd84-b9f9-48c1-ba03-d3555aeb8e64"
},
"statistics": {
"processing time": 6.4246416091918945
}
}
Get Card Condition
Given a one image record, this method returns position of a card (by object/bounding box). For the largest card (object) on image it will also return a Condition
. You can specify a mode
of condition (naming) that you want to return.
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
- Description
List of photos to analyze. Must contain either of
_url
or_base64
field. Maximum number/batch of records is 10.
Optional attributes
- Name
mode
- Type
- string
- Description
One of
tcgplayer
,ebay
orximilar
. Default isebay
.
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 one image record, this method returns position of a card and centering analysis. You can get visualization of grading via _clean_url_card
, _exact_url_card
fields. The _tags
field will give you whether it is autographed, side of the card and type of the card. The centering
information is stored inside a 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
- 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 card that has already analysed background / foreground (card) then set this to true. This will make processing much more precise and faster.
- Name
skip-location
- Type
- boolean
- Description
If your image contains exactly aligned card, used this option. This will skip the location which can in this case go wrong.
- Name
no-image-output
- Type
- boolean
- Description
If true, no output image will be generated which will lead to 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 one image record, the endpoint returns the corners, edges and 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 whose background/foreground has already been analysed. This will make processing much 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 one image record of a card scan (the background must be white), return an url of the card with the background cropped out.
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
- Description
Indicates whether to use AI models to perform the cropping. The AI method is currently under development and using it may provide inferior results. Default: false.
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
}
}