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.

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

POST/v2/grade

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, and card fields.
  • An overall (averaged) grade named final in the grades 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.

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 grades
    • edges – Edge detection results with grades
    • card – Card analysis results including:
      • polygon – Card corner coordinates
      • bound_box – Card bounding box
      • surface – Surface grade
      • centering – 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

POST
/v2/grade
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"
  }
}

POST/v2/condition

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
  • tcgplayer:
    • Conditions: Near Mint, Lightly Played, Moderately Played, Heavily Played, Damaged
  • ximilar:
    • Conditions: Gem Mint, Mint, Near Mint, Excellent, Very Good, Good, Fair, Poor
  • cardmarket:
    • Conditions: Mint, Near Mint, Excellent, Good, Light Played, Played, Poor

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 specifying tcgplayer, ximilar, or cardmarket.

Request

POST
/v2/condition
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
  }
}

POST/v2/centering

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.

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

POST
/v2/centering
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
  }
}

POST/v2/localize

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

POST
/v2/localize
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
  }
}

POST/v2/crop_level

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.

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

POST
/v2/crop_level
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
  }
}

Was this page helpful?