Hobby Card Index slabs and certs API

Cert lookups and population reports.

GitHub OpenAPI

Operations 2

GET /api/v1/prices/{cardId}/population Population report for one card #
GET /api/v1/certs/{grader}/{certNumber} Look up a graded card by cert number #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/hobbycardindex-com:hobbycardindex-com-slabs-and-certs-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

hobbycardindex-com-slabs-and-certs-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Hobby Card Index Data slabs and certs API
  version: '1'
  summary: Real sold prices, photo identification, cert lookups, pop reports, sold sales and price history for sports cards and trading cards.
  description: 'Real sold prices for sports cards and trading cards: a catalog of more than 16 million cards across 25-plus categories (baseball, basketball, football, hockey, soccer, Pokemon, Magic: The Gathering, Yu-Gi-Oh, One Piece and more) with more than 22 million raw and graded prices, refreshed daily, plus card identification from a photo, PSA, BGS, CGC and SGC cert lookups, population reports, verified sold-sale records, daily price history, set lists, market movers, a price watch list with a daily webhook, and bulk price files.


    ## Keys and plans


    Every endpoint needs an API key, sent as the `X-API-Key` header (or `Authorization: Bearer`). Keys come from Settings, API Access, after subscribing. An **Enterprise** plan ($49.99 a month) includes a key for your own business''s internal use: 1 request a second, up to 100,000 a day. Apps, websites and products whose users see the data need a **Commercial plan** (a commercial data license, Terms of Service section 8):


    - Lite (plan id `lite`): $99 a month; 25,000 requests, 25,000 photo scans, 5,000 sold-sale lookups, 150 cert lookups, 10 lookups a second, price history.

    - Growth Lite (plan id `growth_lite`): $249 a month; 125,000 requests, 125,000 photo scans, 25,000 sold-sale lookups, 750 cert lookups, 15 lookups a second, price history.

    - Growth (plan id `growth`): $499 a month; 500,000 requests, 500,000 photo scans, 100,000 sold-sale lookups, 3,000 cert lookups, 20 lookups a second, price history.

    - Platform (plan id `platform`): from $1,500 a month; 2,000,000 requests, 1,500,000 photo scans, 500,000 sold-sale lookups, 50,000 cert lookups, 50 lookups a second, price history, bulk price files.


    A **free setup month** is by application in Settings, API Access (one per company): enough to build and test against real data, with daily pools. Plans, prices and how to buy, including how an AI agent can buy a plan for its user with no account (GET /api/v1/agent/plans, POST /api/v1/agent/checkout): https://hobbycardindex.com/developers#commercial-plans. Questions or a bigger deal: sean@hobbycardindex.com.


    ## Credit the data (required)


    Commercial plans ask for one link back to https://hobbycardindex.com somewhere on your site, such as ''Prices and API supplied by Hobby Card Index''; it does not need to be beside the prices. Every successful JSON object response carries an `attribution` object (text, url, html, required, terms) and an `X-Attribution` header with the same credit, so it can be rendered straight from the response. Put the credit beside the prices or anywhere on your website, such as the footer. Snippet: `Prices from Hobby Card Index`.


    ## Conventions


    - Base URL `https://hobbycardindex.com`; every path starts with `/api/v1/`. Prices are US dollars with two decimals; a grade with no price is `null`. Grade keys: `loose` (raw), `psa10`, `psa9`, `psa8`, `psa7`, `bgs10` (BGS 9.5), `cgc10`, `sgc10`.

    - Successful responses are `{ "success": true, "data": { ... }, "attribution": { ... } }`; errors are `{ "success": false, "error": { "code", "message", "details"? } }` with the HTTP status that fits (400, 401, 402, 403, 404, 409, 413, 429, 500, 503). Streamed downloads (CSV, bulk files, the watch-list prices) are not wrapped.

    - Card ids: pass the integer `id` every response carries, or `ext-` plus the card''s `externalId`. Picture links (`imageUrl`) go through our image proxy and need no key; a link can answer 404 later if the picture is withdrawn, so show a placeholder on a 404.

    - Rate limits: 1 request a second on an Enterprise key, the plan''s lookups a second on a commercial key, with `RateLimit-*` and `X-RateLimit-*` headers on the one-second window. Commercial plans also return `X-HCI-Plan` and `X-HCI-*-Used` / `X-HCI-*-Allowance` headers for the monthly counters.

    - The same data through an MCP server for AI assistants: POST https://hobbycardindex.com/api/v1/mcp, manifest https://hobbycardindex.com/.well-known/mcp.json.'
  termsOfService: https://hobbycardindex.com/terms/
  contact:
    name: Sean Charman, Hobby Card Index
    email: sean@hobbycardindex.com
    url: https://hobbycardindex.com/developers
  license:
    name: Hobby Card Index Terms of Service (section 8, Commercial Data License)
    url: https://hobbycardindex.com/terms/#data-license
  x-logo:
    url: https://hobbycardindex.com/hci-logo2.png
    altText: Hobby Card Index
    href: https://hobbycardindex.com
  x-attribution:
    text: Prices from Hobby Card Index
    url: https://hobbycardindex.com
    html: <a href="https://hobbycardindex.com" rel="noopener">Prices from Hobby Card Index</a>
    required: true
    terms: https://hobbycardindex.com/terms/
