Skip to content

AI Card Grading

PRICING

This page describes API of Card Grading service for images. This service provides a card grading system via AI & Machine Learning (/v2/grade). 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. We provide also lightweight endpoint for identifying condition of the card (/v2/condition). This endpoint if great for automatic submission to online marketplaces.

The API follows the general rules of Ximilar API as described in Section First steps.

Card Grading system, is available in Business and Professional pricing plans..

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

Input quality of images matters

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.

BETA / TESTING

This service is in BETA version. Be aware that some changes for this endpoint are possible in the future. We are improving AI models for grading of trading cards.

Card Grading /v2/grade

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.

Max batch in requests 2

Maximum number of images/records in one request is 2, because multiple AI models are used for analysing grades of the images and the processing of one image can take 10-20 seconds. If you send two records/images please send Front and Back side of the same card (Then it will be count as one record in credit terms). If so, additional field "grades" will be at the top level of the request - it is weighted average from both sides (70 % Front and 30 % Back). Optionally, you can specify Side in the individual record to help us identify the front and back o f the card.

Explanation of grades

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.

Parameters:

  • records: list of photos to analyze
    • must contain either of _url or _base64 field - see section image data for details
    • maximum number/batch of records is 2 (front and back of the same card)
  • front_weight: in range 0.0 to 1.0, default is 0.7
  • no-image-output: (true/false) If true, no output image will be generated which will lead to faster api response

$ 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"}]}'

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 (map) with the following fields:
    • status - a JSON map with a status of the method processing. It contains these subfields:
      • code - a numeric code of the operation status; it follows the concept of HTTP status codes (2XX, 4XX). Specific codes are described for each type of answer (or operation) (see below).
      • text - a text describing the status code
      • error_description - in case of the processing ended with error (codes 4XX), this field contains a detailed description of the error; this might include Java stack traces.
    • Example of status codes that can be returned:
      "status": {"code": 200, "text": "OK"}
      "status": {"code": 402, "text": "aborted by error", error_description="..."}
      "status": {"code": 500, "text": "unknown error", "error_description": "..."}
    • statistics - a map of various statistics about the processing. The only statistic included every time is
      • processing time - time of actual processing of the query [in seconds]
    • records - JSON array with the input records, each record enriched by fields
CLICK TO SHOW JSON RESULT

{
    "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
                },
                {
                    "name": "Card",
                    "id": "e0f155e9-2978-4524-bae2-3d7d3377c2c4",
                    "bound_box": [
                        835,
                        239,
                        1376,
                        892
                    ],
                    "prob": 0.7435819506645203
                }
            ],
            "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
    }
}

Card Condition /v2/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 we support several modes:

  • ebay:
    • This is default mode.
    • More about naming can be found on ebay
    • Conditions for TCG: Near Mint, Lightly Played, Moderately Played, Damaged
    • Conditions for Sport: Near Mint, Excellent, Very Good, Poor
  • tcgplayer:
    • More about naming can be found on tcgplayer.com
    • Conditions: Near Mint, Lightly Played, Moderately Played, Heavily Played, Damaged
  • ximilar:
    • Conditions: Gem Mint, Mint, Near Mint, Excellent, Very Good, Good, Fair, Poor

Max batch in requests 10

Maximum number of images/records in one request is 10.

Parameters:

  • records: list of photos to analyze
    • must contain either of _url or _base64 field - see section image data for details
    • maximum number/batch of records is 10
  • mode: one of tcgplayer, ebay or ximilar

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

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 (map) with the following fields:
    • status - a JSON map with a status of the method processing. It contains these subfields:
      • code - a numeric code of the operation status; it follows the concept of HTTP status codes (2XX, 4XX). Specific codes are described for each type of answer (or operation) (see below).
      • text - a text describing the status code
      • error_description - in case of the processing ended with error (codes 4XX), this field contains a detailed description of the error; this might include Java stack traces.
    • Example of statuses that can be returned:
      "status": {"code": 200, "text": "OK"}
      "status": {"code": 402, "text": "aborted by error", error_description="..."}
      "status": {"code": 500, "text": "unknown error", "error_description": "..."}
    • statistics - a map of various statistics about the processing. The only statistic included every time is
      • processing time - time of actual processing of the query [in seconds]
    • records - JSON array with the input records, each record enriched by fields _objects with Condition
CLICK TO SHOW JSON RESULT

