---
title: "Get Card Details by Graded Card Image"
method: POST
path: "/v1/cards/details-by-cert-ocr"
tags: ["Image Search"]
---

# Get Card Details by Graded Card Image

`POST /v1/cards/details-by-cert-ocr`

## Request

- Base URL: `https://api.cardhedger.com`
- URL: `https://api.cardhedger.com/v1/cards/details-by-cert-ocr`
- Auth: API key in header `X-API-Key`

Extract grader and certificate number from a graded card image, then look up card details.

This endpoint uses AI vision to read the grading label from a card image,
extracts the grading company (PSA, BGS, CGC, etc.) and certificate number,
then returns certificate info and card details (without price history).

Same as `/details-by-certs` but accepts an image instead of certificate numbers.

Provide either `image_url` (public URL) or `image_base64` (base64-encoded image).

**Example curl:**
```bash
curl -X POST -H "X-API-Key: your-api-key-here" \
     -H "Content-Type: application/json" \
     -d '{
       "image_url": "https://example.com/graded-card.jpg"
     }' \
     "https://api.cardhedger.com/v1/cards/details-by-cert-ocr"
```

### Daily limit

**This endpoint is capped at 2000 requests per day per API key.**

The allowance is shared with `/v1/cards/prices-by-cert-ocr` — calls to
either endpoint draw from the same daily pool. It resets at 00:00 UTC and
applies on every subscription tier, because each request runs an AI vision
model over your image.

Once the cap is reached the endpoint returns `429` until reset. The `429`
response carries the quota state in its headers:

| Header | Meaning |
|---|---|
| `X-RateLimit-Limit` | Your daily allowance |
| `X-RateLimit-Remaining` | Calls left today (`0` on a `429`) |
| `X-RateLimit-Reset` | Unix epoch seconds when the quota resets |
| `Retry-After` | Seconds until the quota resets |

Successful responses do not currently carry these headers, so track your
own call count if you need to throttle before hitting the cap.

**Contact sales if you need more capacity** —
[support@cardhedger.com](mailto:support@cardhedger.com?subject=OCR%20capacity%20increase).
Higher daily allowances are available for this endpoint.

Returns certificate info and card details (no price history).

**Daily allowance of uncached lookups.** The first time a certificate is looked up it needs a live call to our grading-data provider and draws on your account's daily allowance of such lookups; repeat lookups are served from cache and do not. See *Rate limits* in the API overview for your tier's allowance.

## Request body

- ImageCertDetailsRequest: Request parameters for image-based certificate details endpoint (no price history).
  - `image_url` string, nullable: Public URL of the graded card image
  - `image_base64` string, nullable: Base64-encoded image of the graded card (with or without data URI prefix)

## Response `200`

Successful Response

- SingleCertResult: Single certificate result in batch lookup.
  - `cert_info` GemRateCertInfo, required: Certificate verification information.
    - `grader` string, required: Grading company (e.g., PSA, BGS, CGC)
    - `cert` string, required: Certificate number
    - `grade` string, required: Card grade (e.g., PSA 10, BGS 9.5)
    - `gemrate_id` string, nullable: Unique card identifier
    - `universal_gemrate_id` string, nullable: Universal card identifier
    - `description` string, nullable: Card description from certificate
  - `card` CardDetails: Detailed card information and metadata.
    - `card_id` string, required: Unique card identifier
    - `description` string, nullable: Full card description
    - `player` string, nullable: Player or character name
    - `set` string, nullable: Card set name
    - `number` string, nullable: Card number in set
    - `variant` string, nullable: Card variant (e.g., Base, Refractor, Prizm)
    - `image` string, nullable: Card image URL
    - `category` string, nullable: Card category (e.g., Baseball, Basketball, Pokemon)
    - `category_group` string, nullable: Category group, derived from the catalog category for indexed cards
    - `set_type` string, nullable: Set type, derived from the catalog set name for indexed cards
  - `card_source` string, nullable: How the card was resolved: 'gemrate_id' for a direct GemRate ID -> CardHedge lookup, or 'card_match' when that lookup found nothing and the card was matched from the GemRate description via the AI card-match fallback. Null when no card was resolved. Cards resolved via 'card_match' have null 'category_group' and 'set_type' -- the matcher does not return those two fields.
  - `match_confidence` number, nullable: AI match confidence (0-1) when 'card_source' is 'card_match'; null otherwise. Treat results derived from a low-confidence match with care.
  - `error` string, nullable: Set to 'gemrate_daily_quota_exceeded' when this certificate needed an uncached GemRate lookup but the account's daily budget for such lookups was already spent (it resets at 00:00 UTC). The row then carries placeholder cert_info (grade 'Unknown') and no card; retry after the reset. Null for every other row.

## Other responses

- `422`: Validation Error
- `429`: Daily OCR quota exceeded. This endpoint allows 2000 requests per day per API key, shared across `prices-by-cert-ocr` and `details-by-cert-ocr`, resetting at 00:00 UTC. See the `Retry-After` and `X-RateLimit-*` response headers. Contact sales at support@cardhedger.com if you need more capacity. A 429 can also mean your account's daily allowance of uncached certificate lookups is used up (see *Rate limits* in the API overview).

## Changes

- **2026-10-05** `a7e88a62d4ba`: 1 info
  - added the optional property `error` to the response with the `200` status

[Operation history](https://skmtc.dev/cardhedger/apis/card-hedge-api/changes/v1/cards/details-by-cert-ocr/post.md)

---

[API](https://skmtc.dev/cardhedger/apis/card-hedge-api.md) - [All operations](https://skmtc.dev/cardhedger/apis/card-hedge-api/llms.txt) - [OpenAPI document](https://skmtc.dev/cardhedger/apis/card-hedge-api/revisions/6de42f192a4d?raw)
