{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/hobbycardindex-com/json-schema/hobbycardindex-com-market-summary-schema.json",
  "title": "MarketSummary",
  "x-generated": "2026-11-11",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/hobbycardindex-com-openapi.json#/components/schemas/MarketSummary",
  "type": "object",
  "properties": {
    "category": {
      "type": [
        "string",
        "null"
      ],
      "description": "The category asked for, or null for the whole market."
    },
    "index": {
      "anyOf": [
        {
          "$ref": "#/$defs/MarketIndex"
        },
        {
          "type": "null"
        }
      ],
      "description": "With a category: its index."
    },
    "sales": {
      "anyOf": [
        {
          "$ref": "#/$defs/IndexSales"
        },
        {
          "type": "null"
        }
      ],
      "description": "With a category: its sales over 7 and 30 days."
    },
    "movers": {
      "anyOf": [
        {
          "type": "object",
          "properties": {
            "period": {
              "type": "string",
              "description": "`7 days`."
            },
            "up": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/Mover"
              }
            },
            "down": {
              "type": "array",
              "items": {
                "$ref": "#/$defs/Mover"
              }
            },
            "updatedAt": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time",
              "description": "When the movers list was rebuilt."
            }
          }
        },
        {
          "type": "null"
        }
      ],
      "description": "With a category: the 5 biggest rising and falling cards (GET /api/v1/market/movers)."
    },
    "indexes": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/MarketIndex"
      },
      "description": "Without a category: every category index."
    },
    "gainers7d": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/MarketIndex"
      },
      "description": "Without a category: the 3 biggest 7-day gainers."
    },
    "losers7d": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/MarketIndex"
      },
      "description": "Without a category: the 3 biggest 7-day losers."
    },
    "playerIndexes": {
      "type": "object",
      "properties": {
        "up": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/MarketIndex"
          }
        },
        "down": {
          "type": "array",
          "items": {
            "$ref": "#/$defs/MarketIndex"
          }
        }
      },
      "required": [
        "up",
        "down"
      ],
      "description": "The 5 biggest 7-day rises and falls among player indexes with at least 25 sales in 30 days and 10 basket cards."
    },
    "updatedAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "When the indexes were last read."
    }
  },
  "required": [
    "category",
    "playerIndexes"
  ],
  "$defs": {
    "IndexChange": {
      "type": "object",
      "properties": {
        "1d": {
          "type": [
            "number",
            "null"
          ],
          "description": "Percent change from the newest value on or before 1 day before `date`; null when the index is younger."
        },
        "7d": {
          "type": [
            "number",
            "null"
          ],
          "description": "Percent change over 7 days."
        },
        "30d": {
          "type": [
            "number",
            "null"
          ],
          "description": "Percent change over 30 days."
        }
      }
    },
    "IndexSales": {
      "type": "object",
      "properties": {
        "last7d": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Sales in the 7 days through `throughDate`."
        },
        "last30d": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Sales in the 30 days through `throughDate`."
        },
        "dollarVolume7d": {
          "type": [
            "number",
            "null"
          ],
          "description": "Those 7 days' sales in US dollars."
        },
        "dollarVolume30d": {
          "type": [
            "number",
            "null"
          ],
          "description": "Those 30 days' sales in US dollars."
        },
        "throughDate": {
          "type": [
            "string",
            "null"
          ],
          "description": "The last day counted (YYYY-MM-DD). Verified sold sales by the day they sold; the counts grow as we add marketplaces."
        }
      }
    },
    "MarketIndex": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "description": "The index id the other index endpoints take: a category id (`pokemon`) or `player-` plus the player (`player-shohei-ohtani`)."
        },
        "type": {
          "type": "string",
          "description": "`category` or `player`.",
          "enum": [
            "category",
            "player"
          ]
        },
        "name": {
          "type": "string",
          "description": "The category or player name."
        },
        "category": {
          "type": [
            "string",
            "null"
          ],
          "description": "The category id; a player's is the category of the top card in the basket."
        },
        "date": {
          "type": "string",
          "description": "The day of the latest value (YYYY-MM-DD)."
        },
        "value": {
          "type": "number",
          "description": "The latest index value."
        },
        "change": {
          "$ref": "#/$defs/IndexChange"
        },
        "basketSize": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Cards in the basket."
        },
        "sales": {
          "anyOf": [
            {
              "$ref": "#/$defs/IndexSales"
            },
            {
              "type": "null"
            }
          ]
        },
        "methodology": {
          "type": [
            "string",
            "null"
          ],
          "description": "How the index is built, in one sentence."
        }
      },
      "required": [
        "id",
        "type",
        "name",
        "date",
        "value",
        "change"
      ]
    },
    "Mover": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "externalId": {
          "type": [
            "string",
            "null"
          ],
          "description": "Secondary id."
        },
        "name": {
          "type": "string",
          "description": "Card name."
        },
        "playerName": {
          "type": [
            "string",
            "null"
          ],
          "description": "Player or character."
        },
        "year": {
          "type": [
            "integer",
            "null"
          ],
          "description": "Year."
        },
        "setName": {
          "type": [
            "string",
            "null"
          ],
          "description": "Set name."
        },
        "cardNumber": {
          "type": [
            "string",
            "null"
          ],
          "description": "Card number."
        },
        "parallel": {
          "type": "string",
          "description": "The parallel, or `Base`."
        },
        "category": {
          "type": "string",
          "description": "The category."
        },
        "imageUrl": {
          "type": [
            "string",
            "null"
          ],
          "description": "Picture through our image link, or null.",
          "format": "uri"
        },
        "direction": {
          "type": "string",
          "enum": [
            "up",
            "down"
          ]
        },
        "priceChangePct": {
          "type": "number",
          "description": "How far the average raw price moved over the period, as a percentage, one decimal."
        },
        "price": {
          "type": [
            "number",
            "null"
          ],
          "description": "The current raw price."
        },
        "averagePrice": {
          "type": [
            "number",
            "null"
          ],
          "description": "The average raw price over the period."
        },
        "prices": {
          "type": "object",
          "properties": {
            "loose": {
              "type": [
                "number",
                "null"
              ],
              "description": "Raw"
            },
            "psa10": {
              "type": [
                "number",
                "null"
              ],
              "description": "PSA 10"
            },
            "psa9": {
              "type": [
                "number",
                "null"
              ],
              "description": "PSA 9"
            }
          }
        },
        "hciUrl": {
          "type": [
            "string",
            "null"
          ],
          "description": "The card's page on hobbycardindex.com.",
          "format": "uri"
        }
      },
      "required": [
        "id",
        "name",
        "direction",
        "priceChangePct"
      ]
    }
  }
}