{
  "openapi": "3.1.0",
  "info": {
    "title": "Hexascore API",
    "version": "1.0.0",
    "summary": "Community scores for games, movies, TV series and books.",
    "description": "Read-only REST API over the Hexascore catalog: every item carries a 0–100 community score and six per-category averages.\n\n- **Auth**: `Authorization: Bearer hx_live_…` — create a key at `/profile/api`.\n- **Format**: JSON, `snake_case` fields, ISO 8601 dates. Errors are RFC 9457 `application/problem+json` with a stable `code`.\n- **Pagination**: cursor based — pass `next_cursor` back as `cursor`.\n- **Plans**: Free = 100 requests in total, 10 items per page, 1 req/s. Pro and Business have monthly quotas, 100 items per page and prepaid credits.\n\nGuides: https://hexascore.com/docs",
    "contact": {
      "name": "Hexascore",
      "url": "https://hexascore.com/docs"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://hexascore.com/terms"
    }
  },
  "servers": [
    {
      "url": "https://api.hexascore.com/v1",
      "description": "Production"
    },
    {
      "url": "/api/v1",
      "description": "This deployment (same API under /api/v1)"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Games",
      "description": "Games: list, detail and genres."
    },
    {
      "name": "Movies",
      "description": "Movies: list, detail and genres."
    },
    {
      "name": "Series",
      "description": "Series: list, detail and genres."
    },
    {
      "name": "Books",
      "description": "Books: list, detail and genres."
    },
    {
      "name": "Search",
      "description": "Find items by text or by an id from another database."
    },
    {
      "name": "Account",
      "description": "Your quota, credits and rate limit."
    }
  ],
  "externalDocs": {
    "description": "Guides",
    "url": "https://hexascore.com/docs"
  },
  "paths": {
    "/games": {
      "get": {
        "operationId": "listGames",
        "tags": [
          "Games"
        ],
        "summary": "List games",
        "description": "Pages through games with filters. Categories for this type: `gameplay`, `fun`, `sound`, `technical`, `visual`, `storytelling` — filter with `min_<category>`. Pass `next_cursor` back as `cursor` until it is `null`.",
        "parameters": [
          {
            "name": "genre",
            "in": "query",
            "required": false,
            "description": "Exact genre, as returned by the genres endpoint.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          {
            "name": "platform",
            "in": "query",
            "required": false,
            "description": "Exact platform name.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "description": "Release year.",
            "schema": {
              "type": "integer",
              "minimum": 1800,
              "maximum": 2100
            }
          },
          {
            "name": "min_score",
            "in": "query",
            "required": false,
            "description": "Minimum community score (hides unscored items).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "max_score",
            "in": "query",
            "required": false,
            "description": "Maximum community score (hides unscored items).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_gameplay",
            "in": "query",
            "required": false,
            "description": "Minimum `gameplay` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_fun",
            "in": "query",
            "required": false,
            "description": "Minimum `fun` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_sound",
            "in": "query",
            "required": false,
            "description": "Minimum `sound` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_technical",
            "in": "query",
            "required": false,
            "description": "Minimum `technical` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_visual",
            "in": "query",
            "required": false,
            "description": "Minimum `visual` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_storytelling",
            "in": "query",
            "required": false,
            "description": "Minimum `storytelling` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort field; prefix with `-` for descending. Unscored/undated items always come last.",
            "schema": {
              "default": "-popularity",
              "x-enum-varnames": [
                "POPULARITY_DESC",
                "POPULARITY",
                "SCORE_DESC",
                "SCORE",
                "RELEASE_DATE_DESC",
                "RELEASE_DATE",
                "RATING_COUNT_DESC",
                "RATING_COUNT"
              ],
              "type": "string",
              "enum": [
                "-popularity",
                "popularity",
                "-score",
                "score",
                "-release_date",
                "release_date",
                "-rating_count",
                "rating_count"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, 1–100. Free plan: up to 10.",
            "schema": {
              "default": 10,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "`next_cursor` from the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Language of titles and synopses (`en`, `pt-BR`, `es`). Falls back to English.",
            "schema": {
              "default": "en",
              "type": "string",
              "enum": [
                "en",
                "pt-BR",
                "es"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/games/{id}": {
      "get": {
        "operationId": "getGame",
        "tags": [
          "Games"
        ],
        "summary": "Get a game",
        "description": "Full record: metadata, community score and per-category averages (`gameplay`, `fun`, `sound`, `technical`, `visual`, `storytelling`), external ids, trailers and the licensed synopsis. An id of another type returns 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Item id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Language of titles and synopses (`en`, `pt-BR`, `es`). Falls back to English.",
            "schema": {
              "default": "en",
              "type": "string",
              "enum": [
                "en",
                "pt-BR",
                "es"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemDetail"
                }
              }
            }
          },
          "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/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/games/genres": {
      "get": {
        "operationId": "listGameGenres",
        "tags": [
          "Games"
        ],
        "summary": "List game genres",
        "description": "Every genre used by this type with its item count. Use `slug` as the `genre` filter.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenreList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/movies": {
      "get": {
        "operationId": "listMovies",
        "tags": [
          "Movies"
        ],
        "summary": "List movies",
        "description": "Pages through movies with filters. Categories for this type: `screenplay`, `acting`, `direction`, `cinematography`, `soundtrack`, `entertainment` — filter with `min_<category>`. Pass `next_cursor` back as `cursor` until it is `null`.",
        "parameters": [
          {
            "name": "genre",
            "in": "query",
            "required": false,
            "description": "Exact genre, as returned by the genres endpoint.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "description": "Release year.",
            "schema": {
              "type": "integer",
              "minimum": 1800,
              "maximum": 2100
            }
          },
          {
            "name": "min_score",
            "in": "query",
            "required": false,
            "description": "Minimum community score (hides unscored items).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "max_score",
            "in": "query",
            "required": false,
            "description": "Maximum community score (hides unscored items).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_screenplay",
            "in": "query",
            "required": false,
            "description": "Minimum `screenplay` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_acting",
            "in": "query",
            "required": false,
            "description": "Minimum `acting` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_direction",
            "in": "query",
            "required": false,
            "description": "Minimum `direction` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_cinematography",
            "in": "query",
            "required": false,
            "description": "Minimum `cinematography` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_soundtrack",
            "in": "query",
            "required": false,
            "description": "Minimum `soundtrack` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_entertainment",
            "in": "query",
            "required": false,
            "description": "Minimum `entertainment` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort field; prefix with `-` for descending. Unscored/undated items always come last.",
            "schema": {
              "default": "-popularity",
              "x-enum-varnames": [
                "POPULARITY_DESC",
                "POPULARITY",
                "SCORE_DESC",
                "SCORE",
                "RELEASE_DATE_DESC",
                "RELEASE_DATE",
                "RATING_COUNT_DESC",
                "RATING_COUNT"
              ],
              "type": "string",
              "enum": [
                "-popularity",
                "popularity",
                "-score",
                "score",
                "-release_date",
                "release_date",
                "-rating_count",
                "rating_count"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, 1–100. Free plan: up to 10.",
            "schema": {
              "default": 10,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "`next_cursor` from the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Language of titles and synopses (`en`, `pt-BR`, `es`). Falls back to English.",
            "schema": {
              "default": "en",
              "type": "string",
              "enum": [
                "en",
                "pt-BR",
                "es"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/movies/{id}": {
      "get": {
        "operationId": "getMovie",
        "tags": [
          "Movies"
        ],
        "summary": "Get a movie",
        "description": "Full record: metadata, community score and per-category averages (`screenplay`, `acting`, `direction`, `cinematography`, `soundtrack`, `entertainment`), external ids, trailers and the licensed synopsis. An id of another type returns 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Item id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Language of titles and synopses (`en`, `pt-BR`, `es`). Falls back to English.",
            "schema": {
              "default": "en",
              "type": "string",
              "enum": [
                "en",
                "pt-BR",
                "es"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemDetail"
                }
              }
            }
          },
          "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/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/movies/genres": {
      "get": {
        "operationId": "listMovieGenres",
        "tags": [
          "Movies"
        ],
        "summary": "List movie genres",
        "description": "Every genre used by this type with its item count. Use `slug` as the `genre` filter.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenreList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/series": {
      "get": {
        "operationId": "listSeries",
        "tags": [
          "Series"
        ],
        "summary": "List TV series",
        "description": "Pages through TV series with filters. Categories for this type: `screenplay`, `acting`, `characters`, `pacing`, `production`, `entertainment` — filter with `min_<category>`. Pass `next_cursor` back as `cursor` until it is `null`.",
        "parameters": [
          {
            "name": "genre",
            "in": "query",
            "required": false,
            "description": "Exact genre, as returned by the genres endpoint.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "description": "Release year.",
            "schema": {
              "type": "integer",
              "minimum": 1800,
              "maximum": 2100
            }
          },
          {
            "name": "min_score",
            "in": "query",
            "required": false,
            "description": "Minimum community score (hides unscored items).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "max_score",
            "in": "query",
            "required": false,
            "description": "Maximum community score (hides unscored items).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_screenplay",
            "in": "query",
            "required": false,
            "description": "Minimum `screenplay` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_acting",
            "in": "query",
            "required": false,
            "description": "Minimum `acting` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_characters",
            "in": "query",
            "required": false,
            "description": "Minimum `characters` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_pacing",
            "in": "query",
            "required": false,
            "description": "Minimum `pacing` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_production",
            "in": "query",
            "required": false,
            "description": "Minimum `production` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_entertainment",
            "in": "query",
            "required": false,
            "description": "Minimum `entertainment` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort field; prefix with `-` for descending. Unscored/undated items always come last.",
            "schema": {
              "default": "-popularity",
              "x-enum-varnames": [
                "POPULARITY_DESC",
                "POPULARITY",
                "SCORE_DESC",
                "SCORE",
                "RELEASE_DATE_DESC",
                "RELEASE_DATE",
                "RATING_COUNT_DESC",
                "RATING_COUNT"
              ],
              "type": "string",
              "enum": [
                "-popularity",
                "popularity",
                "-score",
                "score",
                "-release_date",
                "release_date",
                "-rating_count",
                "rating_count"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, 1–100. Free plan: up to 10.",
            "schema": {
              "default": 10,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "`next_cursor` from the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Language of titles and synopses (`en`, `pt-BR`, `es`). Falls back to English.",
            "schema": {
              "default": "en",
              "type": "string",
              "enum": [
                "en",
                "pt-BR",
                "es"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/series/{id}": {
      "get": {
        "operationId": "getSeries",
        "tags": [
          "Series"
        ],
        "summary": "Get a TV series",
        "description": "Full record: metadata, community score and per-category averages (`screenplay`, `acting`, `characters`, `pacing`, `production`, `entertainment`), external ids, trailers and the licensed synopsis. An id of another type returns 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Item id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Language of titles and synopses (`en`, `pt-BR`, `es`). Falls back to English.",
            "schema": {
              "default": "en",
              "type": "string",
              "enum": [
                "en",
                "pt-BR",
                "es"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemDetail"
                }
              }
            }
          },
          "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/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/series/genres": {
      "get": {
        "operationId": "listSeriesGenres",
        "tags": [
          "Series"
        ],
        "summary": "List series genres",
        "description": "Every genre used by this type with its item count. Use `slug` as the `genre` filter.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenreList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/books": {
      "get": {
        "operationId": "listBooks",
        "tags": [
          "Books"
        ],
        "summary": "List books",
        "description": "Pages through books with filters. Categories for this type: `plot`, `characters`, `writing`, `pacing`, `originality`, `impact` — filter with `min_<category>`. Pass `next_cursor` back as `cursor` until it is `null`.",
        "parameters": [
          {
            "name": "genre",
            "in": "query",
            "required": false,
            "description": "Exact genre, as returned by the genres endpoint.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "description": "Release year.",
            "schema": {
              "type": "integer",
              "minimum": 1800,
              "maximum": 2100
            }
          },
          {
            "name": "min_score",
            "in": "query",
            "required": false,
            "description": "Minimum community score (hides unscored items).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "max_score",
            "in": "query",
            "required": false,
            "description": "Maximum community score (hides unscored items).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_plot",
            "in": "query",
            "required": false,
            "description": "Minimum `plot` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_characters",
            "in": "query",
            "required": false,
            "description": "Minimum `characters` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_writing",
            "in": "query",
            "required": false,
            "description": "Minimum `writing` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_pacing",
            "in": "query",
            "required": false,
            "description": "Minimum `pacing` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_originality",
            "in": "query",
            "required": false,
            "description": "Minimum `originality` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "min_impact",
            "in": "query",
            "required": false,
            "description": "Minimum `impact` average (0–100).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 100
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort field; prefix with `-` for descending. Unscored/undated items always come last.",
            "schema": {
              "default": "-popularity",
              "x-enum-varnames": [
                "POPULARITY_DESC",
                "POPULARITY",
                "SCORE_DESC",
                "SCORE",
                "RELEASE_DATE_DESC",
                "RELEASE_DATE",
                "RATING_COUNT_DESC",
                "RATING_COUNT"
              ],
              "type": "string",
              "enum": [
                "-popularity",
                "popularity",
                "-score",
                "score",
                "-release_date",
                "release_date",
                "-rating_count",
                "rating_count"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, 1–100. Free plan: up to 10.",
            "schema": {
              "default": 10,
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "`next_cursor` from the previous page.",
            "schema": {
              "type": "string",
              "maxLength": 512
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Language of titles and synopses (`en`, `pt-BR`, `es`). Falls back to English.",
            "schema": {
              "default": "en",
              "type": "string",
              "enum": [
                "en",
                "pt-BR",
                "es"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/books/{id}": {
      "get": {
        "operationId": "getBook",
        "tags": [
          "Books"
        ],
        "summary": "Get a book",
        "description": "Full record: metadata, community score and per-category averages (`plot`, `characters`, `writing`, `pacing`, `originality`, `impact`), external ids, trailers and the licensed synopsis. An id of another type returns 404.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Item id (UUID).",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Language of titles and synopses (`en`, `pt-BR`, `es`). Falls back to English.",
            "schema": {
              "default": "en",
              "type": "string",
              "enum": [
                "en",
                "pt-BR",
                "es"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemDetail"
                }
              }
            }
          },
          "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/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/books/genres": {
      "get": {
        "operationId": "listBookGenres",
        "tags": [
          "Books"
        ],
        "summary": "List book genres",
        "description": "Every genre used by this type with its item count. Use `slug` as the `genre` filter.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GenreList"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/search": {
      "get": {
        "operationId": "searchItems",
        "tags": [
          "Search"
        ],
        "summary": "Search items",
        "description": "Typo-tolerant search over titles and synopses in every locale, best match first (up to 50 results).",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "description": "Text to search; typo tolerant.",
            "example": "zelda",
            "schema": {
              "type": "string",
              "minLength": 2,
              "maxLength": 100
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Restrict to one type (`game`, `movie`, `series`, `book`).",
            "schema": {
              "type": "string",
              "enum": [
                "game",
                "movie",
                "series",
                "book"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size, 1–50. Free plan: up to 10.",
            "schema": {
              "default": 10,
              "type": "integer",
              "minimum": 1,
              "maximum": 50
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Language of titles and synopses (`en`, `pt-BR`, `es`). Falls back to English.",
            "schema": {
              "default": "en",
              "type": "string",
              "enum": [
                "en",
                "pt-BR",
                "es"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SearchResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/lookup": {
      "get": {
        "operationId": "lookupItem",
        "tags": [
          "Search"
        ],
        "summary": "Look up by external id",
        "description": "Finds the item for an IMDb, Steam, IGDB, TMDB, ISBN-13, Open Library or Wikidata id. Ids must match exactly (e.g. `tt0111161`, `Q42`).",
        "parameters": [
          {
            "name": "source",
            "in": "query",
            "required": true,
            "description": "Database the id belongs to.",
            "schema": {
              "type": "string",
              "enum": [
                "imdb",
                "steam",
                "igdb",
                "tmdb",
                "isbn13",
                "openlibrary",
                "wikidata"
              ]
            }
          },
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "Id in that database.",
            "example": "tt0111161",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 100
            }
          },
          {
            "name": "locale",
            "in": "query",
            "required": false,
            "description": "Language of titles and synopses (`en`, `pt-BR`, `es`). Falls back to English.",
            "schema": {
              "default": "en",
              "type": "string",
              "enum": [
                "en",
                "pt-BR",
                "es"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ItemDetail"
                }
              }
            }
          },
          "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/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/me/usage": {
      "get": {
        "operationId": "getUsage",
        "tags": [
          "Account"
        ],
        "summary": "Get usage",
        "description": "Plan, quota used in the current period, prepaid credits and rate limit. Counts as one request.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK",
            "headers": {
              "RateLimit-Limit": {
                "description": "Requests in the current quota period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "description": "Requests left in the period.",
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "description": "Seconds until the quota resets (`0` for the lifetime Free quota).",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Quota-Remaining": {
                "description": "Same as `RateLimit-Remaining`.",
                "schema": {
                  "type": "integer"
                }
              },
              "X-Request-Id": {
                "description": "Id of this request; quote it to support.",
                "schema": {
                  "type": "string"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ItemSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "Stable item id.",
            "examples": [
              "0190a1b2-0000-7000-8000-000000000001"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "game",
              "movie",
              "series",
              "book"
            ],
            "description": "Kind of item. List endpoints use the plural path (`/games`, `/movies`, `/series`, `/books`)."
          },
          "slug": {
            "type": "string",
            "description": "URL-safe name, unique per type.",
            "examples": [
              "the-legend-of-zelda"
            ]
          },
          "title": {
            "type": "string",
            "description": "Title in the requested locale, English when missing."
          },
          "release_date": {
            "anyOf": [
              {
                "type": "string",
                "format": "date",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "First release (YYYY-MM-DD)."
          },
          "year": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "score": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "maximum": 100
              },
              {
                "type": "null"
              }
            ],
            "description": "Community score 0–100 (mean of the six categories). `null` until the item has 5 ratings.",
            "examples": [
              87
            ]
          },
          "categories": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 100
                },
                {
                  "type": "null"
                }
              ]
            },
            "description": "Average per category, 0–100, `null` under 5 ratings. Keys by type — `game`: `gameplay`, `fun`, `sound`, `technical`, `visual`, `storytelling`; `movie`: `screenplay`, `acting`, `direction`, `cinematography`, `soundtrack`, `entertainment`; `series`: `screenplay`, `acting`, `characters`, `pacing`, `production`, `entertainment`; `book`: `plot`, `characters`, `writing`, `pacing`, `originality`, `impact`.",
            "examples": [
              {
                "gameplay": 90,
                "fun": 88,
                "sound": 85,
                "technical": 84,
                "visual": 89,
                "storytelling": 86
              }
            ]
          },
          "rating_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Number of community ratings."
          },
          "genres": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "platforms": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Platforms (games only; empty for other types)."
          },
          "cover_url": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ]
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Public page of the item on the website, in the requested locale."
          }
        },
        "required": [
          "id",
          "type",
          "slug",
          "title",
          "release_date",
          "year",
          "score",
          "categories",
          "rating_count",
          "genres",
          "platforms",
          "cover_url",
          "url"
        ],
        "additionalProperties": false,
        "description": "Compact item used in lists and search results."
      },
      "ItemDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
            "description": "Stable item id.",
            "examples": [
              "0190a1b2-0000-7000-8000-000000000001"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "game",
              "movie",
              "series",
              "book"
            ],
            "description": "Kind of item. List endpoints use the plural path (`/games`, `/movies`, `/series`, `/books`)."
          },
          "slug": {
            "type": "string",
            "description": "URL-safe name, unique per type.",
            "examples": [
              "the-legend-of-zelda"
            ]
          },
          "title": {
            "type": "string",
            "description": "Title in the requested locale, English when missing."
          },
          "release_date": {
            "anyOf": [
              {
                "type": "string",
                "format": "date",
                "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$"
              },
              {
                "type": "null"
              }
            ],
            "description": "First release (YYYY-MM-DD)."
          },
          "year": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "score": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0,
                "maximum": 100
              },
              {
                "type": "null"
              }
            ],
            "description": "Community score 0–100 (mean of the six categories). `null` until the item has 5 ratings.",
            "examples": [
              87
            ]
          },
          "categories": {
            "type": "object",
            "propertyNames": {
              "type": "string"
            },
            "additionalProperties": {
              "anyOf": [
                {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 100
                },
                {
                  "type": "null"
                }
              ]
            },
            "description": "Average per category, 0–100, `null` under 5 ratings. Keys by type — `game`: `gameplay`, `fun`, `sound`, `technical`, `visual`, `storytelling`; `movie`: `screenplay`, `acting`, `direction`, `cinematography`, `soundtrack`, `entertainment`; `series`: `screenplay`, `acting`, `characters`, `pacing`, `production`, `entertainment`; `book`: `plot`, `characters`, `writing`, `pacing`, `originality`, `impact`.",
            "examples": [
              {
                "gameplay": 90,
                "fun": 88,
                "sound": 85,
                "technical": 84,
                "visual": 89,
                "storytelling": 86
              }
            ]
          },
          "rating_count": {
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991,
            "description": "Number of community ratings."
          },
          "genres": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "platforms": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Platforms (games only; empty for other types)."
          },
          "cover_url": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ]
          },
          "url": {
            "type": "string",
            "format": "uri",
            "description": "Public page of the item on the website, in the requested locale."
          },
          "locale": {
            "type": "string",
            "enum": [
              "en",
              "pt-BR",
              "es"
            ]
          },
          "translation_fallback": {
            "type": "boolean",
            "description": "True when the requested locale had no title or synopsis and English was used."
          },
          "synopsis": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Synopsis"
              },
              {
                "type": "null"
              }
            ]
          },
          "external_ids": {
            "type": "object",
            "properties": {
              "wikidata": {
                "type": "string"
              },
              "imdb": {
                "type": "string"
              },
              "igdb": {
                "type": "string"
              },
              "steam": {
                "type": "string"
              },
              "tmdb": {
                "type": "string"
              },
              "isbn13": {
                "type": "string"
              },
              "openlibrary": {
                "type": "string"
              },
              "hltb": {
                "type": "string"
              },
              "goodreads": {
                "type": "string"
              },
              "metacritic": {
                "type": "string"
              },
              "rottentomatoes": {
                "type": "string"
              },
              "epic": {
                "type": "string"
              },
              "gog": {
                "type": "string"
              },
              "skoob": {
                "type": "string"
              }
            },
            "required": [
              "wikidata"
            ],
            "additionalProperties": false,
            "description": "Identifiers of the item in other databases. Only known ids are present.",
            "examples": [
              {
                "wikidata": "Q12345",
                "igdb": "the-legend-of-zelda",
                "steam": "123456"
              }
            ]
          },
          "trailers": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "youtube_id": {
                  "type": "string"
                },
                "title": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "youtube_id",
                "title"
              ],
              "additionalProperties": false
            },
            "description": "YouTube video ids; embed as `https://www.youtube-nocookie.com/embed/{youtube_id}`."
          },
          "creators": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Developers, directors, showrunners or authors."
          },
          "countries": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "runtime_minutes": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "pages": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "seasons": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          },
          "episodes": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": -9007199254740991,
                "maximum": 9007199254740991
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "type",
          "slug",
          "title",
          "release_date",
          "year",
          "score",
          "categories",
          "rating_count",
          "genres",
          "platforms",
          "cover_url",
          "url",
          "locale",
          "translation_fallback",
          "synopsis",
          "external_ids",
          "trailers",
          "creators",
          "countries",
          "runtime_minutes",
          "pages",
          "seasons",
          "episodes"
        ],
        "additionalProperties": false,
        "description": "Full item: metadata, scores, external ids, trailers and synopsis."
      },
      "Synopsis": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string"
          },
          "locale": {
            "type": "string",
            "enum": [
              "en",
              "pt-BR",
              "es"
            ],
            "description": "Locale the text is written in."
          },
          "license": {
            "description": "License of the text (e.g. `CC BY-SA 4.0`). Attribute it when you display the synopsis.",
            "type": [
              "string",
              "null"
            ]
          },
          "source_url": {
            "anyOf": [
              {
                "type": "string",
                "format": "uri"
              },
              {
                "type": "null"
              }
            ],
            "description": "Where the text comes from (for attribution)."
          }
        },
        "required": [
          "text",
          "locale",
          "license",
          "source_url"
        ],
        "additionalProperties": false,
        "description": "Synopsis with the license you must honour when showing it."
      },
      "ItemList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemSummary"
            }
          },
          "next_cursor": {
            "description": "Pass as `cursor` to get the next page. `null` on the last page.",
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "data",
          "next_cursor"
        ],
        "additionalProperties": false,
        "description": "One page of items."
      },
      "SearchResult": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ItemSummary"
            }
          }
        },
        "required": [
          "data"
        ],
        "additionalProperties": false,
        "description": "Best matches first. Search is not paginated."
      },
      "GenreList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "slug": {
                  "type": "string",
                  "description": "Exact value to pass as `genre`.",
                  "examples": [
                    "Adventure"
                  ]
                },
                "count": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991,
                  "description": "Items of this type with the genre."
                }
              },
              "required": [
                "slug",
                "count"
              ],
              "additionalProperties": false
            }
          }
        },
        "required": [
          "data"
        ],
        "additionalProperties": false,
        "description": "Genres of a type, most common first."
      },
      "Usage": {
        "type": "object",
        "properties": {
          "plan": {
            "type": "string",
            "enum": [
              "free",
              "pro",
              "business"
            ]
          },
          "quota": {
            "type": "object",
            "properties": {
              "limit": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "used": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "remaining": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              },
              "period": {
                "type": "string",
                "enum": [
                  "lifetime",
                  "month"
                ],
                "description": "`lifetime` on Free (100 requests in total); `month` on paid plans (UTC calendar month)."
              },
              "resets_at": {
                "anyOf": [
                  {
                    "type": "string",
                    "format": "date-time",
                    "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
                  },
                  {
                    "type": "null"
                  }
                ],
                "description": "Next reset; `null` for lifetime quotas."
              }
            },
            "required": [
              "limit",
              "used",
              "remaining",
              "period",
              "resets_at"
            ],
            "additionalProperties": false
          },
          "credits": {
            "type": "object",
            "properties": {
              "balance": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991,
                "description": "Prepaid requests used after the quota runs out (paid plans)."
              }
            },
            "required": [
              "balance"
            ],
            "additionalProperties": false
          },
          "rate_limit": {
            "type": "object",
            "properties": {
              "requests_per_second": {
                "type": "integer",
                "minimum": 0,
                "maximum": 9007199254740991
              }
            },
            "required": [
              "requests_per_second"
            ],
            "additionalProperties": false
          }
        },
        "required": [
          "plan",
          "quota",
          "credits",
          "rate_limit"
        ],
        "additionalProperties": false,
        "description": "Quota, credits and rate limit of the key's account. This call counts as one request."
      },
      "Problem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "Link to the documentation of this error."
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "detail": {
            "type": "string",
            "description": "What went wrong and how to fix it."
          },
          "code": {
            "type": "string",
            "enum": [
              "bad_request",
              "unauthorized",
              "payment_required",
              "forbidden",
              "not_found",
              "rate_limited",
              "internal_error",
              "service_unavailable"
            ],
            "description": "Stable machine-readable error code."
          },
          "request_id": {
            "type": "string",
            "description": "Quote it when contacting support."
          },
          "errors": {
            "description": "Invalid parameters (only on `bad_request`).",
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "path": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              },
              "required": [
                "path",
                "message"
              ],
              "additionalProperties": false
            }
          },
          "plan": {
            "type": "string",
            "enum": [
              "free",
              "pro",
              "business"
            ]
          },
          "limit": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code",
          "request_id"
        ],
        "additionalProperties": false,
        "description": "RFC 9457 problem details (`application/problem+json`)."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid query parameter, cursor, or a `limit` above your plan's page size.",
        "headers": {
          "X-Request-Id": {
            "description": "Id of this request; quote it to support.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "https://hexascore.com/docs/errors#bad_request",
              "title": "Invalid request",
              "status": 400,
              "detail": "Invalid query parameter, cursor, or a `limit` above your plan's page size.",
              "code": "bad_request",
              "request_id": "5f0c8d3e-4b7a-4f43-9a51-2a8c4f3f9b10"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, malformed, unknown or revoked API key.",
        "headers": {
          "X-Request-Id": {
            "description": "Id of this request; quote it to support.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "https://hexascore.com/docs/errors#unauthorized",
              "title": "Missing or invalid API key",
              "status": 401,
              "detail": "Missing, malformed, unknown or revoked API key.",
              "code": "unauthorized",
              "request_id": "5f0c8d3e-4b7a-4f43-9a51-2a8c4f3f9b10"
            }
          }
        }
      },
      "PaymentRequired": {
        "description": "Quota (and credits, on paid plans) exhausted. Upgrade or buy credits.",
        "headers": {
          "X-Request-Id": {
            "description": "Id of this request; quote it to support.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "https://hexascore.com/docs/errors#payment_required",
              "title": "Quota exhausted",
              "status": 402,
              "detail": "Quota (and credits, on paid plans) exhausted. Upgrade or buy credits.",
              "code": "payment_required",
              "request_id": "5f0c8d3e-4b7a-4f43-9a51-2a8c4f3f9b10"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The account that owns the key is suspended.",
        "headers": {
          "X-Request-Id": {
            "description": "Id of this request; quote it to support.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "https://hexascore.com/docs/errors#forbidden",
              "title": "Forbidden",
              "status": 403,
              "detail": "The account that owns the key is suspended.",
              "code": "forbidden",
              "request_id": "5f0c8d3e-4b7a-4f43-9a51-2a8c4f3f9b10"
            }
          }
        }
      },
      "NotFound": {
        "description": "No such item, type or route.",
        "headers": {
          "X-Request-Id": {
            "description": "Id of this request; quote it to support.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "https://hexascore.com/docs/errors#not_found",
              "title": "Not found",
              "status": 404,
              "detail": "No such item, type or route.",
              "code": "not_found",
              "request_id": "5f0c8d3e-4b7a-4f43-9a51-2a8c4f3f9b10"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests per second. Wait `Retry-After` seconds.",
        "headers": {
          "X-Request-Id": {
            "description": "Id of this request; quote it to support.",
            "schema": {
              "type": "string"
            }
          },
          "Retry-After": {
            "description": "Seconds to wait.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "https://hexascore.com/docs/errors#rate_limited",
              "title": "Too many requests",
              "status": 429,
              "detail": "Too many requests per second. Wait `Retry-After` seconds.",
              "code": "rate_limited",
              "request_id": "5f0c8d3e-4b7a-4f43-9a51-2a8c4f3f9b10"
            }
          }
        }
      },
      "InternalError": {
        "description": "Unexpected error. The request was not counted against your quota.",
        "headers": {
          "X-Request-Id": {
            "description": "Id of this request; quote it to support.",
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "https://hexascore.com/docs/errors#internal_error",
              "title": "Internal error",
              "status": 500,
              "detail": "Unexpected error. The request was not counted against your quota.",
              "code": "internal_error",
              "request_id": "5f0c8d3e-4b7a-4f43-9a51-2a8c4f3f9b10"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "Temporarily unavailable. Retry after `Retry-After` seconds.",
        "headers": {
          "X-Request-Id": {
            "description": "Id of this request; quote it to support.",
            "schema": {
              "type": "string"
            }
          },
          "Retry-After": {
            "description": "Seconds to wait.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "example": {
              "type": "https://hexascore.com/docs/errors#service_unavailable",
              "title": "Service unavailable",
              "status": 503,
              "detail": "Temporarily unavailable. Retry after `Retry-After` seconds.",
              "code": "service_unavailable",
              "request_id": "5f0c8d3e-4b7a-4f43-9a51-2a8c4f3f9b10"
            }
          }
        }
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "hx_live_<32 chars>",
        "description": "API key from /profile/api, sent as `Authorization: Bearer hx_live_…`."
      }
    }
  }
}