servers:
- url: https://hobbycardindex.com
  description: Production
security:
- ApiKeyAuth: []
tags:
- name: slabs and certs
  description: Cert lookups and population reports.
paths:
  /api/v1/prices/{cardId}/population:
    get:
      tags:
      - slabs and certs
      summary: Population report for one card
      operationId: getCardPopulation
      description: How many copies PSA, BGS, SGC and CGC have graded, grade by grade, with gem counts and gem rate. We hold a stored report for many cards; a card with none, or one over 30 days old, is fetched live within a daily budget. Platform, or Lite, Growth Lite and Growth with the pop + cert add-on. Pop reports have their own monthly number and stop there (429 POP_LIMIT_REACHED); each call also counts as a request.
      parameters:
      - $ref: '#/components/parameters/cardId'
      responses:
        '200':
          description: The population report, or null when we hold none
          headers:
            X-Attribution:
              $ref: '#/components/headers/X-Attribution'
            X-HCI-Plan:
              $ref: '#/components/headers/X-HCI-Plan'
            X-HCI-Requests-Used:
              $ref: '#/components/headers/X-HCI-Requests-Used'
            X-HCI-Requests-Allowance:
              $ref: '#/components/headers/X-HCI-Requests-Allowance'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            X-HCI-Pop-Used:
              description: Pop reports used this month.
              schema:
                type: integer
            X-HCI-Pop-Allowance:
              description: The plan's monthly pop reports.
              schema:
                type: integer
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    const: true
                  data:
                    $ref: '#/components/schemas/PopulationResponse'
                  attribution:
                    $ref: '#/components/schemas/Attribution'
                required:
                - success
                - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/ServerError'
      security:
      - ApiKeyAuth: []
  /api/v1/certs/{grader}/{certNumber}:
    get:
      tags:
      - slabs and certs
      summary: Look up a graded card by cert number
      operationId: lookupCert
      description: 'The grading company''s record for the cert (grade, autograph grade, player, year, set, card number and population when the grader reports it), the matching card in our catalog with its prices at every grade, and the `slab` block: the price at that exact grade, whether the cert verified, the grader''s own cert page (`verifyUrl`) and their slab photos when they have them. Every commercial size has a monthly number of cert lookups (hard stop, 429 CERT_LIMIT_REACHED); one lookup a second per key. A bad request or a busy day is not counted.'
      parameters:
      - name: grader
        in: path
        required: true
        description: psa, bgs, cgc or sgc.
        schema:
          type: string
          enum:
          - psa
          - bgs
          - cgc
          - sgc
      - name: certNumber
        in: path
        required: true
        description: The cert number printed on the slab label.
        schema:
          type: string
          minLength: 1
          maxLength: 25
      responses:
        '200':
          description: The cert, the card and the slab block
          headers:
            X-Attribution:
              $ref: '#/components/headers/X-Attribution'
            X-HCI-Plan:
              $ref: '#/components/headers/X-HCI-Plan'
            X-HCI-Requests-Used:
              $ref: '#/components/headers/X-HCI-Requests-Used'
            X-HCI-Requests-Allowance:
              $ref: '#/components/headers/X-HCI-Requests-Allowance'
            RateLimit-Limit:
              $ref: '#/components/headers/RateLimit-Limit'
            RateLimit-Remaining:
              $ref: '#/components/headers/RateLimit-Remaining'
            X-HCI-Certs-Used:
              description: Cert lookups used this month.
              schema:
                type: integer
            X-HCI-Certs-Allowance:
              description: The plan's monthly cert lookups.
              schema:
                type: integer
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    const: true
                  data:
                    $ref: '#/components/schemas/CertResponse'
                  attribution:
                    $ref: '#/components/schemas/Attribution'
                required:
                - success
                - data
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/TooManyRequests'
        '503':
          $ref: '#/components/responses/ServerError'
      security:
      - ApiKeyAuth: []