{
    "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": "TCG",
                            "id": "089fa0cd-a399-4c6c-8420-d52a55c0ff02"
                        },
                        {
                            "prob": 0.01926,
                            "name": "Sport",
                            "id": "44b6f95c-b3a5-4f5e-84d0-e6d441f19b3a"
                        }
                    ],
                    "Condition": [
                        {
                            "value": 6.46723,
                            "name": "Card Condition TCG",
                            "id": "21cd7fde-5393-427d-bf9b-cc00920af3e7",
                            "label": "Lightly Played",
                            "mode": "tcgplayer"
                        }
                    ]
                }
            ]
        }
    ],
    "statistics": {
        "processing time": 1.1068902015686035
    },
    "status": {
        "code": 200,
        "text": "OK",
        "request_id": "ef16a269-8c2f-442c-84fa-ad1920c3f664",
        "proc_id": "5bb21221-6008-481f-a68c-11330e479213"
    }
}

Card Grading /v2/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.

Max batch in requests is 2

Maximum number of images/records in one request is 2.

Parameters:

  • records: list of photos to analyze
    • must contain either of _url or _base64 field - see section image data for details
    • maximum number/batch of records is 2 (front and back of the same card)
  • transparent: (true/false) 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.
  • skip-location: (true/false) If your image contains exactly aligned card, used this option. This will skip the location which can in this case go wrong.
  • no-image-output: (true/false) If true, no output image will be generated which will lead to faster api response

$ 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"}]}'

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 (map) with the following fields:
    • status - a JSON map with a status of the method processing. It contains these subfields:
      • code - a numeric code of the operation status; it follows the concept of HTTP status codes (2XX, 4XX). Specific codes are described for each type of answer (or operation) (see below).
      • text - a text describing the status code
      • error_description - in case of the processing ended with error (codes 4XX), this field contains a detailed description of the error; this might include Java stack traces.
    • statistics - a map of various statistics about the processing. The only statistic included every time is
      • processing time - time of actual processing of the query [in seconds]
    • records - JSON array with the input records, each record enriched by fields
      • record will contain card with centering inside. The centring contains several fields left/right, top/bottom, bound_box, pixels, offsets and grade.
        • left/right: ratio between left and right borders (for example "55/45")
        • top/bottom: ratio between top and bottom borders (for example "55/45")
        • bound_box: bounding box of borders in pixels ([xmin, ymin, xmax, ymax])
        • pixels: pixel offsets from each border (left, top, right, bottom) in pixels
        • offsets: relative offsets from each border in percentage (left, top, right, bottom)
        • grade: final grade
CLICK TO SHOW JSON RESULT

{
    "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
                }
            ],
            "_points": [
                [
                    1085,
                    122
                ],
                [
                    2567,
                    813
                ],
                [
                    1604,
                    2877
                ],
                [
                    122,
                    2186
                ]
            ],
            "card": [
                {
                    "name": "CARD",
                    "polygon": [
                        [
                            2118,
                            1219
                        ],
                        [
                            3600,
                            1910
                        ],
                        [
                            2637,
                            3974
                        ],
                        [
                            1155,
                            3283
                        ]
                    ],
                    "bound_box": [
                        1033,
                        1097,
                        3722,
                        4096
                    ],
                    "_tags": {
                        "Category": [
                            {
                                "prob": 0.98706,
                                "name": "TCG",
                                "id": "089fa0cd-a399-4c6c-8420-d52a55c0ff02"
                            }
                        ],
                        "Autograph": [
                            {
                                "prob": 0.98546,
                                "name": "Yes",
                                "id": "00058dcb-592a-4504-9794-2097f24100f7"
                            }
                        ],
                        "Side": [
                            {
                                "prob": 0.98038,
                                "name": "Back",
                                "id": "3442e597-6170-4be7-932f-b2505ddd2ea6"
                            }
                        ]
                    },
                    "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.04200000000000004,
                            0.03369999999999995
                        ],
                        "grade": 9.5
                    }
                }
            ],
            "versions": {
                "detection": "e21f943b",
                "points": "transparent",
                "centering": "1e59a11a_1"
            },
            "grades": {
                "centering": 9.5
            },
            "_exact_url_card": "__URL_CARD__",
            "_clean_url_card": "__URL_CARD__"
        }
    ],
    "transparent": true,
    "statistics": {
        "processing time": 10.295928001403809
    },
    "status": {
        "code": 200,
        "text": "OK",
        "request_id": "cb697010-b0f7-4a47-86a9-f6bb5c3df5f4",
        "proc_id": "d261c5d8-a028-4e61-86cf-21337a360075"
    }
}