{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/getcheapgames-com/json-schema/getcheapgames-com-store-page-out-schema.json",
  "title": "StorePageOut",
  "description": "One store's page (`catalog.store_page`): its identity, the stores table's\nfigures for it, and the games it is cheapest on.\n\nDeclared beside its one route rather than in gcg/schemas.py, and mirrored\nby `StorePageData` in app/src/lib/storePage.ts.",
  "x-generated": "2026-11-10",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/getcheapgames-com-openapi.json#/components/schemas/StorePageOut",
  "properties": {
    "code": {
      "type": "string",
      "title": "Code"
    },
    "name": {
      "type": "string",
      "title": "Name"
    },
    "domain": {
      "type": "string",
      "title": "Domain"
    },
    "accent": {
      "type": "string",
      "title": "Accent"
    },
    "kind": {
      "type": "string",
      "title": "Kind"
    },
    "currency": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Currency"
    },
    "offers": {
      "type": "integer",
      "title": "Offers"
    },
    "games": {
      "type": "integer",
      "title": "Games"
    },
    "wins": {
      "type": "integer",
      "title": "Wins"
    },
    "winsOf": {
      "type": "integer",
      "title": "Winsof"
    },
    "lastCheckedAt": {
      "anyOf": [
        {
          "type": "string",
          "format": "date-time"
        },
        {
          "type": "null"
        }
      ],
      "title": "Lastcheckedat"
    },
    "checkOk": {
      "type": "boolean",
      "title": "Checkok"
    },
    "fees": {
      "type": "integer",
      "title": "Fees"
    },
    "couponCode": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Couponcode"
    },
    "couponDiscount": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "title": "Coupondiscount"
    },
    "couponOffers": {
      "type": "integer",
      "title": "Couponoffers"
    },
    "cheapest": {
      "items": {
        "$ref": "#/$defs/GameCardOut"
      },
      "type": "array",
      "title": "Cheapest"
    },
    "gcgRating": {
      "$ref": "#/$defs/GcgRatingOut"
    },
    "families": {
      "items": {
        "type": "string"
      },
      "type": "array",
      "title": "Families"
    },
    "currencies": {
      "items": {
        "type": "string"
      },
      "type": "array",
      "title": "Currencies"
    },
    "products": {
      "type": "integer",
      "title": "Products"
    },
    "sales": {
      "items": {
        "$ref": "#/$defs/StoreSaleOut"
      },
      "type": "array",
      "title": "Sales"
    },
    "onSale": {
      "items": {
        "$ref": "#/$defs/SaleGameOut"
      },
      "type": "array",
      "title": "Onsale"
    },
    "onSaleCount": {
      "type": "integer",
      "title": "Onsalecount"
    },
    "here": {
      "type": "boolean",
      "title": "Here"
    }
  },
  "type": "object",
  "required": [
    "code",
    "name",
    "domain",
    "accent",
    "kind",
    "currency",
    "offers",
    "games",
    "wins",
    "winsOf",
    "lastCheckedAt",
    "checkOk",
    "fees",
    "couponCode",
    "couponDiscount",
    "couponOffers",
    "cheapest",
    "gcgRating",
    "families",
    "currencies",
    "products",
    "sales",
    "onSale",
    "onSaleCount",
    "here"
  ],
  "$defs": {
    "GameCardOut": {
      "properties": {
        "slug": {
          "type": "string",
          "title": "Slug"
        },
        "title": {
          "type": "string",
          "title": "Title"
        },
        "releaseYear": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "title": "Releaseyear"
        },
        "releaseDate": {
          "anyOf": [
            {
              "type": "string",
              "format": "date"
            },
            {
              "type": "null"
            }
          ],
          "title": "Releasedate"
        },
        "publisher": {
          "type": "string",
          "title": "Publisher"
        },
        "genres": {
          "items": {
            "type": "string"
          },
          "type": "array",
          "title": "Genres"
        },
        "steamAppId": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "title": "Steamappid"
        },
        "coverBase": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Coverbase"
        },
        "logo": {
          "anyOf": [
            {
              "$ref": "#/$defs/LogoOut"
            },
            {
              "type": "null"
            }
          ]
        },
        "priceHistory": {
          "items": {
            "type": "integer"
          },
          "type": "array",
          "title": "Pricehistory",
          "default": []
        },
        "kind": {
          "type": "string",
          "title": "Kind",
          "default": "game"
        },
        "isFree": {
          "type": "boolean",
          "title": "Isfree",
          "default": false
        },
        "freeToKeep": {
          "type": "boolean",
          "title": "Freetokeep",
          "default": false
        },
        "giveaway": {
          "anyOf": [
            {
              "$ref": "#/$defs/gcg__schemas__GiveawayOut"
            },
            {
              "type": "null"
            }
          ]
        },
        "playUrl": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Playurl"
        },
        "edition": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Edition"
        },
        "franchise": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Franchise"
        },
        "offers": {
          "items": {
            "$ref": "#/$defs/OfferCardOut"
          },
          "type": "array",
          "title": "Offers",
          "default": []
        }
      },
      "type": "object",
      "required": [
        "slug",
        "title",
        "releaseYear",
        "publisher",
        "genres"
      ],
      "title": "GameCardOut",
      "description": "A game as a listing renders it.\n\nDeclared rather than derived from `GameOut` so the wire shape of a listing\nis readable in one place. The fields a listing never fills — description,\nthe edition family, package contents — are simply absent instead of being\nserialised as a screenful of nulls."
    },
    "GcgRatingOut": {
      "properties": {
        "average": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "title": "Average"
        },
        "count": {
          "type": "integer",
          "title": "Count"
        }
      },
      "type": "object",
      "required": [
        "average",
        "count"
      ],
      "title": "GcgRatingOut",
      "description": "Our users' rating of the product (gcg/reviews): the average of its\nvisible reviews to one decimal, and how many. The page's header and its\nreviews tab read it here, without asking `/reviews` first."
    },
    "LogoOut": {
      "properties": {
        "src": {
          "type": "string",
          "title": "Src"
        },
        "width": {
          "type": "integer",
          "title": "Width"
        },
        "height": {
          "type": "integer",
          "title": "Height"
        }
      },
      "type": "object",
      "required": [
        "src",
        "width",
        "height"
      ],
      "title": "LogoOut",
      "description": "A game's official logo (`services/game_logos.py`): the served path of its\nWebP, transparent and trimmed to the drawn pixels, and its size in pixels,\nso a page reserves the box before it loads."
    },
    "OfferCardOut": {
      "properties": {
        "store": {
          "$ref": "#/$defs/StoreRefOut"
        },
        "currency": {
          "type": "string",
          "title": "Currency"
        },
        "listPriceCents": {
          "anyOf": [
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "title": "Listpricecents"
        },
        "feeCents": {
          "type": "integer",
          "title": "Feecents"
        },
        "totalCents": {
          "type": "integer",
          "title": "Totalcents"
        },
        "platform": {
          "type": "string",
          "title": "Platform"
        },
        "inStock": {
          "type": "boolean",
          "title": "Instock"
        },
        "regionLocked": {
          "type": "boolean",
          "title": "Regionlocked",
          "default": false
        }
      },
      "type": "object",
      "required": [
        "store",
        "currency",
        "listPriceCents",
        "feeCents",
        "totalCents",
        "platform",
        "inStock"
      ],
      "title": "OfferCardOut",
      "description": "The part of an offer a CARD renders, and nothing else.\n\nA listing sends one of these per offer per game, and the cards read only\nfour things from the set: the cheapest total, its currency and store, and\nthe ceiling the saving badge is measured against. Sending the full\n`OfferOut` there put 24,901 bytes of offer into a 27,704-byte `/deals`\nresponse — **89% of the payload** — to compute those four numbers, and it\nsat on the critical path: nothing paints until it arrives.\n\nField NAMES match `OfferOut` exactly so `bestOfferIn` and `priceSpread` in\nthe browser work against either shape unchanged. The detail page keeps the\nfull object, which is where the dropped fields are actually rendered."
    },
    "SaleGameOut": {
      "properties": {
        "game": {
          "$ref": "#/$defs/GameCardOut"
        },
        "priceCents": {
          "type": "integer",
          "title": "Pricecents"
        },
        "listPriceCents": {
          "type": "integer",
          "title": "Listpricecents"
        },
        "currency": {
          "type": "string",
          "title": "Currency"
        }
      },
      "type": "object",
      "required": [
        "game",
        "priceCents",
        "listPriceCents",
        "currency"
      ],
      "title": "SaleGameOut",
      "description": "A product the store has marked down: its card, and the store's own price and \"was\"."
    },
    "StoreRefOut": {
      "properties": {
        "code": {
          "type": "string",
          "title": "Code"
        },
        "name": {
          "type": "string",
          "title": "Name"
        },
        "accent": {
          "type": "string",
          "title": "Accent"
        },
        "kind": {
          "type": "string",
          "title": "Kind"
        }
      },
      "type": "object",
      "required": [
        "code",
        "name",
        "accent",
        "kind"
      ],
      "title": "StoreRefOut",
      "description": "The store fields a client needs to render an offer.\n\nEmbedded in each offer rather than referenced by id: it removes a\nclient-side join and a second request, and six short records across a\nresponse is nothing next to the round trip it saves."
    },
    "StoreSaleOut": {
      "properties": {
        "id": {
          "type": "integer",
          "title": "Id"
        },
        "title": {
          "type": "string",
          "title": "Title"
        },
        "discount": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Discount"
        },
        "about": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "About"
        },
        "coupon": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Coupon"
        },
        "endsAt": {
          "type": "string",
          "format": "date-time",
          "title": "Endsat"
        }
      },
      "type": "object",
      "required": [
        "id",
        "title",
        "discount",
        "about",
        "coupon",
        "endsAt"
      ],
      "title": "StoreSaleOut",
      "description": "A store-wide sale running now (`StoreSale`), its words as entered."
    },
    "gcg__schemas__GiveawayOut": {
      "properties": {
        "platform": {
          "type": "string",
          "title": "Platform"
        },
        "claimUrl": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "title": "Claimurl"
        },
        "endsAt": {
          "anyOf": [
            {
              "type": "string",
              "format": "date-time"
            },
            {
              "type": "null"
            }
          ],
          "title": "Endsat"
        }
      },
      "type": "object",
      "required": [
        "platform"
      ],
      "title": "GiveawayOut",
      "description": "A giveaway on another store than Steam: what the claim button says and\nwhere it goes (`catalog.GIVEAWAY_ELSEWHERE`). Steam's own is the game's\n`free_to_keep`, whose link the client builds from the appid."
    }
  }
}