components:
  headers:
    X-Attribution:
      description: 'Always "Prices from Hobby Card Index (https://hobbycardindex.com)" on a successful JSON object response: the credit the data must carry.'
      schema:
        type: string
    X-HCI-Requests-Used:
      description: 'Commercial plans only: requests used this month, after this one.'
      schema:
        type: integer
    X-HCI-Requests-Allowance:
      description: 'Commercial plans only: the plan''s monthly requests.'
      schema:
        type: integer
    RateLimit-Remaining:
      description: Requests left in the current one-second window.
      schema:
        type: integer
    RateLimit-Limit:
      description: Requests allowed in the current one-second window (X-RateLimit-* are sent too).
      schema:
        type: integer
    X-HCI-Plan:
      description: 'Commercial plans only: the plan id behind this key.'
      schema:
        type: string
  schemas:
    Slab:
      type: object
      properties:
        grader:
          type:
          - string
          - 'null'
          description: PSA, BGS, CGC, SGC, TGA or null.
        grade:
          type:
          - number
          - string
          - 'null'
          description: The numeric grade, `Authentic`, or null when unread.
        autoGrade:
          type:
          - string
          - 'null'
          description: Autograph grade when the label carries one.
        certNumber:
          type:
          - string
          - 'null'
          description: The cert number read from the label or the grader's record.
        certVerified:
          type: boolean
          description: true when the grader's record for that cert was found and agrees with the label.
        priceAtGrade:
          type:
          - number
          - 'null'
          description: The card's price at exactly this grade when we price that grade; null otherwise (never a neighbouring grade's price).
        verifyUrl:
          type:
          - string
          - 'null'
          description: The grader's own page for the cert (PSA, CGC and TGA open the cert; Beckett and SGC open their lookup page).
          format: uri
        frontImageUrl:
          type:
          - string
          - 'null'
          description: The grader's front slab photo through our image link, when they have one.
          format: uri
        backImageUrl:
          type:
          - string
          - 'null'
          description: The grader's back slab photo through our image link, when they have one.
          format: uri
      required:
      - certVerified
    Attribution:
      type: object
      properties:
        text:
          type: string
          const: Prices from Hobby Card Index
        url:
          type: string
          format: uri
          const: https://hobbycardindex.com
        html:
          type: string
          const: <a href="https://hobbycardindex.com" rel="noopener">Prices from Hobby Card Index</a>
          description: 'Ready to paste: the credit as a link.'
        required:
          type: boolean
          const: true
        terms:
          type: string
          format: uri
          const: https://hobbycardindex.com/terms/
      required:
      - text
      - url
      - html
      - required
      - terms
      description: 'The credit this data must carry wherever it is shown: a visible "Prices from Hobby Card Index" link to https://hobbycardindex.com. Added to every successful JSON object response (also sent as the X-Attribution header).'
    ScanCard:
      type: object
      properties:
        id:
          type:
          - integer
          - 'null'
          description: The catalog id, or null when the match is not in our catalog yet.
        externalId:
          type:
          - string
          - 'null'
          description: Secondary id.
        name:
          type:
          - string
          - 'null'
          description: Card name; a parallel is named in brackets.
        playerName:
          type:
          - string
          - 'null'
          description: Player or character.
        year:
          type:
          - integer
          - string
          - 'null'
        setName:
          type:
          - string
          - 'null'
          description: Set name.
        cardNumber:
          type:
          - string
          - 'null'
          description: Card number.
        printRun:
          type:
          - integer
          - 'null'
          description: Print run for numbered cards.
        parallel:
          type: string
          description: The parallel, or `Base`.
        category:
          type:
          - string
          - 'null'
          description: Category.
        imageUrl:
          type:
          - string
          - 'null'
          description: Picture through our image link, or null.
          format: uri
        confidence:
          type:
          - number
          - 'null'
          description: 0 to 1, three decimals.
    CardRef:
      type: object
      properties:
        id:
          type: integer
          description: The catalog id. Pass it to the other card endpoints.
        externalId:
          type:
          - string
          - 'null'
          description: Our catalog's secondary id for the card. Accepted by the card endpoints as `ext-<externalId>`.
        name:
          type: string
          description: 'The card name, with the parallel in brackets when it is not the base card, for example `Mike Trout [Gold] #US175`.'
        year:
          type:
          - integer
          - string
          - 'null'
          description: The year the card came out (for Pokemon, the year its set was released); null when unknown.
        setName:
          type:
          - string
          - 'null'
          description: The set the card belongs to.
        category:
          type:
          - string
          - 'null'
          description: The category, for example Baseball or Pokemon.
        playerName:
          type:
          - string
          - 'null'
          description: The player or character on the card.
      required:
      - id
      - name
      description: The card block the sales, listings, history and population endpoints return.
    Cert:
      type: object
      properties:
        grader:
          type:
          - string
          - 'null'
          description: PSA, BGS, CGC or SGC.
        certNumber:
          type:
          - string
          - 'null'
          description: The cert number.
        grade:
          type:
          - string
          - 'null'
          description: The grade on the grader's record.
        player:
          type:
          - string
          - 'null'
          description: Player or character on the record.
        year:
          type:
          - string
          - 'null'
          description: Year on the record.
        cardNumber:
          type:
          - string
          - 'null'
          description: Card number on the record.
      additionalProperties: true
      description: The grading company's record for the cert, with whatever fields the grader reports (set, autograph grade, population).
    CertResponse:
      type: object
      properties:
        cert:
          oneOf:
          - $ref: '#/components/schemas/Cert'
          - type: 'null'
        card:
          oneOf:
          - allOf:
            - $ref: '#/components/schemas/ScanCard'
            - type: object
              properties:
                prices:
                  oneOf:
                  - $ref: '#/components/schemas/Prices'
                  - type: 'null'
                  description: null for keys on the pop + certs plan.
          - type: 'null'
          description: The matching card in our catalog with its prices at every grade, or null when the record did not match a card.
        slab:
          oneOf:
          - $ref: '#/components/schemas/Slab'
          - type: 'null'
          description: 'The slab block: grade, cert, whether it verified, price at that grade, the grader''s own cert page and slab photos.'
      additionalProperties: true
    PopulationResponse:
      type: object
      properties:
        card:
          $ref: '#/components/schemas/CardRef'
        population:
          oneOf:
          - type: object
            properties:
              totalPopulation:
                type:
                - integer
                - 'null'
                description: All graders together.
              totalGems:
                type:
                - integer
                - 'null'
                description: Gem copies across graders.
              asOf:
                type:
                - string
                - 'null'
                format: date-time
                description: When the report was taken.
              lastChange:
                type:
                - object
                - integer
                - string
                - 'null'
              graders:
                type: object
                additionalProperties:
                  $ref: '#/components/schemas/GraderPopulation'
                description: 'Keyed by grader: PSA, BGS, SGC, CGC.'
          - type: 'null'
          description: null when we do not hold a report for this card yet.
      required:
      - card
      - population
    Prices:
      allOf:
      - $ref: '#/components/schemas/PriceGrid'
      - type: object
        properties:
          volume:
            type:
            - integer
            - 'null'
            description: Recent sales volume, a count.
          updated:
            type:
            - string
            - 'null'
            format: date-time
            description: When this card's prices were last refreshed.
          fromSales:
            type: array
            items:
              type: string
            description: Grades (keys of this object) whose price came from our own recent sold sales because no other price was on file for that grade.
      description: 'The price block of GET /api/v1/prices/{cardId}: the grade grid plus volume and the last update.'
    GraderPopulation:
      type: object
      properties:
        totalGraded:
          type:
          - integer
          - 'null'
          description: Copies this grader has graded.
        gems:
          type:
          - integer
          - 'null'
          description: Copies at the gem grade.
        gemGrade:
          type:
          - string
          - 'null'
          description: The grade counted as gem for this grader, for example 10 or 9.5.
        gemRate:
          type:
          - number
          - 'null'
          description: gems / totalGraded as a percentage.
        ladder:
          type:
          - object
          - array
          - 'null'
          description: Counts grade by grade, as the grader reports them.
        autoTotal:
          type:
          - integer
          - 'null'
          description: Autograph copies graded.
        nonAutoTotal:
          type:
          - integer
          - 'null'
          description: Non-autograph copies graded.
        lastChange:
          type:
          - object
          - integer
          - string
          - 'null'
          description: The most recent change we recorded for this grader.
      additionalProperties: true
    PriceGrid:
      type: object
      properties:
        loose:
          type:
          - number
          - 'null'
          description: raw (ungraded) price in US dollars; null when there is no price at that grade.
        psa10:
          type:
          - number
          - 'null'
          description: PSA 10 price in US dollars; null when there is no price at that grade.
        psa9:
          type:
          - number
          - 'null'
          description: PSA 9 price in US dollars; null when there is no price at that grade.
        psa8:
          type:
          - number
          - 'null'
          description: PSA 8 price in US dollars; null when there is no price at that grade.
        psa7:
          type:
          - number
          - 'null'
          description: PSA 7 price in US dollars; null when there is no price at that grade.
        bgs10:
          type:
          - number
          - 'null'
          description: BGS 9.5 (BGS 10 when there is no 9.5 price) price in US dollars; null when there is no price at that grade.
        cgc10:
          type:
          - number
          - 'null'
          description: CGC 10 price in US dollars; null when there is no price at that grade.
        sgc10:
          type:
          - number
          - 'null'
          description: SGC 10 price in US dollars; null when there is no price at that grade.
      description: Current prices by grade, in US dollars with two decimals. A grade with no price is null; `bgs10` holds the BGS 9.5 price.
    Error:
      type: object
      properties:
        success:
          type: boolean
          const: false
          description: false on every error the API itself sends. The per-second rate limiter's 429 body has only `error`.
        error:
          type: object
          properties:
            code:
              type: string
              description: Machine-readable code, for example VALIDATION_ERROR, INVALID_PARAM, MISSING_API_KEY, INVALID_API_KEY, KEY_REVOKED, PLAN_REQUIRED, TRIAL_ENDED, NOT_ON_PLAN, REQUIRES_COMMERCIAL_LICENSE, REQUIRES_GROWTH, REQUIRES_PARTNER_PLAN, RATE_LIMITED, MONTHLY_LIMIT_REACHED, DAILY_LIMIT_REACHED, NOT_FOUND, SERVER_ERROR.
            message:
              type: string
              description: What went wrong and, where there is one, what to do about it.
            details:
              type: object
              additionalProperties: true
              description: 'Extra fields on some errors: plans_url, upgrade_url, limit, allowance, plan, upgrade.'
          required:
          - code
          - message
      required:
      - error
      description: The error envelope from every endpoint.
  parameters:
    cardId:
      name: cardId
      in: path
      required: true
      description: The card's `id` from search, scan, movers or watch-list results (an integer), or `ext-` followed by its `externalId` (for example `ext-67890`). Letters, digits, dashes, underscores and dots, up to 150 characters.
      schema:
        type: string
        maxLength: 150
        pattern: ^[a-zA-Z0-9\-_.]+$
  responses:
    NotFound:
      description: 'NOT_FOUND: no card (or file) matches.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    PaymentRequired:
      description: 'TRIAL_ENDED: the free setup month is over and the first month of the plan is not paid yet.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: 'The key''s plan does not include this: PLAN_REQUIRED, DEALER_KEY_SCOPE, NOT_ON_PLAN, REQUIRES_COMMERCIAL_LICENSE, REQUIRES_GROWTH, REQUIRES_PARTNER_PLAN, REQUIRES_PLATFORM_PLAN, REQUIRES_PRICE_FILES, REQUIRES_ENTERPRISE, LISTINGS_NOT_ENABLED. The message says which plan has it and `details.plans_url` where to get it.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    TooManyRequests:
      description: RATE_LIMITED (the per-second window; slow down and retry), RATE_LIMIT_EXCEEDED (the daily ceiling), MONTHLY_LIMIT_REACHED, DAILY_LIMIT_REACHED, SALES_LIMIT_REACHED, CERT_LIMIT_REACHED, POP_LIMIT_REACHED, LISTINGS_LIMIT_REACHED, SCAN_ENGINE_BUSY (Retry-After says when).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    ServerError:
      description: 'SERVER_ERROR (500 or 503): something failed on our side; retry in a minute.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    BadRequest:
      description: 'The request is not valid: VALIDATION_ERROR, INVALID_PARAM, BAD_REQUEST, SEARCH_TOO_BROAD, NO_IMAGE, INVALID_IMAGE.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: No key (MISSING_API_KEY), a key we do not know (INVALID_API_KEY) or one that was revoked (KEY_REVOKED).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: 'Your HobbyCardIndex API key (hci_live_...). `Authorization: Bearer <key>` is accepted too. Keys: https://hobbycardindex.com/developers.'
externalDocs:
  description: Developer documentation with examples in curl, JavaScript and Python
  url: https://hobbycardindex.com/developers